当前位置: 首页 > news >正文

【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (5)--- 异步处理

【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (5)--- 异步处理

目录
  • 【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (5)--- 异步处理
    • 0x00 概要
    • 0x01 异步架构
    • 0x02 训推分离
      • 2.1 为什么训练和推理通常分离?
        • 2.1.1 内存布局根本冲突
        • 2.1.2 计算特性完全相反
        • 2.1.3 RL特有的权重同步问题
        • 2.1.4 工程复杂度爆炸
        • 2.1.5 小结
      • 2.2 Agentic RL的三个分布
        • 2.2.1 第一层分歧
          • 原因A:异步更新(权重同步延迟)
          • 原因B:队列/Buffer的时间延迟
          • 原因C: Filtering改变分布
          • 原因D:PRM打分的异步延迟
          • 原因E:多步 Episode 的时间跨度
          • 原因F: 轨迹时长不均
        • 2.2.2 第二层分歧
          • 原因A:探索 vs 利用的采样差异
          • 原因B:用户行为随时间变化
          • 原因C:Agentic特有的状态分布循环依赖
        • 2.2.3 第三层分歧
        • 2.2.4 拓展
          • 漂移的数学影响
          • 为什么在AgenticRL中比单轮RL更严重
          • 漂移的不均匀性是最大问题
        • 2.2.5 小结
      • 2.3 OpenClaw-RL 如何处理三层分布分歧
        • 2.3.1 第一层
          • 处理机制 1: Weight Sync 期间的 503 Pause
          • 处理机制2:PPO Clip(隐式IS修正)
          • 处理机制3:监控指标
        • 2.3.2 第二层
          • 离线RLHF(InstructGPT)
          • OpenClaw
        • 2.3.3 第三层
        • 2.3.4 三层分歧的处理总结
    • 0x03 调度策略
      • 3.1 异步需求
      • 3.2 "仍然有学习价值"的边界在哪里
      • 3.3 调度策略是算法的一部分
        • 3.3.1 示例 1:Windowed FIFO
        • 3.3.2 示例 2:TITO(Train In Train Out)
        • 3.3.3 示例 3:Stale Sample 过滤阈值
        • 3.3.4 示例4:Decoupled PPO Objective
        • 统一理解
      • 3.4 OpenClaw的调度策略
      • 3.5 改进建议
    • 0xFF 参考

0x00 概要

本系列的目的是:借着对 OpenClaw-RL 源码的学习,来梳理强化学习的一些相关概念和思想。所以,会有一些基础知识、扩展和发散,OpenClaw-RL 只是一个切入点。而且,因为整篇系列是一个整体,所以有些概念的解读/学习会在不同的文章中出现,还请大家谅解。

OpenClaw-RL 是一个用于在线强化学习(Online RL)的框架,专门针对智能体工具使用场景。它通过从环境反馈中提取过程奖励信号来训练语言模型,支持三种主要模式:

  • openclaw-rl:基于二元奖励的强化学习(Binary RL / GRPO)
  • openclaw-opd:基于后见之明提示的在线策略蒸馏(On-Policy Distillation, OPD)
  • openclaw-combine:联合方法,在同一 PPO 更新中同时利用 RL reward 和 OPD teacher signal

framework

0x01 异步架构

OpenClaw-RL 的系统设计是四个异步解耦的循环——policy serving、environment hosting、reward judging、policy training 同时运行、互不阻塞,因此模型可以一边持续服务,一边从刚刚发生的真实交互中在线学习。

组件

这四个组件以零协调开销异步运行:模型服务用户请求的同时,PRM正在评判上一轮交互,训练器同步更新策略------ 三者互不等待。这一设计使得从实时、异构的交互流中进行连续训练成为可行,无需任何流被暂停或批处理来配合其他组件。

在这种模块化设计中,各组件既保持功能独立性又实现数据互通。即,其总体是异步进行的,具体如下:

时间轴 (完全异步, 各组件不相互阻塞):----------------------------- Policy Serving ---------------------------------SGLang:    服务用户 ─────────────────── 暂停(503) ─ 加载新权重 ─ 服务用户 ──►Proxy:     采集数据 ─────────────────── 暂停 ─────── 恢复 ───── 采集数据 ──►----------------------------- Reward Judging ---------------------------------    PRM:       评分 ───── 评分 ───── 评分 ─────────────────────── 评分 ───── 评分 ──►----------------------------- Policy Training---------------------------------    Megatron:  ─ 等待数据 ───────────── 训练 ─ 同步 ─ 等待数据 ─── 训练 ─────────►

系统通过完全异步的设计实现四大核心优势:

  1. 服务连续性保障:策略服务与训练过程解耦,确保7×24小时无中断服务。通过双缓冲机制实现模型热切换,权重更新期间仍可维持原有策略响应。
  2. 实时学习能力:环境反馈与评估结果通过消息队列实时传输,训练模块可立即消化最新交互数据。系统支持每秒百次级的模型参数更新,实现真正意义上的在线学习。
  3. 长周期任务处理:针对软件工程等复杂任务,采用异步环境管理策略。不同任务轨迹可独立推进,通过工作流引擎协调依赖关系,有效缓解长尾延迟问题。
  4. 个性化适应机制:通过会话感知技术区分训练轮次与转发轮次,在保证用户体验的同时积累个性化数据。系统动态调整探索-利用平衡参数,实现用户偏好与模型能力的协同进化。

0x02 训推分离

因为异步架构和训推分离是一体两面,所以我们先介绍训推分离。

同步RL的理想情形(无漂移)是on-policy,即:

时刻 t:1. rollout:使用π_t生成N条样本2. update: 用这N条样本更新  →  得到π_{t+1}3. rollout:使用π_{t+1}生成下一批...即,Policy π_θ  →  生成轨迹  →  立刻更新T_θ  →  重复

每批训练数据100%来自当前policy → 完全on-policy,即生成数据时的 policy = 更新时的 policy = on-policy → 理论保证:importance weight = 1,无需修正。

ratio = π_{t+1}(a|s)/π_t(a|s) = 1(刚更新一步,变化很小)

然而,实际上这是理想情况。

2.1 为什么训练和推理通常分离?

2.1.1 内存布局根本冲突

训练和推理同时在同一块 GPU 上高效运行,物理上就冲突——KV cache 和优化器状态争同一显存。

训练引擎(FSDP/Megatron) 推理引擎(vLLM/SGLang)
显存用途:参数 + 梯度 + 优化器状态(约 4x 参数大小) KV Cache(约 2x 参数大小)
分片方式:ZeRO 参数分片(跨 GPU 不连续) 每卡完整参数(连续 + 量化)
Attention:PyTorch Flash Attention PagedAttention
批处理:固定 batch(padding 对齐) Continuous batching(动态)

由于前向传播占用的显存小于反向传播,所以一般一个 step会首先 rollout 大量的轨迹,然后分批次进行梯度优化。

2.1.2 计算特性完全相反

  • 训练:计算密集(矩阵乘法,GPU利用率高),延迟不敏感
  • 推理:内存带宽密集(每token读权重),延迟极敏感

混合运行会让两者都变慢。

2.1.3 RL特有的权重同步问题

推理(rollout) → 收集数据 → 训练(更新权重) → 推理用新权重 → ...

如果训练和推理在同一进程,参数更新期间无法同时做推理。虽然可以用xccl广播把新权重从Megatron传到 SGLang,但是,这本身就是跨引擎同步,不是同框架内的操作。

比如:

GPU 0-3(Megatron)更新后 → 同步到GPU 4-5(SGLang)同步期间(几十秒到几分钟): →  在途的rollout用的是旧weights  →  同步完成前所有新对话都是off-policy

2.1.4 工程复杂度爆炸

维护一个同时优化 FlashAttention、PagedAttention、ZeRO-3、梯度 checkpoint 的框架,代码复杂度是各自独立的 5-10 倍。因此,主要框架选择了各自专精:

框架 策略
OpenRLHF 彻底分离:Actor(vLLM) + Trainer(DeepSpeed)
VeRL "混合引擎"(同卡串行切换,不是真并行)
AReaL 异步解耦:SGLang 推理 + FSDP 训练,用 xccl 同步权重
TRL 简单 PPO,训练和推理共用 HF 权重(效率最低)

2.1.5 小结

因此,在第 2 个批次及以后,所优化的轨迹都不是那个 model 自己生成的,而是上一个 step 的 model 生成的,这就引入了 off-policy。另外,在 partial rollout 中,一条轨迹可能来自不同的 model,就更加加剧了这个问题。

2.2 Agentic RL的三个分布

在Agentic RL中,有三个分布:

  • π_rollout:采样时的策略分布(策略模型产生训练数据的policy)
  • π_learner:更新时见到的样本分布(learner实际梯度计算用的数据)
  • π_deploy:最终部署时系统实际执行的策略分布(真实环境下policy的行为)

一致的理想情形:完全on-policy + 训练分布 = 部署分布。然而,这三个分布几乎不可能天然一致。

三层分歧的汇总如下:

生成数据                  处理数据              真实服务
π_rollout    ────►      π_learner      ────►  π_deploy↑                      ↑                    ↑
异步更新Gap          Filter + Buffer Gap       探索/利用+分布漂移Gap
k步policy差异        训练分布被人为塑造           用户分布随时间变化PPO clip约束          ?(通常无显式约束)          通常完全不处理

以下,我们会结合OpenClaw-RL 逐层分析为何这几乎不可能。

2.2.1 第一层分歧

第一层分歧:π_rollout ≠ π_learner(Off-Policy Gap)

原因A:异步更新(权重同步延迟)
时刻t:  rollout生成样本(s_0,a_0,...,s_T)使用`π_θ_t`
时刻t+k:learner处理这批样本,更新π_θ_{t+k}π_θ_{t+k} ≠ π_θ_t(中间已经k步更新了)
importance ratio = π_{t+k}(a|s)/π_t(a|s) ≠ 1

在单轮RL里:

  • k很小(一次更新周期)。

在Agentic RL里:

  • 一个episode跑T=20步,在此期间其他worker可能更新了policy
  • step 1的数据用的是π_t,step 20的数据已经是π_{t+20}的环境下生成的

比如(Weight Sync 窗口):

  • 权重同步期间(503 阻断了新的 rollout): → 但已在队列里的样本是同步之前生成的

  • 同步完成后(SGLang 有了新的权重):
    → learner 还在处理同步前的旧样本 → 旧样本的 rollout_log_probs 来自"旧权重的 SGLang"
    → 当前 policy 是"新权重的 Megatron" → ratio 在 weight sync 边界处跳跃

ratio 时间线(示意):

-------------------------[weight sync]-------------------
ratio: 1.0, 1.1, 0.9, 1.2, ... | 1.8, 1.5, 2.1, ...↑ sync 后 ratio 突然变大
原因B:队列/Buffer的时间延迟

OpenClaw具体情况:

  • 轮次N的response进入queue → 等待PRM打分(异步)
  • 在此期间,其他样本继续训练 → policy继续更新
  • PRM打完分,样本进入训练 → 这时policy已经是π_{N+k}
  • policy用π_{N+k}π_N生成的数据上更新 → off-policy

即,系统架构决定了异步性:

rollout worker ────►  buffer/queue   ────►    learner
(连续产生数据)          (样本等待处理)         (继续更新policy)

样本在buffer里等待期间:

  • learner继续更新policy
  • policy从π_t变成了π_{t+k}

当样本被learner取出时:

  • 样本的log_prob是π_t计算的
  • gradient更新的是π_{t+k}
  • ratio=π_{t+k}(a|s)/π_t(a|s) ← 不再 ≈ 1

即使在“同步“系统里:

  • rollout进入queue → 等待learner → 处理时policy已更新
  • queue depth x 更新频率 = staleness
原因C: Filtering改变分布

OPD只保留hint-accepted的样本:

  • → learner看到的分布 = “模型回复较差、有改进空间的那些turn"
  • ⇆ rollout原始分布(所有turn)

Binary RL的at-least-one:

  • → 强制把某些score = 0的样本变成mask = 1
  • → learner见到的有效样本分布被人为调整
原因D:PRM打分的异步延迟
Turn 产生  →  _fire_prm_scoring(异步发出 3 个 judge 请求)↓ 等待 5-30 秒(judge LLM 推理时间)↓ 期间:其他 turn 继续进入 learner
PRM 返回  →  样本进入队列  →  被 learner 处理

样本的 rollout_log_probs 是 5-30 秒前的 policy 计算的,policy 在这 5-30 秒内可能已经更新了若干步

原因E:多步 Episode 的时间跨度

假设每步 2 秒,T=20 步的 episode:

step 1 生成于 t=0, rollout_lp 来自 π_{t=0}
step 20 生成于 t=40s

这 40 秒内如果 learner 更新了 k 步: step 1 的样本被 π_{t=0+40s+training_time} 处理,π 已经变了很多

漂移量 ≈ f(episode_length × step_time × learner_speed)

原因F: 轨迹时长不均

还有一种情况是 轨迹时长不均,比如:Task A: 2秒 Task B:30分钟 Task C:10秒。

如果等所有任务完成再更新: → Task A在 policy v1 时生成,等待时变成 stale → 等 Task B完成,TaskA已经是30分钟前的数据 → 如果不等Task B,则TaskB贡献的梯度在下一轮更新才进来

2.2.2 第二层分歧

第二层分歧:π_rollout ⇆ π_deploy(协变量偏移)

原因A:探索 vs 利用的采样差异

rollout(训练时):

  • temperature = T_high,随机采样 → 生成多样化的响应,探索更广的路径 → 分布更宽、更均匀

deploy(部署时):

  • temperature = T_low(或top-p),更确定性 → 给用户最好的那条路径 → 分布更尖锐、集中在高概率区域

  • D_KL(π_deploy || π_rollout)>0 :用高temperature的数据训练,要使用 low temperature的推理 → 分布不一致

原因B:用户行为随时间变化

训练数据收集时:用户问A类问题。

三个月后部署:用户问B类问题(新需求、新话题、模型能力提升导致用户问更难的)

  • π_rollout在旧的状态分布D_old上采样
  • π_deploy 面对新的状态分布D_new
  • D_new ⇆ D_old → 分布偏移
原因C:Agentic特有的状态分布循环依赖

π_t 决定采样哪些trajectories → trajectories决定遇到哪些states → states的分布影响下一步的 action distribution → action distribution又影响π_{t+1}的训练方向

这是一个循环:

state_distribution = f(policy)policy=f(state_distribution)

当policy更新后,状态分布也会变化 → rollout时的状态分布和deploy时的状态分布持续偏移 → 单轮RL没有这个问题(状态=用户的prompt,不依赖policy)

2.2.3 第三层分歧

第三层分歧:π_learner ⇆ π_deploy(优化目标错位)

  • π_learner优化的是:reward信号所定义的"好“
  • π_deploy面对的是:真实用户的"有用“

当reward真实用户价值时:模型学会了“让judge打高分的技巧“,而不是“真正帮助用户的能力“

具体来说,以下二者不同:

  • learner分布 = “被judge filter后的数据"(有偏)
  • deploy分布 = “所有真实用户请求"(无偏)

2.2.4 拓展

漂移的数学影响

PPO clip假设:ratio∈[1-e,1+e]

  • 正常情况:

    ratio ≈ 1  →  梯度完整保留
    
  • 漂移情况:

    ratio=2.5(新policy更倾向于这个action)  →  min(2.5*A,1.28*A)=1.28*A  →  被clip,损失了49%的梯度信号ratio=0.3(新policy不太倾向于这个action)  → min(0.3*A,0.8*A)=0.3*A   →  低梯度,但方向可能是错的
    

漂移越大 → 被clip的样本越多 → 有效梯度越弱 → 需要更多样本才能达到同样的学习效果。

为什么在AgenticRL中比单轮RL更严重

单轮RL:每条样本 = 1个动作 → 更新 → 立即部署。三个分布分歧最小

AgenticRL:每个 episode=T个动作,T步期间policy可能更新多次(gap ∝ T),环境响应policy 的状态分布循环依赖 → 三个分布分歧随episode长度放大

漂移的不均匀性是最大问题

同一个训练batch里:

  • 样本A:5分钟前生成,ratio=1.1 (新鲜,漂移小)
  • 样本B:30分钟前生成,ratio=3.2 (陈旧,漂移大,被clip)
  • 样本C:2分钟前生成,ratio=0.95 (非常新鲜)

问题:不同样本的漂移程度不同 → 每个样本对梯度的贡献比例不同 → 批次内的有效学习率实际上是不均匀的 → 训练方差增大,不稳定

2.2.5 小结

三个分布不一致是 Agentic RL 的结构性问题,而非工程缺陷:

  • 异步训练把 rollout 和 learner 分开,filter 和 buffer 进一步改变 learner 分布,探索/利用差异和用户行为漂移让 deploy 分布独立演化。
  • 单轮 RL 中这些分歧很小;但是,Agentic RL 中,它们随 episode 长度放大,成为训练不稳定的核心来源。PPO clip 只约束了 rollout-learner 的第一层分歧,后两层几乎没有系统性防护。

2.3 OpenClaw-RL 如何处理三层分布分歧

2.3.1 第一层

π_rollout ≠ π_learner(Off-Policy Gap)

处理机制 1: Weight Sync 期间的 503 Pause

在 503 pause 期间,权重同步时暂停 rollout,防止产生更多 off-policy 数据。

# openclaw_api_server.py
# 权重同步时暂停 rollout,防止产生更多 off-policy 数据
if not self.submission_enabled.is_set():raise HTTPException(status_code=503, detail="submission paused for weight update")

虽然做了处理,但是并不能完全消除问题,比如,在 Megatron更新完权重 → 同步到SGLang(几十秒到几分钟)这期间:

  • √ rollout被503阻断 → 不产生新的off-policy数据 → 减少了weight sync边界的大规模漂移
  • ✗同步完成前已在队列里的样本 → 仍然off-policy(无法消除)
  • ✗样本没有staleness字段(不知道等待了多久)
  • ✗没有importance weighting(所有样本等权,不管新旧)
  • ✗没有自动丢弃“太旧“的样本(ARLArena的OPSM思路)
  • ✗weight sync边界的ratio跳跃没有特殊处理
处理机制2:PPO Clip(隐式IS修正)
# ppo_utils.py (slime/utils/ppo_utils.py:125-148)
ratio = (-ppo_kl).exp()          # ppo_kl 是负的 log-ratio,取负再 exp 得到 π_θ/π_old
pg_loss = -torch.maximum(        # 注意是 torch.maximum(非 torch.min),因为前有负号ratio * advantages,torch.clamp(ratio, 1 - eps_clip, 1 + eps_clip_high) * advantages
)
  • eps_clip / eps_clip_high: 分别控制下/上裁剪阈值,允许非对称 clip(典型值 0.2 / 0.28)
  • 超出 [1-eps_clip, 1+eps_clip_high] 范围的 ratio 被截断 → 防止极端 off-policy 样本主导梯度
处理机制3:监控指标

train_rollout_logprob_abs_diff 会监控漂移量

#Slime 内置
train_rollout_logprob_abs_diff #实时监控 rollout-learner gap
#如果这个值快速上升,说明off-policy问题加重

2.3.2 第二层

第二层:π_rollout ≠ π_deploy(协变量偏移)

OpenClaw的根本优势:在线学习使这层分歧几乎消失

离线RLHF(InstructGPT)
数据收集      →       RM训练       →        PPO训练      →        部署↑                                                            ↑
这是几周前用户的行为分布                                    这是现在用户的行为分布

二者已经不同

OpenClaw
用户    →     直接与SGLang交互   →     数据同时用于训练 
↑                                       ↑
rollout分布                           = 部署分布(同一个系统!)

具体细节如下:

# openclaw_api_server.py:rollout就是服务,服务就是rollout
# 没有单独的rollout服务器 vs 部署服务器的区别
async def _handle_request(self, body: dict[str, Any]):# 同时做两件事:# 1. 服务用户:SGLang 调用是内联的(非 _forward_to_sglang 方法)# 2. 产生训练数据self._fire_prm_scoring(session_id, ...)

残余风险(无显式处理):用户看到模型改进后会提更难的问题 → 逐渐的分布漂移 → OpenClaw 无特殊机制,依赖持续在线学习自然适应。

2.3.3 第三层

第三层:π_learner ≠ T_deploy(优化目标错位)

处理机制:Reward信号直接来自真实用户行为

# _build_prm_judge_prompt:binary reward judge 评估的是"用户实际怎么反应"
# 注意:OPD 流程中使用的是 _build_hint_judge_messages(非此函数)
# 参考 openclaw-opd/openclaw_opd_api_server.py:71
def _build_prm_judge_prompt(response_text, next_state_text, next_state_role):# judge 看的是:#   response_text=模型回复#   next_state_text=用户下一句话(真实行为)# judge 评估的本质问题:#   "根据用户的下一句话,这条回复有没有真正帮到他?"

这是 OpenClaw 最重要的设计决策之一:奖励信号不是人工构造的 proxy,而是从真实用户行为推断的。

对比:

  • RLHF: reward = "这条回复比那条回复更好" (偏好对,离真实使用有距离)
  • OpenClaw: reward ≈ "这条回复之后,用户继续了有意义的对话" (直接连接真实价值)

残余风险: judge 仍然是 LLM, 不是真实用户满意度的完美代理 → 模型可能学会"让 judge 觉得有帮助"而非真正帮到用户

2.3.4 三层分歧的处理总结

分歧来源 OpenClaw 处理方式 剩余风险
层1: 异步更新. gap Filter 改变分布 503 pause + PPO clip 训练时知道哪些被 filter 了 同步窗口内积压样本 filter 偏差不可消除
层2: 训练/部署环境不同 探索/利用差异 在线学习: rollout = deploy real-time 数据天然 on-distribution 用户行为渐进漂移
层3: reward ≠ 真实价值 next_state 作为真实用户信号 judge 仍是近似

结论: OpenClaw 通过:

  • 在线架构几乎完全解决了第二层

  • 通过 503 pause + PPO clip 部分控制了第一层。异步off-policy漂移 = 样本生成时刻和参数更新时刻之间的policy差异,是分布式RL系统的结构性问题。它在Agentic RL里因episode长度而放大,PPO clip 只能约束但不能消除它。

  • 第三层通过 next_state设计大幅缩小,但未完全消除。

这三层分歧在 OpenClaw 里远比传统 offline Agentic RL 框架要小。

0x03 调度策略

Agentic RL 里的on-policy是一个程度问题,而非二元问题,不是“on or off",而是"drift有多大“。

这种不可避免的异步性带来了一个范式转换:

  • 旧问题:“怎么保持on-policy?“
  • 新问题:“多大的偏移还有学习价值?偏移控制在什么范围内训练不会崩?
  • 这是一个完全不同的优化目标:
    • 不是 minimize(off-policy drift),而是 find(drift range where learning signal is still valid)
    • 不是保持on-policy,而是让漂移保持在可学习范围内 → 承认off-policy 是不可避免的 → 把“控制偏移程度“作为核心优化目标

也导致了调度策略必然是算法一部分。

  • 传统RL算法 = 损失函数 + 更新规则
  • Agentic RL算法 = 损失函数 + 更新规则 + 调度策略 (三者缺一不可)

没有调度策略的Agentic RL算法是不完整的规范。

3.1 异步需求

为什么需要 Async RL?同步 RL 的问题:等最长输出完成 → GPU 大量空闲。比如,AIME24 上,同步训练需 41 小时,异步只需 14.8小时 (2.77x 加速),性能完全持平。

举例两个核心挑战。

挑战 1: 数据陈旧性 (Staleness)

训练轮次: v1  →  v2  →  v3  →  v4 (当前)收集轨迹:用 v1 生成的  →  用 v2 生成的  →  on the fly...↑ training 看到的是旧数据

挑战 2: 同一轨迹由多个策略版本生成

LLM 生成 token 序列时被打断 (weight update):token 1-50: 由 v2 生成token 51-100: 由 v3 生成 (weight 更新了)token 101-150: 由 v4 生成

而PPO 假设同一策略生成整条轨迹。

3.2 "仍然有学习价值"的边界在哪里

学习信号失效的三种失效情况:

① Importance Weight 极端化

P_new(t) / P_old(t) >> 1 或 << 1  →  IS修正不稳定,梯度方向噪声极大  →  PPO c1ip阻止这种极端化(这就是ε=0.2/0.28的作用) 

② Advantage符号翻转

"那时候policy 认为好的轨迹,现在的 policy 根本不会走这条路"  →  用旧轨迹的reward 更新新policy,方向反了  →  Stale Sample Filtering 可以阻止这种情况(丢弃超过T步的样本)

③ 分布漂移超出任何IS修正的能力

两个 policy 的 KL太大  →  即使有重要性权重也无法有效校正  →  这时候off-policy 修正 = 病态问题  →  KL 约束或policy约束作为上界

3.3 调度策略是算法的一部分

关键洞察:调度决策直接决定 learner 实际在优化什么分布。我们来看看几种调度算法。

3.3.1 示例 1:Windowed FIFO

严格 FIFO:learner 总是看最老的已完成任务

  • 效果:训练分布=轨迹提交时间的分布
  • 问题:长任务总是等太久才进入训练(慢任务=老数据=更陈旧)

贪心 Async:谁先完成谁先训练

  • 效果:训练分布=按任务完成速度加权
  • 问题:快任务(简单任务)在训练集中被over-represent,模型越来越擅长简单任务,越来越少见到困难任务的轨迹

Windowed FIFO(窗口W):窗口内的已完成任务可以先训练

  • 效果:在“时间局部公平“和“吞吐“之间折中

窗口大小W = 一个算法参数,不是工程参数:

  • W大 → 接近贪心Async → 简单任务over-represent
  • W小 → 接近严格FIFO → 慢任务惩罚大
  • W的选择 = 隐式地选择了训练分布的偏置方向

3.3.2 示例 2:TITO(Train In Train Out)

  • 传统做法:Rollout 产生文本→重新 Tokenize → 喂给 Trainer

  • TITO做法:Rollout产生tokens→直接喂给Trainer(不重新分词)

区别在哪里?重新 Tokenize:可能因为 tokenizer 版本差异产生细微不同→ Trainer 优化的 action 和 Rollout 实际采样的 action 不完全对应 → 梯度的方向≠真正应该更新的方向

TITO是“系统设计”,但它改变的是“梯度到底在优化什么“ → 这是算法问题,只是伪装成了工程问题

3.3.3 示例 3:Stale Sample 过滤阈值

丢弃超过T步前生成的样本

  • T大:更多历史样本进入训练→off-policy drift 更大 →可能 Is 不稳定
  • T小:只用新鲜样本→drift小→但吞吐低,样本效率差

T 的选择 = 定义了"可接受的off-policy范围" = 定义了 policy更新的有效覆盖范围 = 定义了 rollout和learner允许的分布偏移上界。这不是“丢弃多少数据的工程问题”,而是“给这个算法设定正确运行的条件” 。

比如,解决方案: Staleness Control (max_head_off policyness = η)。

η = 0: 退化为同步 RL (最慢,最准确)
η = 1: 允许 1 步 off-policy (one-step overlap, 业界常用)
η = 2-8: AReaL 推荐值,速度 / 质量平衡

当积累轨迹数量 / 陈旧程度超过 η 时,gateway 返回 HTTP 429 — 这就是限流机制的根源。

3.3.4 示例4:Decoupled PPO Objective

解决方案: Decoupled PPO Objective (三策略解耦)

标准 PPO 只有两个策略 (old/new), Decoupled PPO 引入三个:

# π_behave ← 实际采样时的策略版本 (可能很旧)
# π_proximal ← 比当前策略落后一步的策略 (用于稳定化)
# π_θ ← 当前正在训练的策略Loss = -min ((π_θ / π_proximal) * A, # 内层 clip, 对 π_θclip (..., 1-ε, 1+ε) * A
) * min ((π_proximal / π_behave), # 外层 clip, 处理 off-policy 程度clip (..., 1-ε, 1+ε)
)    

这样即使轨迹由不同版本策略生成,也能正确处理 importance ratio。

统一理解

统一理解:调度策略定义了以下三件事(全是算法级决策):

  • ① What samples enter training? → Stale filter+ priority rules → 决定训练分布

  • ② In what order? → Windowed vs Greedy → 决定时间局部性偏置

  • ③ At what staleness? → 从rollout生成到update的时间差 → 决定off-policy程度

这三件事合起来 = "learner实际看到的是什么世界的数据“ ,而这直接决定了policy朝什么方向更新

3.4 OpenClaw的调度策略

OpenClaw当前的“调度策略“如下(大多是隐式的):

① 进入训练的样本:score≠ 0 的turn(Judge过滤) + at-least-one guarantee(防止全零session 贡献零梯度)

② 顺序:output_queuequeue.Queue,标准线程安全队列,非 asyncio.Queue)中使用了 FIFO 顺序,先打分完成的先进入队列 → 近似"贪心Async"(快任务/短对话先完成)

③ Staleness:无显式stale filter,一个用户2小时前的对话和 2分钟前的对话在训练时同等对待

④ 最关键的隐式调度机制:503 pause(weight sync)

  • sync期间:SGLang 权重冻结→所有进行中的对话用同一批权重
  • sync后恢复:积压的对话集中完成 →形成一个"伪 on-policy batch"

④ 有趣的调度特性:

  • weight sync = 隐式的 “同步 on-policy batch 窗口“
  • sync间隔 = 控制这个窗口的时间跨度

3.5 改进建议

改进建议是把隐式调度变成显式算法组件:

① 加 staleness filter:

  • 丢弃超过 K步前生成的 session

  • K=learner更新多少次后认为样本"过期“

  • 这是明确的算法参数,而非工程值

② 按 session freshness 加权:

  • 最新的 session 在 training loss 中有更高权重

  • 类似重要性采样但用时间窗口近似

③ sync 间隔优化:

  • 当前 sync 间隔可能是固定的

  • 应该根据 queue depth 和 staleness 动态调整→让“伪on-policy窗口“的大小受控

TransFormer-封面

0xFF 参考

【论文学习】Stabilizing Reinforcement Learning with LLMs: Formulation and Practices

http://www.rkmt.cn/news/1442851.html

相关文章:

  • 【Sora 2交互设计终极指南】:20年UX专家亲测的5大颠覆性交互范式与落地避坑清单
  • Hermes Agent 实战全解析:从安装避坑到成本控制,附 AI Skills 零代码落地方案
  • 2026 本地企业 AI 搜索优化排行榜:从城市词到推荐答案的增长路径 - 企业服务研究所
  • MAA明日方舟自动化助手:5个步骤实现游戏效率革命
  • 终极指南:3个秘诀让你成为虚幻引擎游戏修改大师
  • 别再瞎试了!用Quartus Prime的Design Space Explorer II,5分钟搞定FPGA时序优化种子筛选
  • WebRTC回声消除定位方法
  • Atcoder Beginner Contest 488
  • 植物大战僵尸玩家必看:PVZ Toolkit如何让你轻松掌控游戏全局
  • 2026北京配眼镜推荐,有人花冤枉钱有人花得值,核心差在哪 - 配眼镜新资讯
  • Obsidian研究模板:5分钟打造你的个人科研知识库
  • Sora 2材质生成革命性突破:5步实现从文本描述到UV映射自动对齐,实测兼容Substance Painter 2024.3+
  • ADS里直接跑MATLAB脚本的工具包,带5个实操例子和一步到位配置指南
  • 3个技巧优化你的Minecraft体验:PCL2启动器内存管理深度解析
  • 【题单】wmr
  • 为什么92%的服装设计师还没用上Sora 2?:2024Q2全球TOP50时装周AI应用数据预警
  • 2026 郑州靠谱GEO公司豆包AI搜索推荐榜!(综合实力TOP5) - 星际AI
  • 西门子S7-1200堆垛机控制工程包:含梯形图程序、HMI图标集、PLC标签与通讯配置文件
  • PanoHead技术揭秘:三平面生成与体积渲染如何实现360度头部合成
  • 北京配眼镜推荐,配眼镜都去哪,五家店从验光到售后横向对比 - 配眼镜新资讯
  • Android 性能优化【篇五:应用启动分析流程】
  • vue父子组件通信(二)祖先调用provide / inject(1)vue2
  • 3分钟定位热键冲突:Hotkey Detective精准排查方案
  • 网盘直链下载助手:告别限速,实现满带宽下载的终极解决方案
  • C++11并发编程:call_once一次性执行+atomic原子类型+CAS无锁编程+自旋锁
  • Meshroom:从照片到3D模型的魔法转换,免费开源工具让创作更简单
  • 2026 温州装修公司避坑指南|选对家装,省心装出理想家 - 速递信息
  • 你的GPU散热真的够吗?深度学习炼丹党必看的温控监控与预警设置指南(以Ubuntu/NVIDIA为例)
  • 3D质感革命:5分钟掌握NormalMap-Online免费在线法线贴图生成器终极指南
  • 2026年只会C语言就业很差吗 C语言真的要完了吗?