是一个整体,所以有些概念的解读/学习会在不同的文章中出现,还请大家谅解。
OpenClaw-RL 是一个用于在线强化学习(Online RL)的框架,专门针对智能体工具使用场景。它通过从环境反馈中提取过程奖励信号来训练语言模型,支持三种主要模式:
- openclaw-rl:基于二元奖励的强化学习(Binary RL / GRPO)
- openclaw-opd:基于后见之明提示的在线策略蒸馏(On-Policy Distillation, OPD)
- openclaw-combine:联合方法,在同一 PPO 更新中同时利用 RL reward 和 OPD teacher signal
0x01 架构
OpenClaw 的 RL 训练 = 一套统一的 PPO 框架 + 三种不同的 advantage 注入方式
┌────────────┬──────────────────────────────┬─────────────────────────────────────┐ │ 方法 │ Advantage 来源 │ 适用场景 │ ├────────────┼──────────────────────────────┼─────────────────────────────────────┤ │ Binary RL │ A = R (raw broadcast) │ 简单场景,只有 ±1 reward │ │ │ reward 标量广播到全序列 │ │ ├────────────┼──────────────────────────────┼─────────────────────────────────────┤ │ OPD │ A_t = teacher_lp_t - old_lp_t│ 有 teacher model 提供 per-token 信号 │ │ │ teacher 的 per-token log-probs │ 需要精细引导,如 hint 机制 │ ├────────────┼──────────────────────────────┼─────────────────────────────────────┤ │ Combine │ A_t = w_rl·R + w_opd·(teacher│ 同时需要 reward 和 teacher 信号 │ │ │ _lp_t - old_lp_t) │ 最灵活,可调权重 │ └────────────┴──────────────────────────────┴─────────────────────────────────────┘关键设计原则:
- 统一 PPO clip 框架:三种方法共享同一套 ratio-based clipped loss
- 数据驱动分流:Combine 通过设置 teacher_lp=rollout_lp 或 reward=0 自动区分 OPD/RL 样本
- 无额外模型:GRPO 替代 Critic,teacher 只做 forward pass(不训练)
- 异步架构:Proxy 实时拦截用户对话,Trainer 后台持续更新
1.1 架构图
OpenClaw-RL 的系统架构图如下:
1.2 File Structure
OpenClaw-RL 的的文件结构如下。
OpenClaw-RL-main/ │ ├── 🧠 核心 RL 框架 │ ├── slime/ # Ray + Megatron-LM 分布式训练 │ └── Megatron-LM/ # NVIDIA 模型并行后端 │ ├── 🏠 个性化 Agent 优化 (Track 1) │ ├── openclaw-rl/ # Binary RL (GRPO) │ ├── openclaw-opd/ # On-Policy Distillation │ ├── openclaw-combine/ # RL + OPD 联合方法 │ └── openclaw-tinker/ # Tinker 云端零 GPU 方案 │ ├── 🌐 通用 Agent RL (Track 2) │ ├── gui-rl/ # GUI Agent (OSWorld) │ ├── swe-rl/ # SWE Agent (mini-swe-agent) │ ├── terminal-rl/ # Terminal Agent (SETA) │ └── toolcall-rl/ # Tool-Call Agent (ReTool) │ ├── 📊 评估 │ └── openclaw-test/ # GSM8K 多轮对话评估 │ ├── 🎨 前端 │ └── openclaw/ # OpenClaw 聊天应用 (TS/Node) │ └── 📄 配置 ├── requirements.txt # 301 个 Python 依赖 └── instructions/ # 环境搭建指南模块职责划分如下。
OpenClaw-RL/ ├─ openclaw-rl/ │ ├─ openclaw_api_server.py ← FastAPI 代理 + PRM 评分 + 样本提交 │ └─ openclaw_rollout.py ← AsyncRolloutWorker: 桥接 API Server ↔ Slime ├─ openclaw-opd/ ← OPD 变体(hint 提取 + teacher log-probs) ├─ openclaw-combine/ ← Combined 变体(RL + OPD 并行) ├─ openclaw-tinker/ ← 无 GPU 云端版(Tinker API) ├─ slime/ │ └─ train_async.py ← 基础 RL 框架(Megatron + SGLang) │ ← 入口:异步训练主循环 ├─ terminal-rl/ gui-rl/ │ swe-rl/ toolcall-rl/ ← Track 2:通用智能体 RL └─ openclaw/ └─ src/ ← OpenClaw TypeScript 应用1.3 四大组件
OpenClaw-RL 的系统设计是四个异步解耦的循环——policy serving、environment hosting、reward judging、policy training 同时运行、互不阻塞,因此模型可以一边持续服务,一边从刚刚发生的真实交互中在线学习。
在这种模块化设计中,各组件既保持功能独立性又实现数据互通。
OpenClaw-RL四大组件 vs 标准RL的区别
四个阶段的模块归属
Policy Serving
定义:运行策略模型、生成response、提供推理能力。
功能定位
- 用户交互入口:接收外部环境的请求并返回响应
- 模型推理服务:转发请求至SGLang推理引擎获取模型响应
- 会话状态管理:维护多轮对话的上下文状态
技术实现
- Web 框架:基于 FastAPI 实现OpenAI 兼容的 /v1/chat/completions接口
- 核心文件:openclaw_api_server.py/ openclaw_opd_api_server.py
具体如下:
| 模块 | 角色 | 位置 |
|---|---|---|
| SGLang Rollout Engine | 真正的 Policy(LLM 推理,GPU 4-5) | Slime 启动,Ray PlacementGroup 管理 |
| OpenClawAPIServer._handle_request() | HTTP 转发代理 | openclaw_api_server.py |
| httpx.post(sglang_chat_url) | 向 SGLang 发送推理请求 | _handle_request() 内 |
| _extract_logprobs_from_chat_response() | 采集 rollout log-probs | openclaw_api_server.py |
| FastAPI /v1/chat/completions | 对外暴露的推理接口(PORT=30000) | _build_app() |
| Megatron Actor(GPU 0-3) | 保存最新策略权重,定期同步给 SGLang | Slime 内部 |
Environment
定义:产生观测(next_state)、定义任务边界。
环境托管模块(Environment Hosting Subsystem)构建智能体操作的真实/模拟环境:
- 个人智能体场景:集成用户终端设备(手机/电脑)的会话系统
- 通用智能体场景:支持云端并行终端、图形界面交互、软件工程开发环境及工具调用沙盒
环境模块通过事件驱动机制实时反馈状态变化,包括用户追问、代码执行结果(stdout/stderr)或界面元素变更等信号。
具体如下:
| 模块 | 角色 | 位置 |
|---|---|---|
| 真实用户 | 发消息(动作) + 看 response(观测) | 外部,无代码 |
| HTTP 请求中的 messages | 用户发出的 observation sequence | FastAPI 请求体 |
| messages[-1](新消息) | next_state,上一轮 turn 的环境反馈 | _handle_request() 第 504 行 |
| X-Session-Id header | 标识同一个 environment episode(会话) | FastAPI header |
| X-Turn-Type: main/side | 区分训练轨迹与非训练交互 | FastAPI header |
| X-Session-Done header | episode 终止信号 | FastAPI header |
Environment在OpenClaw中没有代码实体,它就是“真实用户+HTTP协议“本身。
Reward Judging
定义:评估当前response的质量,产生reward 信号 Binary RL 的 Reward Judge。
效果评估模块(Reward Judging Component)采用双轨制评估机制:
- 量化评估层(PRM Judge):基于预设指标体系生成即时评分(+1/-1等)
- 质性指导层(OPD Hint Extractor):通过自然语言理解技术提取改进建议。
该模块将评估结果与指导信号整合为结构化反馈,构建"教师上下文"用于模型微调。评估过程采用异步批处理模式,支持每秒千级交互的评估吞吐量。
功能定位
- 质量评估:对代理响应进行质量评分
- 评估逻辑:基于下一状态判断助手响应质量
- 评分规则:+1(好)/-1(差)/0(中性)
- 多数投票:多次独立评估取多数结果
- 奖励信号生成:生成用于策略优化的奖励信号
- 过程监督:提供细粒度的过程反馈而非仅结果反馈
技术实现
- 过程奖励模型:通过下一状态评估当前响应质量
- 多数投票机制:执行多次独立评估取多数结果提高可靠性
- 异步评估:在后台线程中执行耗时的LLM评估
- 核心文件:集成在openclaw_api_server.py中的PRM相关逻辑
具体如下:
| 模块 | 角色 | 位置 |
|---|---|---|
| _fire_prm_scoring() | 触发 PRM 评分任务(异步) | openclaw_api_server.py |
| _prm_evaluate() | PRM 评估主逻辑(m=3 并行) | openclaw_api_server.py |
| _query_prm_once() | 单次调用 Judge LLM(GPU 6-7) | openclaw_api_server.py |
| _majority_vote() | 多数投票 → final score | openclaw_api_server.py |
| _build_prm_judge_prompt() | 构造 judge prompt | openclaw_api_server.py |
| SGLang PRM Engine(GPU 6-7) | 运行 Judge LLM 推理 | Slime 启动 |
OPD / Combine 额外的 Reward Judge如下:
| 模块 | 角色 | 位置 |
|---|---|---|
| _fire_opd_task() | 触发 OPD 评估任务(异步) | openclaw_opd_api_server.py |
| _opd_evaluate() | Hint Judge + Teacher LP + Eval | openclaw_opd_api_server.py |
| _query_judge_once() | Hint Judge 单次调用(GPU 6-7) | openclaw_opd_api_server.py |
| _select_best_hint() | 选最优 hint | openclaw_opd_api_server.py |
| _compute_teacher_log_probs() | 教师前向传播(max_new_tokens=0) | openclaw_opd_api_server.py |
| _query_prm_eval_once() | Eval Judge(仅 Combine) | openclaw_opd_api_server.py |
| _prm_eval_majority_vote() | Eval 多数投票(仅 Combine) | openclaw_opd_api_server.py |
Policy Training
定义:利用reward信号更新策略参数
策略训练模块(Policy Training Pipeline)基于Megatron等分布式训练框架构建,采用PPO等强化学习算法实现模型优化。其创新点在于:
- 独立数据队列机制:隔离在线服务与训练数据流
- 增量学习架构:支持动态权重更新而不中断服务
功能定位
- 模型优化:基于收集的样本和奖励信号更新策略模型
- 分布式训练:支持多GPU和多节点分布式训练
技术实现
- 训练框架:基于Slime和Megatron-LM实现
- 算法支持:GRPO、PPO、KL正则化等多种RL算法
- 核心文件:slime/train_async.py及相关训练脚本
具体如下:
| 模块 | 角色 | 位置 |
|---|---|---|
| _maybe_submit_ready_samples() | 等 PRM 完成后触发 sample 提交 | 各 api_server.py |
| _submit_turn_sample() | 构造 Sample 对象(loss_mask, reward) | 各 api_server.py |
| _submit_rl_turn_sample() | RL-only 样本(Combine) | openclaw_combine_api_server.py |
| output_queue.put(...) | 跨线程传递 Sample | 各 api_server.py |
Slime训练主循环:
| 模块 | 角色 | 位置 |
|---|---|---|
| generate_rollout_openclaw() | Slime rollout 入口(被动收集) | openclaw_rollout.py |
| _drain_output_queue() | 等待 N 个样本积累 | openclaw_rollout.py |
| AsyncRolloutWorker.pause/resume_submission() | 控制 API 开关(weight sync 期间暂停) | openclaw_rollout.py |
| compute_advantages_and_returns() | 计算 GRPO/OPD advantage | slime/.../loss.py |
| get_grpo_returns() | GRPO advantage(reward 标量广播) | ppo_utils.py |
| compute_policy_loss() | PPO clip 损失 | ppo_utils.py |
| combine_loss_function() | Combine 自定义损失(w_opd + w_rl) | combine_loss.py |
| Megatron Actor(GPU 0-3) | 执行梯度更新、weight sync | Slime / Megatron-LM |
| RolloutFnTrainOutput | rollout 输出格式(返回给 Slime) | openclaw_rollout.py |
GPU分配
4组件架构各自运行在哪些GPU上?具体如下:
| 组件 | GPU | 实际进程 | 核心代码 |
|---|---|---|---|
| Policy Training | GPU 0-3 | Megatron Actor,TP=4 | slime/ + openclaw_rollout.py |
| Policy Serving | GPU 4-5 | SGLang Rollout + FastAPI Proxy | openclaw_api_server.py |
| Reward Judging | GPU 6-7 | SGLang PRM/Judge | 同一个 openclaw_api_server.py 中的评分逻辑 |
| Environment | 无GPU | OpenClawApp+用户 | openclaw/ (TS app) |
即:
GPU 分配 (8卡节点, run_qwen3_4b_openclaw_rl.sh): GPU 0-3: Megatron Actor (ACTOR_GPUS=4, TP=4) <- Policy Training GPU 4-5: SGLang Rollout (ROLLOUT_GPUS=2, TP=2) <- Policy Serving GPU 6-7: SGLang PRM/Judge (PRM_GPUS=2, TP=2) <- Reward Judging1.4 模型
OpenClaw-RL 优化的是 Qwen3-4B (Actor),它同时也是serve用户的模型(通过SGLang 推理引l擎的权重副本)。三个角色(Actor/Rollout/Judge)用的都是同一个模型,但只有 Actor 被训练更新。
模型详情
具体如下:
① Actor Model (GPU 0-3, Megatron TP=4) = 被优化的 Student模型 = 做 forward/backward/optimizer step 的那个 → 就是OpenClaw-RL 正在训练的模型 ② Rollout Mode1. (GPU 4-5,SGLang TP=2) = 为用户服务的推理引擎 = Actor的权重副本(定期同步) → 不直接训练,只是Actor 的“镜像“ ③ PRM Judge / Teacher (GPU 6-7,·SGLang) = 评分+生成hint+计算teacher_log_probs = 可以是同一模型的另一个实例(OpenClawOPD) → 不被训练,只是工具- 被优化的:只有 ① ActorModel
- ② 和 ① 是同一个模型的不同副本(权重周期性同步)
- ③ 是judge/teacher(固定不变)
具体配置
# run_qwen3_4b_openclaw_rl.sh 中: MODEL_PATH=Qwen/Qwen3-4B #所有角色都用同—个模型 # Actor(训练):Qwen3-4B(Megatron格式,做梯度更新) # Rollout(推理):Qwen3-4B(SGLang 格式,serve 用户) # PRM/Teacher (评估):Qwen3-4B(SGLang 格式,评分/hint/teacher scoring)训练循环
训练循环如下:
User → Rollout (Qwen3-4B) 生成 response → PRM Judge(Qwen3-4B)评分/生成hint → Teacher (Qwen3-4B+hint) 计算 teacher_log_probs → Actor(Qwen3-4B)做梯度更新 ◄─── 这一步优化模型 → 权重同步回Rollout → 下次用户得到更好的response0x02 Slime 的作用
Slime 在 OpenClaw-RL 中,是核心的 RL 后训练框架,负责高效地组织 rollout、trainer和data buffer等模块,实现异步、解耦的RL训练流程。它连接了模型推理(如SGLang)、训练(如 Megatron)和数据流转,支撑了 OpenClaw-RL 的所有 RL 训练范式(OPD,Binary RL,Combine)。
2.1 集成机制
Slime 通过以下机制与OpenClaw组件集成:
插件化架构:通过命令行参数注入自定义函数
异步数据流:OpenClawAPIServer异步生产数据,Slime异步消费
训练资源隔离:不同组件使用独立的GPU资源,避免相互干扰
统一接口:所有OpenClaw变体(RL/OPD/Combine)都遵循相同的集成模式
Slime 启动 SGLang 引擎 └── Slime 启动 SlimeRouter (分配动态端口) └── Slime 将 ip/port 写入 args └── OpenClawAPIServer 读取 args └── 对外暴露 PORT=30000 给 OpenClaw App (用户流量入口) ✓ SGLang 的启动、GPU 分配、端口分配、Router 注册 全部由 Slime 控制 ① 分配 GPU (Ray Placement Group) ② 动态启动 SGLang 推理引擎 + SlimeRouter (port=动态分配 -> args.sglang_router_port) ③ 动态启动 PRM Engine + PRM Router (port=动态分配 -> args.prm_router_port) ④ 启动 Megatron Actor (GPU 0-3, TP=4) ✓ OpenClawAPIServer 只是"寄生"在 Slime 的基础设施上 ◄───────────────────── "此处是关键" ✓ PORT=30000 是外部可见端口, sglang_router_port 是 Slime 内部动态分配的这种设计使得 OpenClaw-RL能够充分利用 Slime强大的分布式训练能力,同时保持 OpenClaw组件的灵活性和可扩展性。
2.2 Slime 扩展
我们来看看 Slime 扩展的机制。
Slime 设计了插件化的钩子系统,OpenClaw-RL 通过 shell 脚本中的参数注入,不修改 Slime 核心即可完整接管整个训练流程。
插件化架构
RolloutManager是Slime中负责管理rollout数据收集的核心类,它通过以下方式(扩展点)集成OpenClaw组件:
- 自定义生成函数:通过--custom-generate-function-path指定
- 自定义奖励函数:通过--custom-rm-path指定
- 自定义损失函数:通过--custom-loss-function-path指定
- 自定义 rollout 函数:通过 --rollout-function-path 指定
具体如下:
# run_qwen3_4b_openclaw_rl.sh 中的关键参数: --rollout-function-path openclaw_rollout.generate_rollout_openclaw # 扩展点1 --custom-generate-function-path openclaw_api_server.generate # 扩展点2 --custom-rm-path openclaw_api_server.reward_func # 扩展点3 # 无需 --custom-loss-function-path (RL用标准GRPO) # run_qwen3_4b_openclaw_combine.sh --custom-loss-function-path combine_loss.combine_loss_function # 扩展点4扩展点的职责
每个扩展点的职责如下:
2.3 OpenClaw-RL 做了哪些工作
OpenClaw-RL 的核心工作量集中在数据采集层 (openclaw_api_server.py),通过 4 个扩展点精准插入 Slime框架,完全不需要修改 Slime/Megatron 核心代码。
OpenClaw-RL 提供的工作量 Slime 框架提供的工作量 ───────────────────────────────────── ───────────────────────────────────── openclaw_api_server.py train_async.py (异步训练主循环) - FastAPI 代理 + 会话管理 Megatron-LM (TP/PP/CP 训练) - PRM 评分 (并发 m 次调用) SGLang (高效推理) - next_state 检测 Ray (分布式任务调度) - at-least-one guarantee GRPO 优势计算 - 样本提交到 output_queue PPO 损失函数 权重同步 (mbridge) openclaw_rollout.py checkpoint 管理 - 被动等待模式 rollout WanDB 日志 - drain_output_queue - pause/resume submission openclaw_opd_api_server.py - hint 提取 judge - teacher log-probs 计算 - top-K 蒸馏 combine_loss.py - combined_adv 计算 - 自定义 PPO loss run_*.sh (5-6个脚本) - GPU 分配配置 - Slime 参数绑定 - 环境变量设置扩展点①
扩展点①: rollout_function_path - 最核心的接管。
关键创新:Slime 框架原本假设 rollout 是主动的 (给模型一个 prompt,模型生成 response)。OpenClaw-RL 把它改成被动等待 (等真实用户对话产生样本)。
函数名:generate_rollout_openclaw()
作用:被 Slime的 RolloutManager调用,负责协调OpenClawAPIServer 收集训练数据
关键操作:
- 获取全局AsyncRolloutWorker 实例
- 启用样本提交(resume_submission())
- 从输出队列收集样本
(_drain_output_queue()) - 禁用样本提交(pause_submission())
具体代码如下:
# openclaw_rollout.py def generate_rollout_openclaw(args, rollout_id, data_buffer, evaluation=False): """ Slime 框架期望: 调用这个函数 → 返回 rollout_batch_size 个 Sample OpenClaw 实现: 不主动生成! 而是等待真实用户对话产生样本 """ worker = get_global_worker(args, data_buffer) if evaluation: # 标准 eval rollout (用 Slime 自带) eval_output, _ = run(eval_rollout(args, rollout_id)) return eval_output worker.resume_submission() # ← 开放 API 接受新会话的样本提交 completed_samples = run( _drain_output_queue(args, worker) # ← 阻塞等待,直到收集到 rollout_batch_size 个样本 ) worker.pause_submission() # ← 关闭提交 (权重更新期间,503 所有请求) return RolloutFnTrainOutput(samples=completed_samples, metrics=...)标准 Slime 模式如下:
训练器 → "给我生成 rollout_batch_size 个样本" → rollout 引擎主动采样OpenClaw-RL 模式如下:
↓ 训练器 → "给我生成 rollout_batch_size 个样本" ↓ generate_rollout_openclaw() 打开阀门,等待... ↓ 用户正常使用 OpenClaw (同时 API Server 收集并评分) ↓ output_queue 积满 rollout_batch_size 个样本 ↓ 关闭阀门 (暂停提交),返回给训练器扩展点 ②③
扩展点 ②③:custom_generate 和 custom_rm (评估用)。
这两个函数是直通接口,真正的评分逻辑已经在 _prm_evaluate() 异步完成并存入 sample.reward。
- 生成函数:openclaw_api_server.py
- 函数名:generate()
- 作用:被Slime在评估模式下调用,用于生成单个样本的响应
- 注意:generate() 是模块级 async 函数,不是 OpenClawAPIServer 的方法
- 实现:调用 SGLang 的 /generate 端点生成响应
- 奖励函数:openclaw_api_server.py
- 函数名:reward_func()
- 作用:被 Slime调用计算样本的奖励值
- 注意:reward_func() 是模块级函数,不是 OpenClawAPIServer 的方法
- 实现:对于OpenClaw-RL,直接返回样本中已有的PRM评分
# openclaw-rl/openclaw_api_server.py 中的两个模块级函数 (仅用于 eval 阶段) # Ref: openclaw-rl/openclaw_api_server.py:141,149 async def generate(args, sample, sampling_params, evaluation=False) → Sample: # 直接调用 SGLang 的 /generate 端点 # 返回带 rollout_log_probs 的 Sample ... async def reward_func(args, sample_or_samples, **kwargs): # 把 sample.reward["score"] 透传回去 (实际评分在 API Server 已完成) return {"score": s.reward.get("score", 0.0)}扩展点 ④
扩展点 ④:custom_loss_function_path (仅 Combine 使用)。
# combine_loss.py def combine_loss_function(args, batch, logits, sum_of_sample_mean): # Slime 框架注入:batch["advantages"] → GRPO 预计算优势 # batch["teacher_log_probs"] → OPD teacher 信号 # logits → Megatron 当前 forward pass 输出 combined_advantages = w_opd * teacher_adv + w_rl * grpo_adv loss = PPO_clip_loss(combined_advantages) + KL_loss return loss, metrics自定义 Advantage 如何接入 Trainer
核心设计思路:API Server 负责"算好所有原材料"(reward、teacher_lp、rollout_lp),Slime 只负责"组装 advantage + 算 loss"。三种方法的 advantage 注入路径各不相同:
- Binary RL 用 Slime 内置 GRPO
- OPD 靠字段劫持
- Combine 用 custom loss
关键区分:不是所有方法都用同一条路径注入 advantage。
Binary RL — 走 Slime 内置 GRPO 路径
reward_func(reward=±1) → Slime 自动计算 GRPO advantage → PPO clip loss ↓ ppo_utils.py L207: advantages[i] = ones_like(kl) * rewards[i] # broadcast- 不需要 custom-loss-function-path
- Advantage 由 Slime 内部的 get_grpo_returns() 计算
- OpenClaw 只负责提供 reward 值
OPD — 劫持 Slime 的 advantage 字段
API Server 把 teacher_log_probs 塞进 sample 字段 ↓ Slime loss.py 读到 teacher_log_probs ↓ advantages[i] = teacher_log_probs[i] - rollout_log_probs[i] # per-token ↓ 正常 PPO clip loss - 也不需要 custom-loss-function-path - Slime 的 loss.py 内部已有 OPD 分支,由 CLI 参数 `--advantage-estimator on_policy_distillation` 触发,而非自动字段检测Combine — 唯一需要 custom loss 的
combine_loss.py::combine_loss_function ↓ 读取 batch["advantages"](GRPO 已算好的) 读取 batch["teacher_log_probs"] 和 batch["rollout_log_probs"] ↓ combined_adv = w_rl * grpo_adv + w_opd * (teacher_lp - rollout_lp) ↓ 用 combined_adv 替换原 advantage → PPO clip loss数据流全景图
2.4 集成
入口
主训练入口:slime/train_async.py,这是Slime异步训练的核心文件,主要功能包括:
- 初始化 Ray 集群:创建 placement groups 分配 GPu资源
- 创建 Rollout Manager:初始化包含 SGLang 引l擎的 rollout 管理器
- 创建训练模型:初始化 actor 和 critic模型
- 异步训练循环:
- 调用rollout_manager.generate.remote()获取训练数据
- 调用actor_model.async_train()执行训练
- 定期保存模型和更新权重
关键调用点
- rollout_data_next_future = rollout_manager.generate.remote(args.start_rollout_id)
- rollout_data_next_future = rollout_manager.generate.remote(rollout_id + 1)
- ray.get(actor_model.async_train(rollout_id,rollout_data_curr_ref))
启动
Slime的主要调用是通过 shell脚本启动的,例如:
OpenClaw-RL:openclaw-rl/run_qwen3_4b_openclaw_rl.sh OpenClaw-OPD:openclaw-opd/run_qwen3_4b_openclaw_opd.sh OpenClaw-Combine: openclaw-combine/run_qwen3_4b_openclaw_combine.sh在这些脚本的最后部分,通过 Ray Job Submit调用 Slime 的主训练文件:
ray job submit --address="http://127.0.0.1:8265" --runtime-env-json="${RUNTIME_ENV_JSON}"\ --python3 train_async.py\--actor-num-nodes 1\ --actor-num-gpus-per-node "${ACToR_GPUS}"\ --rollout-num-gpus "${ROLLoUT_GPUS}"\#...其他参数 --custom-generate-function-path openclaw_api_server.generate\--custom-rm-path openclaw_api_server.reward_func具体参见如下:
循环
Slime 框架的循环如下,可以看到 OpenClaw-RL 如何在其中运作。
- Slime 训练器→调用rollout_manager.generate()
- RolloutManager→调用自定义的generate_rollout_openclaw()函数
- OpenClawRolloutWorker→管理OpenClawAPIServer实例并收集样本
- OpenClawAPIServer→处理用户请求并生成训练样本
Slime 框架 (train_async.py) │ ├── 初始化 Ray cluster + Megatron Actor + SGLang Rollout Engine │ ├── 训练循环 while True: │ │ │ ├── ① 调用 rollout_function_path (generate_rollout_openclaw) │ │ │ │ │ ├── 启动 OpenClawAPIServer (FastAPI on :30000) │ │ ├── resume_submission() <- 开始接受对话 │ │ ├── 等待 output_queue 积满 rollout_batch_size 个 Sample │ │ │ (每个 Sample 已含 rollout_log_probs + reward["score"]) │ │ └── pause_submission() <- 停止接受对话 │ │ │ ├── ② 调用 reward_func() → 返回已有的 score (直通) │ │ │ ├── ③ GRPO advantage 计算 (Slime 内置) │ │ grpo_adv = broadcast(reward) to all tokens │ │ │ ├── ④ Megatron forward pass (TP=4) │ │ │ ├── ⑤ 调用 custom_loss_function (combine_loss 或 Slime 内置) │ │ loss = PPO_clip(combined_adv) + β_KL * KL │ │ │ ├── ⑥ backward + optimizer step (with CPU offload) │ │ │ └── ⑦ 权重同步: Megatron → SGLang (mbridge) │ └── 每 save_interval 步保存 checkpoint2.5 核心模块
几大组件角色定位
- Slime:核心训练框架,提供分布式训练基础设施
- OpenClawAPIServer:API代理服务器,处理用户请求并生成训练样本
- AsyncRolloutWorker:异步轨迹收集工作者,协调数据收集流程
- Trainer:Slime 训练器,负责模型训练和权重更新
采用生产者一消费者一协调者模式:
生产者:OpenClawAPIServer(生成训练样本)
协调者:AsyncRolloutWorker(管理收集流程)
消费者:Slime Trainer(消费样本进行训练)
依赖关系如下:
- Slime(核心框架) → AsyncRolloutWorker(协调层):通过函数调用接口
- AsyncRolloutWorker → OpenClawAPIServer(数据生产层):通过队列和状态控制
- OpenClawAPIServer → SGLang(推理引擎) : 通过 HTTP API 调用
- Slime → SGLang:直接集成SGLang引擎用于评估
调用逻辑详细分析
Slime Trainer 调用 AsyncRolloutWorker
调用入口点
在 slime/train_async.py 中:
#创建rolloutmanager(包含AsyncRolloutWorker) rollout_manager, num_rollout_per_epoch = create_rollout_manager(args, pgs["rollout"], pgs.get("prm")) #异步生成rollout数据 rollout_data_next_future = rollout_manager.generate.remote(rollout_id + 1) #训练actor模型 ray.get(actor_model.async_train(rollout_id, rollout_data_curr_ref))关键调用链
- Slime Train Loop → rollout_manager.generate.remote()
- RolloutManager→调用自定义的generate_rollout_openclaw()
- AsyncRolloutWorker→管理 OpenClawAPIServer 实例
AsyncRolloutWorker 调用 OpenClawAPIServer
初始化调用
在AsyncRolloutWorker.init() 中:
#创建OpenClawAPIServer 实例 self._server = OpenClawAPIServer(args=args, output_queue=self.output_queue, submission_enabled=self._submission_enabled) #启动服务器线程 Self.worker_thread = threading.Thread(target=self._server.run, daemon=True) self.worker_thread.start()状态控制调用
- 暂停提交:worker.pause_submission() → self._server.purge_record_files()
- 恢复提交:worker.resume_submission()→启用_submission_enabled 标志_
- 清理记录:self._server.purge_record_files()→清空内部状态
核心数据结构
Sample对象
来源:OpenClawAPIServer._build_sample_for_turn() _
- 字段:
prompt:用户输入文本 - response:助手响应文本
- tokens:完整token序列
- rollout_log_probs:SGLang生成的对数概率
- teacher_log_probs:教师模型对数概率 (OPD/Combine 使用)
- reward:PRM评分结果
- loss_mask:训练有效性掩码
流向:output_queue → Slime Trainer
内部状态字典
_turn_counts:会话回合计数器
_pending_records:待处理回合记录
_pending_turn_data:待评估回合数据(tokens+logprobs)
eval_scores:PRM评估结果缓存
output_queue
类型:queue.Queue()
内容:(group_index,[sample_list])元组
生产者:OpenClawAPIServer
消费者:AsyncRolloutWorker → Slime Trainer
异步任务队列
_prm_tasks:存储PRM评估的 asyncio.Task
作用:跟踪异步评估状态,避免重复评估
0x03 交互
3.1 数据流
我们来看看真实对话如何从用户流入训练系统。核心设计特点如下:
① 用户无感知 训练在后台异步进行,不影响响应速度
② Zero 标注 next_state 自动成为 reward 信号,无需人工标注
③ 完全私有 对话数据不离开用户服务器
④ 实时持续学习 每次对话都可能成为训练数据,模型持续进化
总体流程如下:
- 训练数据收集路径:用户请求→OpenClawAPIServer(生产样本)→output_queue→ AsyncRolloutWorker (收集样本)→generate_rollout_openclaw()→ RolloutManager → Slime Train Loop → Model Training
- 评估数据生成路径:Slime Evaluation → generate() function → OpenClawAPIServer._forward_to_sglang() → SGLang → Response
- 奖励计算路径:Slime Training → reward_func()→ Sample.reward.score (already computed by OpenClawAPIServer)
关键数据流总结如下:
+-----------------+----------------------------+------------------------------------+ | 阶段 | 核心组件 | 数据 | +-----------------+----------------------------+------------------------------------+ | Policy Serving | SGLang + FastAPI Proxy | token ids, logprobs, response text | | Environment | OpenClaw App (真实用户) | conversation turns, teacher hints | | Reward Judging | LLM Judge (多数投票) | score ∈ {-1, 0, +1} → loss_mask | | Policy Training | Megatron GRPO/OPD/Combine | advantages → gradient updates | +-----------------+----------------------------+------------------------------------+从正常训练循环时序来看,时间轴如下:
时间轴 → T0:用户请求到达→OpenClawAPISerVer处理→样本缓冲 T1:下一状态到达→触发PRM评估→异步评分 T2: Slime 请求数据→AsyncRolloutWorker 启用提交 T3:样本提交到队列→AsyncRolloutWorker收集样本 T4: Slime开始训练→消费样本→更新权重 T5:权重更新完成→AsyncRolloutWorker禁用提交→清理状态 T6:新请求使用新策略→循环继续但是,其总体是异步进行的,具体如下:
时间轴 (完全异步, 各组件不相互阻塞): SGLang: 服务用户 ─────────────────── 暂停(503) ─ 加载新权重 ─ 服务用户 ──► Proxy: 采集数据 ─────────────────── 暂停 ─────── 恢复 ───── 采集数据 ──► PRM: 评分 ───── 评分 ───── 评分 ─────────────────────── 评分 ───── 评分 ──► Megatron: ─ 等待数据 ───────────── 训练 ─ 同步 ─ 等待数据 ─── 训练 ─────────►3.2 模块交互
关键接口 (模块间通信)如下:
OpenClaw App ──HTTP/JSON──► FastAPI Proxy headers: X-Session-Id/Turn-Type/Done FastAPI Proxy ──httpx──► SlimeRouter OpenAI-compatible, logprobs=True SlimeRouter ──httpx──► SGLang Engine /v1/chat/completions FastAPI Proxy ──httpx──► PRM SlimeRouter /generate (plain text prompt) OpenClawAPIServer ──Queue──► AsyncRolloutWorker (group_id, [Sample]) AsyncRolloutWorker ──► generate_rollout_fn RolloutFnTrainOutput generate_rollout_fn ──► Slime → Megatron samples list submission_enabled Event ──► FastAPI Proxy pause(clear)/resume(set)模块交互流程如下:
具体展开如下: