FC-SWE:面向长程软件工程智能体的失败条件化强化学习 FC-SWE: Failure-Conditioned RL for Long-Horizon Software Engineering Agents
把失败补丁与验证器反馈作为上下文训练恢复轨迹,让 SWE 智能体学会从错误中恢复
前置知识
GRPO(组相对策略优化)
一种无需 critic 的强化学习算法:对同一 prompt 独立采样一组(group)响应,用组内奖励的相对比较代替价值网络来估计优势。本文实现采用留一法基线,即轨迹 $c$ 的基线是其余 $G-1$ 条轨迹奖励的均值,再除以它们的标准差做归一化,零方差时有回退处理。
FC-SWE 是在 GRPO 之上改造的,论文的优势估计公式(留一均值、样本标准差、零方差回退)全部沿用 GRPO 实现,不懂组相对比较就看不懂它改了什么。
SWE-bench 与仓库级软件工程智能体
SWE-bench 是仓库级 issue 修复基准:智能体读真实代码库、定位问题、产出补丁,由可执行的测试套件(verifier)判定补丁是否通过,Resolved 率即通过率。SWE-agent 研究智能体与计算机的接口设计,OpenHands、R2E-Gym 等提供智能体基础设施、训练环境与验证器。
本文的实验全部在 SWE-bench Verified 的 500 道题上做,训练数据来自 R2E-Gym 的 4518 个任务,验证器既提供奖励也定义恢复触发条件。
智能体轨迹与多轮工具调用
在执行式智能体训练中,一次完整尝试是一条轨迹:模型输出、工具调用(搜索/编辑/跑测试)与环境观察交替出现,最终以一个候选补丁收尾。每步动作都可能改变仓库状态或揭示下一步决策所需的信息,因此这是长程、有状态的序列决策问题。
FC-SWE 的奖励、优势、损失权重都是定义在'完整轨迹'粒度上的,恢复链也是轨迹的序列,轨迹是全文的基本单元。
验证器反馈与自我修复(self-repair)
失败测试、报错信息、traceback 能揭示补丁为何被拒绝,为修复提供具体线索。但推理时的反馈利用(Self-Refine、Reflexion 等不加权重更新的方法)并不总是有益:已有研究表明对较弱的模型,在同等生成预算下自我修复可能不如独立重采样。
这解释了论文的核心问题——为什么'用上失败反馈'需要在 RL 训练层面显式学习,而不是推理时加个重试循环就行。
研究动机
仓库级软件工程(SWE)是典型的长程任务:智能体要在真实代码库中多轮调用工具(搜索、编辑、运行测试),根据有状态环境的观察逐步决策,最终产出修复 issue 的补丁。目前主流训练方式是用 GRPO 这类强化学习:对每个 issue 独立采样多条完整轨迹,每条轨迹以补丁是否通过测试套件作为 0/1 终端奖励,在固定组内做相对比较。这种设置有一个明显浪费——失败补丁的验证器输出(失败测试、报错、traceback)包含'为什么错了'的诊断信息,却被直接丢弃;同一 issue 的后续采样完全看不到前次失败的原因,只能靠重新采样碰运气。而推理时研究表明,对较弱模型简单的自我修复在同等生成预算下甚至可能不如独立重采样,说明把失败证据用起来并不是加个重试循环就能奏效。更麻烦的是,把恢复过程纳入 RL 训练本身有结构难题:恢复轨迹只有在前次失败时才会被生成(前次结果决定它是否存在),而它的条件上下文又由前次失败执行提供,奖励如何分配、比较组如何选取都需要显式设计。
本文的目标是本文的目标是把'失败后的恢复尝试'纳入策略的 RL 训练本身:当补丁未通过验证时,将仓库恢复到初始任务状态,把失败补丁和验证器诊断输出作为上下文,让同一策略生成恢复轨迹,并用这些'恢复链'优化策略。衡量目标非常具体:在全部 500 道 SWE-bench Verified 任务上、以 Qwen3.5-4B + SWE-agent、三个解码种子平均,FC-SWE 要在同预算对照下超过 GRPO。最终实现 Resolved@1 从 38.9% 提升到 41.7%(+2.9pp),Resolved@2 从 48.5% 提升到 52.8%(+4.3pp),条件恢复率从 15.7% 提升到 19.0%;并且只用两步恢复链训练,就能在 11 次尝试的测试预算下达到 70.7% 累积解决率,超过 GRPO 的 67.3%,同时把达到同等解决率的推理 token 成本明显压低。
与已有工作不同的是,把反馈引入训练并非新想法,但已有工作各有取舍:Satori-SWE 做无智能体的迭代补丁精修;ContextRL 从全负组中用参考解条件的错误报告恢复正样本,但优化前会从上下文中删除失败响应与报告;MulFeRL 用反馈重新生成全失败组并做跨状态对比优化;LaMer 重启失败回合并优化包含后续结果的回报;PivoARL 从错误状态重试并隔离错误后缀的信用。FC-SWE 看到的被忽视之点是:在仓库级智能体场景下,恢复轨迹的存在性由前次验证结果决定,其条件上下文又由前次失败执行提供——这是一个结果依赖的链式结构。作者没有回避这种非平稳性,而是用两个专门机制(轨迹局部奖励、活跃集优势估计)把结构显式建模进 GRPO:每条已执行轨迹保留自己的验证器判定,比较组只由实际执行过的同 issue 轨迹组成,未执行的占位槽被排除在统计与损失之外。
核心方法
直觉上,FC-SWE 像是教一个工程师'看测试报告改 bug':第一次改挂了,就把失败的 diff 和测试报错摆在工作台前,仓库被彻底还原干净,然后基于这些证据再改一次,且两次改动各自独立评分——后一次成功不会洗白前一次的失败。技术路线是把 GRPO 扩展到'结果依赖的恢复链':对每个 issue 独立采样 $G$ 条初始轨迹(主实验 $G=8$),每条链最多 $R$ 次尝试($R=2$);活动指标递归定义为 $q_{c,1}=1$,且当 $q_{c,r-1}=1$ 时 $q_{c,r}=1-y_{c,r-1}$,即恢复尝试当且仅当前一次执行且失败时才执行。当第 $r$ 次尝试失败时,控制器记录补丁与验证器诊断输出,把仓库恢复到原始任务状态,构造上下文 $h_{c,r+1}=\mathcal{C}(x, \mathrm{patch}(\tau_{c,r}), \mathrm{verify}(\tau_{c,r}))$,生成恢复轨迹。训练时用轨迹局部奖励保证每条轨迹继承自己的验证器结果,用活跃集优势估计在'同 issue 所有实际执行过的轨迹'内做留一法相对比较,最后以 token 归一化的裁剪策略梯度更新。
核心创新在于承认并正确处理恢复链的'结果依赖性',拆成两个互补机制。第一是轨迹局部奖励:$r_{c,r}=y_{c,r}$(仅当 $q_{c,r}=1$,未执行的位置记为 $\bot$),一条'先失败后恢复'的链的奖励序列是 $[0,1]$ 而非广播最终结果的 $[1,1]$——后者会把正奖励错误分给被拒绝的初始补丁;只优化最后一条轨迹则会丢掉失败行为提供的对比信号。第二是活跃集优势估计:比较组取同一 issue 下所有实际执行的初始+恢复轨迹 $\mathcal{V}_x=\{(c,r): q_{c,r}=1\}$,用留一均值作基线 $b_i=\frac{1}{|\mathcal{V}_x|-1}\sum_{j\in\mathcal{V}_x, j\neq i} r_j$,再用同一组奖励的样本标准差归一化(沿用零方差回退,$\epsilon=10^{-6}$),未执行行既不进统计也不进损失。与标准 GRPO 的本质区别是:比较集合随验证结果变化,基线不再是动作独立的,作者明确指出该更新不再继承标准无偏性保证——这是把'失败触发、失败条件化'结构写进优势估计所付出的理论代价,换来的是跨尝试的对比信号。
方法步骤详情
完整流程分五步。第一步采样初始轨迹:对批次中 16 个任务各采 8 条独立轨迹(64K 上下文、每条最多 100 次模型-工具交互),OpenHands 执行搜索、编辑、运行测试,产出补丁 $p_1$,验证器给出二值结果 $y_{c,1}$。第二步失败触发恢复:若 $y_{c,r}=0$ 且 $r<R$,控制器记录 $\mathrm{patch}(\tau_{c,r})$ 与诊断输出 $\mathrm{verify}(\tau_{c,r})$(后者区别于二值结果 $y_{c,r}$),把仓库恢复到原始任务状态以防临时文件、进程与工具状态跨尝试泄漏,再按 $h_{c,r+1}=\mathcal{C}(x,\mathrm{patch},\mathrm{verify})$ 在固定上下文预算内格式化并截断原始 issue 与失败证据,生成恢复轨迹。第三步奖励赋值:每条已执行轨迹获得自己的验证器结果,$R=2$ 时可能的序列为 $[1,\bot]$(首次成功)、$[0,1]$(成功恢复)、$[0,0]$(两次失败)。第四步优势估计:在同一 issue 的活跃集内做留一均值基线与标准化,非活动行不参与。第五步策略更新:优势广播到策略生成的有效 token,提示、环境观察、复制的失败上下文与填充均为零损失权重(失败补丁只在生成它的轨迹中承担损失);被标记为无效工具调用或畸形思考的助手消息 token 优势覆写为 $-5$;用 token 归一化的裁剪目标更新并异步同步权重。
技术新颖性
与最相关工作的区别可概括为三点。其一,与'广播最终链结果'或'只优化最后一条轨迹'的做法不同,FC-SWE 保留每条已执行轨迹并赋予其自己的验证器判定,既不让恢复成功改写早期失败的奖励标签,也不丢弃失败轨迹作为负样本的对比价值(虽然恢复成功能通过比较集间接影响早期轨迹的相对优势)。其二,与 ContextRL(优化前从上下文删除失败响应与报告)、MulFeRL(全失败组重生成+对比优化)不同,FC-SWE 在优化时保留失败补丁与验证器输出作为显式条件上下文,恢复轨迹是带着证据生成的完整多轮工具使用轨迹。其三,与 LaMer(回报包含后续结果)、PivoARL(隔离错误后缀信用)不同,FC-SWE 给每次尝试独立验证器奖励,只在实际执行的同 issue 轨迹间比较。消融支撑了设计必要性:去掉训练时失败上下文使条件恢复率从 19.0% 跌到 12.6%,去掉轨迹局部奖励使其从 20.4% 跌到 17.7%,而共享奖励变体再叠加去掉运行时惩罚会在第 28 到 31 步间从 76.6% 崩到 2.3%。
实验结果
主实验在全部 500 道 SWE-bench Verified 上进行,三个解码种子平均(Table 1)。基座 Qwen3.5-4B 为 Resolved@1 27.9%、Resolved@2 36.3%、条件恢复 11.6%;从同一基座分别训练的 GRPO 达到 38.9%/48.5%/15.7%,FC-SWE 达到 41.7%/52.8%/19.0%,即在 Resolved@1 与 Resolved@2 上分别超过 GRPO 2.9 和 4.3 个百分点,且首次尝试性能没有为恢复能力买单。训练前期(前 70 步)FC-SWE 与 GRPO 的首次尝试成功率几乎持平(平均差 −0.7pp),但第二次尝试平均再贡献 10.6pp,合计领先 9.9pp。消融(Table 2)显示:去掉训练时失败上下文(Fresh-retry,保留重试与全部奖励机制、只不给失败证据),三项降为 40.4%/47.9%/12.6%,说明单纯多一次干净重试不够;去掉轨迹局部奖励,条件恢复从 20.4% 降到 17.7%、Resolved@2 从 54.8% 降到 51.8%;共享奖励变体再去掉运行时惩罚则训练在第 28 步的 76.6% 崩到第 31 步的 2.3%。反馈 vs 重采样对照(Figure 4a)是点睛之笔:Base 与 GRPO 用反馈重试反而不如独立重采样(11.6% vs 13.7%;15.7% vs 18.6%),只有 FC-SWE 反转了这一关系(19.0% vs 17.0%),证明'善用失败证据'是被训练出来的能力。上下文消融(Figure 4b):只给失败补丁 15.7%、无反馈 17.0%、验证器+补丁 19.0%,验证证据比仅看旧补丁高 3.3pp。测试时扩展(Figure 5a):虽只训练两步链,FC-SWE 在 $K=11$ 时达 70.7%(GRPO 67.3%、Base 61.1%)。token 效率(Figure 5b):达到 ≥50% 解决率的最低成本预算下,FC-SWE/GRPO/Base 每任务约 3.15M/4.39M/8.22M tokens;达到 60% 时为 5.08M/6.29M/13.57M。
查看结构化数据
| 任务 | 指标 | 本文 | 基线 | 提升 |
|---|---|---|---|---|
| SWE-bench Verified 全部 500 题(首次尝试解决) | Resolved@1(avg@3 解码种子) | 41.7% | GRPO 38.9%(Base 27.9%,Qwen3.5-9B 41.2%) | 较 GRPO +2.9pp,4B 模型接近 9B 基座 |
| SWE-bench Verified(两次尝试累积解决) | Resolved@2(avg@3) | 52.8% | GRPO 48.5%(Base 36.3%,Qwen3.5-9B 50.4%) | 较 GRPO +4.3pp,超过 9B 基座 |
| SWE-bench Verified(初始失败后的恢复) | 条件恢复率 | 19.0% | GRPO 15.7%(Base 11.6%) | +3.3pp;且优于自身独立重采样的 17.0%,方向与 Base/GRPO 相反 |
| SWE-bench Verified(11 次尝试测试预算) | Resolved@11(累积) | 70.7% | GRPO 67.3%(Base 61.1%) | +3.4pp,收益延伸到训练视野($R=2$)之外 |
| SWE-bench Verified(推理成本) | 达到 ≥50% 解决率时的每任务累积 tokens | 约 3.15M | GRPO 4.39M,Base 8.22M | 比 GRPO 省 28%、比 Base 省 62%;60% 档为 5.08M vs 6.29M vs 13.57M |
局限与改进
作者承认的局限:其一,恢复奖励依赖可执行的验证器,'部署时验证器下的恢复'被明确列为未来工作——真实工程中常没有现成测试套件可给出干净的二值判定;其二,活跃集基线随验证结果变化后不再是动作独立的,更新失去标准无偏性保证,论文只指出而未做理论修正;其三,token 成本由记录的输入 token 与估计的生成 token 合成,且只比较推理成本、不涉及训练算力或实际墙钟速度,离散成本点也可能超出目标值不同幅度。我自己的观察:第一,严格的同源对照只在 Qwen3.5-4B 上完成,Qwen3.5-9B 与 Nemotron-3-Nano-4B 只是推理参考,方法收益随模型规模如何变化未知;第二,$R=2$ 的链很短,更深的链下活跃集方差、上下文预算与稳定性未探索;第三,失败上下文被 $\mathcal{C}$ 截断到固定预算,超长 traceback 或大补丁的信息损失没有量化;第四,条件恢复率绝对值仍只有 19.0%,多数初始失败依然无法在两次内救回,失败证据的利用率还有很大空间。
独立分析的弱点
第一,验证器依赖:整套方法假设失败信号来自可执行测试套件。在测试稀疏或很弱的私有仓库中,$\mathrm{verify}(\tau)$ 可能只是 linter 输出甚至为空,恢复条件化会退化为 patch-only 条件——消融显示其条件恢复率仅 15.7%,明显低于完整方案。改进方向:用 LLM-as-judge、静态分析或运行时错误合成部分验证信号,并按证据质量对条件内容加权。第二,基线有偏:活跃集依赖验证结果,可能对'更易触发恢复的 issue'产生系统性偏置,长尾上难易任务的梯度权重失衡。改进方向:重要性加权修正,或用结果无关的分层基线(如只在初始轨迹内估计基线、对恢复轨迹做修正项)。第三,评测协议绑定:所有数字都在 verifier-assisted 协议下报告,干净重置与反馈注入是评测器的一部分,与真实'单次交付、无重试辅助'场景有差距,社区间横向比较需谨慎;改进方向是补充无辅助条件下的标准 Pass@K。第四,奖励仍是二值 0/1,把部分通过(N 个测试过 M 个)纳入可能更稳,但需要防 reward hacking。第五,运行时惩罚(无效工具调用/畸形思考覆写 $-5$)对共享奖励变体是稳定性的关键,但其与其他奖励方案的交互只在单一配置下验证,泛化性存疑,值得做系统敏感性分析。
未来方向
作者明确提出的方向是把恢复能力迁移到'部署时可用的验证器',例如利用 CI 日志、运行时报错等弱信号做恢复条件化。基于论文成果还可以延伸:其一,把 $R=2$ 扩展为更深的自适应恢复链,让策略学习一个 stop/continue 决策,自主决定继续重试还是放弃,并与测试时算力分配联合优化;其二,把失败上下文从'截断的证据包'升级为可交互的证据检索——策略可以重新运行失败测试、打开具体文件,而不是被动接收固定预算的摘要;其三,将活跃集优势估计与 GiGPO 等步级分组方法结合,在恢复链内部做更细粒度的信用分配,同时尝试修正结果依赖基线带来的偏差;其四,在 9B 以上更强基座上验证收益是放大还是收敛,并测试跨基座迁移;其五,把'失败条件化 + 轨迹局部奖励 + 活跃集优势'这套组合迁移到其他有执行反馈的长程智能体任务(Web 操作、数据分析、运维修复),检验其通用性;其六,探索部分通过信号(测试子集通过率)作为密集奖励,配合防作弊机制。
复现评估
复现路径清晰但工程门槛高。训练数据是 R2E-Gym 十个仓库的 4,518 个任务,rollout 用 OpenHands 执行;RL 每步 16 任务 × 8 条初始链、64K 上下文、最多 100 轮交互,恢复使实际轨迹数可到 128+ 条/步,需要大规模可并行沙箱与多节点 GPU 投入(论文未公布具体 GPU 数量)。评测需 SWE-agent + 全部 500 道 SWE-bench Verified × 3 个解码种子,成本可控但不便宜。论文公开了关键实现细节:$G=8$、$R=2$、$\epsilon=10^{-6}$、无效工具调用/畸形思考的优势覆写 $-5$、消融从 step-26 检查点续训、超参与 checkpoint 选择在附录 B、逐种子结果在附录 E、跨模型运行时设置在附录 F。但截至本解读,代码、训练数据与模型权重的官方开源渠道尚不确定,若不开源,独立复现的主要工程量在于搭建稳定的控制器(验证器划定尝试边界、干净重置、失败证据注入与截断)以及分布式批量中的活跃集掩码与非活动行处理。对只想验证核心思想的团队,可以先用小规模 R2E-Gym 子集与单步恢复链复现方向性结论。
论文图表