ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenClaw-RL 源码阅读笔记(4):架构拆解与 Slime/PPO 配置骨架

OpenClaw-RL 源码阅读笔记(4):架构拆解与 Slime/PPO 配置骨架 1. 从一次训练卡死说起OpenClaw-RL 架构到底怎么读如果你正在复现 OpenClaw-RL 的训练流程大概率会遇到一个很迷惑的现象脚本跑起来了SGLang 在服务Megatron 在等数据PRM 在打分但训练循环就是不动。日志里没有报错GPU 占用也正常可rollout_batch_size迟迟凑不满。这个问题我第一次读源码时也卡了很久最后发现根因不在算法而在架构理解——OpenClaw-RL 把 Slime 原本主动生成 rollout的假设改成了被动等待真实用户对话产生样本。OpenClaw-RL 是一个面向在线强化学习Online RL的框架专门针对智能体工具使用场景。它从环境反馈中提取过程奖励信号来训练语言模型支持三种主要模式openclaw-rl基于二元奖励的 GRPO、openclaw-opd基于反思之明提示的在线策略蒸馏、openclaw-combine在同一 PPO 更新中同时利用 RL reward 和 OPD teacher signal。适合谁适合想把真实用户交互变成训练数据、又不想改 Slime/Megatron 核心代码的开发者。这篇笔记聚焦架构层源码阅读围绕 Slime 与 PPO 的模块划分、调用链与配置入口展开。我会给出可复制的config.toml骨架、TaoToken 统一 Key/API 通道接入 AI 工具的settings.json片段以及逐步验证动作帮你确认架构理解与配置生效。读完之后你应该能自己画出数据从用户请求到梯度更新的完整路径。2. 前置准备TaoToken 统一 Key 与 API 通道在动手读源码之前先把 AI 工具的接入通道理顺。OpenClaw-RL 的调试过程需要频繁调用模型做对比验证如果每个工具都单独配 Key切换成本很高。TaoToken 提供统一的 Key/API 通道官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 不加 UTM。你需要先拿到 API Key。登录后进入控制台在 API Keys 页面创建一个新 Key复制保存。这个 Key 会同时用于模型对话验证、Coding Plan 以及后续的接入文档对照。对于长期编码和 Agent 场景建议直接开通 Coding Plan这样在调试 OpenClaw-RL 的 rollout 逻辑时不会因为额度问题中断。模型对话入口可以用来快速验证 Key 是否生效接入文档则提供了不同工具链的配置模板。拿到 Key 之后在项目根目录创建或修改settings.json把统一通道写进去。下面是我实测可用的片段{ ai_provider: { base_url: https://taotoken.net/api, api_key: sk-your-taotoken-key, default_model: claude-sonnet-4-20250514, timeout_seconds: 120, max_retries: 3 }, tools: { model_chat: { endpoint: https://taotoken.net/api/v1/chat/completions, stream: true }, coding_plan: { enabled: true, workspace: ./openclaw-rl-workspace } } }注意base_url不要带末尾斜杠否则部分 HTTP 客户端会拼出双斜杠导致 404。api_key用你刚创建的那串不要提交到 git建议放进.env再用环境变量注入。3. 架构拆解Slime 与 PPO 的模块划分3.1 统一 PPO 框架 三种 advantage 注入OpenClaw-RL 的 RL 训练本质是一套统一的 PPO 框架 三种不同的 advantage 注入方式。这个设计原则很关键理解了它后面读代码就不会迷路。方法Advantage 来源适用场景Binary RLA Rraw broadcast简单场景只有 ±1 rewardOPDA_t teacher_lp_t - old_lp_t有 teacher model 提供 per-token 信号CombineA_t w_rl·R w_opd·(teacher_lp_t - old_lp_t)同时需要 reward 和 teacher 信号三条路径共享同一套 ratio-based clipped loss区别只在 advantage 怎么算出来。Binary RL 走 Slime 内置 GRPOreward 广播到全序列OPD 靠字段劫持API Server 把teacher_log_probs塞进 sampleSlime 的loss.py读到后自动算 per-token advantageCombine 是唯一需要自定义 loss 的用combine_loss.py::combine_loss_function读batch[advantages]和batch[teacher_log_probs]加权合成后再进 PPO clip。3.2 文件结构与模块职责OpenClaw-RL 的目录划分很清晰核心 RL 框架在slime/个性化 Agent 优化在openclaw-rl/、openclaw-opd/、openclaw-combine/通用 Agent RL 在gui-rl/、swe-rl/、terminal-rl/、toolcall-rl/。模块职责划分如下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 并行 ├── slime/ │ └── train_async.py ← 基础 RL 框架Megatron SGLang └── terminal-rl/ gui-rl/ swe-rl/ toolcall-rl/ ← Track 2 通用智能体 RLopenclaw_api_server.py是整个数据采集层的核心它同时承担了 FastAPI 代理、PRM 评分、样本提交三件事。openclaw_rollout.py里的AsyncRolloutWorker是桥接层负责管理 API Server 实例并收集样本。slime/train_async.py是训练主循环入口。3.3 四大组件的异步解耦OpenClaw-RL 的系统设计是四个异步解耦的循环——policy serving、environment hosting、reward judging、policy training 同时运行、互不阻塞。模型可以一边持续服务一边从刚刚发生的真实交互中在线学习。GPU 分配8 卡节点run_qwen3_4b_openclaw_rl.shGPU 0-3: Megatron Actor (ACTOR_GPUS4, TP4) - Policy Training GPU 4-5: SGLang Rollout (ROLLOUT_GPUS2, TP2) - Policy Serving GPU 6-7: SGLang PRM/Judge (PRM_GPUS2, TP2) - Reward Judging Environment: 无 GPUOpenClaw App 用户三个角色Actor/Rollout/Judge用的都是同一个 Qwen3-4B但只有 Actor 被训练更新。Rollout 是 Actor 的权重副本定期同步PRM Judge 是固定不变的 judge/teacher。3.4 Slime 的插件化扩展点Slime 设计了一套插件化的钩子系统OpenClaw-RL 通过 shell 脚本中的参数注入不修改 Slime 核心即可接管整个训练流程。四个扩展点# 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-pathRL 用标准 GRPO # run_qwen3_4b_openclaw_combine.sh --custom-loss-function-path combine_loss.combine_loss_function # 扩展点4扩展点 1 是最核心的接管。Slime 框架原本假设 rollout 是主动的给模型一个 prompt模型生成 responseOpenClaw-RL 把它改成被动等待等真实用户对话产生样本。generate_rollout_openclaw()被 Slime 的RolloutManager调用负责回调 OpenClawAPIServer 收集训练数据。# openclaw_rollout.py def generate_rollout_openclaw(args, rollout_id, data_buffer, evaluationFalse): Slime 框架期望: 调用这个函数 - 返回 rollout_batch_size 个 Sample OpenClaw 实现: 不主动生成! 而是等待真实用户对话产生样本 worker get_global_worker(args, data_buffer) if evaluation: 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(samplescompleted_samples, metrics...)标准 Slime 模式是训练器 → 给我生成 rollout_batch_size 个样本 → rollout 引擎主动采样。OpenClaw-RL 模式是训练器 → 给我生成 rollout_batch_size 个样本 → 打开闸门等待 → 用户正常使用 OpenClaw同时 API Server 收集并评分→ output_queue 积满 → 关闭闸门返回给训练器。4. 可复制配置config.toml 骨架与 settings.json4.1 config.toml 骨架下面是我整理的可复制config.toml骨架覆盖 Slime 与 PPO 的关键配置入口。你可以直接放到项目根目录按需改路径和 GPU 数。[model] path Qwen/Qwen3-4B actor_gpus 4 rollout_gpus 2 prm_gpus 2 tensor_parallel 4 [slime] train_async_entry slime/train_async.py rollout_function_path openclaw_rollout.generate_rollout_openclaw custom_generate_function_path openclaw_api_server.generate custom_rm_path openclaw_api_server.reward_func # combine 模式才需要下面这行 # custom_loss_function_path combine_loss.combine_loss_function [ppo] advantage_estimator grpo # 可选: grpo / on_policy_distillation clip_range 0.2 kl_coef 0.01 rollout_batch_size 32 max_new_tokens 512 temperature 0.7 [prm] judge_samples 3 # 多数投票次数 m3 score_range [-1, 0, 1] async_eval true [server] api_port 30000 sglang_router_port 0 # 0 表示由 Slime 动态分配 prm_router_port 0 [taotoken] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY几个容易踩坑的点advantage_estimator选on_policy_distillation时Slime 的loss.py内部已有 OPD 分支不需要再配custom_loss_function_pathsglang_router_port和prm_router_port填 0 让 Slime 动态分配避免端口冲突rollout_batch_size要和实际并发用户量匹配太小会频繁触发权重同步太大则训练延迟高。4.2 settings.json 接入片段前面第 2 节已经给了settings.json的基础片段这里补充一个针对 OpenClaw-RL 调试场景的增强版把模型对话和 Coding Plan 都挂到统一通道{ ai_provider: { base_url: https://taotoken.net/api, api_key: sk-your-taotoken-key, default_model: claude-sonnet-4-20250514 }, openclaw_rl: { debug_chat_endpoint: https://taotoken.net/api/v1/chat/completions, coding_plan_enabled: true, log_level: debug } }debug_chat_endpoint用于在训练卡住时单独发一条请求验证模型通道是否正常排除是网络问题还是架构问题。5. 验证请求与成功结果配置写完之后不要直接跑完整训练先做三步验证。第一步验证 TaoToken 通道。用 curl 发一条最小请求curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-20250514, messages: [{role: user, content: ping}], max_tokens: 16 }成功结果返回 JSON 里choices[0].message.content有内容usage.total_tokens大于 0。如果返回 401检查 Key返回 404检查base_url是否多了斜杠。第二步验证 Slime 扩展点加载。启动训练脚本后观察日志里是否出现rollout_function_path和custom_rm_path的加载记录。成功标志是看到generate_rollout_openclaw被调用且OpenClawAPIServer在:30000端口监听。# 另开终端验证 API Server 是否起来 curl -s http://127.0.0.1:30000/v1/models | head -c 200成功结果返回模型列表 JSON说明 FastAPI 代理已就绪。第三步验证样本收集。发一条模拟用户对话观察output_queue是否收到样本curl -X POST http://127.0.0.1:30000/v1/chat/completions \ -H Content-Type: application/json \ -H X-Session-Id: test-session-001 \ -H X-Turn-Type: main \ -d { model: qwen3-4b, messages: [{role: user, content: 帮我写一个快速排序}], logprobs: true }成功结果返回带logprobs的响应同时训练日志里出现sample submitted to output_queue或类似记录。如果rollout_batch_size设为 1此时训练循环应该开始消费样本并进入 forward/backward。6. 本篇常见错排查6.1 训练循环卡在_drain_output_queue现象日志停在waiting for rollout_batch_size samplesGPU 占用正常但无进展。原因rollout_batch_size设得比实际并发用户量大或者resume_submission()没被调用。检查generate_rollout_openclaw里worker.resume_submission()是否执行以及 API Server 的submission_enabled事件是否被 set。排查动作把rollout_batch_size临时改成 1发一条对话看是否触发训练。如果触发说明是批量大小问题如果不触发检查_drain_output_queue的阻塞条件。6.2 PRM 评分一直返回 0现象sample.reward[score]始终是 0GRPO advantage 全为 0梯度不更新。原因PRM Judge 的 prompt 构造有问题或者judge_samples多数投票逻辑没生效。检查_build_prm_judge_prompt()的输出是否符合预期以及_majority_vote()是否收到 m3 个独立结果。排查动作单独调用_query_prm_once()打印原始 judge 输出。如果 judge 返回格式不匹配解析逻辑score 会 fallback 到 0。6.3 Combine 模式 loss 报维度不匹配现象combine_loss_function里combined_adv和logits维度对不上。原因batch[teacher_log_probs]和batch[rollout_log_probs]的 token 长度不一致或者w_opd/w_rl权重没配。检查 API Server 提交样本时teacher_log_probs是否按max_new_tokens0的 forward 结果正确填充。排查动作在combine_loss_function入口打印batch[advantages].shape和batch[teacher_log_probs].shape确认两者在 token 维度对齐。6.4 权重同步期间请求 503现象用户对话在权重更新期间收到 503。原因这是设计行为pause_submission()会关闭提交purge_record_files()清理状态。如果 503 持续时间过长说明权重同步mbridge卡住。排查动作检查 Megatron → SGLang 的 mbridge 同步日志确认save_interval和同步耗时。如果同步超过预期考虑减小模型或增加同步带宽。7. 继续深入从架构理解到实操验证读到这里你应该能画出 OpenClaw-RL 的完整数据流用户请求 → OpenClawAPIServer生产样本→ output_queue → AsyncRolloutWorker收集样本→ generate_rollout_openclaw() → RolloutManager → Slime Train Loop → Model Training。评价数据走generate()函数奖励计算走reward_func()两者都是模块级函数不是 OpenClawAPIServer 的方法。下一步建议你按这个顺序动手先用模型对话入口验证 TaoToken 通道再对照接入文档把settings.json配好然后跑rollout_batch_size1的最小训练循环确认样本能进能出。长期编码和 Agent 调试场景直接开 Coding Plan避免额度中断打断你的源码阅读节奏。架构理解到位之后Slime 的四个扩展点就是你的操作面板。改rollout_function_path换数据来源改custom_rm_path换奖励逻辑改custom_loss_function_path换 advantage 合成方式。OpenClaw-RL 的工作量集中在数据采集层Slime/Megatron 核心代码一行不用动——这也是它最值得学的地方。
返回列表