2011 年的 DAgger 被搬回来训 SWE 智能体,4B 模型干翻一票 8B 系统
核心摘要
这一年 SWE 智能体的训练几乎被三类配方瓜分:SFT 蒸出来的模仿,GRPO 这类带验证奖励的 RL,以及最近大热的在线蒸馏 OPD。每一类都各自踩坑:SFT 训练态干净到不真实,部署时一旦走错一步就回不来;RL 奖励稀疏到长程任务里几乎不传梯度;OPD 又被冷启动卡住,弱学生自己跑根本到不了正例轨迹。这篇 arXiv 2605.12913 把 Ross 等人 2011 年的经典模仿学习算法 DAgger 直接挪进多轮 LM 智能体的 post-training,做法朴素得让人不太敢相信会 work:rollout 时每一轮按一个概率 \(\beta\) 让 teacher 接管,全程在每个访问到的状态上都向 teacher 询问一个动作标签,然后拿 cross-entropy 训学生。SWE-Bench Verified 上,4B 学生跑到 27.3 分超过一众已发表的 8B SWE 智能体,8B 学生跑到 29.8 分压过 SWE-Gym-32B,离 32B 旗舰也只差不到 5 分。我的判断是:这不是新算法,但它把 2011 年那篇 paper 的核心 insight 重新校准到 LLM 长程交互这个新场景里,干净到几乎没有 trick,结果反而最有说服力。
论文信息
- 标题:Revisiting DAgger in the Era of LLM-Agents
- 作者:Changhao Li, Rushi Qiang, Jiawei Huang, Chenxiao Gao, Chao Zhang, Niao He, Bo Dai
- arXiv:2605.12913
- 提交:2026 年 5 月 13 日
- 任务:SWE 智能体 post-training,benchmark 用 SWE-Gym Holdout 和 SWE-Bench Verified
一、你训出来的 SWE Agent 为什么一上线就跑偏
先说一个让人有点头疼的现象。
SFT 训出来的 SWE 智能体,在训练集上看损失曲线一切正常,挪到 SWE-Bench Verified 上跑几次你就会发现:模型经常在第几轮干了一件错误的事,之后就再也回不来了。错的不是模型不会写代码,而是它从某个 turn 开始进入了一段它训练时从来没见过的上下文,接下来每一步都是在错误的状态分布上做决策,越滚越偏。
这件事在模仿学习教科书里有个干净的名字:covariate shift,再加上 multi-turn 的 compounding error。Ross 等人 2011 年那篇 DAgger 论文给过一个非常漂亮的理论结果——纯 behavior cloning 的误差随 horizon 呈二次增长,而把训练数据收集在学生自己的状态分布上、用专家在那个状态下的动作做监督,误差可以压回线性。
但这两年 LLM agent 火起来之后,整个社区基本上跳过了这条线索,大家拥抱的是另外两条路:
| 方法 | 它做对了什么 | 它的真问题 |
|---|---|---|
| SFT | 密集的 token 级监督,训练超稳 | 只在 teacher 走过的状态上训,部署时 covariate shift |
| RL with verifiable rewards | 在学生自己的 rollout 上学,分布对齐 | 奖励是稀疏的 0/1,长 horizon 信用分配几乎没信号;group sampling 又贵又容易 advantage 塌缩 |
| On-Policy Distillation | 在策略状态加密集 teacher 监督,看起来兼得 | 冷启动直接劝退,弱学生 rollout 早期全是失败前缀,teacher 监督到的都是死局 |
论文真正想问的问题就一句话——
有没有一种方法,能同时拿到密集监督、在策略状态覆盖,又不被冷启动卡死,还顺便兼容 black-box teacher?
读到这里我的第一反应是:这不就是 DAgger 吗?只是 LLM 这个圈子集体忘了它而已。作者其实就是这个意思,他们把这套思路重新搬回多轮 LLM 智能体场景,没有炫技、没有花里胡哨的 loss,把工程上能干净落地的部分钉死。
二、方法:让学生开车走,但每一步都让老师告诉你正确动作
2.1 一句话讲清核心 idea
学生自己走轨迹,但每访问一个状态,都让 teacher 在同样的上下文里给一个动作标签出来,拿这个标签训学生。少数 turn 直接换成 teacher 接管,把学生从死局里拽回来,让训练数据里始终有走向成功的轨迹片段。
这就是关键。状态分布对齐由学生 rollout 提供,密集监督由 teacher 的逐 turn 标签提供,冷启动问题由 teacher 偶尔接管来兜底。三件事一个机制全解了。
2.2 两种 rollout 协议
文中给了两种 mixing 方式,逻辑都不复杂。
DAgger-style:turn 级伯努利切换。 每一轮独立按 \(\beta_i\) 决定是 teacher 出手还是学生出手。\(\beta_i\) 随训练迭代衰减——前几轮 teacher 介入多一点保证轨迹能走到正例,后面慢慢交给学生让分布逼近部署态。
形式上,每个 turn 的指示变量 \(b_t \in \{0,1\}\) 独立采样:
实验里他们用的衰减是 \(\beta_i = \max(0.6, 1.0 - 0.2(i-1))\),5 轮训练,从 1.0 衰减到地板 0.6。
AggreVaTe-style:轨迹级切换。 给一条轨迹采样一个学生前缀长度 \(\kappa \sim \rho_i\),从 0 到 \(T_{\max}\),前 \(\kappa\) 轮学生自己跑,后面 teacher 直接补完。
实验中 \(\rho_i\) 设为 0 到 40 的均匀分布,因为他们观察到学生 rollout 一般 40 turn 之内就结束了。
2.3 监督信号怎么收
这块是整个方法最干净的地方,也是和 OPD 最本质的差别。
不管这一轮最终是谁执行的,在每个访问到的状态 \(s_t\) 上,都额外去查询一次 teacher 的动作 \(\tilde{a}_t \sim \pi_e(\cdot \mid s_t)\) 作为训练标签。
也就是说,learner 学的是「在这个我(学生)真实会遇到的上下文里,teacher 会怎么操作」。然后训练目标是标准的 token 级交叉熵:
OPD 也在学生 rollout 上训,但它用的是 teacher 在学生轨迹上的 logits 做 reverse-KL 蒸馏——这就要求 teacher 是 white-box,对 GPT、Gemini 这种纯 API 模型直接不可用。DAgger 这里 teacher 只需要能在任意状态下给出一个动作(token 序列),black-box 完全没问题。
2.4 一个统一的视角
作者很贴心地把 SFT / RL / OPD / DAgger 全部写进一个统一的 update 框架:
四种方法的差别就压缩到「状态分布 \(p_s\)、动作分布 \(p_a\)、权重 \(w(s,a)\)」三个轴上:
| 方法 | 状态分布 \(p_s\) | 动作分布 \(p_a\) | 权重 \(w(s,a)\) |
|---|---|---|---|
| SFT / BC | \(d_{\pi_e}\)(teacher 走过的状态) | \(\pi_e\) | 1 |
| RL (Policy Gradient) | \(d_{\pi_\theta}\) | \(\pi_\theta\) | advantage \(A(s,a)\) |
| OPD | \(d_{\pi_\theta}\) | \(\pi_\theta\) | \(-\log \frac{\pi_\theta}{\pi_e}\) |
| Ours (DAgger-style) | \(d_i^{\rm turn}\)(学生-教师 turn 混合分布) | \(\pi_e\) | 1 |
| Ours (AggreVaTe-style) | \(d_i^{\rm traj}\)(学生前缀+教师补完) | \(\pi_e\) | 1 |
这个表看下来你会有一种「啊原来如此」的感觉——DAgger 在这套语言里是把状态分布换成了学生-教师混合分布,但动作分布和权重保持和 SFT 一致。换言之,DAgger 是 SFT 的状态分布修正版。简单到不像一个新算法,但正因为简单,它继承了 SFT 全部的训练稳定性,没有 PPO 那种 ratio clip 的 trick,也不需要 group rollout 的算力开销。
三、实验:4B 学生干翻 8B 系统,8B 学生顶上 32B
3.1 主表
实验设置先说清楚。Teacher 是 Qwen3-Coder-30B-A3B-Instruct,学生是 Qwen3-4B-Instruct-2507 和 Qwen3-8B。训练数据 SWE-Gym 2338 个任务,留出 100 个做 holdout。所有方法都用 OpenHands 这个 SWE 智能体框架做 rollout,scaffold 完全对齐——这一点对公平性来说很关键,避免不同方法之间的 prompt 工程差异污染数据。
| Method | SWE-Gym Holdout | SWE-Bench Verified |
|---|---|---|
| Qwen3-4B baseline | 5.0 | 11.2 |
| Qwen3-4B + GRPO | 8.0 | 11.6 |
| Qwen3-4B + SFT | 15.0 | 22.9 |
| Qwen3-4B + OPD | 16.0 | 23.4 |
| Qwen3-4B + DAgger-style | 17.0 | 27.3 |
| Qwen3-4B + AggreVaTe-style | 16.0 | 24.5 |
| Qwen3-8B baseline | 2.0 | 7.7 |
| Qwen3-8B + GRPO | 4.0 | 8.2 |
| Qwen3-8B + SFT | 12.0 | 23.4 |
| Qwen3-8B + OPD | 16.0 | 26.2 |
| Qwen3-8B + DAgger-style | 19.0 | 29.8 |
| Qwen3-8B + AggreVaTe-style | 17.0 | 27.3 |
| SkyRL-Agent-8B-v0 | -- | 9.4 |
| SWE-smith-LM-7B | -- | 15.2 |
| R2E-Gym-7B-Agent | -- | 19.0 |
| SWE-Gym-32B | -- | 20.6 |
| R2E-Gym-32B-Agent | -- | 34.4 |
| SWE-Dev-32B | -- | 36.6 |
几个数字读下来感受很直接。
4B 学生在 SWE-Bench Verified 上跑到 27.3,比同一份训练数据、同一份 scaffold 下的 OPD 多了 3.9 个点,比 SFT 多了 4.4 个点。再看下半部分 published 系统,27.3 已经超过 SkyRL-Agent-8B-v0、SWE-smith-LM-7B 和 R2E-Gym-7B-Agent 这些 7B/8B 级别的 SWE 智能体。
8B 学生 29.8,比 OPD 多 3.6 个点,关键是它压过了 SWE-Gym-32B 的 20.6 整整 9 个点,距离 R2E-Gym-32B-Agent 也只差 4.6 个点——后者用了 R2E-Gym 自己更大的训练数据,scaffold 也不完全一样。
我自己看到这个数会想一个问题:published 32B 系统的训练数据和 trick 都不一样,这种跨系统对比的可比性其实有水分。但作者的诚实之处在于,他们在主表上半部分做了「同初始化、同数据、同 scaffold」的 head-to-head 对比——OPD 是同期最强的 post-training baseline,DAgger 干净地比 OPD 高 3 到 4 个点,这部分对比是没什么水分的。
3.2 数据扩展的稳定性:DAgger 同时治冷启动和后期偏移
这张图我觉得是全文最值得品的一张。

四条曲线:DAgger-style(蓝实线)、AggreVaTe-style(橙实线)、SFT(绿虚线)、OPD(粉点线)。横轴是 effective training samples,纵轴是 SWE-Gym Holdout 的解决率。
看 3K 样本那个点。OPD 才 9,SFT 10,AggreVaTe 已经 13,DAgger 12。这正是冷启动效应——OPD 早期学生 rollout 大量失败前缀,supervisor 监督到的都是没价值的状态;DAgger 因为 teacher 偶尔接管,早期就拿到了能走到成功的轨迹片段。
再看 9K 那个点。DAgger 17,SFT 15。这是 covariate shift 的影响——SFT 已经把 teacher 的状态分布学完了,但它学的从来不是部署时学生自己会遇到的状态。DAgger 在后期 \(\beta\) 衰减之后,训练数据状态分布越来越靠近 deployment,监督依然密集。

OOD benchmark 上更夸张。SFT 在 7K 处达到 20 然后掉到 19,这是非常典型的 over-imitation 表现——继续在 teacher 状态上喂数据,反而损害了对真实部署状态的泛化。DAgger 一路涨到 26。
一个算法同时治了 OPD 的冷启动 和 SFT 的后期偏移,这件事在我看来比绝对数字更值钱。
3.3 Reverse KL:直接量了一下「学生在自己的轨迹上离 teacher 有多远」

这张图度量的是 \(D_{\mathrm{KL}}(\pi_\theta \| \pi_e)\) 在学生 rollout 状态上的平均值,越低说明学生在自己部署时会遇到的状态分布上越靠近 teacher。
SFT 那条绿色虚线特别戏剧化:先从 0.27 跌到 0.10,然后从某个点开始反弹回 0.126。这是 covariate shift 的直接证据——SFT 早期学生还在 teacher 状态附近,divergence 低;训得越久学生策略变化越大,自己 rollout 就跑到 teacher 训练集没覆盖的地方了,KL 反弹。
DAgger 和 AggreVaTe 两条线下到 0.10 之后基本水平,没有反弹。OPD 稳定在 0.11 到 0.12 之间,介于 SFT 和 DAgger 之间。
这个 reverse-KL 实验非常聪明。它把「covariate shift」这个偏理论的概念翻译成了一个可以测的标量,并且实验结果直接对应了主表上的性能差距。
3.4 失败模式分析:DAgger 把 agent 推向了「更难的失败」
| Method | Resolve | Submission | Syntax/Runtime | Context Overflow | Budget Exhaustion |
|---|---|---|---|---|---|
| Qwen3-4B baseline | 11.2 | 52.1 | 6.6 | 29.4 | 49.2 |
| + GRPO | 11.6 | 53.4 | 2.8 | 28.1 | 48.9 |
| + SFT | 22.9 | 97.6 | 20.3 | 55.1 | 13.9 |
| + OPD | 23.4 | 98.5 | 17.6 | 15.4 | 40.3 |
| + DAgger | 27.3 | 97.9 | 15.9 | 57.5 | 19.3 |
| + AggreVaTe | 24.5 | 97.2 | 17.9 | 60.1 | 16.2 |
注:百分比读法见原表,Syntax/Runtime 在 submitted-but-unresolved 里算,Context Overflow 和 Budget Exhaustion 在 no-submission 里算。
我读这张表读了好几遍才理顺。几个观察:
GRPO 几乎没改变什么。submission rate 53.4,跟 base model 的 52.1 几乎一样。多数 no-submission 失败是 budget exhaustion,说明 agent 大量 rollout 跑到 turn budget 用完了还没干完活。这其实是 sparse reward 的典型副作用——模型不知道该收尾,因为它没有任何 step-level 信号说「该 finish 了」。
SFT 和 OPD 都学到了「该提交」,submission rate 飙到 97.6 和 98.5。但 SFT 的 syntax/runtime 错误率 20.3 是所有训练方法里最高的,OPD 在 no-submission 里 repetitive-loop 占 44.3——它会陷入重复操作的死循环。
DAgger 的 syntax/runtime 降到 15.9,repetitive-loop 也低;它的主要失败模式变成了 context overflow(57.5)。这个表述方式我挺欣赏的:DAgger 把 agent 推向了「更难的失败」——不是不会做、不是工具用错、不是死循环,而是任务太复杂、上下文窗口不够装。这个 bottleneck 不是算法问题,是模型 context window 的物理限制。
AggreVaTe 的 wrong-file rate 是所有方法里最低的 15.7,作者推测是因为它有更长的 teacher 连续轨迹,teacher 能完整演示如何在仓库里定位文件。这是一个很自然的解释:turn-level 切换可能在「找文件」这种需要连续几步连贯操作的子任务上不如轨迹级切换。
四、我的判断:朴素,但是干净
读完整篇我有几个比较强的判断。
它不是新算法,它是新视角下的老算法。 DAgger 的核心 idea 2011 年就在那里了,状态分布对齐 + teacher 标签。这篇论文真正的贡献是在 LLM agent 这个新场景下把它做干净——选对 benchmark、选对 baseline、把 OPD 这个最强对手钉死在主表里、把统一框架那张表写出来。这种工作不会拿 best paper,但它会改变下一拨 SWE 智能体训练的默认 recipe。
它压住了 OPD 这个最强对手,是真有说服力的。 同期 NVIDIA、Anthropic、Qwen3 报告都在押 OPD,这篇直接在同初始化、同数据、同 scaffold 的设置下比 OPD 多 3 到 4 个点。OPD 还要求 teacher 是 white-box,DAgger 不需要——意味着你拿 GPT 或 Claude 当 teacher 也可以做。这是工程上很大的便利。
32B 系统对比那一块要打个折扣。 R2E-Gym-32B 用了完全不同的训练数据和 scaffold,SWE-Dev-32B 也是。所以「8B 接近 32B」这个 narrative 你别完全照单全收,但「8B 在同样数据和 scaffold 下显著超过 32B 的 SWE-Gym-32B」这个判断是 solid 的。
最值得追问的两个 limitation。 第一,teacher 是 Qwen3-Coder-30B-A3B,本身就是个 black-box 的 LM,它在「错误状态」下给的标签是不是真的「正确」?经典 DAgger 假设有 oracle expert,但 LLM teacher 本身就有犯错的可能,teacher error 会不会复合?论文没正面处理。第二,整个研究只测了 SWE 一个领域,scaffold 也只测了 OpenHands。Web navigation、agentic RAG、math-with-tools 这些其他长程任务上是不是一样 work,作者自己在 conclusion 里也承认是 future work。
对工程的启发挺直接的。 如果你正在训 SWE 智能体或者类似的长程工具调用 agent,从 SFT 切到 DAgger-style 的成本极低——rollout pipeline 加一个伯努利切换、一个 teacher 标签查询,loss 不变。试一下完全没成本。我会赌它在大多数场景下能给你几个点的提升。
还有一个 meta 层面的观察。 LLM 这个圈子这两年的算法进展其实大量来自于「把以前 RL/IL/控制领域踩过的坑重新踩一遍」——RLHF 之后 GRPO 出来,说到底是 policy gradient 的现代化;OPD 是 distillation 的某种变体;这篇 DAgger 又把 covariate shift 这个老问题翻出来。这倒不是说 LLM 圈在重复造轮子,更像是新场景倒逼大家把以前不被重视的工具重新拿出来对齐。下一个被重新发现的可能是什么?我赌的是 model-based 那套——给 LLM agent 加一个 world model,让它能 plan 之后再 act。
五、一个工程上的小细节
我重读 method 部分时注意到一个挺重要的实现细节:训练时不是每个 (state, action) 对单独算 loss,而是把同一条轨迹里共享前缀的 transition 打包到一个 forward 里,用 loss mask 来保证梯度等价于逐对独立更新。
这件事看着平淡,但对训练效率影响极大。SWE 任务的 context 经常 32K+,每个 turn 重新 forward 一遍 prefix 是不可承受的开销。这种 packing 实现差不多是 LLM agent 训练 pipeline 的标配,但它对正确性的影响不小——尤其是当某个 turn 是学生动作时,你需要在这个 turn 之后断开 chunk,不能让 teacher label 条件在反事实的轨迹上。论文这块只写了一行字("applying a loss mask to ensure the gradient remains equivalent"),但实际工程上是需要小心处理的。
如果你打算复现这套方法,建议先把 packing 和 loss masking 的逻辑画清楚再写代码。这是这套方法的隐藏陷阱。
六、收尾
把 2011 年的 DAgger 拿回来对齐 LLM 智能体,看起来朴素,但当你把方法放在「OPD vs SFT vs RL」这个三方角力的语境里看,它解决的恰好是三方都没解决的问题——同时给你密集监督、在策略覆盖、冷启动鲁棒、black-box 兼容。
这种工作的价值不在于震撼,而在于干净。它没有 hack、没有花哨的目标函数、没有难调的超参,五轮迭代、\(\beta\) 从 1 衰减到 0.6,整个 recipe 一张 A4 纸就能讲完。你能把它写在团队的 onboarding 文档里直接上手。
如果你也在训长程的 agent,无论 SWE、web、tool-use,这套思路值得把 SFT pipeline 改一改试试。预计你能拿到 3 到 5 个点的提升,几乎是免费的。
觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我