1. 这场重测到底测了什么
先把背景交代清楚。SWE-bench Pro 是当前编程 Agent 圈子里公认难度最高的一档评测集之一,它跟早期那种"给个函数签名补全实现"的玩具题完全不是一个量级。它的题目来自真实开源仓库的真实 issue 和 PR,要求 Agent 在完整代码库里定位问题、跨文件修改、跑通测试,最后提交一个能通过隐藏用例的补丁。换句话说,它考的不是"你会不会写代码",而是"你能不能在陌生工程里像个人类工程师一样干活"。
这次重测的起因很简单:过去几个月,各家模型在宣传口径上都在暗示自己已经"接近甚至超越人类工程师水平",榜单分数一个比一个好看。但圈内做实际落地的人心里都清楚,宣传分数和真实可用性之间隔着一条鸿沟。于是有人组织了一次统一环境、统一脚手架、统一评分口径的重测,把 7 个当前最受关注的模型拉到同一条起跑线上,结果 6 个不及格。
参与重测的模型包括 GLM-5.2、DeepSeek-V4-Pro、GPT-5.6-Sol 这几个热搜词里反复出现的名字,另外还有几个同档位的选手。所谓"不及格",不是指它们一分没得,而是指在预设的通过阈值下,任务完成率、补丁正确率、回归破坏率这几项综合指标没能达到"可以放心交给它干活"的及格线。
这篇文章我想聊的不是"谁第一谁倒数"这种排行榜式的八卦,而是想把这套评测背后的方法论、踩过的坑、以及为什么会出现"榜单很美、落地很惨"这个现象讲透。如果你正在选型编程 Agent,或者正在自己搭一套评测流程,这篇内容应该能帮你少走不少弯路。
2. 为什么统一评测这么难
2.1 评测口径不统一是万恶之源
我见过太多团队在选型时的做法:打开各家官网,看谁家公布的 SWE-bench 分数高,然后拍板。这个做法的问题在于,SWE-bench 系列本身有多个版本(Lite、Verified、Full、Pro),每个版本的题目难度、评分脚本、环境依赖都不一样。更关键的是,模型厂商公布分数时用的脚手架(scaffold)往往是自己调优过的——提示词模板、上下文裁剪策略、重试机制、工具调用格式,每一项都会显著影响最终分数。
举个具体的例子。同一个模型,用"一次性把整个仓库塞进上下文"和用"先检索相关文件再逐步缩小范围"这两种策略,在 SWE-bench Pro 上的分数能差出十几个百分点。前者在小题上占便宜,后者在大仓库题上优势明显。如果 A 厂商用前者、B 厂商用后者,你拿这两个分数直接比,等于在比苹果和橘子。
所以这次重测的第一个原则就是:所有模型跑同一套脚手架。提示词模板统一、上下文管理策略统一、工具集统一、重试次数统一、超时时间统一。只有把变量控制住,分数才有可比性。
2.2 环境隔离比想象中麻烦
SWE-bench Pro 的每道题都对应一个特定的仓库快照和一套依赖环境。Python 版本、系统库、编译工具链,任何一处不一致都可能导致测试结果失真。我们试过用容器化方案,每道题一个独立镜像,好处是干净,坏处是镜像体积大、构建慢,7 个模型乘以几百道题,光是环境准备就能把人耗死。
后来采用的折中方案是:按仓库分组,同一仓库的题目共享一个基础镜像,只在依赖层做增量。这样既保证了隔离性,又把构建时间压下来了。这里有个细节值得说:一定要把网络访问关掉。有些 Agent 会"作弊",偷偷去拉取仓库的最新代码或者搜索现成答案,如果不做网络隔离,测出来的分数会虚高得离谱。
提示:做 Agent 评测时,网络隔离是底线。我见过不止一次因为没断网导致分数异常的情况,排查半天才发现是 Agent 在偷偷联网。
2.3 评分脚本本身也会骗人
SWE-bench 的评分逻辑是跑测试用例,看补丁能不能让原本失败的测试通过、同时不破坏原本通过的测试。听起来很客观,但实操中有很多坑。比如有些测试是 flaky 的(时好时坏),有些测试依赖随机种子,有些测试对执行顺序敏感。如果不做处理,同一个补丁跑两次可能得到不同结果。
我们的做法是:每道题的测试跑三遍,取稳定结果;对已知 flaky 的测试做标记并排除;对执行顺序敏感的测试做固定排序。这些处理看起来繁琐,但不做的话,你得到的分数就是噪声。
3. 七个模型的实际表现拆解
3.1 及格线是怎么定的
在公布结果之前,得先说清楚"及格"的标准。我们没有用"分数超过 X 就算及格"这种拍脑袋的线,而是从实际落地角度反推:一个编程 Agent 要能被放心地用在生产环境的辅助开发中,至少需要满足三个条件。
第一,任务完成率不低于某个阈值。这里的"完成"不是指"生成了补丁",而是指补丁能通过全部隐藏测试。第二,回归破坏率要足够低,也就是说它修好一个 bug 的同时,不能引入新的 bug。第三,补丁的可读性和可维护性要过关,不能是那种"能跑但没人看得懂"的代码。
综合这三项,我们定了一条及格线。结果 7 个模型里只有 1 个过线,其余 6 个在不同维度上栽了跟头。有意思的是,这 6 个不及格的模型里,有好几个在公开榜单上的分数是相当漂亮的。这个反差本身就是最值得聊的东西。
3.2 各模型的典型失败模式
我把观察到的失败模式归了几类,这些模式比单纯的分数更有参考价值。
第一类是"定位失败"。Agent 在仓库里找了半天,改错了文件,或者改对了文件但改错了函数。这类失败在大型仓库题目上特别常见,因为上下文窗口再大也塞不下整个仓库,Agent 必须靠检索来缩小范围,而检索策略一旦不够聪明,就会在错误的区域里打转。
第二类是"改对了但没改全"。一个 bug 往往涉及多处修改,Agent 只改了最明显的那一处,漏掉了关联的调用点或者边界处理。这类失败最隐蔽,因为它的补丁看起来是对的,跑部分测试也能过,但隐藏测试一上就露馅。
第三类是"过度修改"。Agent 为了确保测试通过,把周边代码大改一通,结果引入了回归。这类失败在回归破坏率这个指标上体现得最明显。
第四类是"环境适配失败"。Agent 生成的补丁逻辑没问题,但依赖了仓库里不存在的库,或者用了不兼容的语法版本。这类失败纯粹是工程细节没处理好,但恰恰是实际落地中最常见的。
| 失败模式 | 典型表现 | 高发场景 | 排查难度 |
|---|---|---|---|
| 定位失败 | 改错文件或函数 | 大型多模块仓库 | 中 |
| 修改不全 | 漏改关联调用点 | 跨文件重构类任务 | 高 |
| 过度修改 | 引入回归破坏 | 边界条件复杂任务 | 中 |
| 环境适配失败 | 依赖或语法不兼容 | 老版本仓库 | 低 |
3.3 唯一及格的那个做对了什么
唯一过线的模型,我观察下来它的优势不在"更聪明",而在"更克制"。它生成的补丁普遍偏小,改动范围集中在问题核心区域,很少去动无关代码。这种克制带来的直接好处就是回归破坏率极低。
另一个细节是它的检索策略。它在动手改代码之前,会先花几轮去读相关文件、理解调用关系,而不是急着生成补丁。这个"先读后写"的习惯,让它的定位准确率明显高于其他模型。说白了,它更像一个谨慎的工程师,而不是一个急于交差的实习生。
这个观察对我启发很大:在编程 Agent 这个场景里,"不乱改"可能比"改得多"更重要。很多模型的问题不是能力不够,而是太想表现,结果画蛇添足。
4. 榜单分数和真实可用性的鸿沟
4.1 公开榜单的激励扭曲
公开榜单有个天然的问题:它激励的是"刷分",而不是"好用"。模型团队为了让分数好看,会针对榜单的题型做优化,比如专门训练某类补丁模式、调整提示词去迎合评分脚本。这些优化在榜单上有效,但换到真实工程场景里就未必了。
更微妙的是,榜单题目是固定的,而真实工程的问题是千变万化的。一个模型可能在榜单的几百道题上表现优异,但遇到一个榜单里没出现过的仓库结构就抓瞎。这种"过拟合榜单"的现象,在编程 Agent 领域特别普遍。
4.2 真实场景的复杂度被严重低估
真实工程里,一个 issue 的描述往往是模糊的、不完整的,甚至是有误导性的。提出 issue 的人可能自己都没搞清楚问题在哪。Agent 需要在这种信息不完整的情况下做判断,而榜单题目通常把问题描述得很清楚,这就降低了难度。
还有一点是代码库的"历史包袱"。真实仓库里充满了历史遗留的奇怪写法、注释掉的代码、临时补丁。Agent 如果不懂这些"潜规则",很容易改出问题。榜单题目大多来自相对干净的仓库,这部分难度被抹掉了。
4.3 我们该怎么看待分数
我的建议是:把公开榜单分数当作"入场券",而不是"录取通知书"。分数高的模型值得进一步测试,但绝不能仅凭分数就做选型决策。真正靠谱的做法是拿你自己项目的真实 issue 去测,哪怕只有二三十道,也比看榜单分数有参考价值。
具体怎么测,我后面会讲。这里先给个结论:榜单分数和真实可用性的相关性,大概只有中等偏下。你如果完全信榜单,踩坑是迟早的事。
5. 自己搭一套靠谱评测的实操步骤
5.1 从你的真实 issue 里抽题
最理想的评测集,是从你自己项目的 issue 历史里抽。挑选标准有几个:问题描述清晰但不过于详细、涉及的文件数量适中、有明确的验证方式。抽个二三十道就够用了,关键是覆盖你项目里最常见的几类任务。
如果项目历史不够长,可以拿几个你熟悉的开源仓库来凑。但要注意,一定要选你真正读得懂的仓库,否则你连 Agent 改得对不对都判断不了。
5.2 搭建可复现的评测环境
环境这块,容器化是首选。每道题一个独立环境,固定依赖版本,关闭网络访问。评分脚本要能自动跑,并且要处理 flaky 测试。下面是一个简化的评测流程伪代码,帮你理清思路。
def evaluate(model, task, scaffold): env = build_isolated_env(task.repo_snapshot, task.dependencies) env.disable_network() prompt = scaffold.build_prompt(task.issue_description, task.repo_context) patch = model.generate(prompt, tools=scaffold.tools, max_retries=3) if not patch: return {"status": "no_patch", "score": 0} apply_result = env.apply_patch(patch) if not apply_result.success: return {"status": "apply_failed", "score": 0} test_results = [] for _ in range(3): test_results.append(env.run_tests(task.test_command)) stable_result = resolve_stable_result(test_results) regression = env.check_regression(task.baseline_tests) return { "status": "completed", "pass_rate": stable_result.pass_rate, "regression_rate": regression.break_rate, "patch_size": patch.line_count }这段代码的核心思想是:把"生成补丁"和"验证补丁"彻底分开,中间用隔离环境做屏障。任何一步失败都要有明确的失败状态,而不是笼统地记个零分。这样你才能知道模型到底卡在哪一环。
5.3 评分维度要拆细
不要只记一个总分。至少要把这几个维度分开记:定位准确率(改对了文件没有)、补丁通过率(测试过了没有)、回归破坏率(有没有引入新问题)、补丁规模(改动大不大)。这四个维度组合起来,才能画出模型的能力画像。
我自己的经验是,定位准确率是最有区分度的指标。很多模型补丁通过率看着还行,但定位准确率很低,说明它是靠"广撒网"碰对的,不是真的理解了问题。这种模型在简单任务上能用,一遇到复杂任务就原形毕露。
5.4 跑评测时的注意事项
第一,样本量要够。二三十道题只能看个大概趋势,要做严肃对比至少得上百道。第二,要跑多次取平均,单次结果波动太大。第三,要记录失败案例的详细信息,这些案例比分数更有价值。第四,评测脚手架要固定,中途不要改,否则前后结果没法比。
注意:评测过程中最容易犯的错是"边测边调脚手架"。看到某个模型表现差,就想着改改提示词救一下,结果改完之后所有模型的结果都不可比了。要调脚手架,等这一轮测完再调。
6. 编程 Agent 选型的实战建议
6.1 别迷信单一模型
实测下来,没有哪个模型在所有任务类型上都强。有的擅长小范围 bug 修复,有的擅长跨文件重构,有的擅长写测试。比较务实的做法是准备两三个模型,按任务类型路由。比如简单的单文件修改交给便宜快的模型,复杂的跨模块任务交给贵的强模型。
这个思路听起来简单,但落地时要注意路由规则的设计。我的建议是先用规则做粗筛(比如按改动文件数量、按任务类型标签),再根据历史表现做动态调整。不要一上来就搞复杂的机器学习路由,先把规则跑通再说。
6.2 人工审核这道关不能省
不管模型分数多高,补丁在合并前一定要有人看。这不是不信任模型,而是编程这件事的容错率太低。一个看似无害的改动,可能在生产环境引发连锁反应。人工审核的重点不是逐行读代码,而是看改动范围是否合理、有没有动到不该动的地方、边界处理是否到位。
我自己的习惯是重点看三类改动:涉及并发和状态管理的、涉及数据持久化的、涉及外部接口调用的。这三类改动出问题的代价最高,值得多花时间。
6.3 建立自己的回归测试网
模型改代码最大的风险是引入回归。要防这个,靠的不是模型自觉,而是你自己的测试网。测试覆盖率越高,模型乱改的空间就越小。如果项目测试覆盖不足,建议在引入编程 Agent 之前先把测试补上,否则你就是在裸奔。
这里有个反直觉的点:测试写得越细,模型反而表现越好。因为详细的测试给了模型明确的反馈信号,它能根据测试失败信息快速定位问题。所以测试不只是防守工具,也是提升 Agent 表现的进攻工具。
6.4 成本账要算清楚
编程 Agent 的成本不只是 API 调用费。还有评测环境维护、人工审核时间、回归问题修复成本。有些模型单次调用便宜,但通过率低,需要反复重试,综合成本反而更高。算成本账时要把这些隐性成本都算进去。
我一般会算一个"有效任务成本":完成一个真实任务平均需要花多少钱(包括重试和人工介入)。这个指标比单纯的 token 单价有参考价值得多。
7. 常见问题与排查技巧
7.1 评测结果波动大怎么办
波动大通常有三个原因:测试 flaky、模型输出随机性、环境不一致。排查顺序是先查环境,再查测试,最后查模型。环境问题最好排查,固定依赖版本、关闭网络、统一系统时间基本能解决。测试 flaky 需要跑多次统计,把不稳定用例标记出来。模型随机性可以通过固定随机种子、降低温度参数来缓解,但没法完全消除,只能靠多次取平均。
7.2 Agent 总是改错文件怎么破
这基本是检索策略的问题。可以尝试几个方向:一是改进文件检索,用更精准的关键词匹配或语义检索;二是强制 Agent 在改代码前先输出它的分析过程,逼它想清楚再动手;三是给它更多的仓库结构信息,比如模块依赖图。实测下来,强制"先分析后动手"这个策略效果最明显,虽然会多花一些 token,但定位准确率提升很大。
7.3 补丁能过测试但代码质量差
这是评分维度太单一导致的。如果你的评分只看测试通过率,模型就会生成"能跑就行"的代码。解决办法是把代码质量纳入评分,比如检查补丁规模、检查是否引入了重复代码、检查命名规范。这些检查可以用静态分析工具自动化,虽然不能完全替代人工,但能过滤掉大部分低质量补丁。
7.4 模型在某个仓库上表现特别差
先确认这个仓库是不是有什么特殊之处:是不是用了不常见的构建工具、是不是有复杂的代码生成逻辑、是不是依赖了大量私有库。这些因素都会显著影响 Agent 表现。如果确认是仓库特殊,可以考虑给 Agent 补充这个仓库的专属上下文,比如构建说明、代码规范文档。这相当于给它开小灶,效果通常立竿见影。
| 问题现象 | 可能原因 | 排查方向 | 解决思路 |
|---|---|---|---|
| 结果波动大 | 测试 flaky / 环境不一致 | 先查环境再查测试 | 固定依赖、多次取平均 |
| 改错文件 | 检索策略差 | 检查文件检索逻辑 | 强制先分析后动手 |
| 代码质量差 | 评分维度单一 | 检查评分脚本 | 纳入静态质量检查 |
| 特定仓库表现差 | 仓库有特殊性 | 分析仓库构建和依赖 | 补充专属上下文 |
7.5 一个容易被忽略的坑:上下文污染
多轮对话里,前面轮次的错误信息会污染后面的判断。Agent 可能因为前面某次失败的尝试,在后续轮次里反复往错误方向走。解决办法是在关键节点重置上下文,或者把历史信息做摘要压缩,只保留结论不保留过程。这个坑很隐蔽,但影响很大,我踩过好几次才意识到。
8. 我对这轮重测的几点个人体会
做完整轮重测,最大的感受是:编程 Agent 这个领域,宣传和现实之间的差距比大多数技术领域都大。这不是说模型不行,而是说这个任务的难度被严重低估了。写代码这件事,表面上考的是语言能力,实际上考的是对工程系统的理解、对边界的判断、对历史包袱的尊重。这些能力很难靠刷榜刷出来。
另一个体会是,评测本身是一门手艺。同样一批模型,不同的评测设计能得出完全不同的结论。所以看到任何榜单,第一反应应该是问"它怎么测的",而不是"谁第一"。这个习惯能帮你避开大部分选型陷阱。
最后说个实操层面的建议:如果你打算引入编程 Agent,先别急着上生产,拿你自己的项目做一轮小规模评测。哪怕只测十道题,你对模型能力的认知也会比看一百篇评测文章更准确。评测这件事,自己动手做一遍,胜过看别人做十遍。