05 / Agentic Post-Training研究

Rollout 系统:从任务到一次策略更新

旗舰导读 · Worker、队列、长轨迹、策略滞后与故障恢复。

贯穿 Agentic RL 的完整数据流,深入同步/异步调度、partial trajectory、张量对齐与训练恢复。

READ WITH A QUESTION

读完这一章,你应该能够

  • 追踪一条轨迹从任务到训练张量的全过程
  • 量化吞吐、队列和策略滞后的权衡
  • 设计可恢复的多轮 rollout 数据接口
前置理解 Agent 的组成边界 · 推理 RL 中的优势与概率比 · 异步 Python 基础
本章目录 · 0 个小节

一张 GPU 利用率图无法解释整个训练系统

假设 trainer 更新一批样本只需数秒,但浏览器任务有的十秒结束,有的要数分钟。同步等待最慢轨迹会让 GPU 空闲;不断异步积累又会让轨迹过期。Agentic RL 的核心系统问题,是在任务完成速度不同、资源类型不同、策略持续变化时,仍然产生可用于学习的数据。

课程分析:目标不应只是每秒生成 token,而是固定资源下,每小时进入训练的有效信息,以及独立任务成功率的提升。若提高并发只增加超时、重复任务和陈旧样本,表面吞吐提升并没有变成训练收益。

一条任务的完整生命周期

CODE / 可复制
Task:任务版本、难度、种子与预算
Harness:system prompt、工具 schema、上下文
Policy inference:token、log-prob、policy version
Tool call:解析动作、校验参数
Environment execution:执行、异常、资源计量
Observation:状态投影,返回 Harness 并继续下一动作
Terminal state:成功、失败、截断或基础设施异常
Grader / verifier:独立验证与证据
Reward:分项分数与聚合规则
Trajectory storage:内容寻址、版本与完整性
Training batch:分组、mask、old/reference log-prob
Policy update:loss、梯度、checkpoint 与权重同步

这是一张有反馈环的图:观察回到 Harness 继续行动,策略更新后权重发布到 inference worker。一次轨迹可以包含多次模型推理和环境动作,不应把一次 API 请求等同于一个 RL 样本。

四类 Worker,各自拥有什么

Worker主要工作瓶颈与必留记录
Rollout / harness worker管理任务状态机、解析调用、串联观察并发、内存、每轮事件与任务 id
Inference workerprefill、decode、log-prob 与权重版本GPU、KV cache、请求队列、采样参数
Environment worker终端/浏览器/编译器等动作执行CPU、RAM、磁盘、进程/容器限制
Trainer worker前向重算、优势、loss、反向和优化GPU、通信、有效 token、更新版本

Grader 可以独立服务,也可与环境或 rollout 侧部署,但权限和数据边界仍应清晰。Reference、reward model、critic 是否需要独立模型取决于算法;GRPO 不要求独立 critic,不意味着整个系统只有一份模型权重。

真实源码:沿着 verl 的调用链走一次

固定版本为 8e03c039f9a70750490c93196b759b332fc029fd。打开 verl/experimental/agent_loop/agent_loop.py,从 AgentLoopManager.generate_sequences 开始:将 DataProto 输入分块,通过 Ray worker 并发生成,再拼接输出。接着读 AgentLoopWorker.generate_sequences → _run_agent_loop → AgentLoopBase.run,最后回到后处理。固定源码

源码观察:AgentLoopOutput 定义 prompt_ids、response_ids、response_mask、可选 response_logprobs、reward_score、轮数与性能指标。response_ids 包含模型生成 token 和工具观察;mask 才区分哪些属于策略动作。后处理将其 padding 并组装成批张量。字段依据

由此得到一个重要不变量:token ids、log-prob、mask、position ids、模态输入和版本元数据必须描述同一段序列。多轮 chat template 重新编码可能改变边界,不能靠字符串长度猜 token mask。工具输出可参与 attention,却不能直接当作模型采样动作计算策略梯度。

数据对象概念形状检查点
prompt / response token ids[B,P] / [B,T]padding 方向、截断和模板
response mask[B,T]动作=1,观察/padding=0
behavior / old / current log-prob[B,T]条件前缀、版本、采样分布语义
group id[B]同任务候选属于同组
reward / advantage[B] 或 [B,T]终态奖励与 token 广播规则

这些形状是课程对接口的概念说明,真实 DataProto 同时包含 tensor 与非 tensor 字段。算法端可继续读 compute_grpo_outcome_advantage,把任务组与 mask 映射到优势。算法源码

同步与异步,改变的不只是速度

同步路径通常是采样一批、等待终止与评分、更新、同步权重。容易确认样本版本,但受到长尾轨迹阻塞。异步路径让 rollout 持续生产、trainer 持续消费,可在生成与训练分离的 GPU 池运行,也可在共享池中调度。代价是样本来自不同策略版本,任务筛选顺序也改变。

verl 在本次查阅的 V1 文档中区分 sync、colocate_async、separate_async;其 partial rollout 会保留已生成前缀和 log-prob,恢复时可能用新版本继续,因此一条轨迹可跨多个版本。文档同时区分轨迹内部版本跨度及其相对 trainer 的陈旧程度。已固定版本的文档

课程分析:不要把“最多滞后两轮”当成算法保证。两次很小更新与两次大更新的分布距离可能完全不同。版本差适合快速过滤,实际还应看概率比尾部、clip 比例、KL 估计和有效样本量。

ESS=(∑iwi)2∑iwi2,wi≥0.\mathrm{ESS}=\frac{(\sum_i w_i)^2}{\sum_i w_i^2},\qquad w_i\ge0.

这是权重集中程度指标,不能单独证明重要性采样无偏。丢弃 stale trajectory 还可能偏向短任务:难题完成慢,因此更易过期。按难度和轨迹长度报告拒收率,避免训练集悄悄变成容易任务集。

Partial trajectory:保留前缀不等于保留全部状态

恢复需要两种状态:语言前缀和真实环境状态。语言 KV cache 可以重建,但浏览器会话、文件修改和后台进程不一定能重放。若工具动作已执行、观察还没写入轨迹,重试可能重复执行有副作用动作。

课程分析:建议使用 episode_id + step_id + action_id 做事件幂等键,分别记录动作提交、执行确认、观察持久化。恢复时先核查动作是否已生效。只有 token 前缀而没有环境快照的 partial trajectory,不能被称为可完整恢复。

若同一轨迹跨版本采样,至少保留每个动作段的行为版本和 log-prob。把整条轨迹标成最后版本,会错误描述早期动作的采样分布。实验性的经验复用要说明支持条件、截断或权重策略,不能默认视为 on-policy。

吞吐失衡与资源调度

令有效轨迹到达率为 λ\lambda,trainer 消费能力为 μ\mu。在持续 λ>μ\lambda>\mu 时,队列积压和策略滞后不断增加;持续 λ<μ\lambda<\mu 则 trainer 饥饿。系统稳定时,Little 定律给出平均队列内数量与平均停留时间的关系 L=λWL=\lambda W,但它不替代对非平稳 RL 的实际测量。

课程分析:动态 batching 应同时考虑 token 预算、KV 容量、请求年龄和环境等待。长短请求混合可能提高总体利用率,也可能让长轨迹长期得不到服务。至少画出队列年龄 p50/p95、每阶段等待时间、有效 token 吞吐、CPU 环境利用率与 timeout 分布。

GPU 池大小不应固定为“训练一半、生成一半”。复杂环境可能是 CPU 或外部服务限速;长上下文可能卡在 prefill;长回答可能卡在 decode。测量瓶颈后再调资源比例,并把权重广播、模型切换和 KV 重建时间计入成本。

失败重试、存储与 checkpoint

轨迹存储建议追加事件、最终封存,记录 task、policy、harness、environment、grader 五个版本。缺少任一版本都会削弱复现实验的能力。奖励为空与奖励为零应是不同状态,基础设施失败也不应默认为策略失败。

checkpoint 不只保存权重:还要包含优化器、scheduler、随机状态、数据游标以及队列恢复策略。对于在途任务,可以保存后恢复,也可以明确放弃并重发;两者都应防止重复消费、丢失任务和版本错配。verl 的异步文档描述了对待处理任务与已完成轨迹采用不同恢复方式的处理,具体策略应以所选版本为准。恢复接口说明

可运行调度实验

CODE / 可复制
python3 -m labs.run --experiment rollout --seed 7

本站实验使用离散事件模拟,比较同步等待与异步消费,计算版本滞后和拒收。它没有启动 Ray、GPU、vLLM 或容器,因此测得的是给定任务时长分布下的调度行为,不是硬件 benchmark。预期同步与异步在耗时、接受样本数或 lag 指标上出现差异;异步不保证在所有配置下获胜。

工程任务:增加一组耗时为普通任务十倍的任务,逐步改变最大允许 lag。报告总完成数、训练接收数、长任务拒收率和 trainer 空闲比例。然后写出轨迹 schema 与两条故障恢复用例:工具执行后 worker 崩溃;权重同步中 trainer 崩溃。通过这些用例后,再将模拟器中的角色映射到真实集群服务。

MAKE IT RUN

把这一章放进实验里

调整变量,观察机制,再运行本地 Python 实验验证。

进入实验

本章证据与源码

引用代表相应来源支持的结论,不意味着公开了完整训练配方。

源码观察verl:多轮 Agent rollout 的标准化接口volcengine · 8e03c039f9a7源码观察verl V1 Async Trainerverl-project · 8e03c039f9a7源码观察verl:GRPO 组内优势与 PPO clipped lossvolcengine · 8e03c039f9a7源码观察SWE-agent:Harness 的 step 与 run 边界SWE-agent · 3ea751c087f3

留下你的工程判断

记录一个还没有解释清楚的现象,或下一次实验要控制的变量。笔记仅保存在当前浏览器。

自动保存在本机 · 可在“我的学习笔记”导出
理解机制,比记住结论更重要。