跳到主要内容

28.2% 不是重点,论文里那 10.8% 才是

P99
P99

· 阅读约 8 分钟

群里传的那几张截图,截的都是同一个数:28.2%。论文是 ProductWebBench,10 月 22 号挂上 arXiv,cs.SE 和 cs.AI 双挂,正文加附录 35 页。这数不是这篇里最值得转的那一个。

测试范围先划一下。我读的是 PDF 正文和附录,没拿到那 8,737 次运行的原始 trace,也没复现他们的 harness,更没去核对 320 个 Change 任务里到底有多少个真的过了“参考实现通过、错误实现不通过”那道准入。所以下面凡是谈设计的,是我读出来的;凡是谈数字的,只能停在“他们报告了什么”这一层,不是我测的。这个区别决定了哪些部分我能下判断、哪些不能。

28.2% 的分母,按论文口径,是“通过了全部请求工作检查的 Change 运行”——Change,不含那 80 个 Build。也就是说这个数描述的是:目标功能做对了,站点别的部分坏了。典型症状三条:路由渲染成空白、页面横向溢出、控制台报错。

数字本身不离谱,跟我自己那套土办法量级对得上。问题在分母。我在正文里翻了两遍,没找到具体是多少次运行,只有口径描述。13 个模型、8,737 次运行是总盘子,切到“过了全部请求工作检查的 Change 运行”还剩多少?得自己从附录表里倒推。我没推——推出来的数没有第二个人能核。

一个百分比不给分母,就是我一直在说的裸数字。能看,不能信。这条标红。

那一栏没人截图

论文里还有一栏,我读完最想抄走。

每个任务在开测前固定一份仓库快照,检查项是确定性的、浏览器端跑出来的证据;然后同一套检查会先在未改动的原始仓库上跑一遍。这句轻描淡写,但它把整件事的性质给改了。

常规 agent benchmark 怎么算分——跑一遍,看目标达成没有,没达成就记模型头上。致命缺陷在这:你分不清“模型改坏的”和“仓库本来就有的”。真实前端仓库里一堆本来就溢出的 div、本来就在报的 console warning,谁来背这个锅?大部分评测的做法是人工贴标签,或者干脆当没看见,把噪声算进失败率。

有了未改动快照的基线读数,每一次回归都能被精确归因。论文原话大意是“不是事后人工贴标签”。这句我信,因为逻辑上它必然成立:同一个检查,改之前 pass,改之后 fail,那这次 fail 就是这次 patch 带来的。不用判断,两次读数就够了。

我自己也干过类似的事,干得很土:手动 checkout 一份干净分支跑一遍,记下来,再切回改动那条分支。碰上依赖装不上的仓库,这一步直接废掉。他们把它做进了评测流程的固定环节,这是工程上的差别,不是想法上的差别。

那两个数别跟 28.2% 并排放

论文里还有两个数,容易被拼成“三成左右都出问题”。

10.8% 的运行会把此前已经通过的浏览器状态重新变成失败;在同时具备两种读数的 586 次运行里,18.3% 破坏了已验证的状态。

口径完全不一样。前者的分母是 Change 运行全体,具体多少仍然没给明;后者的分母只有 586,那是“同时具备两种读数”的那一小撮。586 按我自己的标准偏薄,⚠️ 先当方向参考。

我一开始确实想把 28.2%、29.5%、18.3% 凑成一句“三个三成”,写完自己看了一眼就划掉了。分母不是一批运行,凭什么并排。数字都是真的,摆在一起是假的。

第 9 条

这是我读下来认为整篇里最该被同行抄走的设计:模拟用户按阶段逐步揭示需求,而此前已经通过的检查,在本次运行的后续阶段中仍然持续生效。

评分器变成有状态的了。不是每阶段跑一遍然后清空,是累积的。第 2 阶段过了的检查项,到第 5 阶段还得过。

多阶段任务里最常见的作弊路径不是“做不出来”,是“为了做第 3 阶段,把第 1 阶段的东西拆了”。单阶段评分对这种事完全失明——每一阶段单独看都满分。累积检查一上,立刻暴露成 10.8%。

去年我做过一版多轮改代码的跑测,每轮独立打分,出来的通过率高得我自己都不信。回放 trace 才发现模型在第三轮把第一轮写的路由文件整个覆盖了,因为它觉得那文件“多余”。当时没累积检查,只能人工看 diff,看了二十来条就看不下去了。样本三十出头,结论没敢发。

ProductWebBench 把这个设成了默认行为,背后有确定性的浏览器证据撑着——不是让另一个模型来判“这样改算不算破坏”,是检查项直接复跑。这几年我看过的评测设计里,这是少数几个不用打问号的。

静态 DOM 检查已经通过的运行里,29.5% 在交互测试中失败。

这个数我一点都不意外,反而觉得偏低。DOM 结构对不对,跟点下去有没有反应,中间隔着一整个事件绑定层。按钮的 class、textContent、父节点层级全对,onclick 绑到了一个已经被替换掉的节点引用上——静态检查一路绿灯,点下去什么都不发生。手写代码都常犯,何况模型改的。我自己的检查里,交互这一层是最难做的:要模拟真实点击、等异步、还要分清“根本没绑上”和“绑上了但请求挂了”。做深了成本极高,做浅了等于没做。他们报了这个数,说明至少做了一层。做到什么深度,附录里应该有,我没细看,不下判断。

论文的立场那句,我认为是整篇的核心:应该把补丁放到它实际落地的运行系统里去评分,而不是只核对目标功能实现了没有。

这话说得客气,实际上是在打一大片现有 benchmark 的脸。核对目标功能,等于把 patch 当评分单位——你交个 diff,我看这个 diff 实现了几条需求,实现几条给几分,至于这个 diff 合进去之后整个站点还活不活,不在评分范围内。

这不一定是在偷懒,是成本问题。要让补丁“落地”再评分,得有一个能跑起来的仓库、能起服务的环境、还能在上面做重复跑测的确定性检查。320 个 Change 任务,每个固定快照、每阶段给需求、跑浏览器证据,8,737 次运行背后是多少机时,他们没报,但肯定不是小数目。这也是我为什么只读不复现——这套东西我一个人扛不动。

320 个 Change 对 80 个 Build。前者改已有代码,后者从零建站、长周期。论文没把两者分开报——至少正文里我没找到分开的表格。如果最终是合在一起算的,那 80 个 Build 的权重就被 320 个 Change 稀释掉了。

长周期任务偏偏是我最想知道结果的那一档。从零建站,需求分阶段给,中途还得反复回去维护已通过的状态——这才是真实工作流的形状。改一个已有仓库,说到底还是单点的;建站是连续的。

要是分开报,我猜 Build 的连续性失败率会比 Change 高,可能高不少。这是猜,没有数据支撑,不写进结论。这一条标“没测到”,等他们更新版本我再翻。

置信标签

高置信的部分:这套“未改动快照做基线 + 累积检查持续生效”的设计,方法论上比单纯统计任务完成率强一档。读完我没有任何犹豫。13 个模型、8,737 次运行的盘子,在同类工作里算厚的。

方向大致对、还不敢当结论的部分:28.2%、10.8%、29.5% 这三个百分比,量级我信,有效数字不信。分母交代不清、Build 和 Change 没分开报、586 那个子样本偏薄——这三条里任何一条,都足以让一个百分比在小数点后一位上失去意义。

证据不够、先别信的部分:任何形式的跨模型排名。论文没有按任务类型分桶的通过率明细,我没找到,不分桶的排名在我这儿一直不算排名。

要拿这套东西做产品决策的,先等他们把分母补上,或者自己从 320 个任务里挑个子集跑一遍基线。我这边等脚本能跑起来,会拿自己的仓库改一版对照。数字对不上,我再来写第二篇。