前几天我又在跑一个写 Bash 的 agent 评估。同一个模型、同一组任务、同一温度,就换了个接收输出的包装,分数从 71 掉到 18。同事在旁边瞅了半天,第一句是:“你是不是把 prompt 改坏了?”我没改 prompt,连输出都没改,改的是执行前那段解析逻辑。
后来翻到 2608.13547,我第一反应是:啊,原来这事儿有人系统地量出来了。
先停一下,问个问题:给 agent 打分的那个“匹配分数”,到底在匹配什么?
我们习惯默认它问的是“模型把任务做对了吗”。可它实际匹配的是最终状态。最终状态是两段东西叠出来的:模型生成了什么命令,以及那串命令怎么被塞回执行环境。匹配分数才不管这俩谁出的问题,它只管最后像不像。
这两段一旦糊在一起,就有个挺荒诞的后果:GPT-5.6-sol 在某个配置下匹配得分只差 -3.6 个百分点。你一看——几乎打平,没啥好说的。然后有人把同一批回复原封不动喂给一个故意不转义的解析器,分数往下砸了 64.3 个点;换个场景,把边界信息提前说清楚,分数又捡回来 60.7 个点。
那个 -3.6 是什么?它就不是模型的能力差。它是一个真实损失撞上一个真实补偿,俩互相咬合之后剩下的残差。你盯着残差看,以为在看模型,其实看的是两条路径在互相抵消。
这么说吧,我们给 agent 打分时,根本没办法把“模型”从“执行路径”里揭下来。任何一次执行都得经过一个接口,接口自己有脾气。
再往下呢?这个接口最容易被忽略的一层在哪儿?
序列化。模型吐的是 token,执行环境等的是字符串,中间得有人做“包装—传输—拆包”。我们平时看不顺眼的地方是 prompt 清不清楚,看得顺眼的是命令生成了、执行了、分数出来了。夹在中间那层序列化被当成隐形的。
但它不是隐形的。它是一段活代码,写的人得决定:字符串里的引号、空格、变量展开、花括号,哪些是模型想表达的意思,哪些只是传输格式。决定错了,模型生成的东西传过去就变成了另一个东西。
我那次评估最后定位到的问题小得让我想笑——一条命令里有个单引号没转义,agent 本来要写的是一个文件名,重新解析之后被拆成两个参数。单看这条命令,模型没错;单看解析器,也正常。放进同一条管子里,错就出来了,还错得特别像模型自己犯蠢。
这恰恰是这类失败最烦人的地方:它看起来完全像生成阶段的错。你以为是模型不懂引号,其实模型那一层根本没碰着,坏的是它外面那截传输带。而匹配分数这种只看最终状态的口径,天然没法告诉你坏在哪层。它只能说结果不对,然后把这笔账记在模型头上。
QuoteBench 干的最狠的事,是把执行路径这个隐形的东西显式做成了变量:一个故意不转义的新解析器,一个交叉了“生成契约”和“执行传输方式”的网格。然后做了一件特朴素的活——把同一批重放回复,在原来的路径下跑一遍,再在这个带病的路径下跑一遍。成功率掉 55.4 到 73.2 个百分点。
这数字读起来像“哦,新解析器真差”。但它真正说的是另一码事:我们之前看到的那些高分,有相当一部分是脆的。不是说模型在该场景下真会露馅的部分被修好了,是执行路径恰好没在那个点上绊它。换个解析器,同一批回复,塌一半多。
我一开始也以为,既然是接口没转义,那让模型自己把转义修了不就行了。后来才反应过来,没那么简单。论文里有句话我盯了很久:在插值点做转义可以复现每条重放回复在原始路径下的结果,所以披露边界之后,任何恢复只能来自模型改变生成。意思是,你没法靠事后修解析器去“还原”原意。边界一旦披露,解析器就定了,之后的分数回升必须是真的,是模型在生成时就把边界吃了进去。这么说吧,那个恢复分数有意义——它测的不是打补丁,是模型多快能改自己的输出行为去适配一条没见过的新执行路径。
再往下还有个让我更不安的问题。现在前沿模型的“原始生成能力”已经差不多饱和,理想路径下大家差不了几个点。真正拉开差距的,恰恰是这种适应边界的能力。想比较两个模型,在最干净的环境里跑标准任务,分数越来越没区分度。可你换换执行路径——换个序列化格式、换个解析器、换个验证器——有些模型的分数就跳变。这时候你才看得出来,它到底是真学会了生成命令,还是只学会了在某个特定接口前面表演。
而我们用同一个匹配分数去量这两件事,然后宣布一个模型比另一个强。这个“强”有多可信?26 对可比较的模型里,有 1 对出现了明确排名反转,另外 4 对的差异只取决于某个任务有没有踩在那种边界上。
先停一下,承认我前面说得有点滑。我把“真学会生成命令”和“只学会表演”说成两个东西了。这个二分不严谨。更准确的是:每个模型都在同时干这两件事,只是比例不同。我们量到的分数永远是这俩的混合,混合比取决于执行路径给“表演”留了多大空间。
这层我还没完全想明白。但顺着它往下,会觉得“模型能力”这个说法本身就有点站不住。我们平时说某个模型的 coding 能力多强,是把它的输出当成一个独立于评测环境的属性。但既然执行路径能造成几十个百分点的位移,“模型能力”还有多少是能独立谈论的?它更像模型和接口之间长出来的东西。你要说它强,得说明是在哪个接口前面强;你要说它不行,也得说明是生成不行,还是管道不行。现在的匹配分数,把这两种不行糊成了一团。
所以说回来,那天晚上那个 53 分的分差,根子不在模型抽风,在我压根没把“执行路径”当成一个需要报告的变量。我以为自己在比两个模型,其实比的是两条我还没说清差在哪儿、执行链。
这个洞让很多结论悬空:排行榜名次、benchmark 进步、某模型突然又超了谁三个点——要是不知道这些数字是在什么配置、什么生成契约、什么执行路径、什么最终状态验证器下面量出来的,它们就只是数字。
我目前只想出一个苗头:别再把“匹配分数”当一个东西报。至少报两列,一列在干净、披露了边界的环境里,一列在带病环境里。俩数放一起看,间隙大不大,才接近我们真正想知道的。这层还没剥透,先搁这儿。