Elea Notes.

SWE-bench Verified 里有 13.6% 的错题:题面与答案不符

人工重读全部 500 道题,68 道的题面与标准答案不对应。剔掉它们重排,131 个智能体里 64.1% 名次改变。

先说结论

  • SWE-bench Verified 是给编程智能体打分最常被引用的那把尺子。它的 500 道题号称经过人工核验。一项新研究把这 500 道逐个人工重读了一遍,发现 68 道(13.6%)的题面和答案根本不是一回事
  • 病根在造题的流水线:题面取自 GitHub 上的 issue(用户报的问题),标准答案取自那个 issue 链接到的 PR(开发者提交的修改)。流水线假设「PR 恰好做完了 issue 说的事」,而真实仓库里这条假设经常不成立
  • 后果不是「题目偏难」,是给分给错了人。把这 68 道题剔掉重排榜单,131 个参赛智能体里 84 个(64.1%)名次发生变化,前十名有 9 个位置动了。
  • 一个反直觉的相关性:从没被任何智能体解开的 34 道题里,41.2% 是错题;而被 100 个以上智能体解开的题里只有 5.7%。榜单末尾的「难题」有相当一部分不是难,是不可能。
  • 论文顺手做了一个自动检测器 PaiChecker,在两个别的数据集上二分类准确率到 92.12% / 91.67%。但对读者更有用的是那份错题分类表,它可以直接搬去审自己的评测集。

这篇讲的是评测集本身的正确性,而不是模型能力。区分这两件事很重要:如果尺子是弯的,那么所有用这把尺子量出来的结论都要重新审。

一道错题长什么样

先看一个具体的。sphinx-doc__sphinx-10614 这道题,题面是 issue #10570,一个关于 Sphinx 文档工具画继承关系图时链接错的问题。标准答案那个 PR,同时关掉了三个 issue

于是评分脚本的行为变成这样:智能体读到的题面只描述了一个问题,而验收用的测试来自一个修了三个问题的补丁。它把 #10570 完全正确地修好,仍然判错——因为另外两个问题它压根不知道存在。

这不是「题难」。题面里没有任何线索指向那两个问题,读题的人再聪明也推不出来。用考试打比方:卷面写着算第一小问,判分却按三小问的总分给,而且不告诉你还有两问。

反过来的形态也有。sympy__sympy-13852 里,那个被当作标准答案的 PR 自己是有 bug 的——它引入了随机失败的测试,后面还要再补一个 PR 修。但评测集把这个有缺陷的 PR 冻结成了「正确答案」。也就是说,要拿分,你得复现出跟当年那位开发者一样的 bug

机制:五类错位

把 500 道题手工读完之后,作者归出五个模式,共 11 个细分场景。这张表是这篇论文最能直接拿走的东西:

                                        SWE-bench Verified 500 道
                                        ├── 432 道对齐
                                        └──  68 道错位 (13.6%)

   SC  PR 范围溢出 (32.4%)  ─────────────────┤  PR 做的比 issue 要求的多
       SC-1 (12) 一个 PR 关掉多个 issue,题面只给一个
       SC-2  (2) 顺手加了 issue 没提的新功能
       SC-3  (2) 捎带修了别的既有 bug
       SC-4  (6) 夹带了给其他 issue 的补丁

   DP  PR 本身有缺陷 (44.1%) ────────────────┤  标准答案自己是坏的
       DP-1 (14) 引入新 bug,后续还要修
       DP-2 (16) 只修了一半,需要后续补

   IS  题面不完整 (26.5%) ───────────────────┤  关键信息在 issue 的评论里
       IS-1 (12) 维护者追问后,报告者才补上细节
       IS-2  (6) 要解决的问题在讨论中被改掉了

   FP  后续补丁 ─────────────────────────────┤  仓库里已经有前一半答案
       FP-1  (2) 修的是前一个 PR 引入的 bug
       FP-2  (1) 补充前一个 PR 的遗漏

   UL  未指定的字面量 ───────────────────────┘  测试断言 issue 里没有的确切字符串
       UL-1  (1) 例如异常消息的精确措辞

注意最大的一类是 DP(占错题的 44.1%):标准答案本身不完整或有害。第二大类 SC 是题面比答案窄。第三类 IS 是题面比答案窄的另一种形态——信息存在,但存在于智能体看不到的地方(issue 下面的讨论)。

UL 这类只有 1 道,但值得单独说,因为它揭示了自动评测的一个通病。astropy__astropy-13033 的 issue 说「抛一个异常,告诉用户到底缺哪些必需列」,没规定措辞。测试补丁断言的是这个精确字符串:

TimeSeries object is invalid -- expected ['time', 'a'] as the
first columns but found ['time', 'b']

语义完全正确但措辞不同的实现,一律判错。评分机制卡在了实现细节上,而那个细节无法从题面推导出来。

为什么这样设计

得说清 SWE-bench 为什么会长成这样,否则会误以为是作者偷懒。

要造一个真实的编程评测集,你需要三样东西:一个人类可读的任务描述、一份可执行的验收标准、以及一个能跑起来的代码仓库快照。GitHub 恰好免费提供了全部三样:issue 是描述,PR 的测试是验收,仓库历史给快照。用正则从 PR 描述里抓 fixes #1234 就能把它们配上对。

这个设计的价值在于规模和真实性:你能几乎零成本地拿到几千道来自真实项目的任务,而不是人工编造的玩具题。SWE-bench 因此成了行业标准,这是它应得的。

代价是配对的正确性完全依赖开发者的书写纪律。而真实项目里,一个 PR 顺手多修两个 bug 是美德不是罪过;把细节写在评论里而不是重新编辑 issue 正文是常态;先合一个不完整的修复再补第二个也很正常。流水线要求的那种一一对应,是软件工程实践里本来就不存在的东西

值得强调的是 SWE-bench Verified 已经是人工筛过的版本——OpenAI 请开发者逐条核验过题面是否充分。13.6% 的错位率是在这层人工核验之后的残留。作者选它正是因为这点:这里都有 13.6%,没筛过的同类数据集只会更高。

论文里那句话说得直接:同一条流水线也在生产训练数据。错位的配对在训练里就是噪声监督,教模型去产出不完整、无关、甚至有缺陷的补丁。评测集的问题会通过训练渠道二次污染模型。

边界

几个必须说清的限制。

相关不是因果。 「没被解开的题里 41.2% 是错题」不等于「错题导致解不开」。也可能是难题恰好倾向于伴随复杂的 PR,而复杂 PR 更容易顺手多修东西。作者自己在论文里明确写了这是相关性证据,不是因果证据。这个自我约束值得记一笔。

错位判定有主观成分。 作者用了开放编码加多人交叉复核(第二作者复审,分歧由第三作者裁决)来控制,IS 那类还刻意绑定了一个客观锚点——只有当仓库维护者本人也追问缺失信息时才算题面不完整,理由是连熟悉项目的人类专家都推不出来,模型自然也推不出来。这个判据比「我觉得题面不清楚」硬得多,但终究是人的判断。

重排榜单的位移不大。 64.1% 的智能体名次变了(42 升 42 降),听起来剧烈,但多数只动 1-2 名。最大的位移是 +5(ugaiforge)和 -4(Bracket.sh、AutoCodeRover-v2.1)。结论应该是「排名的精度不如小数点暗示的那么高」,不是「榜单完全无效」。

至于「多小的分差算没有意义」,得用对的那个统计量。平均通过率上升 2.77 个百分点,但齐涨的那部分恰恰不改变任何名次——如果每个智能体都正好涨 2.77,位移会是 0 而不是 84/131。能造成互换的是涨幅之间的:论文给的区间是 −0.24 到 +4.49 个百分点,所以一次重打分最多能翻转 4.49(0.24)=4.734.49-(-0.24)=4.73 个百分点的原始差距。这一版初稿写的是 3 个百分点,取自那个平均值,低估了约 1.6 倍——而且是往「榜单比实际更精确」的方向低估的。

PaiChecker 的数字是二分类准确率。 92.12% 说的是「判断有没有错位」,更难的完整分类(exact match,五类标签全对)是 84.66%。检测器本身也是 LLM 驱动的多智能体系统,用的是 GPT-5.3 Codex、Qwen-3.5 Plus、Gemini-3.1-Pro Preview、Claude-Sonnet-4.6 四种底座。用 LLM 审 LLM 的评测集,这个循环的可靠性还需要更多独立验证。

这篇是会议论文的预印本(ASE ‘26,10 月在慕尼黑),arXiv 上 7 月 30 日首发、8 月 2 日更新。数字可能随终稿微调。

来源

  1. PAIChecker: Uncovering and Checking PR-Issue Misalignment in SWE-Bench-Like BenchmarksarXiv