verl/grpo、dapo、ppo、
rloo、reinforce-baseline、remax、distillation、sft。
和 NeMo-RL 不同,verl 提交时需要 --model 和 --train-data。可观测性是 platform。
verl 镜像是部署侧的产物(
FORGE_IMAGE_VERL 或 FORGE_RUNTIME_REGISTRY_FILE)。
管理员先发布它,别人才提交得了;没有它时提交失败,错误会点名缺的是运行时,而不是方法。创建时写明版本
verl.trainer.main_ppo(sync V1);0.8 的 main_ppo_sync 已被上游移除,catalog 不再保留旧运行时。
如果存在 experiments/my-verl/main.py,就用这个文件当入口(verl-recipe 风格:子类化 TaskRunner / RayPPOTrainer)。只改奖励可以继续用配置里的 custom_reward_function.path。
模型和数据在提交时必填
和 NeMo-RL 不同,verl 绑定要显式路径。recipe 映射:data.train.dataset;CLI 只是覆盖。数据集。
缺了必填的模型/数据声明,sf validate 会在本地失败。
RL 方法怎么选
这里的 RL 方法跑的都是同一个verl.trainer.main_ppo;recipe 只钉死一件事——algorithm.adv_estimator,而它就是方法本身。
在
config.yaml 里写 algorithm.adv_estimator 会在提交时被拒:它是方法的身份,不是旋钮。要换 estimator 就换方法。
loss 变体(GSPO、CISPO、GMPO、clip-cov / kl-cov、GPG)才是旋钮——在上面任一 recipe 上设 policy_loss_mode。
DAPO
verl/dapo 是配置,不是自带的 trainer:0.9 的主干 main_ppo 已经包含论文里的四件套,所以 recipe 只钉死
algorithm.filter_groups.enable 与 dapo reward manager,论文取值作为参数默认值下发(裁剪 0.2/0.28、
token-mean、4096 token 超长软区、惩罚系数 1.0、每题 16 条、两条路径的 KL 全关)。
提交前有两件事要知道:
- 动态采样是在 rollout 阶段按
filter_metric判定一组的,所以那时奖励必须已经算出来:要么用规则奖励函数, 要么让奖励模型独占一个资源池。共卡的奖励模型是在采样之后才打分的,上游会直接 assert。 - 每步耗时天然是波动的——合格的组不够就继续补采。想要「DAPO 去掉动态采样」那一档,用
verl/grpo配clip_ratio_high=0.28和loss_agg_mode=token-mean。
rollout 校正(TIS / IcePop)
即使权重完全一致,rollout 引擎(vLLM,bf16)和训练器(FSDP,fp32)也不是同一个策略;rollout 变旧或被补采 会把这个差距进一步拉大。每个 verl RL 方法都暴露了校正开关:rollout_calculate_log_probs 不是可选项:没有 rollout 侧自己的 log-prob,就没有可比对的行为策略;平台会在编译期
直接拒绝这种组合,而不是让它悄悄不生效。rollout_is 不设时只出 mismatch 指标、不做校正——新环境上先这么跑一轮
是合理的第一步。
On-policy 蒸馏要两个资源池
verl/distillation 的教师推理服务跑在自己的 Ray placement group 里,是叠加在训练池之上申请的。
所以作业要声明两个资源池,并把 teacher 角色映射到第二个:
trainer.nnodes,用教师池填 distillation.nnodes。只给一个池的提交会在编译期被拒,
而不是挂在等资源上。多池作业只支持 kuberay 与 slurm 后端。
拓扑
adapter 用FORGE_CLUSTER_* 写 trainer.nnodes / trainer.n_gpus_per_node(有教师池时用主池的形状)。
导出 / 评测
sf eval 可以把验证样本挂回训练 run(带 --run-id)。见流水线。