SWE Agent
SWE Agent · arXiv 2025 · 2508.03501v1

Long-Context SWE Agent:用 0/1 奖励训练多轮软件工程智能体

修一个 GitHub issue 不是“一次生成补丁”,而是一串“执行命令、看报错、再改”的交互。论文把 SWE 任务当成 POMDP, 先用拒绝微调让模型学会正确的工具格式,再用 DAPO 在真实仓库环境里做多轮 RL;主奖励是补丁是否通过测试的 0/1 信号,另加超长轨迹的长度惩罚。

Alexander Golubev 等 · Nebius / Humanoid arXiv 2508.03501v1 ↗
TL;DR · 30 秒抓住核心

论文先做一个区分:数学题和单次代码生成可以当成“多臂赌博机”,输入一个问题、输出一个答案、拿一个奖励,中间没有环境反馈;软件工程不是。智能体要执行 grep、读文件、改代码、跑测试;每个动作都会产生可观察的转移(其中一部分会改变仓库状态),并返回新的观察。它把这种任务形式化成 POMDP,并指出当时的 LLM RL 大多停留在单轮设定(§1、§2.1)。

训练分两段。RFT:先让 Qwen2.5-72B-Instruct 在 7,249 个任务上各尝试 10 次,只留下补丁能通过测试的 6,548 条轨迹(rollout + 筛选),再在这批成功轨迹上做 1 个 epoch 的 SFT——SFT 是 RFT 的一部分。RL:用改过的 DAPO,每个问题采 10 条完整轨迹,按组内均值/标准差算优势;主奖励是补丁通过测试为 1、否则为 0,另加超长轨迹的线性惩罚。

RL 分两个课程阶段:先在 65k 上下文、最多 40 轮里训练,等性能到约 32%(论文未说明该阈值对应哪个评测集)后切到 131k、最多 80 轮,并把训练池从 7,249 个任务筛到 2,028 个。最终 SWE-bench Verified 的 Pass@1 是 39.04%,比 RFT 后的 20.46% 高 18.6 个百分点(RFT 用 65k、最终模型用 131k 评测,这一差值还含 65k→131k 与 40→80 轮的变化);Pass@10 是 58.4%。

边界同样清楚:奖励依赖 SWE-rebench 训练任务自带的验证测试套件(SWE-bench Verified 只用于评测),训练只覆盖 Python issue 类任务(原文未按任务类型细分,§3.1);完整流程要 16 个 H200 节点;Pass@1 与 Pass@10 之间还差 19.4 个百分点,说明模型经常“生成了对的候选但没选中”。和领先的开放权重模型比,按 Pass@1,Verified 上比 DeepSeek-V3-0324 低 0.52 个百分点,SWE-rebench 的 May 低 1.75、June 高 0.25,两个分片一低一高;按 Pass@10,三个分片(Verified/May/June)都低于 DeepSeek(Table 1)。

39.04%
SWE-bench Verified Pass@1
最终模型,131k 上下文
18.6pp
Pass@1 · RL 阶段差(含 65k→131k)
39.04% − 20.46%
58.4%
同一模型的 Pass@10
比 Pass@1 高 19.4 个百分点
01

修 issue 是状态化交互,不是一次性生成

先分清“赌博机式任务”和“部分可观察的交互任务”,这决定了 RL 能优化什么。

论文的出发点是一个建模差异。数学推理、单次代码生成这类任务可以写成 (问题 → 答案 → 奖励) 的单步过程:模型看不到中间状态,也没有机会根据环境反馈改变策略。论文把它称为 bandit-style 或退化的 MDP(§1、Figure 2 上半)。

软件工程任务不是这样。一个 issue 只给出自然语言描述,仓库的真实状态(文件内容、依赖、测试结果)对智能体是部分可观察的;它只能通过动作去获取观察:运行 ls 或 grep 看目录和代码,打开文件,修改某几行,运行测试,读失败日志。每个动作都会产生可观察的转移(其中一部分会改变仓库状态),下一步的决策依赖完整的动作—观察历史。论文把它写成 POMDP(§2.1),Figure 2 的下半部分给出与单步任务的对比(§1)。

单步任务

奖励可以直接归因到一次输出

模型生成一个答案,验证器判对错,奖励回到这次生成。信用分配只发生在一个回答内部,RL 的组内比较足以工作。

SWE 任务

奖励只出现在 episode 结束

补丁是否通过测试,要等智能体执行 submit 后才知道。中间几十步没有即时奖励,哪一步导致成功或失败并不直接可见。

这个建模带来两个直接后果。第一,轨迹会很长:一个任务可能要几十轮命令和修改,上下文里堆满文件片段、报错和 diff。论文最终把训练上下文推到 131k,单条 episode 最多 80 轮(§3.3)。第二,奖励是稀疏的 0/1:中间步骤没有人工奖励,唯一信号是最终补丁有没有通过验证测试。论文明确把 R(τ) ∈ {0,1} 作为策略优化的唯一任务信号(§2.1)。

这也解释了为什么“直接上 RL”不够。基础模型常常连工具格式都写不对:命令格式错误、编辑时缩进不符合要求(§2.3 的 edit 要求精确缩进)。论文说初始 checkpoint 在 SWE-bench Verified 上只有约 11%,主要失败原因是指令跟随不正确(§3.2)。如果 RL 从这种状态开始,大部分 rollout 都会因为格式错误拿 0 分,组内比较没有有效梯度——原文没有直接给出这个实验,推断(依据:§3.2 说初始 checkpoint 的主要失败是指令跟随/格式,RFT 正是为修正它而设计)。RFT 的作用就是先把这些“无效动作”清掉。

02

闭源模型、推理时搜索、教师蒸馏:三条路都贵

论文要证明的是:不靠教师模型,RL 阶段只靠环境交互和 0/1 奖励(RFT 仍用自生成成功轨迹做 SFT),也能把开源模型推到同一档。

论文在引言里列出当时做高性能 SWE 智能体的三条常见路线(§1):

路线 1

闭源模型 + 复杂脚手架

用 GPT-4 之类的专有模型,外面套一层工程化的工具和流程。效果稳定,但成本高、模型不可控,研究社区难以复用。

路线 2

推理时扩展

用 MCTS、best-of-N 或多次采样在推理阶段搜索。算力换准确率,部署时延迟和成本都会上升。

路线 3

教师模型蒸馏

让更强的教师生成“完美轨迹”,再 SFT 学生模型。需要高质量示范数据。

Table 2 把近期的专用 SWE 智能体按“是否使用教师蒸馏”分了类。这个分类很重要:教师蒸馏路线里,32B 模型可以在 SWE-bench Verified 上到 40.2%(SWE-agent-LM-32B);不用教师的方法里,DeepSWE-32B 到 42.2%。论文的最终模型在 Table 2 的 after 列是 39.0%(与 Table 1 的 Pass@1 39.04% 对应),处在这个区间的同一档,但它的卖点不是“最高分”,而是不用教师数据;RL 阶段只用 0/1 环境奖励(RFT 用自生成成功轨迹做 SFT)。

论文选择 RFT + RL 的组合。RFT 仍然需要模型自己产生成功轨迹,但不需要外部教师;RL 则在 RFT(采样筛选 + SFT)的基础上继续用环境反馈优化策略(§3.2、§3.3)。论文在 §1 的论点是:RL 通过与环境交互直接优化策略,可能在不依赖教师模型的情况下取得更强性能。

03

ReAct 循环 + 稀疏奖励 + 组内优势

方法不新在网络,而在把多轮交互、长轨迹和 0/1 奖励接进 DAPO。

智能体怎么动:工具、轮数与 submit

智能体采用 ReAct 式循环,动作—观察历史会拼进每一次决策。工具集包括(§2.3):任意 shell 命令(ls、cat、grep 等);一个按行替换文件内容的 edit 命令,要求给出精确缩进;search_file、open、goto 这类检索与导航工具;以及一个无参数的 submit 命令,调用后 episode 结束。智能体可见的是 issue 描述、失败测试套件与仓库快照(§2.3);数据集记录还含 ground-truth patch(§3.1)。

奖励在 episode 结束时计算:最终补丁通过验证测试套件则 R(τ)=1,否则为 0。中间步骤的即时奖励全为 0,所以整条轨迹只有终点信号(§2.1)。这个设定和真实开发接近,但也把信用分配问题留给了算法。

RFT:先让模型学会“怎么用工具”

RFT 的流程在论文里写得很具体(§3.2):用初始 checkpoint 在 7,249 个 SWE-rebench 任务上各生成 10 条轨迹,只保留补丁通过测试的轨迹,一共得到 6,548 条;在这批成功轨迹上做 1 个 epoch 的监督微调。训练时屏蔽掉所有触发环境格式错误的 agent turn,Loss 只落在格式正确的动作上。

口径提示:原文 §3.2 的 6,548 条与 §4.3 的 batch 64 / 50 个梯度步不吻合(6,548 / 64 ≈ 102.3;50 × 64 = 3,200);推断 可能 batch 是全局/每设备口径,或只用了部分轨迹,论文未说明。此处按原文并列,不替它消解。

这一步不是“学解题思路”,而是“学接口”。原文说基础模型的主要失败是指令跟随不正确、命令不符合要求格式(§3.2);§2.3 的 edit 命令还要求精确缩进。把这些无效动作从 Loss 里去掉,模型会更快稳定在可执行的交互模式上。RFT 后 Verified Pass@1 从 11.42% 到 20.46%,差 9.04 个百分点(base 用 131k、RFT 用 65k 评测,见 Table 1 caption;差值含评测上下文变化)。

DAPO:组内比较,不需要 critic

RL 阶段用 DAPO。它属于 GRPO 一系:对同一个初始 observation 采一组 G 条完整轨迹,用组内奖励的均值 R̄ 和标准差 σR 归一化每条轨迹的终点奖励,得到这条轨迹的优势:

Â(i) = (R(τ(i)) − R̄) / (σR + δ)
Eq. 3 · R̄ = (1/G) Σ R(τ(i));δ 是数值稳定项。这个优势会应用到该轨迹的所有 token 上。论文每个问题采 G=10 条(§3.3;§4.2 复述为每个问题 10 条)。

DAPO 相对 GRPO 的改动有四条,论文都写进了 §2.2:token-level loss(按 token 平均,而不是每条轨迹等权);动态采样(优势为 0 的样本被丢掉,不让它们占据计算);软超长惩罚(超过长度阈值后线性扣分,而不是直接把轨迹截断);以及非对称 clip(上下界分开设置,Stage 1 为 [0.2, 0.3],Stage 2 为 [0.2, 0.26])。

软超长惩罚的公式是:

Rfinal(τ) = R(τ) + Rlength(τ)
Rlength(τ) = 0,若 |τ| < Lthr;否则 (Lthr − |τ|) / (Tmax − Lthr)
Eq. 6–7 · Lthr 是惩罚阈值,Tmax 是最大 episode 长度。超过阈值后越长扣得越多;它加在测试奖励上,不改变“通过/不通过”的主信号。

为什么不用 PPO:PPO 需要一个学出来的 critic 来估计优势,critic 本身要训练、会引入额外的不稳定;组内比较直接用同一组轨迹的终点奖励做基线,省掉了这个网络(§2.2)。代价是每组必须采多条完整轨迹,而 SWE 的轨迹很长,所以采样成本高。

04

65k 先学交互,131k 再学长程,课程把池子从 7,249 筛到 2,028

这一节把两阶段超参数、数据过滤和基础设施摊开。

数据:从 21,336 到 7,249

训练数据来自 SWE-rebench:21,336 个任务,覆盖约 3,400 个 Python 仓库;每个任务包含 GitHub issue、失败测试套件、可复现的仓库快照,以及 ground-truth solution patch(§3.1),原文没有把任务类型限定为 bug fix(§3.1)。论文按四条规则过滤(§3.1):任务正确性(去掉测试因无效引用/导入而失败的任务,如 AttributeError、ImportError);受控复杂度(只保留最多修改 7 个文件、少于 500 行代码的任务);LLM 质量评分(去掉原数据集中 LLM 评分 3.0 的任务,理由包括 issue 描述不清、任务过复杂或测试补丁有缺陷);确定性测试(50 次重复运行,去掉 flaky 任务)。最终留下 7,249 个任务,也就是过滤掉 14,087 个。

Table 3 转录 + §3.3 · 每轮问题数、训练池、batch、clip 来自 Table 3;上下文 65k/131k 与最大轮数 40/80 来自 §3.3;RFT 与优化器设置见下文 §4.3(不在本表)。
阶段上下文最大轮数 Tmax每轮问题数训练池Batch sizeClip 范围
Stage 1 RL65k403007,249128[0.2, 0.3]
Stage 2 RL131k801002,028256[0.2, 0.26]

Stage 1 用 65k 上下文,已经超过多数开源模型默认的 32k;论文说这个长度还不够覆盖长堆栈或长 diff 历史,所以在性能到约 32% 后切到 Stage 2(论文未说明该阈值对应哪个评测集;Figure 1/4 的中间评测用 Verified-50,Table 1 的完整 Verified 上 Stage 1 为 35.74%):上下文升到 131k,最大轮数从 40 翻到 80,同时降低高 clip 上界、增大 batch、降低每轮问题数,让训练更接近 on-policy(§3.3)。131k 是通过 YaRN 位置编码(factor = 4.0)实现的(§4.3)。

课程:去掉“已经会做”和“从来没做对”的任务

Stage 2 开始前做一次性的课程调整。论文定义任务的累计解决率:它在之前所有训练迭代中的成功率。累计解决率超过 2/3 的任务被移除(说明已经能稳定解决),累计解决率始终为 0 的任务也被移除(说明大概率不可解)。训练池因此从 7,249 缩到 2,028,筛掉 5,221 个任务(§3.3)。

优化与基础设施

RFT:1 个 epoch,学习率 5×10−6,AdamW,weight decay 0.1,10 步 warmup,cosine 衰减到 0,batch 64,共 50 个梯度步。RL:学习率 10−6,1 个 epoch,梯度裁剪 1.0,AdamW(β1=0.9、β2=0.999、ε=1e−8、weight decay 0.1)(§4.3)。6,548 条成功轨迹与这里的 batch 64 / 50 步不吻合(6,548/64≈102.3,50×64=3,200);原文未说明,见 §3.2 后的口径提示。

整个流程是同步的:rollout 生成完再训练,没有策略滞后(on-policy)。每个问题采 10 条轨迹,每轮产生 2–8 个优化步,具体取决于 batch size 和优势非零的轨迹数。训练与推理都在 16 个 H200 节点上完成;为了在 131k 序列上做全参数训练,用了 context parallelism(§4.2)。论文未报告总 GPU 小时、token 数或单轮墙钟;§4.2 给出 16 个 H200 节点;Appendix C 给出单 pod 配置(8×H200、32 CPU、960 GiB、JAX、vLLM 0.7.4),但没有总量指标。同步训练的一个已知问题是 straggler:一轮的耗时取决于最慢的那条轨迹。

RL 总共跑了 100 多个训练迭代(over 100 RL iterations,§4.1)。论文未给出 Stage 2 的迭代次数,也未说明每轮采样是否放回;因此无法判断 2,028 个任务是否被重复采样(Stage 1 的 300 问题/轮、Stage 2 的 100 问题/轮见 Table 3)。

05

一条流水线:RFT 采样筛选 → SFT(RFT 的一部分)→ 65k RL → 课程筛选 → 131k RL

上半部分是训练流水线,下半部分是一条 episode 内的交互循环。

7,249 个任务 SWE-rebench Python 仓库 RFT 采样筛选 每个任务 10 条轨迹 只留通过测试的 得到 6,548 条 SFT 1 epoch RFT 的一部分 屏蔽格式错误 turn RL Stage 1 65k 上下文 最多 40 轮 训练池 7,249 课程筛选 累计解决率 > 2/3 或 = 0 的移除 RL Stage 2 131k 上下文 最多 80 轮 池 2,028 单条 episode:act → observation → act → … → submit → 跑测试 → 奖励 R ∈ {0, 1} 动作:shell / edit / search_file / open / goto / submit;历史条件每一次决策 10 条轨迹一组 → 组内归一化优势 → DAPO token-level 更新
按 Figure 2 与 §3–§4 重绘(Figure 1 只提供训练趋势,不参与本图结构):覆盖 RFT 采样筛选、SFT(RFT 的一部分)、两阶段 RL、课程筛选与单条 episode 的交互循环。未覆盖工具调用的具体实现、失败轨迹的存储格式、分布式训练的通信细节与评测脚本;页面不对 agent 行为做模拟。

流水线里只有 RL 两段用环境 0/1 奖励更新策略。RFT(采样筛选 + SFT)负责把模型带到“能正常跑完 episode”的起点;Stage 1 在 65k 上下文、最多 40 轮上训练;课程筛选把已经稳定解决和完全解不出的任务拿掉;Stage 2 把上下文扩到 131k、最大轮数提到 80(§3.3)。评测时不再更新参数,只把最终 checkpoint 放到同样的工具环境里跑。

06

Pass@1 从 11.4% 到 39.0%,但长上下文阶段的收益并不均匀

先看主表和分阶段柱状图,再看三个反直觉点:Stage 2 的 Pass@1 在 Verified 上涨、May 下降、June 小幅上涨(Pass@10 下 May/June 不涨)、Pass@1 与 Pass@10 的差距、以及与 DeepSeek 的逐项对比(结论按 Pass@1 / Pass@10 分开)。

Table 1 是主结果。Pass@1 是 10 次运行的平均值,括号里是标准误;最终模型和基线用 131k 评测,中间模型用各自训练阶段的上下文长度(65k)评测。

Table 1 转录 · SWE-bench Verified 与 SWE-rebench 的 May / June 分片;Pass@1 为 10 次运行平均 ± 标准误,Pass@10 为百分数;所有模型使用其 Hugging Face 配置中的默认解码参数(与 §4.3 的训练 rollout 采样设置不同)。
模型SWE-bench VerifiedSWE-rebench MaySWE-rebench June
Pass@1Pass@10Pass@1Pass@10Pass@1Pass@10
Qwen2.5-72B-Instruct11.42 ± 0.2431.014.50 ± 1.3340.014.63 ± 1.0336.6
+ RFT @ 65k20.46 ± 0.4243.022.50 ± 1.1845.020.98 ± 1.5143.9
+ Stage 1 RL @ 65k35.74 ± 0.2854.636.50 ± 1.5955.031.22 ± 0.8053.7
+ Stage 2 RL @ 131k39.04 ± 0.5058.435.00 ± 1.5452.531.71 ± 1.3153.7
DeepSeek-V3-032439.56 ± 0.4762.236.75 ± 0.9260.031.46 ± 1.3858.5
Qwen3-235B no-thinking25.84 ± 0.3754.427.25 ± 1.1557.522.93 ± 2.1648.8
Qwen3-32B no-thinking20.40 ± 0.3444.021.75 ± 1.5450.017.56 ± 1.3036.6
Llama4 Maverick15.84 ± 0.5447.219.00 ± 1.7250.013.66 ± 1.7939.0

交互:切换 Pass@1 / Pass@10,看四个训练阶段

下面把 Table 1 的四个训练阶段画成柱状图,按基准分组。切换指标会重画全部柱子;同一组里从左到右是 Base、RFT、Stage 1、Stage 2。数值逐字来自 Table 1。

当前读数
Pass@1 · Verified:11.42 → 20.46 → 35.74 → 39.04;May:14.50 → 22.50 → 36.50 → 35.00;June:14.63 → 20.98 → 31.22 → 31.71
Base RFT Stage 1 Stage 2
手算:三组阶段差值与口径与上面的图表同一数据源

配置 A:Verified · Pass@1。RFT − Base = 20.46 − 11.42 = 9.04;Stage 1 − RFT = 35.74 − 20.46 = 15.28(页面写 15.3);Stage 2 − Stage 1 = 39.04 − 35.74 = 3.30;RL 总计 = 39.04 − 20.46 = 18.58(页面写 18.6)。

配置 B:SWE-rebench May · Pass@1。Stage 1 = 36.50,Stage 2 = 35.00,Stage 2 相对 Stage 1 低 36.50 − 35.00 = 1.50 个百分点;同一阶段在 June 分片是 31.71 − 31.22 = 0.49 的上升。

配置 C:Pass@10 直读。Verified:31.0 → 43.0 → 54.6 → 58.4;May:40.0 → 45.0 → 55.0 → 52.5;June:36.6 → 43.9 → 53.7 → 53.7。Pass@10 为 Table 1 表格直读,不做插值或重新计算;Stage 2 相对 Stage 1 在 June 持平(53.7 → 53.7),Verified 为 54.6 → 58.4。

交互只做表格读数与柱高映射,不计算平均、标准差或标准误;Table 1 的 ± 值是原文报告的标准误,页面不重新计算。图表里的柱高按百分数直接映射,不做归一化。

训练账:阶段差 9.04 / 15.3 / 3.3,口径不同不能直接当贡献拆分

在 Verified 上,RFT 把 Pass@1 从 11.42% 拉到 20.46%,差 9.04 个百分点(base 用 131k、RFT 用 65k 评测);Stage 1 的 RL 把它拉到 35.74%,差 15.3 个百分点(同为 65k,是唯一同口径的阶段差);Stage 2 再差 3.3 个百分点(同时改了上下文、轮数、batch、clip,以及训练池——课程筛选从 7,249 到 2,028——和每轮问题数(§3.3、Table 3),不是纯算法贡献)。RL 两段合计比 RFT 高 18.6 个百分点,最终是 RFT 基线的 1.91 倍(39.04 / 20.46)。

反直觉 1(Pass@1):Stage 2 在 Verified 和 June 上涨、在 May 下降。按 Pass@1,把上下文从 65k 扩到 131k、轮数从 40 扩到 80 后,Stage 2 在 Verified 和 June 上涨、在 May 下降:Verified 从 35.74 涨到 39.04,涨 3.3 个百分点;June 只涨 0.49 个百分点;SWE-rebench May 从 36.50 掉到 35.00,低 1.5 个百分点。推断 只有 Verified 的涨幅明显——June 的 +0.49 落在两个阶段各自的标准误(±0.80 与 ±1.31)之内(依据:Table 1 的 Pass@1 ±SE 比较;原文没有这句显著性判断)。按 Pass@10,方向不同:Verified 54.6 → 58.4,May 55.0 → 52.5,June 53.7 → 53.7(持平);三个分片里只有 Verified 上涨。论文没有对 May 的下降给出解释,也没有把它归因于课程筛选或上下文变化;这里按 Table 1 原样并列,不替原文消解。

反直觉 2:Pass@10 远高于 Pass@1。最终模型 Verified Pass@1 是 39.04%,Pass@10 是 58.4%,相差 19.4 个百分点。论文据此指出,模型生成的候选里经常存在正确解,只是单次选择没选中;这为后续接重排或 best-of-n 留了空间(§3.3)。注意这是“候选里有没有”和“最终提交哪一个”的差别,不是模型不会做。

反直觉 3:对 DeepSeek 的比较要分片看,而且 Pass@1 / Pass@10 方向不同。按 Pass@1,Verified 上 DeepSeek-V3-0324 是 39.56%,比最终模型高 0.52 个百分点;SWE-rebench May 上 DeepSeek 36.75%,高 1.75 个百分点;June 上 DeepSeek 31.46%,最终模型 31.71%,最终模型高 0.25 个百分点(31.71 − 31.46)。按 Pass@10,DeepSeek 在三个分片都更高:Verified 62.2 对 58.4、May 60.0 对 52.5、June 58.5 对 53.7(Table 1)。按 Pass@1,只有 June 略高 0.25,Verified/May 分别低 0.52/1.75,不能概括为追平;按 Pass@10 三个分片都低。

和专用 SWE 智能体比:不是 Table 2 的最高分

Table 2 汇总了专用 SWE 智能体。下表转录 Table 2 全部 9 行。“Teacher Distillation”列表示训练是否用了教师模型生成的轨迹。

Table 2 转录 · “before” 是基座模型训练前的 Pass@1,“after” 是训练后的最终成绩;均指 SWE-bench Verified。
智能体基座模型BeforeAfterTeacher Distillation
OursQwen2.5-72B-Instruct11.439.0No
DeepSWE-32BQwen3-32B2342.2No
SkyRL-Agent-14B-v0Qwen3-14B18.021.6No
SWE-agent-LM-32BQwen2.5-Coder-32B-Instruct14.340.2Yes
Skywork-SWE-32BQwen2.5-Coder-32B-Instruct6.438.0Yes
R2EGym-Agent-32BQwen2.5-Coder7.034.4Yes
SWE-Fixer-72BQwen2.5-72B-Base–30.2Yes
SWE-Gym-32BQwen2.5-Coder-32B-Instruct7.020.6Yes
SWESynInfer-72BQwen2.5-72B-Instruct25.430.2Yes

表里有三个不用教师的方法:最终模型 39.0%,DeepSWE-32B 42.2%,SkyRL-Agent-14B-v0 21.6%。Table 2 的 after 列原文只写 final performance,未注明指标;Ours 的 39.0 与 Table 1 的 Pass@1 39.04 对应,DeepSWE/SkyRL 的 42.2/21.6 按原文转录,不能断言均为 Pass@1。按 Table 2 的 after 数值,DeepSWE-32B 比最终模型高 3.2 个百分点。用教师蒸馏的 32B 模型里,SWE-agent-LM-32B 也到 40.2%。所以这篇论文的位置是“不用教师、RL 阶段只用环境奖励的强基线”,不是“所有设置下的最高分”。

训练里的两个坑

坑 1:不要一概丢掉超长轨迹。常见做法是把超过上下文长度的轨迹过滤掉,以减少奖励噪声。论文说这要谨慎:在它的设定里,超长轨迹往往意味着智能体陷入了重复循环;把这些轨迹丢掉,也就丢掉了“循环”这个失败模式的负样本,模型反而学不会如何跳出循环,训练中这种循环会更频繁(§4.4)。

坑 2:训练 rollout 必须来自 πold。训练中途升级 vLLM 后,运行时默认启用了 top_k 和 min_p。一开始评测指标变好,但继续训练 5–10 个迭代后开始下降。论文把这个现象归因于 rollout 分布和训练分布的错配:DAPO 的重要性采样比只有在 rollout 来自 πold 时才有意义,换解码参数相当于从另一个分布采样(§4.4)。这里说的是训练 rollout 的采样解码(§4.3 的 temperature=1.0、禁用 top_p/top_k 等),不是 Table 1 评测所用的默认解码。这是一个工程细节,但会直接影响复现。

07

它解决不了:测试即裁判、Python issue 类任务、算力门槛

这些限制决定了这套方法能不能搬到别的任务,以及复现成本有多高。

限制 1

奖励依赖测试套件

0/1 奖励来自 SWE-rebench 训练任务自带的验证测试(SWE-bench Verified 只用于评测)。测试通过不等于补丁正确:模型可能针对测试写特例,也可能修好测试覆盖的部分却破坏未覆盖的行为。论文未报告超出测试的语义正确性检查。

限制 2

只覆盖 Python issue 类任务

训练数据是 SWE-rebench 的 Python issue 类任务,原文未按任务类型细分(§3.1)。新功能开发、重构、文档、跨语言仓库都没有实验;任务分布一变,RFT 和 RL 学到的工具使用模式未必迁移。

限制 3

算力与工程门槛

16 个 H200 节点、全参数训练、131k 上下文、100 多个训练迭代。论文未报告总成本;没有同等算力和训练框架的研究者难以完整复现。

没有解决“选择”问题。Pass@1 39.04%、Pass@10 58.4%,说明候选里经常已经有正确补丁,但模型自己选不中。论文只把这个差距作为一个观察和未来方向,未描述重排器或提交前的验证/自我检查。实际部署时,这个差距会直接变成“再多试几次”的成本。

没有风险意识。智能体被训练成“尽力提交一个补丁”,没有“这题我没把握,先停下或求助”的动作。论文在讨论里把不确定性估计和放弃机制列为未来工作;当前模型在低成功率的任务上也会走完 episode 并提交。

同步训练的限制。论文明确说异步框架可能有更好的扩展性,但为了消除轨迹滞后选择了同步;同步的 straggler 问题会让每轮时间取决于最慢的轨迹(§4.2)。这意味着吞吐和资源利用率还有优化空间,但论文未报告异步版本的对照实验。

什么时候别用:如果任务没有可自动运行的验证测试、代码执行有安全风险、或者仓库状态无法快速快照和回滚,这套方法的奖励和 rollout 都搭不起来。反过来,在有测试、有沙箱、任务类型稳定的软件工程场景里,它的路径很直接:先用成功轨迹教会模型用工具,再用 0/1 结果做多轮策略优化。