SWE-bench 学习笔记:代码模型评测,终于从刷题走向真实修 Bug

消化 SWE-bench 论文:为什么传统代码生成评测不足以衡量软件工程能力,SWE-bench 如何用真实 GitHub issue、仓库上下文和测试执行构造可执行评测。

这篇是对论文 SWE-bench: Can Language Models Resolve Real-World GitHub Issues? 的学习笔记。

如果要理解代码模型评测从“写函数”走向“做软件工程”的转折,SWE-bench 是绕不开的一篇。

在它之前,很多代码评测集中在 HumanEval、MBPP 这类任务:给模型一段函数签名和描述,让它补全函数,然后跑单元测试。这类评测很有价值,但它测的是一种相对干净的能力:在隔离环境里写一小段代码。

真实软件工程不是这样。真实修 Bug 往往需要读 issue、理解项目结构、定位相关文件、跨函数修改、跑测试、处理依赖、避免破坏已有行为。SWE-bench 把评测对象从“能不能写代码”推进到“能不能在真实仓库里解决问题”。

1. 传统代码评测缺了什么

一个刷题式代码任务通常长这样:

给定函数签名
写出函数体
通过隐藏测试

这能测算法、语法、边界条件,但它故意省掉了很多真实软件工程里的困难:

  • 你不知道该改哪个文件。
  • 你需要理解已有抽象和调用关系。
  • 问题描述可能模糊,issue 里不直接给答案。
  • 需要同时改多个函数或类。
  • 需要兼容已有测试。
  • 需要跑项目测试,而不是只跑一个小函数。
  • 需要避免引入回归。

所以一个模型在 HumanEval 上高分,不代表它能接一个 GitHub issue 并修好。

SWE-bench 的核心价值,就是把“代码生成”评测变成“代码维护”评测。

2. SWE-bench 怎么构造任务

SWE-bench 从真实 GitHub issue 和对应 pull request 中构造任务。论文里的数据集包含 2,294 个软件工程问题,来自 12 个流行 Python 仓库。

每个任务大致包含:

一个真实代码仓库
一个 issue 描述
模型需要生成 patch
评测系统把 patch 应用到仓库
然后运行测试判断问题是否解决

这和传统 benchmark 最大的差别,是答案不再是一段孤立文本,而是一个可执行补丁。

模型不能只“解释应该怎么改”,也不能只写一个看似合理的片段。它必须改对文件、改对逻辑、保持项目能跑,并通过测试。

论文早期实验里,表现最好的 Claude 2 只能解决 1.96% 的问题。这个数字今天看起来很低,但它的意义很大:它说明真实软件工程评测比刷题难得多,也说明原有评测可能高估了模型离实用编程助手的距离。

3. SWE-bench 的评测哲学:用执行结果说话

SWE-bench 最值得学的是它的评测哲学:

不问代码看起来像不像,不问解释漂不漂亮,只问 patch 能不能在真实项目里通过验证。

这和 LLM-as-a-Judge 是完全不同的路线。代码任务如果能运行测试,就应该优先运行测试。单元测试、回归测试、lint、类型检查、构建流程,都是比主观评分更硬的信号。

这种评测会逼模型面对真实边界:

  • import 是否正确。
  • 修改是否破坏旧 API。
  • 是否漏掉边界 case。
  • 是否只修了表面症状。
  • 是否引入新的测试失败。
  • 是否生成了不可应用的 patch。

也正因为这样,SWE-bench 很适合评估 Agent,而不只是基座模型。一个真正的代码 Agent 需要搜索文件、读上下文、编辑、运行测试、根据失败修复。这是一条交互式工作流,不是一次性生成。

4. 后续演化也很重要

SWE-bench 后来形成了一个 benchmark family。官方站点里可以看到 Full、Verified、Lite、Multilingual、Multimodal 等版本。

其中 SWE-bench Verified 是 500 个经过人工过滤的实例;Lite 适合成本更低的实验;Multilingual 扩展到更多编程语言;Multimodal 处理带视觉元素的问题。这些演化说明一个现实:真实代码评测不能只靠一次性数据集,它需要持续清洗、分层和扩展。

这也提醒我们看 SWE-bench 分数时要小心:

  • Full、Lite、Verified 不是同一个难度。
  • Agent scaffold 会极大影响结果。
  • 成本预算、步数限制、上下文策略都会影响成绩。
  • 数据污染和 benchmark 过拟合需要持续关注。

所以 SWE-bench 最好被看成一套评测范式,而不是一个永远固定的排行榜。

5. 工程团队怎么借鉴 SWE-bench

如果你要评测自己的代码 Agent,不一定要直接跑完整 SWE-bench。更实用的是借它的方法,做一个内部 mini-SWE-bench。

第一步,从历史 issue、bugfix PR、线上事故里抽样。

样本要来自真实问题,不要全靠人工编题。真实问题会自然包含模糊描述、项目上下文、边界条件和历史包袱。

第二步,把任务还原到修复前状态。

也就是给 Agent 一个旧版本仓库和 issue 描述,让它自己找问题。不要把相关文件直接喂给它,否则会低估定位难度。

第三步,准备验证脚本。

最理想是单元测试或集成测试。没有测试时,可以补一个最小 reproducer。评测标准一定要可执行,不能只靠“看起来改对了”。

第四步,记录完整轨迹。

对代码 Agent 来说,最终 patch 只是结果。你还要看它读了哪些文件、跑了哪些命令、测试失败后怎么修、是否浪费大量步骤、是否改了无关文件。

第五步,用多指标报告。

除了 resolved rate,还应该看:

patch apply 成功率
测试通过率
平均成本
平均步数
无关文件修改率
回归测试失败率
人工复核通过率

这样才能知道 Agent 是真的会修,还是靠大改、碰运气、过拟合测试。

6. SWE-bench 的局限

SWE-bench 很强,但也有边界。

第一,它主要来自开源 Python 项目。企业内部代码、前端项目、微服务系统、数据平台、移动端工程,问题形态可能不同。

第二,测试通过不等于完全正确。测试覆盖不足时,模型可能写出刚好过测试但设计很差的 patch。

第三,issue 到 PR 的映射会带来选择偏差。能被收集进数据集的问题,未必代表所有真实软件工程任务。

第四,随着 SWE-bench 影响力变大,数据污染和 leaderboard overfitting 会越来越重要。模型可能在训练中见过 issue、patch 或相关讨论。

第五,它评估的是“给定 issue 修复代码”,但真实工程还包括需求澄清、设计评审、迁移方案、性能权衡、安全审计、上线回滚等更长链条。

所以不要把 SWE-bench 当成软件工程能力的全部。它更像一个坚实起点:先证明模型能在真实仓库里改出可执行 patch。

7. 我的 takeaway

SWE-bench 的最大贡献,是把代码模型评测从“答案像不像”拉回到“改动能不能跑”。

这对所有 LLM 应用评测都有启发。只要任务最终会落到某个执行系统,就不要只评文本。能执行就执行,能测试就测试,能复现就复现。

对代码 Agent 来说,真正的评测对象不应该只是模型输出,而是整条工作流:

理解 issue
定位上下文
制定修改
编辑代码
运行测试
根据失败修复
输出最小 patch
避免回归

这条链路里任何一环弱,真实可用性都会下降。

所以我会把 SWE-bench 作为代码 Agent 评测的基本范式:真实任务、真实仓库、可执行验证、完整轨迹、多指标报告。做到这些,评测才从“演示模型会写代码”变成“证明模型能参与软件维护”。