- 人工智能
- 大模型
- 强化学习
- AI Agent
- 微调
【免费下载链接】OpenClaw-RL
OpenClaw-RL: Train any agent simply by talking
本文基于 slime 仓库的 Debug 指南 展开。slime 是 OpenClaw-RL 仓库内置的高性能 RL 训练框架(Megatron 训练后端 + SGLang 推理后端),本文聚焦 RL 训练中最棘手的三个问题域:模型精度对齐校验、训练/推理链路分离调试、以及大规模 rollout 中 SGLang illegal memory access 的定位思路。读完本文,你将掌握一套可复现的「训练第一步/第二步精度检查流程」、四个专门用于训推分离的调试参数,以及一套系统的 IMA 排查方法论。
一、为什么要先解决精度对齐问题
在 RL 训练中,rollout 生成质量与训练数值正确性互为前提:如果 rollout 生成的是乱码,后续的 reward、log_probs、advantage 计算全部失去意义;如果训练端 log_probs 与 reference 模型对不上,KL 惩罚与优势估计就会被污染。因此 slime 的调试指南把「精度对齐」放在第一位,并将其拆成两个阶段逐步验证。
二、训练第一步的精度检查
训练第一步是整条 RL 链路的「开机自检」。slime 建议按以下三个层次依次排查。
2.1 rollout 生成是否为「人话」
第一步先看 rollout 生成结果。如果生成内容不是正常语言,优先怀疑四类原因:
- 参数没有正常加载:检查日志中是否有 Megatron 成功加载 ckpt 的记录。对应源码路径 slime/slime/backends/megatron_utils/actor.py 中的
initialize_model_and_optimizer调用,加载失败或路径错误时会在该环节暴露。 - 更新参数有误:确认所有参数都完成了转换与一一对应,特别是参数名是否根据并行配置做了转换。例如当
pp_size > 1时,第二个 stage 提供的参数的 layer id 是否正确。一个比较彻底的办法:在对应模型的 SGLang 实现的load_weights中把加载到的所有参数保存下来,与 ckpt 中的参数逐一比对是否一致。从源码结构看,SGLang 侧的参数加载与权重同步逻辑位于 slime/slime/backends/sglang_utils 目录下。 - SGLang 特殊 buffer 释放问题:如果所有参数更新都正确仍出现乱码,有可能是 SGLang 中某些特殊 buffer 在 release 时被提前释放。
- pretrain 模型本身的差异:如果测试用的是 pretrain 模型,可以换成同结构的 instruct 版本,验证该乱码是否是 pretrain 模型特有的现象(例如 pretrain 模型对 chat template 不敏感导致的异常输出)。
2.2 rollout stats 中 log_probs 与 ref_log_probs 是否完全相等
查看打印的 rollout stats:log_probs与ref_log_probs应在第一步完全相等(即 kl=0),且数值较小。这是「训练端与推理端前向结果一致」的直接证据。
- 如果不完全相等,一般是 Transformer Engine 中某些 non-deterministic kernel 导致的。典型例子:在某些 TE 版本中,Megatron 需要加
--attention-backend flash强制使用 Flash Attention,从而避免 Context Parallelism(CP)下 fused attention 的数值不稳定。slime 的 Megatron 侧已将该参数纳入模型构建配置,相关逻辑见 slime/slime/backends/megatron_utils/model_provider.py 附近的attention_backend处理。 - 如果数值较大(例如 > 1),则分两种情况:
- 值非常大:基本是训练配置有问题(如 reward 计算、KL 系数、数据拼接等环节出错);
- 值只是略大于 SFT loss 的水平(例如 instruct 模型的 logprob 到了 0.8 左右):大概率是数据不符合训练的 chat template,或不符合冷启动的数据分布。
2.3 推一训一场景下 kl 与 grad_norm 检查
在推一训一(num_steps_per_rollout == 1)的配置下进一步验证:kl 是否为 0、grad_norm 是否较小。
如果这里出现问题,基本上可以锁定为 Megatron / Transformer Engine 相关的 bug。文档中给出的典型例子是:MoE 模型需要开启--moe-permute-fusion(对应 Megatron 侧的 MOE permutation fusion 优化开关),否则数值与梯度行为不符合预期。KL 指标的实际计算位置可参考 slime/slime/backends/megatron_utils/loss.py 中kl的生成与传递逻辑,它在不同 advantage estimator(GRPO / PPO / Reinforce++ 等)下被用于构造 rewards 或优势。
三、训练第二步的检查
进入训练第二步后,对于训推一体(colocate)模式,核心检查点是:
- 能否正确加载第二步(即从第一步训练的模型状态继续 rollout);
- 是否会出现 OOM(显存溢出)。
这一步主要暴露的是资源规划类问题,可结合 slime 的 placement group 分配逻辑(见 slime/slime/ray/placement_group.py)来核对训练、推理各自的 GPU 预算是否冲突。
四、训练与推理分离调试:四个关键参数
slime 支持将训练部分和推理部分完全拆开分别调试,带来两个直接收益:
- 调优/debug推理部分时,只用少量卡就能启动任务(不必拉起完整训练栈);
- 调优/debug训练部分时,可以固定模型输入,彻底去除 rollout 的随机性,让训练问题可复现。
这组参数在 slime/slime/utils/arguments.py 的add_debug_arguments中定义。
4.1--debug-rollout-only:只跑推理,不加载 Megatron
开启后,slime 将不加载 Megatron 训练栈,只初始化 SGLang,用于单独调试推理部分。
源码层面的行为佐证:
- 在 slime/slime/backends/megatron_utils/actor.py 中,
debug_rollout_only时 actor 初始化直接return 0跳过模型/优化器构建; - slime/slime/backends/sglang_utils/sglang_engine.py 中将 actor GPU 数量置 0;
- 训练侧的
train/save_model/update_weights等入口在 megatron actor.py 与 [L1416-L1444] 中均被短路(仅记录 rollout 数据后返回)。
同时,开启该参数后 slime 会自动调整资源配置(见 arguments.py):关闭 colocate 与 offload,并强制train_memory_margin_bytes=0(因为不涉及训练显存预留)。
4.2--debug-train-only:只跑训练,不初始化 SGLang
开启后,slime 将不加载 SGLang,只初始化 Megatron,用于单独调试训练部分。
源码行为佐证:
- 在 slime/slime/ray/rollout.py 中,
debug_train_only时all_rollout_engines直接置空,不创建任何 rollout engine; - slime/slime/ray/placement_group.py 中只按 actor(及 critic,若启用 PPO)的 GPU 数量创建 placement group;
- eval 阶段也会被跳过(见 slime/slime/ray/rollout.py)。
4.3--save-debug-rollout-data /your/saved/debug/data_{rollout_id}.pt:保存每次 rollout 结果
开启后,每次 rollout 的结果都会被保存,可与--debug-rollout-only配合使用。注意路径中必须包含{rollout_id}占位符,实际保存方式为args.save_debug_rollout_data.format(rollout_id=rollout_id):
- 训练数据保存为
data_0.pt、data_1.pt…(rollout_id 为数字); - eval 数据保存为
data_eval_0.pt、data_eval_1.pt…(带eval_前缀),对应实现见 slime/slime/ray/rollout.py 的_save_debug_rollout_data:文件内含rollout_id与samples(由Sample.to_dict()序列化)。
此外,slime 还提供--dump-details参数:一旦设置,会自动把save_debug_rollout_data推导为{dump_details}/rollout_data/{rollout_id}.pt(见 arguments.py),适合整体导出调试数据。
4.4--load-debug-rollout-data /your/saved/debug/data_{rollout_id}.pt:回放固定输入
开启后,会从args.load_debug_rollout_data.format(rollout_id=rollout_id)加载数据,并且不会初始化 SGLang(自动设置debug_train_only=True)。这样训练部分的输入完全固定,可以放心地切换各种并行策略、损失函数或超参进行调优,而无需担心 rollout 随机性的干扰。
对应实现细节:
- arguments.py 在参数校验阶段检测到
load_debug_rollout_data后自动强制debug_train_only=True; - slime/slime/ray/rollout.py 的
_get_rollout_data中,不再调用生成函数,而是直接torch.load(...)["samples"]并还原为Sample对象; - 配套参数
--load-debug-rollout-data-subsample <ratio>可以只取前后各一半样本进行快速调试(见 arguments.py 与 rollout.py),适合样本量较大的场景。
⚠️ 互斥约束:
debug_rollout_only与debug_train_only不能同时开启,代码中对此有显式断言(见 arguments.py)。
4.5 配套工具:查看已保存的 rollout 数据
仓库还提供了查看 dump 数据的独立脚本 slime/slime/utils/debug_utils/display_debug_rollout_data.py,可直接以模块方式运行:
python -m slime.utils.debug_utils.display_debug_rollout_data \ --load-debug-rollout-data /your/saved/debug/data_{rollout_id}.pt它会遍历 0~999 的 rollout_id 并按train/eval两类前缀自动发现文件,展示每条样本的prompt、response、reward、status、metadata等白名单字段,并基于保存的样本重新计算性能指标(compute_perf_metrics_from_samples),适合在加载调试数据前先快速确认数据内容是否符合预期。同目录下还有 replay_reward_fn.py 与 send_to_sglang.py 等配套调试工具,分别用于回放 reward 函数与将数据重新发送给 SGLang。
五、Debug SGLang illegal memory access(IMA)
在大规模 RL 训练中,不时会遇到 SGLang 的 illegal memory access(IMA,非法内存访问)问题。这类错误通常伴随 CUDA 报错并导致引擎崩溃,slime 给出了如下四条递进式的排查建议。
5.1 开启CUDA_LAUNCH_BLOCKING=1
CUDA_LAUNCH_BLOCKING=1 bash your_rl_script.sh该环境变量会让 CUDA kernel 同步执行,报错时能直接定位到触发崩溃的 kernel,而不是在异步执行后丢出一个泛化的 IMA。这是所有 CUDA 类调试的第一步。
5.2 开关投机采样与 CUDA Graph
开启/关闭投机采样(speculative decoding)与CUDA Graph的组合,观察问题是否消除:
- IMA 经常出现在CUDA Graph replay 的 padding中;
- 也可能与投机采样与主模型的差异有关(投机 draft 模型与 target 模型行为不一致时,replay 的显存布局可能错位)。
通过两组开关的各种组合(如只开 graph、只开投机、全关),可以快速缩小问题范围。slime 通过--sglang-前缀将 SGLang 的全部参数无缝透传(见 introducing_slime 博客),因此可以灵活控制这些开关。
5.3 关闭 deepep
如果训练或推理中开启了deepep(DeepEP:用于跨节点 MoE all2all 通信优化的库),可以尝试关闭后对比是否有差别:
- SGLang 侧通过
--sglang-moe-a2a-backend deepep、--sglang-deepep-mode auto等参数控制(参考 deepseek-r1 示例); - Megatron 侧通过
--moe-enable-deepep控制(参考 glm4.5-355B-A32B 示例)。
deepep 涉及自定义的 all2all 与显存复用路径,是 IMA 的高发区之一,关闭它是重要的二分定位手段。
5.4 使用 CUDA Core Dump 定位报错 kernel
如果上述开关无法定位问题,可以尝试CUDA Core Dump方式,在崩溃时抓取 GPU 侧的完整内存快照与 kernel 调用栈,从而精确定位出错 kernel。这一方法最早由 vLLM 团队在公开博客中系统介绍(CUDA Core Dump: An Effective Tool to Debug Memory Access Issues and Beyond),其核心思路是:将 CUDA 崩溃转储为 core dump,再通过分析工具还原出具体是哪一行 kernel、哪个内存地址触发了非法访问,相比反复试开关效率高得多。建议将其作为 IMA 排查链路的最后手段。
六、调试方法论小结
| 调试目标 | 关键手段 | 对应源码/文档 |
|---|---|---|
| 推理精度 | 训练第一步 rollout「人话」检查、log_probs == ref_log_probs(kl=0) | debug.md、loss.py |
| 训练数值 | num_steps_per_rollout==1下 kl=0、grad_norm 小;开启--moe-permute-fusion、--attention-backend flash | model_provider.py |
| 推理侧分离 | --debug-rollout-only+--save-debug-rollout-data | arguments.py |
| 训练侧分离 | --debug-train-only/--load-debug-rollout-data(自动置位 debug_train_only) | rollout.py |
| 数据检查 | display_debug_rollout_data查看 dump 样本 | display_debug_rollout_data.py |
| IMA 定位 | CUDA_LAUNCH_BLOCKING、开关投机/Graph、关闭 deepep、CUDA Core Dump | 本指南第五节 |
最后提醒两点实践前提:
- 并行配置影响参数名:当
pp_size > 1时,不同 stage 的 layer id 与参数名都会随并行策略变化,精度对齐检查时必须按实际并行配置核对; - 分离调试的定位边界:
--debug-rollout-only场景下 slime 会强制关闭 offload 与显存预留相关配置,因此分离调试通过不代表训推一体(colocate)模式也能通过,第二步的「训推一体加载与 OOM 检查」仍需在完整模式下验证。
遵循上述流程,可以在 RL 训练初期快速把「推理侧乱码」「训练侧数值异常」和「大规模推理侧崩溃」三类最常见问题隔离到最小复现单元,再用分离调试参数与源码级检查手段逐个击破。
- 人工智能
- 大模型
- 强化学习
- AI Agent
- 微调
【免费下载链接】OpenClaw-RL
OpenClaw-RL: Train any agent simply by talking
相关推荐
OpenClaw-RL(slime)RL 训练调试实战指南:精度对齐、训练/推理分离调试与 SGLang IMA 排查
OpenClaw RL(slime)RL 训练调试实战指南:精度对齐、训练/推理分离调试与 SGLang IMA 排查 本篇技术指南聚焦于 OpenClaw R
人工智能大模型强化学习AI Agent微调Slime RL 训练框架 Debug 实战指南:精度对齐、训推分离调试、量化 Checkpoint 与分布式单步调试
Slime RL 训练框架 Debug 实战指南:精度对齐、训推分离调试、量化 Checkpoint 与分布式单步调试 本篇技术指南聚焦 slime(LLM p
人工智能大模型强化学习RLHF分布式训练OpenClaw-RL 中的 slime:连接 Megatron 与 SGLang 的高性能 RL 后训练框架实战指南
OpenClaw RL 中的 slime:连接 Megatron 与 SGLang 的高性能 RL 后训练框架实战指南 本篇文章围绕 OpenClaw RL 仓
人工智能大模型强化学习AI Agent微调
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考