先问再修:用QA对识别Coding Agent的"知识盲区"——ACQUIRE论文解读

你有没有发现:现在的Coding Agent在SWE-bench上越做越卷,但很多错误看起来特别"低级"——不是模型推理能力不行,而是它对代码库一无所知就开始动手

举个真实的场景:一个issue说"删除索引时如果unique_together有相同字段就崩溃了"。模型顺着关键词定位到django/db/backends/base/schema.py,扫了两眼就开始改。但真正要修的逻辑分散在好几个地方——index删除、数据校验、跨模型约束。模型改了一处,测试还是挂;换个位置再改,测试又挂;越改越深,越走越远。

问题到底在哪?它缺的不是"会不会写代码"的能力,而是这个仓库内部到底是怎么组织的这种知识。

上海交通大学等团队的这篇ACQUIRE(arXiv 2607.11111)就给出了一个挺漂亮的解法——不要先动手去修,而是先用QA对把知识缺口问清楚再修


核心摘要

ACQUIRE把"软件问题修复"这件事显式拆成了两个阶段:第一阶段让一个Questioner Agent基于issue生成N个针对性问题,N个并行的Answerer在只读仓库里探索回答,产出QA知识集;第二阶段Resolver拿到issue和知识集,再去生成补丁。

在SWE-bench Verified上,ACQUIRE在GPT-5-mini和DeepSeek-V3.2上分别拿下 3.8 个百分点4.4 个百分点 的Pass@1提升,但成本只有LingmaAgent的1/2到1/4,是SWE-Debate的1/5到1/14。

最让我觉得有意思的不是这个数字,而是他们做的Oracle实验——用一个"上帝视角"的Questioner加上Answerer去喂原本失败的116个实例,居然恢复了26个。这说明对于相当一部分issue,"缺知识"是修复失败的真因,不是借口。


论文信息

  • 标题:Know Before Fix: QA-Driven Repository Knowledge Acquisition for Software Issue Resolution
  • 作者:Haotian Lin, Silin Chen, Xiaodong Gu, Yuling Shi, Chengxi Pan, Jiaqi Ge, Mengfan Li, Jianghong Huang, Mengchieh Chuang, Beijun Shen, Haibing Guan
  • 机构:上海交通大学(主)、University of Pittsburgh、Guangdong Technion-Israel Institute of Technology
  • 链接:https://arxiv.org/abs/2607.11111
  • 提交日期:2026-07-13
  • 代码:https://github.com/LionLin2003/ACQUIRE

为什么需要ACQUIRE:现有方法哪里不work

现在的预修复探索方法基本可以分成两派,我用一个对比表说清楚:

方法类型 代表 核心思路 不足
定位导向 LocAgent、CoSIL 生成"可疑位置列表"或"代码片段集合" 只给指针,模型得自己猜"为什么这些位置相关"
上下文增强 LingmaAgent、SWE-Debate 构建结构化摘要 / 多代理辩论 摘要粒度粗,模型容易浅尝辄止
QA驱动 ACQUIRE 先识别知识缺口,用问答显式获取 多花N步前期开销

这两派的问题,论文里一句话点得很到位:他们都没有显式识别"代理还缺乏什么仓库知识"就开始修复。模型拿到一个"嫌疑位置列表"之后,必须自己脑补出"这个位置和issue之间到底什么关系"——这个脑补的过程,往往就是事实性错误的来源。

更扎心的数据是论文里没大书特书的:那些失败的尝试 token成本是成功解决的4倍以上,执行步骤几乎是两倍。意思就是,模型在错误的修复方向上越走越远,越走越贵。这跟我们平时用Agent的体验是吻合的——很多时候你看到Agent"看起来在忙",但其实在绕远路。


ACQUIRE的核心设计

图1:ACQUIRE框架概览

图1:ACQUIRE的两阶段框架。左半边是Stage I的Questioner和Answerer协作产QA对,右半边是Stage II的Resolver拿到QA知识集生成补丁。最右侧"No Knowledge"展示无知识注入时的修复路径——模型直接动手,绕远路还修不对。

整个框架就三块东西:

Questioner:决定"该问什么"

Questioner拿到issue描述后,按一套四类问题模板生成N个问题。模板不是硬约束,是引导。论文里给了四类:

类别 问什么 例子
机制与行为 内部逻辑流、数据转换、状态管理 "认证系统实际如何验证用户凭据?"
设计与契约 API契约、类层次、错误规范 "数据库连接类的接口契约是什么?"
定位与结构 代码布局、模块组织、依赖关系 "登录功能实现在哪里?"
生态与规范 外部库行为、协议规范 "HTTP/1.1对chunked传输编码有什么要求?"

为什么要分类?消融实验直接给出了答案——没了分类,问题就堆在"机制/行为"那一类,Coverage评分掉了0.78分,Pass@1掉了3.8个点。换句话说,分类不是形式,是逼着Questioner从不同维度去思考。

Answerer:决定"怎么找到答案"

每个问题分给一个独立的Answerer实例,在只读模式下自主探索仓库回答。三条硬性约束:

  1. 回答必须引用具体仓库制品(文件路径、函数名、代码行为),不许靠参数知识
  2. 收集够证据就主动提交,不要无限探索
  3. 找不到证据就显式承认缺口,不要编

这种"只读加自我约束"的设计,避免了Answerer在改仓库的同时污染自己的判断。而且每个Answerer独立运行、互不知道其他问题——论文说这样可以防止跨实例上下文把探索带偏到已访问过但其实不相关的代码区域

Resolver:决定"怎么用这些知识"

Resolver和Mini-SWE-Agent共享相同的scaffolded shell交互环境,拿到issue加知识集后就正常跑修复循环。知识集是预注入到Resolver消息最前面的,不是动态交错的。论文解释了为什么这样做:

  • 保持两阶段解耦的模块化
  • 从第一步起Resolver就有完整知识上下文,避免早期决策在信息不全时做出

值得注意的一个细节:QA是"补充性而非指令性"上下文,告知Resolver策略但不覆盖其独立验证和调整能力。这点挺重要——如果QA就是命令,那Answerer出错就完蛋;如果是建议,Resolver还能二次校验。


四类问题的实证分布

论文做了一件特别值得同行学习的事:他们让人工分析了116个由Oracle Questioner生成的问题,按四类打标。结果是这样的:

  • 机制与行为:70.7 个百分点(占绝对多数)
  • 设计与契约:18.1 个百分点
  • 定位与结构:7.8 个百分点
  • 生态与规范:3.4 个百分点

这数据挺有意思。"机制/行为"占七成,说明大部分issue失败的原因是模型不知道代码内部到底怎么工作,而不是不知道代码在哪。这跟很多人的直觉相反——很多人以为"找位置"是coding agent的痛点,结果发现理解逻辑才是真正的大头。

定位只占7.8个百分点也反驳了"代码定位是核心难题"这个被广泛传播的论调。说实话,看完这个分布我有点意外,我原以为占比最大的会是"定位",结果发现工程师真正缺的,是把代码读懂的能力。


实验结果:数字说话

图2:44个Fail转Pass实例的轨迹阶段组成

图2:44个Fail转Pass实例的轨迹组成对比。左环是无QA注入(3917步),右环是有QA注入(3246步)。Locating阶段从41.7%降到38.4%,Fixing阶段从17.4%降到15.9%,而Reproducing和Verifying的比例反而上升——意味着Agent把更多精力放在了"先复现加后验证"上。

主实验用SWE-bench Verified,500个真实GitHub issue,骨干模型是DeepSeek-V3.2和GPT-5-mini。所有baseline都共享Mini-SWE-Agent作为底层修复代理(这是Princeton/Stanford团队的100行极简Agent),确保对比公平。

Method Model Pass@1 Avg Cost Avg Time
Mini-SWE-Agent GPT-5-mini 58.4% 0.024 美元 187 秒
LocAgent GPT-5-mini 57.8%(掉 0.6 个点) 0.048 美元 437 秒
CoSIL GPT-5-mini 55.2%(掉 3.2 个点) 0.035 美元 224 秒
LingmaAgent GPT-5-mini 60.0%(涨 1.6 个点) 0.309 美元 823 秒
SWE-Debate GPT-5-mini 59.8%(涨 1.4 个点) 0.738 美元 1552 秒
ACQUIRE GPT-5-mini 62.2%(涨 3.8 个点) 0.054 美元 302 秒
Mini-SWE-Agent DeepSeek-V3.2 66.4% 0.055 美元 815 秒
LocAgent DeepSeek-V3.2 68.8%(涨 2.4 个点) 0.060 美元 1046 秒
CoSIL DeepSeek-V3.2 68.7%(涨 2.3 个点) 0.059 美元 750 秒
LingmaAgent DeepSeek-V3.2 67.4%(涨 1.0 个点) 0.155 美元 1421 秒
SWE-Debate DeepSeek-V3.2 68.2%(涨 1.8 个点) 0.382 美元 2517 秒
ACQUIRE DeepSeek-V3.2 70.8%(涨 4.4 个点) 0.073 美元 1042 秒

这张表里几个我得特别拎出来说的事:

第一,ACQUIRE在两个骨干模型上都拿了最大Pass@1提升,但成本只是SWE-Debate的1/14,时间只是LingmaAgent的1/2到1/3。

第二,LocAgent和CoSIL在GPT-5-mini上甚至退步了——意味着对小型模型来说,简单的"位置列表"反而是噪声。这个反直觉的结果其实很有杀伤力,它直接挑战了"做更强的定位就能让模型更好"的假设。

第三,LingmaAgent和SWE-Debate虽然有一致提升,但端到端时间是ACQUIRE的1.4到5倍成本是2到14倍。换句话说,那些依赖MCTS或多代理辩论的方案在性价比上输得很彻底。


消融实验:拆开看看哪部分在起作用

Method Pass@1 变化
ACQUIRE 完整版 70.8% 基准
ACQUIRE-Proposal(换成单步方案生成) 66.0% 掉 4.8 个点
ACQUIRE-FreeQ(去掉类别模板) 67.0% 掉 3.8 个点

消融实验有两个关键发现:

1. "方案生成"为什么反而有害

ACQUIRE-Proposal把整个QA管道替换成"单步方案生成"——也就是让模型直接给出修复方案,而不是先生成问题。结果Pass@1从70.8掉到 66.0%,甚至低于无预修复信息的Mini-SWE-Agent(66.4%)

这个结果挺让我意外的。直觉上"先想方案再修"应该比"先答问题再修"更直接。但论文的解释是:当预修复信息是"方案"时,Resolver会过早被引导到具体修复路径,丧失探索空间。而QA对是开放性的——它告诉Resolver"这里有这些知识",但具体怎么修还是Resolver自己定。

这是个值得记的洞察:预修复信息的形式决定了它是被消费还是被误导。把"答案"喂进去反而约束了探索,把"知识"喂进去反而释放了探索。

2. 类别模板的真正价值是什么

ACQUIRE-FreeQ的Pass@1掉3.8个点,论文做了详细的人工对比,发现最大的损失在 Coverage(涨 0.78 分)和 Diagnostic Utility(涨 0.38 分)。也就是说,没了分类,问题就堆在"机制/行为"那一类,模型看不到"设计约束"、"代码位置"这些维度

500次配对投票里,ACQUIRE被偏好294次,ACQUIRE-FreeQ只被偏好111次——优势非常明显。


QA对数量的影响

图3:QA对数量N对Pass@1和成本的影响

图3:N等于0到3的敏感性曲线。蓝线Pass@1在N等于2时达到峰值70.8%,N等于3时反而回落到69.0%;橙线Avg Cost随N单调上升。N等于2是性价比最优。

N Pass@1 Avg Cost
0 66.4% 0.055 美元
1 69.0% 0.060 美元
2 70.8% 0.073 美元
3 69.0% 0.082 美元

这张图给了我两个意外:

  • N等于1就能涨2.6个点,只多花不到一分钱——边际收益在第一对QA时就显现了
  • N等于3反而回落到69.0%——第三对QA倾向于与已覆盖知识重叠,更长的注入上下文稀释了修复代理的注意力

第二个发现特别重要。直觉上"知识越多越好",但其实在上下文窗口宝贵的LLM里,冗余知识会跟修复信号抢注意力。这点对所有"预注入知识"的工程方案都有借鉴价值——别因为"反正有空间"就一直塞东西。


QA知识到底有没有用?证据是什么

论文做了三件挺扎实的事来证明QA对是真的在起效,不是凑数。

1. 事实可靠性审计

4名CS硕士(每人4年开发经验)独立审核232个QA对。230对(99.1 个百分点)标记为Supported——其中 42.2 个百分点完全准确,56.9 个百分点有轻微偏差(行号/函数归属等局部细节不精确,但核心声明正确)。只有 0.9 个百分点含未支持的声明

这个审计结果直接堵住了"Answerer可能在编造"的质疑。

2. 行为层面的影响

500实例的平均Agent轮次 减少 7.1 个百分点;其中44个Fail转Pass实例 减少 17.1 个百分点。轨迹分析显示:

  • Locating阶段减少 23.8 个百分点
  • Fixing阶段减少 24.1 个百分点
  • Reproducing和Verifying比例反而上升(涨 1.4 个百分点和 3.5 个百分点)

翻译成人话:Agent不再花那么多时间"找位置"和"动手改"了,反而把更多精力放在了"先复现"和"后验证"上。这其实是更健康的工程节奏——谁都知道,先复现再改、最后再验证,是修复bug的标准流程,但模型平时就是做不到。

3. Pass转Fail退化分析

有22个原本能Pass的实例,注入QA后退化成了Fail。论文人工检查了这22个轨迹:

  • 只有5个是QA本身误导(强调相关但非golden的位置或机制)
  • 17个是QA没问题,失败源于Resolver端(过度泛化正确线索、只实现部分修复、引入不必要修改)

这个分解挺重要——它说明回归瓶颈不在知识质量,而在Resolver如何利用知识。换句话说,就算喂的是完美的知识,模型也可能用错。这给后续研究指了条明路。


案例研究

图4:ACQUIRE在sphinx-doc实例上的案例

图4:左边是Mini-SWE-Agent的117步过程,在typeshints.py里试了12到20种参数类型,绕了一大圈最后报错;右边是ACQUIRE的52步过程,Questioner问"该仓库的API doc解析器如何处理param一起出现的多个类型",Answerer直接定位到docfields.py和writers/field_lists.py,Resolver 3步找到根因、修改并验证通过。

这个case把ACQUIRE的优势说得特别清楚。

Mini-SWE-Agent 117步:模型看到issue里"param dict[str, str]"这种语法错误提示,开始在typeshints.py里反复试各种参数解析方式,类型转换、错误处理、HTML渲染全试了一遍,最后还是没搞定。

ACQUIRE 52步:Questioner看了一眼issue就问了一个非常精准的问题——"该仓库的API doc解析器如何处理param同时出现多个类型的情况"——Answerer直接定位到docfields.py的process_doc_info方法和writers/field_lists.py的hlist方法。然后Resolver看了这两个QA,3步就锁定了根因、修改并验证通过。

65步的差距就是这么来的。模型不傻,差的是有人提前告诉它"这代码库里的'参数'到底是怎么处理的"。


行为模式:QA到底把Agent引向何方

图5:Agent轮次分布对比

图5:左图是500个实例的轮次分布,右图是44个Fail转Pass实例的分布。蓝色是无QA注入,橙色是有QA注入。所有实例的均值下降 7.1 个百分点,Fail转Pass实例的均值下降 17.1 个百分点——分布整体往左移,长尾被显著截断。

这个分布图也佐证了前面的分析。QA注入后:

  • 整体分布左移(更快完成)
  • 右侧长尾被截断(那些绕远路的实例变少了)
  • 44个Fail转Pass实例的左移更明显(17.1 个百分点对比 7.1 个百分点)

这个模式说明ACQUIRE不是在某些特定类型的issue上work,而是在全局层面让Agent"少绕路"


我的判断

读完这篇论文,我觉得最值钱的洞察不是框架本身,而是那个"先问再修"的范式转变

过去两三年做Coding Agent的思路大概是这样:先看issue,再看代码,再尝试修,修不好就反思,然后换种修法。ACQUIRE的作者把"反思"这一步从"修不好再反思"提前到"动手前反思"——而且不是单一Agent反思,是显式地把"我不知道什么"用QA对的形式表达出来。

这个paradigm的厉害之处在于:

第一,它把隐式知识缺口显式化了。"代码理解不足"这种模糊的痛点,被拆成"机制是什么、设计约束在哪、模块怎么组织"这种可回答的问题。一旦显式,就能量化、能审计、能改进。

第二,它证明了知识缺口是真实存在的、且可被结构化填补的。Oracle实验恢复26个/116个失败实例,说明"知识缺"不是借口,是真因。

第三,它的成本收益比非常漂亮。N等于2配置下,DeepSeek-V3.2涨4.4个点只多花 0.018 美元,这比让模型在错误方向上多绕几圈便宜太多了。

不过我也得说几个让我犹豫的地方

  1. 回归分析的22个退化里有17个源于Resolver端——说明这个框架对Resolver的能力是有要求的。如果底层Agent不够强,预修复知识可能反而成为噪声。
  2. N等于3就回落到69%——这个上限提醒我们,"知识预注入"不是银弹,过长的上下文会分散注意力。
  3. 静态预注入对比动态交错——论文明确选择了前者,理由是"模块化"和"避免早期决策在部分信息下做出"。但我怀疑在某些issue上,动态让Agent在debug过程中"按需"请求知识会比一次性塞进去更精准。这个权衡值得后续工作继续探索。
  4. 目前只测了Python仓库——论文说QA驱动范式本身是语言无关的,但prompt和评估都针对Python,迁移到Java/Go/C++等强类型语言时问题模板的"类别边界"可能需要重新校准。

另外有一点我得提一下——在2026年4月SWE-bench Verified的公开榜单上,Claude Opus 4.7跑出了87.6个百分点、Claude Mythos Preview 93.9个百分点。ACQUIRE的70.8个百分点在DeepSeek-V3.2上是比这些SOTA低很多的分数。但这并不意味着ACQUIRE"差"——它用的是Mini-SWE-Agent加DeepSeek-V3.2的组合,跟Claude的专有scaffold不是一个赛道。

如果硬要对比,得在同样的harness下做才有意义。所以更公正的判断是:ACQUIRE在它选择的模型组合下,把Pass@1从66.4个百分点推到了70.8个百分点,相对提升6.6个百分点,且显著优于同harness下的所有baseline


写在最后

如果你也在做Coding Agent,ACQUIRE给的启发挺直白的:别让模型一开始就"动手",先让它把"我不知道什么"想清楚

工程上的落地门槛也不高——你甚至不需要重写你的Agent,只需要:

  1. 在issue输入后加一个Questioner prompt
  2. 并行跑几个只读Answerer(用你的现有Agent加只读模式就行)
  3. 把QA对拼到Resolver的消息前面

N等于1就能涨2.6个点,边际成本几乎可以忽略。这种"用现有工具加少量prompt工程"就能落地的方案,比那些需要重训整个Agent的研究友好得多。

回到论文题目——Know Before Fix。这个标题特别准确地抓住了核心:先承认"我不知道",再去获取"我需要知道",最后才是"我能修"。

这不就是经验丰富的工程师日常做的事情吗?只不过以前我们要靠人脑问自己,ACQUIRE让LLM把它显式化了。


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我。