论文解读 · Long-Horizon Agentic RL

CompactionRL:把"上下文压缩"从推理技巧变成可训练的动作

长程 agent 迟早会撞上上下文墙。业界的常规做法是到了墙边就做一次摘要、然后在新窗口里继续——但摘要本身从来没有被训练过。CompactionRL 把摘要 token 也塞进 RL 的损失里,和执行动作共享同一个任务奖励。

CompactionRL: Reinforcement Learning with Context Compaction for Long-Horizon Agents
Yujiang Li*, Zhenyu Hou*, Yi Jing, Jie Tang, Yuxiao Dong · 清华大学 / Z.AI · arXiv:2607.05378v1(2026-07-06)
模型:GLM-4.7-Flash (30B-A3B)、GLM-4.5-Air (106B-A30B);该方法已被用于 GLM-5.2 (750B-A40B) 的 RL 流水线

一句话:当上下文预算耗尽时生成的那段摘要,不是预处理,而是一个决定后续所有动作成败的策略行为——所以它必须被 RL 训练,而不是被当作外部工具调用。

核心结论速览

01问题:长程 agent 撞上的那堵墙

SWE-bench、Terminal-Bench 这类任务的形态是:反复"推理 → 调工具 → 看环境反馈 → 改计划"。ReAct 风格的做法是把完整交互历史一路拼进 prompt,于是上下文长度随轨迹单调增长。工具输出、中间推理、报错信息、半成品补丁堆在一起,很容易在任务完成之前就把窗口撑爆。

把窗口做长不是答案:一方面成本高,另一方面长序列上的有效信息利用率本身会退化(论文引了 LongBench / RULER 那条线)。所以长程 agent 的 RL 训练必须在固定上下文预算下跑通。

上下文压缩(context compaction)是自然的解法:历史快撑满时,把之前的交互摘要成一个短状态,agent 从"摘要 + 一小段最近历史"继续。但此前的用法基本都是推理期启发式或外部记忆操作。论文指出,在 RL 训练里压缩的地位要更根本:

关键观察

一旦摘要替换了原始历史,它就决定了后续所有动作能看到什么信息。任务成败不只取决于执行策略,也取决于压缩策略。既然是策略,就该被优化。

不做压缩 Prompt step 1 step 2 ··· step N 上下文预算耗尽 Stopped ✗ 做压缩 Prompt step 1 step 2 ··· step N 压缩:策略自己生成一段 Summary Prompt Summary 最近 k=2 步 step N+1 ··· Completed ✓
复现原文 Figure 1(左)。压缩让执行在固定窗口下继续:预算耗尽时不是停止,而是把过去压成摘要、开一个新 trace。注意新窗口里同时保留了"摘要"和"最近 k 步的原始交互"——远程信息靠摘要,近处状态保持精确。

02先导实验:摘要模型换一个,成绩差 6.5 个点

论文先用一个干净的对照说服你"摘要很关键":执行 agent 固定为 GLM-4.7-Flash,只替换负责写摘要的模型

摘要模型(执行模型固定为 GLM-4.7-Flash)SWE-Verified Pass@1平均压缩次数 / trace
Qwen3.5-27B55.51.010
GLM-4.7-Flash(自己给自己写摘要)50.51.075
Qwen3-30B-A3B49.01.126

6.5 个点的差距,全部来自"谁来写这段摘要"。而且好的摘要还顺带减少了压缩触发次数——信息保留得好,后续就不需要反复重新探索、把窗口重新撑爆。一份丢掉了关键文件路径、报错信息、失败命令或半成品补丁的摘要,会让后面每一个动作都失效,哪怕执行策略本身很强。

结论很直接:压缩是一个性能关键的决策过程,不是被动的预处理步骤。那就把它一起训。

03方法:把压缩塞进 rollout 采集

① 触发条件

把交互历史记为 h_t = (s, u, z_1, ..., z_t),其中 s 是 system prompt,u 是用户指令,z_i = (a_i, o_i) 是"助手响应 + 环境观测"对。z_i 被当作原子步——工具调用和它的反馈绝不会被压缩切开。

C 为上下文预算,压缩在剩余预算低于阈值 T_comp 时触发:

C − |h_t| < T_comp (实验中 C = 64k / 80k,T_comp = 10,240)

② 摘要生成与上下文重建

触发后,把一段固定的摘要指令 q_sum 追加到当前历史后,从当前策略里采样一段摘要:

S_t ~ π_θ( · | h_t ⊕ q_sum )

q_sum 要求模型保留继续任务所需的信息:原始目标、已完成的动作、重要观测、未解决的错误、当前状态、以及合理的下一步。然后重建上下文:

h̄_t = (s) ⊕ u_resume(S_t) ⊕ (z_{t−k+1}, ..., z_t) 默认 k = 2

即 system prompt + 含摘要的固定续写模板 + 最近 k 步原样保留(塞不下时再减小 k)。这个设计的分工很清楚:长程信息靠摘要压缩,近端环境状态保持逐字精确——因为 agent 下一步动作往往直接依赖上一条工具输出的确切内容。

③ 段(segment)与共享奖励

一条带压缩的完整 rollout 被自然切成一串生成 token 段:

τ = (σ_1, ..., σ_K) 每个 σ 要么是执行段,要么是摘要段

关键点:摘要器不是外部模块,摘要 token 由同一个可训练策略采样,并被计入 RL 目标。每条 rollout 拿到一个由任务正确性决定的终局奖励 R(τ),这个奖励分配给该 rollout 的所有可训练段

一个刻意的设计选择

论文不引入单独的"摘要质量奖励"。理由:人工设计的摘要指标(覆盖率、压缩比、ROUGE 之类)未必反映"哪些细节对解题真正有用"。与其猜,不如让终局任务奖励直接告诉摘要器什么该留。

04为什么 GRPO 在这里用不了

GRPO 这类组相对方法的做法是:对每个 prompt 采一组 G 条完整 rollout,用组内奖励归一化来估计 advantage。压缩把这个假设打碎了:

所以 CompactionRL 选择 PPO + 显式 critic:基于价值函数的 advantage 估计不依赖固定大小的奖励组,天然支持数量可变的压缩段——甚至支持一个 prompt 只采一条 rollout(实验里 group size 就是 1)。

值得注意的趋势

这和近期 VC-PPO、VAPO 的结论是一条线上的:critic-free 方法在可验证奖励的短任务上很好用,但长程信用分配上 critic 依然有不可替代的价值。CompactionRL 给出了一个更强的理由——在压缩设定下,组相对基线不是"效果差一点",而是结构上无法构造。

05两个针对压缩轨迹的修正

① Token 级损失归一化

轨迹长度和摘要长度差异极大(执行段可能几千 token,摘要段两千出头)。论文用 token 级损失而非序列级损失。设 M 为一个 batch 中所有被优化的助手 token 位置:

ρ_{s,i}(θ) = π_θ(y_{s,i} | x_{s,i}) / π_θ_old(y_{s,i} | x_{s,i}) L_π = − (1/|M|) · Σ_{(s,i)∈M} min( ρ_{s,i}·Â_{s,i} , clip(ρ_{s,i}, 1−ε, 1+ε)·Â_{s,i} )

归一化分母是 token 数而不是样本数。如果按段平均,压缩事件更多的 rollout 就会贡献更大的梯度权重——哪怕两条 rollout 拿的是同一个任务奖励。token 级归一化消除了这个 segment-count 偏置,让每个可训练 token 权重相等。

② 跨轨迹 GAE(Cross-Trajectory GAE)

这是全文最精巧的一处。每个段被独立优化,意味着朴素的段级 GAE 会把共享的终局奖励放在每一段的末尾。对早期段来说,任务结果看起来比实际"近"得多——于是那些发生在任务完成很久之前的动作和摘要被过度加分。

σ_s 内的局部 GAE 照常算:

A^loc_{s,i} = Σ_{ℓ=0}^{n_s−i} (γλ)^ℓ · δ_{s,i+ℓ} δ_{s,i} = r_{s,i} + γ·V_φ(x_{s,i+1}) − V_φ(x_{s,i})

然后令 N_{>s} = Σ_{j>s} n_j 为该 rollout 中段 σ_s 之后生成的可训练 token 总数,施加一个轨迹位置修正

Â_{s,i} = (γλ)^{N_{>s}} · A^loc_{s,i}

为什么这样就对了?如果终局奖励出现在每个独立优化段的最后一个 token 上,那么修正后 token (s,i) 处的奖励项折扣是

(γλ)^{N_{>s} + n_s − i}

——这正好等于它在拼接后的完整压缩轨迹里到终局的真实距离。一行乘法,把被压缩切断的时序信用重新接了起来。

执行段 σ₁ 摘要 σ₂ 执行段 σ₃ 摘要 σ₄ 执行段 σ₅ R 一条 rollout(压缩把它切成数量不定的段,全部共享同一个终局奖励 R) N₍>1₎ = σ₁ 之后所有可训练 token 数 → σ₁ 内的 advantage 统一乘以 (γλ)^N₍>1₎ N₍>3₎ → σ₃ 的折扣更轻 越靠前的段,折扣越重 (否则每段末尾都"看起来"紧挨着任务成功,早期动作被过度加分)
跨轨迹 GAE 的直觉:每个段独立做 GAE 之后,再按"后面还有多少 token"整体打一次折扣,把被压缩边界打断的时序距离补回来。
1.0 0 rollout 起点 任务完成 终局奖励在每个 token 上的有效折扣 朴素段级 GAE:每段末尾都回到 1 跨轨迹修正后 σ₁ | σ₂ | σ₃ | σ₄ | σ₅
示意(非原文图)。红色锯齿是把每个段当独立轨迹的后果——第一段结尾处的动作被当成"马上就要成功";绿色是修正后的单调折扣,与拼接轨迹里的真实时序距离一致。

06实验设置

读表前必读:两种评测口径

Single (×1):关闭压缩,只有一个 Peak Length 窗口的预算。
Compacted (×4):允许最多 3 次压缩,有效预算 = 4 × Peak Length,但峰值工作上下文不变
这正是论文要卖的点:不加长最大窗口,只延长可用视界。

07主结果

模型峰值长度SWE-V ×1SWE-V ×4TB2.0 ×1TB2.0 ×4
公开报告 / 参考基线(脚手架可能不同,仅供参考)
GPT-5 mini (2025-08-07)400k72.031.9
Qwen3-Coder-480B-A35B-Instruct256k66.523.9
gpt-oss-120b128k62.018.7
Qwen3-Coder-30B-A3B-Instruct256k51.914.6
Qwen3.5-35B-A3B64k58.027.0
Terminus-KIRA 脚手架 · 30B 规模
GLM-4.7-Flash (30B-A3B)64k47.550.514.613.4
+ RL(不含压缩)64k50.048.016.912.4
+ CompactionRL64k43.756.016.920.2
Terminus-KIRA 脚手架 · 106B 规模
GLM-4.5-Air (106B-A30B)80k57.859.817.921.4
+ RL(不含压缩)80k58.362.520.223.6
+ CompactionRL80k57.366.821.424.5

Pass@1 (%)。注:本文所有结果(含 Qwen3.5-35B-A3B)的 SWE-bench Verified 都在随机 200 条子集上评测,公开基线则是全集,不能直接横比。

SWE-bench Verified
压缩评测 (×4)
50.5 GLM-4.7-Flash
48.0 + RL(不含压缩)
56.0 + CompactionRL
SWE-bench Verified
压缩评测 (×4)
59.8 GLM-4.5-Air
62.5 + RL(不含压缩)
66.8 + CompactionRL
Terminal-Bench 2.0
压缩评测 (×4)
13.4 GLM-4.7-Flash
12.4 + RL(不含压缩)
20.2 + CompactionRL
Terminal-Bench 2.0
压缩评测 (×4)
21.4 GLM-4.5-Air
23.6 + RL(不含压缩)
24.5 + CompactionRL
基座标准 RL(不含压缩)CompactionRL

Terminal-Bench 2.0 的条长按 2× 放大以便观察。

三条可以带走的读数:

  1. 在固定峰值上下文下,CompactionRL 的压缩推理成绩在两个 benchmark 上都是最好的。压缩感知训练确实提升了"在被压缩过的历史上继续行动"的能力。
  2. 标准 RL 的收益不迁移。它能提升单窗口执行(30B:47.5→50.0),但到了压缩推理反而掉(50.5→48.0;TB2.0 甚至 13.4→12.4)。训练时没见过压缩历史,测试时就不会用。
  3. CompactionRL 在单窗口下会掉(30B:47.5→43.7)。论文明说这是预期内的:关掉压缩就和训练设定失配,超长截断率上升。

08消融一:压缩训练与摘要训练各自贡献了什么

这张表额外加了一列 Long:用两倍大的非压缩窗口(30B 用 128k,106B 用 160k)作为"假装上下文足够长"的强参照。

系统训练预算摘要入损失SWE ×1SWE ×4SWE LongTB ×1TB ×4TB Long
30B:×1/×4 用 64k 峰值,Long 用 128k
GLM-4.7-Flash47.550.553.514.613.416.9
+ RL(不含压缩)-64k64k50.048.048.516.912.412.4
+ RL(不含压缩)-128k128k48.352.559.011.823.614.6
+ CompactionRL(不训摘要)64k×452.554.550.29.012.411.2
+ CompactionRL64k×443.756.049.016.920.216.9
106B:×1/×4 用 80k 峰值,Long 用 160k
GLM-4.5-Air57.859.859.517.921.420.8
+ RL(不含压缩)-80k80k58.362.561.820.223.621.1
+ RL(不含压缩)-160k160k63.064.564.020.823.023.6
+ CompactionRL(不训摘要)80k×454.564.561.617.621.520.2
+ CompactionRL80k×457.366.862.121.424.522.5

两点:

09消融二:两个优化修正缺一不可

系统(GLM-4.5-Air-SFT,80k×4 评测)SWE-bench VerifiedTerminal-Bench 2.0
GLM-4.5-Air59.821.4
+ CompactionRL66.824.5
− 去掉 token 级损失归一化60.0 −6.821.3 −3.2
− 去掉跨轨迹 GAE63.0 −3.822.5 −2.0

去掉 token 级损失归一化后,成绩几乎完全掉回基座水平(66.8 → 60.0,基座 59.8)——也就是说压缩训练的全部收益都被 segment-count 偏置吃掉了。这个结论有点反直觉:跨轨迹 GAE 是论文里数学上更漂亮的那个部件,但真正致命的是更朴素的那个损失权重问题。

10行为分析与训练动态

压缩行为(SWE-bench Verified,GLM-4.5-Air,80k×4)

系统压缩次数 / trace工具调用 / trace触发压缩任务上的 Pass@1
GLM-4.5-Air-SFT0.4783.435.4
RL-80k(不含压缩)0.2148.229.0
RL-160k(不含压缩)0.2663.545.9
CompactionRL(不训摘要)0.5890.842.4
CompactionRL0.3660.747.7

这张表比主表更有信息量。CompactionRL 的压缩次数(0.36)和工具调用数(60.7)都比基座和"不训摘要"变体低,但比不含压缩的 RL 高。也就是说:

训练动态(原文 Figure 4)

11局限(论文自述)


12值得带走的三点

  1. "压缩是一个动作,不是一个工具"这个视角切换,是本文的全部价值所在。 Table 1 那 6.5 个点的先导实验先把问题立住:摘要器决定成败。剩下的工作都是在回答"那怎么训它"。不引入人造摘要奖励、只用终局任务奖励反传,是个克制而正确的选择。
  2. 压缩把 RL 的数据结构改了,算法必须跟着改。 一条 rollout 变成数量不定的段,直接导致组相对方法失效(→ 回到 PPO + critic,group size = 1)、序列级损失产生 segment-count 偏置(→ token 级归一化)、段级 GAE 错置终局奖励(→ (γλ)^{N>s} 修正)。这三处改动是同一个根因的三个推论,很干净。
  3. 消融告诉你哪个部件真正在挑担子。 去掉 token 级损失归一化,66.8 掉到 60.0——基本回到起点。工程上如果只能实现一件事,先把损失归一化做对,再去做那个更漂亮的跨轨迹折扣。
和相邻工作的关系

SUPO 把摘要式上下文管理引入多轮 RL 并与工具使用联合优化;ReSum 用周期性外部摘要工具 + 分段轨迹训练摘要条件化 agent;Context-Folding 把上下文管理建模成可 RL 训练的 branch-and-fold 技能。CompactionRL 的差异点在于:面向长程编码 agent,把执行段与压缩段放在同一个 PPO 目标下联合训练,并明确处理了压缩带来的损失权重与跨段信用分配问题。

另外值得注意:本文 group size = 1 的设定,和单轨迹异步优化(SAO)那条线是同一个方向上的两种解法——前者靠 critic,后者靠改进的重要性采样与价值模型工程。两篇都在说同一件事:长程 agentic RL 里,"组"这个结构越来越难维持了。


← 全部解读