假设你是米其林餐厅的老板,想招一位真正的行政总厨。你不会出“默写菜谱”这种纸上谈兵的考题,而是把候选人直接带进一间正在营业的后厨:一位客人刚投诉“罗宋汤端上来是凉的”,后厨里堆着几十种食材、半成品,还有冒泡的高汤锅。候选人必须自己找出是哪道工序出了问题、动手补救,还得保证其他招牌菜的味道一点都不变差。——这就是 SWE-bench 在做的事。 SWE-bench 是 2023 年普林斯顿团队提出的代码理解评测基准:它从 12 个真实开源 Python 仓库(django、sympy、matplotlib 等)里收集历史 bug 与官方修复补丁,整理成 2,294 道考题,只把“仓库代码 + 问题描述”交给 AI,看它能否产出能合入仓库的补丁。评分规则极为严格:该修好的测试必须全过,原本正常的测试一个都不能坏。 本文用“总厨认证考试”这个比喻贯穿始终,带你拆解考题设计、评分指标、评测流水线,再看 Agent 进厨房实操、RAG 翻菜谱取料等进阶玩法,最后解读历年“考生”的成绩单与常见误区。
掌握 SWE-bench,你就能科学地衡量 AI 模型读懂真实代码库、定位缺陷并产出合格补丁的能力——这是构建代码智能体与 AI 研发助手时最硬核的评估基本功。
可视化演示
展示SWE-bench代码理解评测:Issue到代码理解的流程、Agent读取编辑测试流程、修复通过率评估,通过交互理解真实软件工程任务评测。
本节配有交互动效(进入视口后自动加载,约 3KB)。
任务理解:Issue到代码 理解Issue与代码库 定位并修复问题 Issue→Fix 真实软件工程任务
评测定位
学校里的厨艺考试,通常是“给你一颗土豆,切成均匀细丝”——食材干净、目标明确。但真实餐厅的后厨根本不是这样:几十种食材堆着,油锅咕嘟冒泡,客人的投诉各有各的蹊跷。SWE-bench 选择的就是后者:一间正在营业的真实厨房。
2023 年,普林斯顿团队把 12 个真实的 Python 开源仓库(django、sympy、matplotlib、requests 等)搬进考场,从这些仓库的历史 bug 中整理考题。每个任务实例包含三样东西:一份仓库代码快照、一段 bug 描述(GitHub issue)、一份参考答案(真实修复补丁)。模型全程看不到答案,只能靠自己阅读理解。
任务的形式化定义如下:模型拿到“仓库 + issue”,要产出一个能干净合入的补丁。它考的不是“会不会写函数”,而是“能不能读懂整间厨房”——先定位病灶,再动手修补,最后保证不闯祸。
1. 输入—仓库代码:仓库是某个提交状态下的完整源码,对应“后厨全貌”——几万行代码、几十个模块,bug 可能藏在任何角落。
2. 输入—Issue 描述:来自真实的 GitHub issue,对应“客人投诉”:现象、复现步骤、期望行为,但不给任何定位提示。
3. 输出—补丁:模型必须产出统一 diff 格式的补丁,能够被 git apply 干净合入——相当于交出一份“后厨能直接照做”的整改方案。
所以 SWE-bench 的定位是“代码理解评测”而非“代码生成评测”:它考的是读得懂、找得准、修得对,而不只是写得快。
数据构建
考试委员会的出题人不会自己编菜谱,他们去翻各大餐厅的“投诉记录本”:哪桌客人真的抱怨过、哪位大厨后来真的改了菜,这些“有据可查的事故”才配成为考题。
数据构建分四步走。第一步在 GitHub 上抓取 Pull Request;第二步筛出“该 PR 修复了某个 issue”且改动以代码为主、不含新增依赖的样本;第三步跑通“复现—修复—测试”闭环,确认 bug 可复现、补丁有效;第四步把修复补丁与测试补丁分离存档,模型只能看到前者。
原始版本最终保留 2,294 个实例,来自 12 个 Python 仓库。后来官方又做了人工核验,挑出 500 条“答案没有歧义”的实例,称为 SWE-bench Verified,成为行业通用的报告口径。最关键的原则是时间切分:测试集里的 issue 与补丁,都是模型训练截止时间之后才出现的,防止“偷看答案”。
1. 候选过滤:只保留“有对应合并 PR”的 issue,代表这个 bug 确实被官方修过,答案客观存在。
2. 测试配对:修复 PR 里必须包含测试补丁,否则无法自动化判分——就像没有评审标准就不能给菜品打分。
这些考题全部来自真实事故,“后厨真的救回过这道菜”,所以答案客观、可复现、可自动验证。
评测指标
评审团定下两条铁律:第一,被投诉的菜端上来必须达标,这叫“新增测试必须通过”;第二,原本的招牌菜绝不能因为这次改良而变难吃,这叫“原有测试不能回归”。两条都满足,这道题才算“解决”。
技术术语里,前者叫 FAIL_TO_PASS(修复前失败、修复后必须通过的测试),后者叫 PASS_TO_PASS(修复前后都必须通过的测试)。评分的分母是全部实例,分子是“解决”的实例数——每道题要么记 1 分,要么记 0 分,没有中间地带。
一个补丁哪怕只弄挂了一个 PASS_TO_PASS 测试,也直接判零分。这种“零容忍回归”的设计是有意为之:真实软件工程里,修一个 bug 引入十个 bug 的“假修复”,比不修更糟糕。
1. 求和取平均:$N$ 是实例总数,$\frac{1}{N}\sum$ 表示把所有“解决”的题目的得分加起来再求比例。
2. 指示函数:$\mathbb{1}[\text{条件}]$ 在条件成立时等于 1,否则为 0——就像裁判举牌,要么通过要么不通过。
3. 双条件交集:$F_i \subseteq \text{Pass}_i$ 表示第 $i$ 题的 FAIL_TO_PASS 测试全部通过;$P_i \subseteq \text{Pass}_i$ 表示 PASS_TO_PASS 测试全部通过;$\land$ 表示两者缺一不可。
两条铁律一叠加,想靠“蒙对一半”拿分?门都没有。这个指标逼着模型做“无损修复”,而不是拆东墙补西墙。
评测流程
考试当天,考务组按标准流程走:先把厨房按原样布置好(装好依赖),再请厨师交方案,然后把方案实际做一遍端给评审(跑测试),最后记分归档。
SWE-bench 的评测流水线完全自动化。第一步搭建隔离环境:用 conda 创建虚拟环境、安装依赖、把仓库 checkout 到指定 commit;第二步把模型产出的补丁合入仓库(git apply);第三步在改动后的仓库上运行全部 P2P 和 F2P 测试;第四步按判定规则汇总得分。
官方还会单独统计一个中间指标——“补丁是否干净合入”。许多模型生成的补丁根本合不进去,属于“连方案都交不上”。于是整个链路可以分解成两个条件概率的乘积,方便定位瓶颈出在哪一环。
1. 第一道卡口:$P(\text{补丁合入})$ 是补丁能干净 apply 的概率,对应“方案能被后厨直接照做”。
2. 第二道卡口:$P(\text{全部测试通过} \mid \text{补丁合入})$ 是条件概率——在补丁能合入的前提下,评审团全部通过的概率。
流水线上每一环都可能掉链子,评测的价值就是帮你把“哪一环最弱”精确揪出来,再针对性优化。
Agent 评测
静态评测像“闭卷交方案”:厨师不许进厨房,只准在纸上写整改步骤。而 Agent 模式是“开卷实操”:厨师真的走进厨房,可以开火、尝味道、翻冰箱,发现不对立刻改。
2024 年普林斯顿团队推出 SWE-agent,搭建了一个 Agent-计算机接口(ACI),让模型通过终端自动读写文件、运行命令、执行测试,在“修改 → 观察 → 再修改”的循环中逼近正确补丁。评测内容从“一步生成补丁”升级为“多回合决策”。
评测需要给 Agent 设置回合预算:最多执行多少次命令、消耗多少 token。每一回合它都会新增观察(测试输出、报错堆栈),信息集合单调增长;最终分数仍然按“补丁能否通过全部测试”来算,考核方式不变。
1. 观察累积:$\text{Obs}_t$ 是第 $t$ 回合拿到的测试输出或报错信息,不断并入信息集合——就像厨师每尝一口汤,对火候的了解就多一分。
2. 回合预算:$K_{\max}$ 是最大回合数,防止 Agent 无限试错,逼它在“探索”与“收敛”之间做取舍。
会动手、会看火候的 Agent,解决率通常明显高于只会纸上写方案的模型——这也是 2024 年后顶级模型普遍标配 Agent 能力的原因。
RAG 增强
整间厨房太大,总不能把所有食材都搬到操作台上。聪明的做法是让副手先去档案室,翻出与“罗宋汤投诉”最相关的几份菜谱和配料单,只把这几样端过来。
这就是 RAG(检索增强生成)在代码理解评测里的角色:把仓库文件切块、向量化建立索引;当 issue 到达时,用相似度检索挑出 top-k 个相关文件;把“相关代码 + issue”拼接成上下文,让模型在这个精挑细选的上下文里生成补丁。
检索质量直接决定修复质量——检索漏掉真正的 bug 文件,模型再聪明也白搭。实践上常用召回率、命中率来评估检索模块;在几十万行的超长仓库中,RAG 的性价比远高于把全量代码硬塞进上下文。
1. 向量编码:$\mathbf{e}_q$ 是 issue 的嵌入向量,$\mathbf{e}_{d_j}$ 是第 $j$ 个代码块的嵌入向量——相当于给“投诉”和“菜谱”各自贴标签。
2. 相似度排序:$\cos(\cdot)$ 衡量两个向量在语义空间里的接近程度,值越大表示越相关。
3. 取前 k:$\text{Top-}k$ 只保留最相关的 k 个代码块作为上下文,避免无关食材干扰判断。
先“精准取料”再下锅,而不是把整个厨房搬上操作台——这正是 RAG 的精髓,也是超长代码库场景下的必备策略。
实践现状
翻看历届考生的成绩单,进步速度快得惊人,但离“满分总厨”仍然很远。在 SWE-bench Verified(500 道人审核验题)上,2023 年初最好的模型解决率不足 5%;2024 年中期约三成;2025 年顶级模型已突破六成、逼近七成。
与此同时,还有三成以上的问题连最强 AI 也束手无策。失败原因大致归为三类:定位不准(找不到 bug 所在文件或函数)、补丁缺陷(语法错误或修复不完整)、环境差异(依赖安装失败、测试不稳定)。对应的优化策略是:强化检索与代码导航、Agent 多轮自检与自我修复、评测基建标准化与多次运行取均值。
1. 起点:2023 年基线模型在真实仓库上几乎全军覆没,说明“看懂整间厨房”远难于“写好单个函数”。
2. 拐点:2025 年 Agent + 长上下文 + RAG 的组合把解决率推到六成左右,但远未饱和。
这份成绩单告诉我们:代码理解仍是 AI 的“硬骨头”,但每一年都在肉眼可见地变软。谁能啃下剩下的三成,谁就握住了下一代研发工具的门票。
AI 应用场景
企业自建“代码修复能力考核中心”
阶段:模型评估与选型
解决的问题:企业引入 AI 代码助手前,靠人工抽检 Code Review 来评估模型,成本高、标准不统一、样本少,很难回答“这个模型到底能不能修好我们仓库里的 bug”。
具体案例:某 DevOps 团队在私有仓库上按 SWE-bench 流程构建内部评测集——抽取 200 个历史 bug,配好复现环境与测试用例,分别给 GPT-4 和 Claude 出题。结果显示某模型“定位能力强但补丁常带语法错”,据此调整了后续的提示词策略与模型选型,接入 CI 后误报率显著下降。
代码助手接 RAG 增强修复
阶段:RAG 应用开发
解决的问题:大型 monorepo 动辄几十万行代码,上下文窗口装不下,助手面对 issue 常常“答非所问”——因为相关的那个 bug 文件根本没进上下文。
具体案例:某中间件团队把仓库按文件粒度切块做 embedding,issue 到达后先检索 top-20 相关文件,再让模型结合代码块生成补丁。上线后同类缺陷的修复一次通过率提升了约一倍,token 成本反而比“全量塞入”降低了 60%。
Agent 自动化修 bug 流水线
阶段:Agent 工程化
解决的问题:开源项目维护者每天要处理几十个 issue,人工复现、定位、修 bug 耗时巨大,低优先级问题长期积压。
具体案例:某开源团队接入 SWE-agent 系统:issue 到达后,Agent 自动创建隔离环境、复现失败、定位代码位置并提交 PR,维护者只做最后的人工审核。一个季度内自动提交的 PR 中约四成被直接合入,团队把省下的时间投入到架构重构上。
Python 演示
#!/usr/bin/env python3"""SWE-bench 风格评测器 模拟 SWE-bench 判定逻辑: 一个补丁必须让所有 FAIL_TO_PASS 测试通过,且所有 PASS_TO_PASS 测试不回归, 才判定该问题被解决.""" class SWEBenchEvaluator: def __init__(self, problems): self.problems = problems self.results = [] def apply_patch(self, source, patch): # 逐条执行替换, 模拟 git apply 将补丁合入仓库 for old, new in patch: source = source.replace(old, new) return source def run_tests(self, source, tests): # 简化测试: 测试特征串出现在源码中即视为通过 passed = [] for test in tests: if test in source: passed.append(test) return passed def evaluate(self, predict_fn): solved = 0 for idx, prob in enumerate(self.problems): patch = predict_fn(prob["issue"]) source = self.apply_patch(prob["source"], patch) passed = self.run_tests(source, prob["all_tests"]) ftp_ok = all(t in passed for t in prob["fail_to_pass"]) ptp_ok = all(p in passed for p in prob["pass_to_pass"]) ok = ftp_ok and ptp_ok self.results.append((idx, ok)) solved += int(ok) return solved / len(self.problems) def simple_model(issue): # 实习厨师: 只会按 issue 关键词套用三种固定补丁 if "排序" in issue: return [("[3,1,2]", "[1,2,3]")] if "最大值" in issue: return [("max_value = -999", "max_value = values[0]")] if "反转" in issue: return [("return values", "return values[::-1]")] return [] # 不会修的题就交空补丁 def main(): problems = [ { "issue": "排序函数输出顺序错误", "source": "def sort_list(values):\n return [3,1,2]", "all_tests": ["def sort_list(values):", "return [1,2,3]"], "fail_to_pass": ["return [1,2,3]"], "pass_to_pass": ["def sort_list(values):"], }, { "issue": "求最大值函数对负数输入失效", "source": "def max_val(values):\n max_value = -999\n return max_value", "all_tests": ["def max_val(values):", "max_value = values[0]"], "fail_to_pass": ["max_value = values[0]"], "pass_to_pass": ["def max_val(values):"], }, { "issue": "反转函数没有真正反转", "source": "def reverse_list(values):\n return values", "all_tests": ["def reverse_list(values):", "return values[::-1]"], "fail_to_pass": ["return values[::-1]"], "pass_to_pass": ["def reverse_list(values):"], }, { "issue": "空列表输入应该返回 None 而不是抛异常", "source": "def first_item(values):\n return values[0]", "all_tests": ["def first_item(values):", "if not values: return None"], "fail_to_pass": ["if not values: return None"], "pass_to_pass": ["def first_item(values):"], }, ] evaluator = SWEBenchEvaluator(problems) accuracy = evaluator.evaluate(simple_model) print("SWE-bench 风格评测准确率: %.0f%%" % (accuracy * 100)) for idx, ok in evaluator.results: mark = "解决" if ok else "未解决" print("问题 %d (%s): %s" % (idx + 1, problems[idx]["issue"], mark)) if __name__ == "__main__": main()
source = self.apply_patch(prob["source"], patch)模拟 git apply,把模型输出的补丁逐条替换进源码。passed = self.run_tests(source, prob["all_tests"])简化版测试执行:测试特征串出现在源码中即认为通过。ftp_ok = all(t in passed for t in prob["fail_to_pass"])检查全部 FAIL_TO_PASS 测试是否通过,对应“投诉菜必须修好”。ptp_ok = all(p in passed for p in prob["pass_to_pass"])检查原有 PASS_TO_PASS 测试是否仍全过,对应“招牌菜不许变难吃”。ok = ftp_ok and ptp_okand就是评测里的"∧":两条铁律缺一不可。if "排序" in issue:实习厨师模型只按关键词套固定补丁,对应最简单的规则式基线。return [] # 不会修的题就交空补丁空补丁必然导致 F2P 失败,模拟“不会修”的场景。accuracy = evaluator.evaluate(simple_model)跑完整评测流水线,输出最终解决率。
常见误区
误区我以为 SWE-bench 和算法题库一样:给一段题目描述,模型写一个函数,运行通过就得分。既然是“编程评测”,核心当然是看代码写得好不好。
正解SWE-bench 的核心是“代码理解”:模型要先在可能几万行的真实仓库里找到 bug 位置,再产出能合入的补丁,最后还要保证原有测试不回归。它考的是从“读懂”到“定位”再到“动手修”的完整链路,而不是从零写一个新函数,更不看手速。
为何常见:因为大多数公开编程评测都是“给题—写码—判分”模式,大家默认 SWE-bench 也是同一套玩法,忽略了它“真实仓库 + 真实 issue”的设计初衷。
误区修复的目标就是把 bug 修好,所以只需要盯住新增的测试,它们全过不就说明问题解决了吗?
正解判定标准是 F2P 全过且 P2P 全过。P2P 是仓库原有的测试——相当于“招牌菜不许做难吃”。如果修好 bug 却让 10 个原有功能挂掉,本题直接判失败、记 0 分。这个设计专治“拆东墙补西墙”的假修复。
为何常见:人们习惯单点看待“bug 是否消失”,而真实软件工程最怕回归,所以 SWE-bench 特意把“不回归”放进了硬性评分条件。
误区既然支持大上下文,干脆把整个代码库都喂给模型,信息最全,免得检索漏掉关键文件导致修复失败。
正解冗余信息会稀释模型的注意力、推高成本,还可能让模型把无关模块的编码风格“学”进补丁。正确做法是按需检索 top-k 个最相关文件,只把“和这道菜相关的食材”端上操作台。实验表明,恰到好处的上下文往往比全量塞入效果更好。
为何常见:大上下文窗口的宣传让不少人产生“塞得越多越安全”的错觉,忽视了信息噪声对推理质量的伤害。
误区在 SWE-bench 上跑完一次拿到 80%,就可以放心上生产了,分数就是模型能力的真实写照。
正解代码评测受环境依赖、随机测试顺序、网络安装等因素影响,同一个模型跑两次结果可能不同。严谨的做法是多次运行取均值并记录标准差,还要人工抽检部分样本确认没有“凑巧通过”。评测结果应该是一个区间,而不是一个孤零零的数字。
为何常见:把“单次通过”误当成“稳定通过”,忽略了容器环境与测试执行中的随机波动。
面试题
Q1. SWE-bench 的核心评测对象是什么?
- A.编写全新项目的代码能力
- B.理解仓库并修复缺陷的能力← 正确答案
- C.将自然语言翻译成代码的能力
- D.解决复杂数学证明题的能力
答案:B。SWE-bench 考的是“代码理解 + 缺陷修复”:模型在真实仓库中定位 bug 并产出补丁。它不考从零写新代码(A),不考翻译(C),也不考数学(D)。
Q2. SWE-bench 的任务实例主要来自哪里?
- A.各大竞赛刷题网站的题库
- B.大学计算机教材的课后习题
- C.真实开源仓库的历史问题← 正确答案
- D.大模型自我生成的测试题目
答案:C。SWE-bench 从 12 个真实开源 Python 仓库(如 django、sympy)的历史 GitHub issue 与修复 PR 中构建实例,强调“真实事故”,而非题库、教材或 AI 生成题。
Q3. 一个补丁被判为“解决”该问题的完整条件是?
- A.FAIL_TO_PASS 全部通过即可
- B.PASS_TO_PASS 全部通过即可
- C.两个测试集合必须全部通过← 正确答案
- D.至少一个测试集合通过即可
答案:C。评判标准是双条件交集:全部 FAIL_TO_PASS 通过(修好了投诉的菜)且全部 PASS_TO_PASS 通过(招牌菜没变难吃),二者缺一不可,只有 C 完整正确。
Q4. PASS_TO_PASS 测试的核心作用是什么?
- A.防止补丁破坏原有功能← 正确答案
- B.验证新功能是否被实现
- C.衡量补丁运行的耗时
- D.检查补丁的注释质量
答案:A。PASS_TO_PASS 是修复前就应通过的原有测试,用来检测“回归”——防止补丁修好一个 bug 却弄坏其他功能,所以选 A。B 是 FAIL_TO_PASS 的职责,C、D 与测试判定无关。
Q5. SWE-bench Verified 相比原始版本的主要改进是什么?
- A.全部换成了竞赛类题目
- B.人工核验剔除有歧义样本← 正确答案
- C.移除了所有真实代码仓库
- D.只保留前端框架类项目
答案:B。SWE-bench Verified 是官方用人工核验方式从 2,294 个实例中挑出的 500 个“答案无歧义”样本,排除了 issue 描述不清、补丁不止一种等争议题。它没有换题型(A)、没有移除真实仓库(C)、也不是只留前端(D)。
Q6. 静态评测时,模型拿到一个 issue 后需要输出什么?
- A.对 bug 严重程度的打分等级
- B.能够合入仓库的代码补丁← 正确答案
- C.对源码逐行的中文注释
- D.一个全新项目的完整架构
答案:B。模型的任务是产出统一 diff 格式、能被 git apply 干净合入的补丁。输出严重度打分(A)、中文注释(C)或新项目架构(D)都不是这轮考试要求的答案形态。
Q7. Agent 模式与传统静态评测的核心区别是什么?
- A.能执行命令并观察反馈结果← 正确答案
- B.完全不能接收任何环境反馈
- C.评测过程完全不需要跑测试
- D.Agent 必须由人工全程遥控操作
答案:A。Agent 模式(如 SWE-agent)让模型通过终端执行命令、读写文件、跑测试并观察输出,形成“修改→观察→再修改”的闭环;静态评测则是一次性交出补丁。B、C 与事实相反,D 把 Agent 误解成人工遥控。
Q8. 下列哪些做法能有效提升 SWE-bench 解决率?(多选)
- A.检索仓库中相关代码片段← 正确答案
- B.Agent 多轮执行测试修正← 正确答案
- C.直接忽略原有测试用例
- D.构建失败回溯重试机制← 正确答案
答案:ABD。RAG 检索(A)、Agent 多轮反馈(B)和失败后重试(D)都是业界验证有效的策略。C 会直接导致 PASS_TO_PASS 判定失败,属于自毁行为。
Q9. 关于 SWE-bench 评测复现偏差,下列说法正确的是?(多选)
- A.依赖版本不同环境不一致← 正确答案
- B.随机测试失败导致波动← 正确答案
- C.多次运行结果完全一致
- D.需多次运行取均值降低← 正确答案
答案:ABD。依赖安装顺序、随机测试、网络波动都会造成复现偏差(A、B 正确),因此严谨评测应多次运行取均值并记录标准差(D 正确)。C 说“完全一致”过于绝对,现实中很少成立。
Q10. 某补丁让全部 FAIL_TO_PASS 通过,但破坏了 2 个 PASS_TO_PASS 测试,最终结果是什么?
- A.该问题仍判定为已解决
- B.该问题直接判定为未解决← 正确答案
- C.该问题按比例得一半分数
- D.该问题进入人工二次评审
答案:B。评分是“零容忍回归”:只要有一个 PASS_TO_PASS 失败,本题直接记 0 分,没有部分得分(C 错),也不存在二审(D 错)。修好投诉的菜但弄坏招牌菜,依旧不算解决。