Thinking Longer, Not Larger: Enhancing Software Engineering Agents via Scaling Test-Time Compute
基本流程
核心思想
-
目标:让小规模开源模型(如32B参数)在单GPU上达到与大型闭源模型(如671B参数)相近的性能。
-
关键策略:
-
内部测试时计算(Internal TTC):训练模型进行更长的多步推理。
-
外部测试时计算(External TTC):在推理时生成多个候选方案,并通过验证筛选最优解。
-
运行过程详解
1. 内部TTC:增强模型的推理深度
-
数据收集:
-
从GitHub高星仓库(≥1000星)收集“问题-代码库-合并的拉取请求”三元组。
-
过滤简单问题,保留需多步解决的复杂问题(如修改1-5个代码文件的问题)。
-
-
轨迹生成:
-
使用大模型(如DeepSeek R1)生成详细的解决轨迹,包括:
-
代码库理解(定位需修改的文件)、
-
错误定位(找到具体错误位置)、
-
补丁生成(编写修复代码)、
-
补丁验证(自动生成复现代码验证正确性,使用 一个LLM Agent 自动build环境,让LLM生成复现代码(Reproduction Code),之后通过生成的复现代码来检验)
-
-
-
拒绝采样:
-
过滤低质量轨迹,仅保留需要复杂推理的问题(如小模型无法单步解决的)。
-
保留中间正确的推理步骤,即使最终补丁错误。
-
-
模型训练:
- 用筛选后的轨迹训练小模型(如32B的Qwen2.5 Coder),使其学会多步推理逻辑。
2. 外部TTC:优化推理时的搜索策略
-
关键阶段搜索:
-
在代码库理解、错误定位、补丁生成三个阶段,生成多个候选方案。
-
使用过程奖励模型(PRM)评估中间步骤的正确性,保留得分高的候选(类似“淘汰赛”)。
-
-
执行验证:
-
生成补丁后,自动运行复现代码验证是否修复问题。复现代码由LLM生成,基于项目ExecutionAgent搭建的环境,使用golden patch 按照回归测试的方式验证复现代码,如果生成的复现代码未通过就通过相似性检验给补丁打分。
-
检查补丁是否破坏现有功能(如运行单元测试)。
-
-
最终排序:
- 用结果奖励模型(ORM)对通过验证的补丁排序,选择最优解。
3. 结合内部与外部TTC
-
内部TTC让模型具备深度推理能力,外部TTC通过搜索和验证提升成功率。
-
例如:模型先通过长链推理生成多个补丁(内部TTC),再通过PRM和ORM筛选最佳补丁(外部TTC)。
Reward Model 训练
1. 过程奖励模型(PRM)
-
目标:评估中间步骤(如代码库理解、错误定位)的正确性。
-
训练步骤:
-
数据构建:
-
利用内部TTC生成的高质量轨迹数据(包含正确的多步推理过程)。
-
对每个中间步骤(如文件定位、错误位置)标注二元标签(正确=1,错误=0)。
-
-
输入格式:
- 输入包括问题描述、当前阶段的上下文信息(如代码片段、执行日志)和候选中间输出。
-
模型训练:
-
使用交叉熵损失函数进行二分类训练:
-
\[\mathcal{L}_{\text{PRM}} = -\sum_{i=1}^{N} \left[ y_i \log(p_i) + (1-y_i) \log(1-p_i) \right] \]
-
其中 \(y_l\) 是标签(0或1),\(\pi\) 是模型预测的“正确”概率。
-
-
应用场景:
- 在代码库理解、错误定位阶段,用PRM对多个候选方案评分,保留高评分路径。
-
2. 结果奖励模型(ORM)
-
目标:对最终生成的补丁进行排序,选择最优解。
-
训练步骤:
-
数据构建:
-
收集通过执行验证的补丁对(通过验证的补丁为“胜者”,未通过的为“败者”)。
-
例如,同一问题的多个补丁中,通过单元测试的标记为高质量,失败的标记为低质量。
-
-
训练方法:
-
采用Direct Preference Optimization (DPO) 框架,直接优化模型对补丁的偏好:
-
\[\mathcal{L}_{\text{ORM}} = -\mathbb{E}_{(x,y_w,y_l)} \left[ \log \sigma \left( \beta \log \frac{\pi_\theta(y_w|x)}{\pi_{\text{ref}}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{\text{ref}}(y_l|x)} \right) \right] $$   \]
-
-
输入格式:
- 输入为问题描述和候选补丁,无需中间推理步骤。
-
应用场景:
- 在外部TTC的最后阶段,用ORM对通过验证的补丁排序,选择最高分补丁。
-
关键设计
-
数据质量保障:
-
PRM依赖内部轨迹的拒绝采样(仅保留复杂问题的多步轨迹)。
-
ORM依赖执行验证(运行复现代码和单元测试)确保补丁正确性。
-
-
效率优化:
-
PRM和ORM均基于较小模型(如32B Qwen2.5)微调,确保快速推理。
-
PRM专注于关键阶段(如代码库理解),避免全流程验证的计算开销。
-
效果验证
-
在SWE-bench Verified测试集(500个真实GitHub问题)中:
-
32B模型达到46%的问题解决率,超过DeepSeek R1 671B(41.2%)和OpenAI o1(45.6%)。
-
模型能动态分配更多计算资源给复杂问题(如生成更长的推理步骤)。
-
消融实验结果
1. 内部TTC的消融实验
(1) 实验设计
-
基线模型:Qwen2.5 Coder 32B(未经过内部TTC训练)。
-
对比组:
-
完整内部TTC(SWE-Reasoner):包含长链思维(Long CoT)训练 + 拒绝采样。
-
移除长链思维(w/o. LongCoT):仅用短链思维(Short CoT)数据训练(由Claude 3.5生成单步推理)。
-
移除拒绝采样(w/o. Rejection):使用未过滤的合成轨迹训练(含低质量数据)。
-
无任何内部TTC(w/o. All):仅用Prompt-based CoT(推理时提示模型分步思考,无训练)。
-
(2) 实验结果(SWE-bench Verified)
-
关键结论:
-
长链思维训练对性能提升最关键(+8.8%),说明显式学习多步推理比单步推理更有效。
-
拒绝采样过滤低质量数据可提升4.6%,验证了数据质量的重要性。
-
Prompt CoT效果最差,表明仅依赖推理时提示无法替代内部化的多步推理训练。
-
(3) 分难度分析
-
将问题按解决难度分为5级(1=最简单,5=最难):
- 长链思维在困难任务(Level 5)优势最大:
完整内部TTC解决率是Short CoT的6倍(12% vs 2%),说明复杂问题需依赖长链推理。
- 长链思维在困难任务(Level 5)优势最大:
2. 外部TTC的消融实验
(1) 实验设计
-
基线策略:执行验证(Exec)策略。EXEC策略仅使用执行验证(regression tests and issue reproduction)来选择最终补丁,如果多个补丁通过了执行验证,则随机选择一个补丁以解决问题。
-
Issue Reproduction 是回归测试的前置步骤:
-
首先通过复现问题确认bug的存在。
-
然后修复问题,并将复现的测试用例转化为回归测试,确保问题不会再次出现。
-
-
Regression test(回归测试) 是一种长期的质量保证手段:
- 在修复问题后,回归测试会被添加到测试套件中,持续验证代码的稳定性。
-
-
对比组:
-
完整外部TTC(Dev-Search):PRM + ORM + 执行验证。
-
仅用ORM(ORM_Exec):保留执行验证,用ORM替代随机选择。
-
多数投票(Voting):标准化补丁格式后选择高频补丁(类似Agentless方法)。
-
(2) 实验结果(100个样本子集)
-
关键结论:
-
PRM的早期干预至关重要:Dev-Search在预算=8时领先Exec随机选择11%,说明中间步骤筛选能减少无效计算。
-
ORM提升稳定性:ORM_Exec在预算=8时比随机选择高9%,验证了学习补丁偏好的有效性。
-
预算增加的效果:Dev-Search随预算提升性能,但纯随机选择(Exec)在预算=8时性能下降,说明无引导的搜索可能引入噪声。
-
(3) 分难度分析
-
中等难度任务(Level 3-4):外部TTC提升最显著(预算=8时+15%)。
-
极难任务(Level 5):预算增加可能无效(性能略降),表明模型自身能力上限。
3. 联合消融实验
-
内部+外部TTC组合:完整方法达到**46%**解决率,显著高于单独使用内部TTC(37.6%)或外部TTC(44.0%)。
-
计算分配现象:模型对复杂问题自动生成更长推理链(Level 5问题平均多50% token),验证了动态计算分配的有效性。
消融实验总结
-
内部TTC:
-
长链思维训练是核心,拒绝采样保障数据质量。
-
对困难任务提升显著,说明小模型需显式学习复杂推理。
-
-
外部TTC:
-
PRM和ORM缺一不可,前者优化搜索路径,后者确保最终质量。
-
盲目增加预算无效,需结合智能筛选(如Dev-Search)。
-
-
协同效应:
- 内部TTC提供高质量候选,外部TTC进一步优化,两者结合超越单独使用。