复杂仓库里的 bug,很少像面试题那样把输入、输出、相关函数全摆到桌面上。issue 描述通常只说症状,根因可能藏在另一个模块、一个约定俗成的接口契约,甚至一个第三方协议细节里。代码 Agent 修不动,常见原因并非补丁生成能力不够,而是还没搞清楚仓库就开始动手。
论文《Know Before Fix: QA-Driven Repository Knowledge Acquisition for Software Issue Resolution》抓住了这一点。它把修复前的探索改造为更明确的流程:先问出 Agent 缺什么仓库知识,再让另一个只读 Agent 去仓库里找证据回答,修复 Agent 拿着这些问答再写补丁。这个框架叫 ACQUIRE。先会问,才更会改。
代码 Agent 的很多失败,败在过早动手
现在不少预修复方法会给 Agent 提供更多上下文:可疑文件列表、调用图、仓库摘要、多个 Agent 的修复争论。这些东西有用,但共同问题是偏“修复导向”——它们默认 Agent 拿到线索后,能自己补齐为什么相关、接口怎么用、改动边界在哪里。对于简单 bug,这个假设还能成立;一旦问题跨模块、跨抽象层,线索很容易变成噪声。
ACQUIRE 的判断更像真实开发流程。一个有经验的工程师接手陌生仓库,通常不会看到报错就改文件,而会先问几个问题:这段逻辑到底怎么走?这个类的接口契约是什么?相关代码在哪一层?外部库有没有特殊规则?把这些问题回答清楚,补丁才不容易变成碰运气。
这篇工作里有一个关键动机实验。研究者拿 SWE-bench Lite 中 Mini-SWE-Agent 在 DeepSeek-V3.2 下失败的 116 个实例,构造带特权信息的 oracle QA:问题由黄金测试补丁辅助生成,答案只基于黄金补丁涉及文件。只注入一组这样的问答后,26 个原本失败的实例被修好。这个数字不代表现实系统上限,却说明了一件事:不少失败并非模型完全无能,正确的仓库理解可以把被压住的修复能力释放出来。
这个实验也解释了为什么“更多上下文”这个方向走到一定程度会撞墙。上下文长,不代表信息对;文件打开得多,不代表理解深。Agent 需要的是能把症状连接到机制的知识,而不是一堆还要自行消化的材料。
ACQUIRE 的关键在于把未知改写成可回答的问题
ACQUIRE 有三个角色。Questioner 根据 issue 生成问题;Answerer 在只读环境里探索仓库,给出带文件、函数、行为证据的答案;Resolver 负责修改代码。流程被拆成两段:知识获取在前,补丁生成在后。这样做的好处是,修复开始之前,Agent 已经拿到一组相对稳定的仓库理解,不必边猜边改。
问题模板来自对 116 个 oracle 问题的人工归纳。五名计算机专业研究生把知识缺口分成四类:机制与行为,占 70.7%,关心功能逻辑和数据流;设计与用法,占 18.1%,关心接口契约和设计约定;位置与结构,占 7.8%,关心代码在哪里、模块怎么组织;生态与标准,占 3.4%,关心第三方库、协议或语言语义。
这个分类很有工程感。修 bug 时最怕的情况不是找不到一个关键词,而是只知道关键词,却不知道它处在什么机制里。机制问题能让 Agent 追到数据怎么流;契约问题能限制补丁边界;结构问题能缩小搜索空间;外部标准问题能避免把库行为或协议要求改错。
默认设置下,每个 issue 生成 2 个问题,多个 Answerer 并行探索,彼此隔离。隔离不是形式主义,它能避免一个 Answerer 的错误方向污染另一个问题;并行则把知识获取的墙钟时间压到最慢那个 Answerer 附近。Answerer 运行在 Mini-SWE-Agent 风格的 shell 环境中,但只读,不改仓库状态。
这个设计比“给一串可疑文件”信息密度更高。文件列表只告诉 Agent 可能去哪看,QA 则把“为什么看这里”“看完该得出什么约束”也带进来。它没有剥夺 Resolver 的判断权,答案被当作补充上下文,Resolver 仍然可以继续验证、修改、回滚。
4.4 个百分点看起来不大,但它赢在稳定和成本结构
主实验跑在 SWE-bench Verified 上,包含 500 个真实 GitHub issue。评测模型是 GPT-5-mini 和 DeepSeek-V3.2,基线包括 Mini-SWE-Agent、LocAgent、CoSIL、LingmaAgent、SWE-Debate。评价指标是 Pass@1、平均成本和平均耗时,补丁是否成功由开发者测试验证。
结果很清楚。GPT-5-mini 上,Mini-SWE-Agent 的 Pass@1 是 58.4%,ACQUIRE 到 62.2%,提升 3.8 个百分点;DeepSeek-V3.2 上,从 66.4% 到 70.8%,提升 4.4 个百分点。LocAgent、CoSIL 这类定位型方法在 DeepSeek-V3.2 上有收益,但在 GPT-5-mini 上会退化;LingmaAgent、SWE-Debate 更稳定,却明显更贵更慢。
这里要冷静解读。4.4 个百分点不是让代码 Agent 一夜跨越到资深工程师水平,它的价值在于两点:跨模型都涨,说明方法不太依赖某个模型的特殊能力;涨幅来自相对轻量的知识获取,而不是把整个仓库暴力读一遍。
ACQUIRE 也有额外开销。GPT-5-mini 上平均成本从 0.024 美元升到 0.054 美元,平均时间从 187 秒到 302 秒;DeepSeek-V3.2 上成本从 0.055 美元升到 0.073 美元,时间从 815 秒到 1042 秒。但和更重的预修复方法相比,它的成本和时间仍比较克制。论文给出的概括是,LingmaAgent 和 SWE-Debate 的端到端时间约为 ACQUIRE 的 1.4 到 5 倍,成本约为 2 到 14 倍。
这个取舍对工程落地很重要。自动修复系统如果每个 issue 都要多跑几倍时间、多花十几倍成本,即使指标漂亮也很难大规模使用。ACQUIRE 的收益曲线没有那么夸张,却更接近可部署的中间地带:花一点前置理解成本,换掉一部分后续盲目试错。
轨迹变短,比单个成功率数字更有意思
DeepSeek-V3.2 下,ACQUIRE 相比 Mini-SWE-Agent 出现 44 个 Fail→Pass,也有 22 个 Pass→Fail,净增 22 个成功实例。研究者人工审计了 232 组 QA,230 组被标为 Supported,占 99.1%;其中 98 组完全准确,132 组核心正确但有局部细节偏差,只有 2 组存在无根据主张。
这组审计很关键,因为它回答了一个自然怀疑:多塞一段 LLM 生成的解释,会不会只是把幻觉包装成上下文?至少在这批样本里,答案质量相当高。更有意思的是,局部行号、函数归属之类的小偏差并没有破坏大多数核心结论,说明 QA 的主要价值在于机制级理解,而不是机械复制代码位置。
QA 的作用也体现在行为轨迹上。注入 QA 后,500 个实例的平均 Agent 轮数下降 7.1%;在 44 个被救回的实例上下降 17.1%。这些恢复实例的总步骤从 3917 降到 3246。更重要的是,减少集中在知识密集环节:定位阶段减少 23.8%,修复阶段减少 24.1%。QA 相关步骤占全部步骤 40.4%,在定位和修复阶段分别达到 51.5% 和 50.6%。
这组数字说明,ACQUIRE 主要减少了盲找和盲改,把 Agent 的精力从“我该打开哪个文件”转到“我该怎么验证这个修复”。它没有替代测试,也没有保证每次编辑都正确;它更像把调试前半程的地图画清楚,让后半程少绕路。
不过,QA 可靠不等于修复一定正确。22 个 Pass→Fail 回归里,只有 5 个被判定为 QA 明显带偏;这 5 个案例对应 10 组 QA,其中只有 1 组有无根据主张。换句话说,很多失败源于 Resolver 把一个真实但不充分的线索过度放大。下一步难点会落在“如何批判性使用知识”,而不能只追求更多知识。
两个问题最好,Sphinx 案例也说明它为什么有效
QA 数量的实验很有工程味。没有 QA 时,DeepSeek-V3.2 上 Pass@1 是 66.4%,平均成本 0.055 美元;1 组 QA 到 69.0%,成本 0.060 美元;2 组 QA 达到 70.8%,成本 0.073 美元;3 组 QA 反而回落到 69.0%,成本升到 0.082 美元。

这提醒我们,上下文不是越多越好。两个互补问题能覆盖不同知识缺口,第三个问题可能开始重复,甚至稀释 Resolver 的注意力。对代码 Agent 来说,知识获取也需要预算和取舍。一个好问题的价值,可能超过十个松散片段。
消融实验也支持这个判断。把 QA 流程替换成单次修复建议,Pass@1 从 70.8% 掉到 66.0%,比不加预修复信息的 Mini-SWE-Agent 还低。去掉分类模板,让 Questioner 自由提问,Pass@1 掉到 67.0%。问题质量评分里,分类模板在覆盖度上高 0.78,在诊断效用和推理深度上各高 0.38。也就是说,问什么问题本身就是能力,不是随便让模型生成几个疑问句就行。
论文里的 Sphinx 案例很直观。issue 是 :param dict(str, str) opc_meta: 渲染错误。Mini-SWE-Agent 被关键词带到 typehints.py、writers/html.py、autodoc 的钩子逻辑里,117 步都没有访问真正的 docfields.py。ACQUIRE 的问题聚焦 :param 类型解析机制,Answerer 找到 sphinx/util/docfields.py 里的 split 调用:它会把 dict(str, str) opc_meta 在括号内部空格处切开,导致类型和参数名错位。Resolver 随后直接打开正确文件,做括号感知的拆分逻辑,52 步完成修复,步数减少约 55%。
这个案例的启发不在于 split 有多难,而在于提问方向改变了搜索路径。症状看起来像渲染问题,关键词会把 Agent 带到 HTML writer 或 typehint 处理;问题一旦落到 param 类型解析机制,搜索就会自然指向 docfields.py。好问题把症状翻译成机制,修复路线随之变短。
ACQUIRE 给代码 Agent 的启发很明确:修复真实仓库 issue,稀缺资源不只是更多 token,更是可验证的仓库理解。把未知拆成好问题,再把答案建立在仓库证据上,这件事看起来朴素,却可能成为 Agentic Coding 从“能改代码”走向“能维护仓库”的基础能力。对这类方向感兴趣的开发者,欢迎在 云栈社区 一起交流实践经验。