跳到主要内容
日志全是绿的,产物全是错的

日志全是绿的,产物全是错的

阿舟
阿舟

· 阅读约 8 分钟

大概两个月前的一个下午,我盯着 CI 日志看,全是绿的。

agent 跑完了,exit code 0,单测全过,pipeline 一路通关。然后我打开它生成的那张对账表——收入和支出两列,反了。

不是格式错,是逻辑错。它把两列的语义理解反了,然后非常自信、非常高效地,把一整个错误的方案执行到了底。

这就是我现在最怕的那种翻车。不是它崩,是它不崩。

agent 挂了,你有栈、有 trace、知道它死在哪一行,再蠢的 bug 也留了线索。它不报错的时候,你手上什么都没有——只有一个看起来像回事的结果,和一份你根本不知道该不该信的日志。

我管这个叫静默错误。它贵的地方不在于错,在于错得像个正确答案。

更气人的是它不一定复现。

同一段 prompt,同一个输入,第一次两列反了,第二次没有。我拿着第一次的日志去复现,连跑五遍,五遍都对。跑到第四遍,我已经开始怀疑是不是我自己记错了。

麻烦是双份的:这一次的结果你不知道能不能信;出了事,你又连案发现场都保不住,更别说定位成因。

我一直在等有人把这件事系统化。等的不是一个更聪明的模型——模型再强也解决不了,问题不在它聪不聪明,在于它做对做错这件事本身没被记成可查的东西。

这段时间 agent 的可观测性工具不少,绝大多数在做另一件事:trace、span、token 计数、延迟、工具调用次数。这些是仪表盘。

画外音:仪表盘能告诉你车开多快,不能告诉你车开反了方向。

前段时间翻 arXiv 翻到一篇,2611.04507,11 月 3 号挂的 v1,4 号就更了 v2。我特意点开 v2 的变更记录看了一眼,只修了作者单位的排版。十一页,一张图,六张表,六个作者。

开篇那句基本就是我想说的:即使智能体用的工具和跑的基础设施都正常,它照样可能做出错误决策,或者烧掉本来不该烧的资源。接着它老老实实承认了更难的那部分——非确定性让这类问题很难复现,也很难定位成因。

看到这句我愣了一下。不是因为它说得多深,是终于有人把这句话白纸黑字写进论文里了。

方法叫 Signals。第一件事是搭一套问题分类:8 个族,45 种类型,每种类型有定义,还有"需要什么证据才能判成这一类"。

45 这个数字,我第一反应是太多了,谁记得住。往下看才明白,这 45 种不是给人背的,是给判定过程当坐标用的。你不用记住全部,你需要的是在说"这里有问题"的时候能落到一个具体类型上,而不是笼统地说"agent 表现不太好"。

然后它把问题分成三类:已经实际发生的失败、潜在的风险暴露、效率上的浪费。

再往下是我觉得整篇里最有价值的一步——把彼此关联的零散发现合并成一个面向工程的问题单元,叫 Signal。每个 Signal 带两样东西:一个开发者能直接动手的处置动作,和一个用来检验"我改完到底有没有改对"的检查项。再按证据强弱给严重程度评级。

我最服的其实不是那 45 种类型,是"证据条件"这个东西。

它把"我觉得这次 agent 跑得有点怪"逼成了"我拿出证据,证明这里属于第几类问题"。这两句话之间的距离,就是玄学和工程的距离。

我以前审 agent 的产物基本靠手感——看一眼,觉得哪里不对,再翻日志找。手感好的时候快,手感不好的时候一个真问题能从眼皮底下溜过去。反过来也糟:我觉得有问题,翻了半小时,最后发现是我自己多疑。

有了证据条件,至少"我说有问题"这句话得附材料。附不上,闭嘴。

接着说那个数。91.43% 的 F1,我看到的时候是兴奋的,冷静下来就变成了怀疑。

我倒不怀疑作者造假,我怀疑这个数能说明的东西比看上去少。

它在公开的智能体执行数据上评估,匹配的对象是"参考问题"。问题来了:参考问题是谁标的?

45 种类型是作者自己定义的坐标系。如果参考集也是按这套坐标系标出来的,那这个 91.43% 衡量的更像是"方法输出和标注体系之间的一致性",而不是"这套东西在真实生产环境里能不能抓到真问题"。内部一致性和外部有效性,差得很远。一篇论文能证明前者就已经不错,但它证明不了后者。

换我是作者,大概也只能这么评——公开数据就那么点,真要做外部有效性验证,得跟几家公司要生产 trace,那成本不是一篇 arXiv 能覆盖的。理解,但我不会把这个数当成生产可用的证据。

不过说完这句我有点心虚。我自己手上连一份像样的 trace 数据集都没有,凭什么要求别人的评估做到外部有效。先把自己那边收拾干净再挑刺吧。

另一个数更值得说:比同模型、同分类体系的单次 LLM 基线高约 18 个百分点。

这个对比我信,但我信的理由跟那 18 无关。

单次 LLM 基线是什么?把一整段执行轨迹丢给模型,问它这里面有什么问题。这种用法我试过,输出大概长这样:

- 建议检查边界情况是否处理正确
- 可以考虑增加错误重试机制
- 注意资源消耗

语法正确,信息量为零。照着这三条改,改到明年也不知道从哪下手。

所以那 18 个点的差距,我认为主要来自"有没有把检查项列成清单",而不是方法本身有多高明。换句话说,这个对比真正证明的是:把开放问题收敛成有限选项,比让模型自由发挥强。这事我在 prompt 上缴过智商税,换个名字也一样成立。

那 Signals 的价值到底在哪?不在那个 F1,在它的结构。它把一次 agent 执行变成了一份可以归档的东西。

三类问题里,"效率上的浪费"我要单独说。

已经发生的失败最好抓,有报错、有异常输出,眼睛看得见。潜在风险也还行,这次没炸但条件一变就炸,动脑子能想到。浪费是这三类里最没人管的。

agent 多跑了几轮、同一个文件反复读、为了改一行把整个大文件塞进 context、跑了一次根本不需要的搜索——全都不报错。成本不写在日志里,写在账单里,月底才看见。

我有一阵子对过一次账:某个天天跑的任务,消耗是三个星期前的四倍。代码没改,prompt 没改,模型也没换。

我想查是哪一步开始变胖的。

查不出来。因为我根本没留那几天的执行轨迹。日志只有我自己打的那几行,agent 中间干了什么、调了几次工具、每次塞了多少 context,全没有。

画外音:想省 token,先花 token 把 trace 存下来 😅。逻辑有点荒谬,但它是真的。

说到账单想起来了,前阵子有人问我订阅费值不值——答案一直没变,按投入产出算,别为"用了高级工具"的仪式感付钱。扯远了,回正题。

论文里还有个设计我一开始没太在意:它能持续跑。后续的 agent 执行,既可能给已有的 Signal 补证据,也可能暴露新问题。

后来越想越觉得,这个设计对效率类比对付失败类重要。

失败了,你当场就会去查,查完就完了,不需要什么持续监控。浪费不一样——浪费是没人看的,你得让一个东西长期盯着,才能把"这三周比上三周多花四倍"这种慢变量揪出来。

非确定性在这里反而成了帮手。一次跑不出结论的,跑十次就有样本。同一个问题在十次执行里出现三次,那就是个真问题,不是运气。

我没在现在的项目上直接套 Signals。45 种类型我连记都记不全,更别说按证据条件一条条去标。但我照着它的思路改了几个地方。

最小的一个:验收标准写成可执行的。

# 以前
做完之后看一下结果对不对

# 现在
跑 python verify.py --input out.csv
把完整输出贴给我
任何一行 FAIL 就停下来,不要自己修,先告诉我

"看一下对不对"这句话,agent 的翻译是"我觉得对"。这跟没说一样。

还有一条,每次的 trace 都存。不为今天查,为三个月后出事的时候能回溯。

最要紧的一条:凡是 agent 说"我已经修好了",先别信。不是不信它,是不信"修好了"这三个字。修没修好,得有个检查项说话。没有检查项的"修好了",可信度跟我小时候跟老师说"作业写了"是一个量级。

回到那篇论文。我不会说它把问题解决了。它解决的是一半——把"agent 出问题"这件事,从一种玄学,变成一种能被记录、被分类、被举证的东西。

举证很枯燥。填分类、附证据、给个严重程度,听着就想跳过。但它是唯一一条路。在你能一条一条拿出证据之前,所有关于 agent 靠不靠谱的讨论,都只是在聊手感。

跑通了不等于跑对了。日志全绿,也可能只是错得比较安静。

这句我打算贴在显示器边上。

阿舟
阿舟

写代码写到一半开始怀疑人生,靠 AI 工具续命,顺手把踩过的坑都记下来。

查看主页 →