论文链接:arxiv.org/abs/2606.20512 开源代码:github.com/asashepard/probe-and-refine-tuning 发表时间:2026 年 6 月 发表机构:Williams College(威廉姆斯学院,美国顶尖文理学院) 作者:Asa Shepard(第一作者,负责实验设计与论文撰写)、Jeannie Albrecht(通讯作者,导师,负责方法学与论文指导)
一、论文背景
1.1 什么是"代码仓库的隐性知识"
要理解这篇论文,先得搞清楚一个问题:为什么大模型直接去改一个陌生代码库,经常会改错地方?
一个真实的开源代码仓库(比如 Django、scikit-learn)不是一堆随机堆叠的文件,它是无数工程决策沉淀下来的产物:哪些子系统负责什么、命名约定是什么、调试时该按什么顺序排查、历史上哪些修法踩过坑……这些知识藏在老贡献者的脑子里,而不在代码本身。
一个从未接触过这个仓库的大模型,要么靠"试错"去重建这些隐性知识,要么干脆一头扎进错误的文件里,提出一个把毫不相干的子系统搞崩的修复。
1.2 AGENTS.md:给 Agent 的"操作手册"
工程师们想出了一个直观的办法:在仓库根目录放一个文件(通常叫 AGENTS.md、CLAUDE.md 或类似名字),把仓库的约定、入口点、测试运行方式、调试策略写进去,作为给代码 Agent 看的"操作手册"。
根据调研,截至 2025 年已有 2,303 个这样的文件在公开仓库中被活跃使用。它本质上就是"给 AI 写的 README"——告诉 Agent 这个仓库怎么构建、怎么跑测试、代码组织是怎样的。
1.3 一个悬而未决的争论:这玩意到底有没有用?
问题来了:AGENTS.md 到底帮不帮忙? 现有的两项研究得出了完全相反的结论:
| 研究 | 结论 | 测量指标 |
|---|---|---|
| Lulla et al. (2026) | 人工整理的 AGENTS.md 有用:运行时间减少 28.6%,输出 token 减少 16.6% | 效率(成本),而非正确性 |
| Gloaguen et al. (2026) | LLM 生成的上下文文件有害:SWE-bench Lite 解决率下降约 3% | 正确性(resolve rate) |
Gloaguen 还发现一个有趣的现象:Agent 会字面照搬文件里的指令,哪怕这些指令是反作用的——比如文件里提到某个工具,Agent 就会把它用得比没有指导时多 160 倍。
这个分歧让一线开发者无所适从:到底该不该投入精力维护这类指导?里面该写什么?又该怎么生成?
1.4 关键直觉:问题出在"怎么生成"而非"要不要有"
这篇论文的核心直觉是:指导文件这个概念本身没问题,问题出在它怎么被生产出来。
一次性 LLM 生成(single-pass)只能产出泛泛而谈的建议。但一个老贡献者真正掌握的知识是操作性的、具体的:某个子系统该跑哪个测试文件、某类 bug 该顺着哪个模块去排查、哪些修法历史上坑过下游。这种知识没法靠内省获得,只能从观察到的失败中学到。
作者还从微调文献里借来一个启发:Betley 等人发现,在单个狭窄任务上微调(比如只让模型写不安全代码)会让模型在毫不相关的任务上也出现广泛的行为变化。论文想问的是:这种"窄信号→宽效果"的现象,能不能在提示词层面也复现?也就是说,用一小批自己生成的 bug 修复任务去迭代,能不能塑造 Agent 在一大批无关任务上的行为?
二、论文定位和关联工作
2.1 这个工作在整个版图里的位置
这篇论文处于"代码 Agent 的指令/上下文工程“这个交叉地带。它不去改模型、不去改脚手架(scaffold)、不去改上下文窗口,而是只改 Agent 拿到的仓库指导文本,并把它当作第一类变量来系统研究。这在 SWE-bench 文献里是相当少见的——大多数改进都集中在模型、脚手架或上下文窗口上,而"Agent 自己的指令"很少被系统地变化和优化。
2.2 三条相关的技术脉络
脉络一:AGENTS.md / 上下文文件有没有用
最接近的两项工作(Lulla、Gloaguen)上面已介绍,结论相反。论文的定位是调和这个分歧:它指出分歧的根源在于"指导怎么生成"以及一个两篇都没操纵的变量——步数预算(step budget)。论文还引用了 Vasilopoulos (2026) 的观点:单文件清单在超过约 10 万行代码后就不灵了,需要分层架构——这是本文 ≤3000 字符单文件方案共同承认的局限。
脉络二:代码 Agent 的脚手架与基准
论文在 SWE-bench Verified(500 个经人工验证的真实 GitHub issue)上评测。SWE-bench 的规则很"诚实”:Agent 改完代码后,只有当补丁能让项目留出的测试套件通过,才算"解决"。Agent 由一个**脚手架(scaffold/harness)**驱动——它决定模型每步看到什么、能做什么。现有脚手架五花八门:从定制命令接口(SWE-agent)、固定流水线(Agentless 的"定位→修复"序列)到树搜索(SWE-Search)。本文的贡献与这些正交:它固定一个脚手架,只变指导文本。
脉络三:仓库级知识与自我改进
一条线是给 Agent 注入结构性知识:RepoGraph 注入代码实体关系图,AutoCodeRover 在抽象语法树上导航。另一条线是迭代改进 Agent 的输出:Self-Refine 和 Reflexion 把自我批评喂回下一次尝试。但这些都是每个任务内部的修正,用完即弃。Probe-and-refine 不同:它精炼的是一个持久的、可复用的指导文件,跨许多合成任务迭代,产出的是整个仓库级别的指导。
最概念上接近的是 Meta Context Engineering (MCE, Ye et al. 2026)——一个双层优化框架,协同演化"上下文工程技能"和它们产出的上下文工件。MCE 同样主张"上下文应通过反馈精炼而非一次性生成",但它是个带完整智能体工具使用的通用元学习系统;而 probe-and-refine 故意做到极简,只用单轮 LLM 调用。因为 MCE 没在 SWE-bench 上评测,两者关系是概念性的而非实证的。
2.3 机制上的远亲:窄信号→宽效果
离本文领域最远、但机制最接近的一类工作记录了"窄训练信号→宽行为变化":Betley 等人发现窄微调会引发广泛失配;Cloud 等人发现这种隐性行为特质传递只在共享初始化的模型间成立,跨家族会崩塌。Probe-and-refine 在提示词空间而非权重空间操作,但结构一样:每轮 10 个合成探针重塑了几百个无关评测问题的行为,而观察到的跨模型崩塌正好对应了跨家族传递的失败。
三、问题定义
3.1 从现实困惑到抽象问题
现实里的困惑是:“AGENTS.md 到底该不该写?“但这个问题没法直接研究,因为它混进了太多变量:谁写的、写多长、用什么模型、给多少步预算、在什么基准上测。
论文把这个问题抽象成一个可控制的实验问题:
在固定模型、固定脚手架、固定评测基准的前提下,只改变"仓库指导文本"这一个变量,指导文本的"生产方式"是否是决定 Agent 表现的关键因素?如果是,什么样的生产方式有效?
3.2 三个对照条件
为了隔离"指导"这一变量,论文定义了三个条件,除了指导文本外其余全部相同:
| 条件 | 含义 |
|---|---|
no_context | 裸 Agent,不给任何仓库指导 |
static_kb | 静态知识库:tree-sitter 解析的仓库结构 + 一次性 LLM 生成的泛泛建议 |
probe_refined | 在 static_kb 基础上,用 probe-and-refine 过程迭代精炼出的专门指导 |
这里的精妙之处在于 static_kb 的两层设计:结构层保证两个有指导的条件共享相同的仓库特定基础;程序层保证 probe-and-refine 的增益来自迭代精炼本身,而不是"多了一些泛泛建议”。这样就把"迭代精炼的价值"干净地隔离出来了。
3.3 最本质的问题
剥离所有外部信息后,论文真正要回答的本质问题是:
一个完全由单轮 LLM 调用组成、不做任何智能体推理的过程,能否仅凭"合成失败"的反馈,生产出能显著改善 Agent 行为的指令?
换句话说,作者想搞清楚:当前代码 Agent 的瓶颈,到底是推理能力,还是指令质量? 一个在调优期间完全不做智能体推理的过程,能让答案更清晰——如果它能奏效,就说明指令质量是一阶变量。
四、问题解法
4.1 整体思路:用"合成探针"去"诊断+打补丁”
Probe-and-refine 的思路非常直白,可以用一句话概括:生成一批假的 bug 修复任务(探针),让模型试着解决,看它在哪里失败,然后把这些失败诊断成对指导文件的修改。
这个过程的灵感来自一个朴素观察:老贡献者的知识"只能从观察到的失败中学到"。那就人为制造一些失败,让模型从自己的失败里学。
4.2 四类单轮 LLM 调用
整个过程完全由单轮 LLM 调用组成——没有多步 Agent 循环、没有工具调用、没有强化学习。每一轮(共 3-5 轮,每轮约 22 次调用)包含四类调用:
第 1 步:生成探针(Generate probes) 一次调用生成 10 个合成 bug 修复任务,从仓库代码库出发,温度 0.9 以保证多样性,瞄准不同的子系统和失败模式。关键:这些探针和 SWE-bench 评测实例完全不同,防止基准污染。探针会跨轮去重。
第 2 步:尝试补丁(Attempt) 对每个探针,模型在当前指导文件下尝试生成一个补丁(单轮调用,不是完整 Agent 循环)。
第 3 步:评判与诊断(Judge) 对每个尝试,模型评判它哪里失败了、为什么失败,并给出可操作的指导修改建议。这一步要求模型产出足够"有诊断性"的输出——这是整个循环能否转起来的关键(后面跨模型实验会证明这点)。
第 4 步:聚合编辑(Apply edits) 把所有诊断聚合成对指导文件的机械式修改(加上仓库特定的测试路径、子系统追踪说明、输出质量要求等),受 3000 字符上限约束。
4.3 为什么这么"简陋"是故意的
论文反复强调一个设计哲学:这个过程的简单是刻意的。 作者想知道瓶颈是推理能力还是指令质量,而一个调优期间不做任何智能体推理的过程,能把答案暴露得更明显。如果这么简陋的过程都能奏效,那"指令质量"就必然是一阶变量。
4.4 最终产物:一个 ≤3000 字符的文本文件
整个过程给每个仓库产出一个紧凑的(≤3000 字符)文本工件。这个长度是精心选的:约 750 token,约占 16k 有效上下文窗口的 5%,把大部分上下文留给 issue 文本和命令输出。
从字符数看,static_kb 平均 1,687 字符,probe_refined 平均 2,754 字符——精炼后长了 63%。但论文特别指出:问题不是"更多文本有没有用",而是"对的文本有没有用"。Gloaguen 等人已经证明更长的 LLM 生成上下文反而会降低性能,所以单纯加长不是答案。
4.5 消费端:固定的编码 Agent + 兜底
产出的指导文本喂给一个固定的编码 Agent——它在循环里读代码、跑命令、提修改。如果 Agent 在步数预算内没产出补丁,就触发一个单轮兜底(fallback):直接从 issue 描述和已积累的上下文生成补丁。两条路径的补丁都经过清洗(去掉测试文件修改、强制 diff 格式)后再评测。
关键细节:兜底路径几乎从不产出正确补丁(四轮里只有 5 个兜底补丁解决成功,成功率 5.2%)。所以"少触发兜底"本身就是优势——probe-and-refine 的兜底率最低(14.8%),意味着它最常通过 Agent 自己的循环产出补丁。
4.6 主实验结果
在 SWE-bench Verified 的 500 个实例上、200 步、四次独立试验:
| 条件 | 解决率(均值±SD) | 覆盖率 | 精度 |
|---|---|---|---|
| no_context | 25.5% ± 2.2% | 41.7% | 61.0% |
| static_kb | 28.3% ± 1.4% | 50.6% | 56.0% |
| probe_refined | 33.0% ± 1.8% | 56.2% | 58.6% |
排序 probe_refined >> static >> no_context 在 4/4 次试验里无一例外成立。混合效应逻辑回归在 6000 个观测上对两个关键对比都给出 p<0.001。
把增益拆解:从 no_context 到 probe_refined 共提升 7.5 个百分点,其中 2.8pp 来自静态知识库(结构层),4.7pp 来自迭代精炼。结构层贡献约 37%,迭代精炼在它之上叠加了大部分价值。
4.7 最关键的发现:改进的是"覆盖率"而非"精度"
这是全文最反直觉、也最重要的结论。论文把"解决率"拆成两个因子:
$$\text{解决率} = \text{覆盖率} \times \text{精度}$$- 覆盖率:Agent 产出了能被 SWE-bench 评测器接受(格式正确、能干净 apply、不崩测试套件)的补丁的实例比例。
- 精度:在已产出可评测补丁的实例里,真正解决的比例。
结果:精度在三个条件下统计上恒定(约 59%,p=0.119),差异完全来自覆盖率。probe_refined 比 no_context 多覆盖了 14.5 个百分点(约多 72 个可评测补丁)。
翻译成大白话:指导文件并没有让 Agent 把补丁写得更对,而是让 Agent 更可能产出"一个能被评测的、打到正确文件的补丁"。 它帮的是"找到对的文件",不是"写出更好的修改"。
这和定位分析(Section 5)吻合:probe_refined 独有解决的 31 个实例,大多是"问题陈述里点了一个用户面 API,但真正要改的文件在一个不显然的内部模块里"。模型按符号名搜会进错文件,而精炼指导里编码的子系统结构和追踪说明把它引向了正确的模块。
4.8 步数预算实验:指导让"更多步数"变得有用
Section 6 做了一个 12 格实验(3 条件 × 4 步数预算:25/50/100/200),发现:
- 无指导的 Agent 很快饱和:不管给多少步,探索都很快就到顶,因为它"要么早早打补丁,要么打不出来"。
- 不同指导类型在不同阈值上激活:指导文件让 Agent 能有成效地使用更大的步数预算。没有指导,多给步数也没用。
- probe-and-refine 有一个 50 步的"下陷"——在步数太少时,它规定的"复现→追踪→打补丁"工作流来不及完成,反而比简单条件略低;但步数上去后它反超并拉开差距。
一个形象的说法:无指导的 Agent 像个没头苍蝇,早早撞一次墙就停了;有指导的 Agent 像个有流程的工程师,步数越多越能按流程走完。
4.9 跨模型实验:指导是"模型特定"的
Section 7 用 NVIDIA-Nemotron-3-Nano-30B-A3B 替换 Qwen3.5-35B-A3B,发现三件事:
- 调优循环本身在弱模型上转不动:Nemotron 生成的补丁太稀疏,评判步骤找不到可操作的东西,5/12 个仓库在第一轮后产出零个新探针和零个修改。
- 静态指导反而伤害弱模型:在 Nemotron 上,所有指导条件都不如无指导基线(no_context 28.4% > probe_refined 27.0% > static_kb 24.6%)。原因是指令跟随干扰——Nemotron 会把"保持补丁最小"这类指令字面理解,从"执行"切换到"空谈"。
- 跨模型指导迁移是灾难性的:把 Qwen 调出的指导直接给 Nemotron,解决率暴跌到 13.2%。机制是"以分析代服从(compliance by analysis)"——Nemotron 读了 Qwen 详细的指令后,不去跑命令,而是写出一段"我打算怎么做"的分析,导致不产命令的轮次多 71%,触发大量兜底级联。
核心教训:指导文件编码的是"模型特定的行为校准",不是可迁移的仓库知识。 实践者应该用"最终消费指导的那个模型"来调指导。
五、必要知识反推
假设找一个完全没有相关知识和信息的人去做这个工作,他从"发现问题"到"解决问题"必须掌握哪些知识?又如何把它们融合?
5.1 发现问题阶段需要的知识
代码 Agent 的工作机制:得知道 LLM Agent 是"读代码→跑命令→提修改"的循环,且它的表现不只取决于模型本身,还取决于脚手架和它拿到的上下文。否则你根本看不到"指令质量"这个变量。
仓库隐性知识的存在:得理解一个仓库里有大量"不在代码里、在老贡献者脑子里"的操作性知识(子系统边界、调试流程、历史踩坑)。否则你不会想到"要把这些知识喂给 Agent"。
现有研究的矛盾:得知道 Lulla 和 Gloaguen 两项研究结论相反,否则你意识不到"指导到底有没有用"是个未解的问题,更不会想到"分歧根源在生成方式"。
窄信号→宽效果的跨域类比:得知道 Betley 等人的微调工作(窄任务引发宽行为变化),才能产生"能否在提示词层面复现"的灵感。这是整个方法的思想种子。
5.2 解决问题阶段需要的知识
SWE-bench 的评测逻辑:得知道它要求补丁格式正确、能干净 apply、让留出测试套件通过。这样你才能理解"覆盖率"和"精度"的分解,也才能设计出防止基准污染的探针去重机制。
单轮 vs 多步调用的区别:得清楚"单轮 LLM 调用"和"Agent 循环"的差别,才能故意选择"调优期间不做智能体推理"这个极简设计,从而把"推理能力"和"指令质量"两个变量分开。
tree-sitter 代码解析:得知道 tree-sitter 是个增量式源码解析器,能提取仓库的主要 hub、入口点、import 关系,才能搭出 static_kb 的结构层作为对照基础。
统计学方法:得会用混合效应逻辑回归(控制实例和试验的随机效应)、McNemar 配对检验、Wilson 置信区间,才能在 6000 个观测上得出可信的显著性结论,而不是被单次运行的噪声误导。
温度参数的作用:得知道温度 0.0 保证可复现、0.9 保证探针多样性,才能在"控制变量"和"避免重复"之间取得平衡。
5.3 知识融合的路径
这些知识不是简单堆叠,而是要融合成一条因果链:
观察到"指令质量被忽视"(知识 1+2)→ 注意到现有研究矛盾(知识 3)→ 借微调的窄信号类比产生灵感(知识 4)→ 设计"合成失败驱动精炼"的极简过程(知识 6)→ 用 tree-sitter 搭对照(知识 7)→ 用 SWE-bench 评测并防污染(知识 5)→ 用统计方法验证(知识 8)→ 用温度控制可复现性(知识 9)
关键融合点:把"窄信号→宽效果"这个来自权重空间的现象,移植到提示词空间——这是整篇论文最核心的知识跨界。作者明确声明"不主张机制等价",但"经验模式结构上类似"这个洞察,是把两个看似无关的领域(微调失配 vs 指令精炼)连起来的桥梁。
六、论文中可以提取的通用性灵感
这部分寻找论文里可以推广到其他领域的普适性知识、结论和做法。
6.1 “指令质量是被忽视的一阶变量”
论文最强的通用结论:在优化一个智能系统时,“给它的指令/提示质量"和"模型能力/算力预算"是同一量级的一阶变量,却被严重忽视。
这个洞见不限于代码 Agent。在任何"LLM + 外部系统"的场景里(客服、数据分析、写作助手),人们习惯性去卷模型、卷上下文窗口、卷脚手架,却很少系统地把"指令本身"当作可优化的第一类对象。当你发现系统表现卡住,先问一句"是不是指令写得不行”,可能比换更大的模型更划算。
6.2 “合成失败驱动精炼"是一种通用范式
probe-and-refine 的范式是:生成合成任务 → 观察失败 → 把失败诊断成对指导的修改 → 迭代。 这个范式完全可以推广:
- 客服系统:生成合成客户咨询,看系统答错在哪,精炼客服 SOP 文档。
- 检索增强(RAG):生成合成查询,看检索/生成在哪失败,精炼检索策略说明。
- 任何"Agent + 操作手册"的场景:只要有一个"可复用的指导文件"和一个"能评判成败的任务”,就能套这个循环。
核心抽象:与其一次性写完美的手册,不如用失败反馈持续打磨手册。
6.3 “覆盖率 vs 精度"的分解思维
论文把"解决率"拆成"覆盖率×精度”,然后发现改进全在覆盖率、精度恒定。这种"把一个聚合指标拆成两个因子分别归因"的做法极其通用:
- 推荐系统的 CTR = 曝光率 × 点击率,改进到底来自更多曝光还是更高点击?
- 客服解决率 = 接通率 × 解决精度,瓶颈在接通还是在解决?
- 任何"产出能被评判的中间产物"的流水线,都可以问:增益来自"更可能产出可评判的东西"还是"产出的东西更好"?
当你改进了一个系统,先做因子分解,往往能避免在错误的环节上使劲。
6.4 “调优期间不做目标任务的推理"作为一种诊断手段
作者故意让调优过程不做任何 Agent 循环,目的是隔离变量:如果这么简陋的过程都奏效,那"指令质量"就一定是一阶变量。这是一种通用的实验设计智慧:
当你想证明 X 是关键变量时,把所有其他能力都剥到最简。如果最简版都能奏效,X 的作用就无可辩驳。
这适用于任何"归因"场景:想证明某个因素重要,就把它之外的一切都降到最低。
6.5 “行为校准是模型特定的,不可跨模型迁移”
跨模型实验揭示:为模型 A 调出的行为指导,给模型 B 用可能是灾难。 这背后是更深的普适原理:
任何"行为校准工件”(无论来自权重更新、训练数据还是提示词调优)都编码了模型/家族特定的信号,不能干净地跨家族迁移。
这对任何做多模型部署的人都是警示:你为一个模型精心调的 prompt、SOP、few-shot 示例,换模型时必须重新校准,不能想当然地复用。Cloud 等人在蒸馏里发现的"跨家族传递崩塌"和这里的"跨模型指导崩塌"是同一个现象在不同层面的再现。
6.6 “窄信号→宽效果"可能是提示词空间的普遍现象
论文最大的 speculative 灵感:微调里的"窄任务引发宽行为变化”,可能在提示词层面同样存在。 十个合成探针能重塑几百个无关任务的行为——如果这个现象普遍成立,它意味着:
你不需要海量数据来改变 LLM 的行为倾向,一小批精心设计的"窄信号"任务,通过迭代反馈写进提示词,可能就足够。
这对"如何低成本地塑造 Agent 行为"有深远意义——它把"行为塑造"从昂贵的微调,降到了廉价的提示词迭代。当然,作者诚实地标注这是推测,需要表征层面的研究来证实。
七、总结
这篇论文用一种近乎"简陋"的方法回答了一个被忽视的大问题:代码 Agent 的指令质量,是一阶变量。
它没有更大的模型、没有更花哨的脚手架、没有强化学习,只有约 22 次单轮 LLM 调用构成的"生成探针→尝试→诊断→打补丁"循环。但就是这个循环,让 SWE-bench Verified 解决率从 25.5% 提到 33.0%,而且改进来自"让 Agent 跑到对的文件"而非"把补丁写得更对"。
对实践者的三条建议藏在论文结论里:给会反复处理 issue 的仓库投入迭代精炼的指导;确保步数预算容纳规定的工作流;用最终消费指导的模型来调指导——给别的模型调的指导可能反而有害。
而更深层的启示是:在我们急着换更大的模型之前,也许该先看看,我们给现有模型写的"操作手册",写得到底好不好。