Config:Hydra/OmegaConf 如何进入 trainer 和 worker
verl 的配置不是“运行参数列表”,而是算法、数据、worker 后端、rollout 引擎、checkpoint/weight sync 的连接层。很多训练行为不是在 Python 里硬编码,而是由 verl/trainer/config/ppo_trainer.yaml 的 defaults 和命令行 override 组合出来。
先验知识
读 config 前,需要知道:
- Hydra 会从一个主配置文件开始,根据
defaults把多个 YAML 组合成一棵OmegaConf DictConfig。 - 命令行里的
a.b.c=value会覆盖配置树里的同名字段。 - verl 同时使用两种配置形态:trainer 主循环里经常直接读
OmegaConf字段,worker 初始化时又经常用omega_conf_to_dataclass()转成 dataclass。 - YAML 里的
_target_告诉 Hydra 或omega_conf_to_dataclass()这个配置应该实例化成哪个 Python 类。 actor_rollout_ref是一个组合命名空间,里面同时有 actor、rollout、reference、model 和 hybrid engine 相关配置。
本页原先不适合小白的地方
原说明列了常见字段,但缺少三条关键链路:
ppo_trainer.yaml的 defaults 如何把actor@actor_rollout_ref.actor映射到实际字段。- config 如何进入
RayPPOTrainer,再进入ActorRolloutRefWorker、TrainingWorker。 - YAML 字段如何对应 Python dataclass 字段,以及哪些字段仍在 trainer 中作为
DictConfig直接读取。
入口:main_ppo.py
当前入口使用 Hydra:
@hydra.main(config_path="config", config_name="ppo_trainer", version_base=None)
def main(config):
auto_set_device(config)
config = migrate_legacy_reward_impl(config)
run_ppo(config)也就是说,默认配置来自:
verl/trainer/config/ppo_trainer.yaml命令行示例:
python -m verl.trainer.main_ppo \
data.train_files=$HOME/data/gsm8k/train.parquet \
actor_rollout_ref.model.path=Qwen/Qwen2.5-0.5B-Instruct \
actor_rollout_ref.rollout.name=vllm \
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=4 \
trainer.n_gpus_per_node=1这些 override 会在 TaskRunner.run() 中被 OmegaConf.resolve(config) 解析,然后传给 RayPPOTrainer(config=...)。
defaults 怎么映射到源码字段
ppo_trainer.yaml 的 defaults 是读配置的第一入口:
defaults:
- model_engine: dp
- actor@actor_rollout_ref.actor: ${model_engine}_actor
- data@data: legacy_data
- ref@actor_rollout_ref.ref: ${model_engine}_ref
- rollout@actor_rollout_ref.rollout: rollout
- model@actor_rollout_ref.model: hf_model
- critic@critic: ${model_engine}_critic
- model@critic.model: hf_model
- reward@reward: reward
- algorithm@algorithm.rollout_correction: rollout_correction
- _self_读法:
actor@actor_rollout_ref.actor: ${model_engine}_actor:从trainer/config/actor/目录加载对应 YAML,并挂到config.actor_rollout_ref.actor。- 默认
model_engine: dp,所以 actor 默认来自actor/dp_actor.yaml。 dp_actor.yaml又 defaults 到actor.yaml,并补上 FSDP 相关字段。critic@critic: ${model_engine}_critic默认加载critic/dp_critic.yaml。rollout@actor_rollout_ref.rollout: rollout加载rollout/rollout.yaml。model@actor_rollout_ref.model: hf_model加载 HF 模型配置。
所以命令行里改 model_engine=megatron 会让 actor/ref/critic 默认换到 Megatron 系列配置,而不是只改一个字符串。
配置如何进入 trainer
TaskRunner.run() 做了这些事:
validate_config(config, use_reference_policy=..., use_critic=...)
tokenizer = hf_tokenizer(...)
train_dataset = create_rl_dataset(config.data.train_files, config.data, ...)
resource_pool_manager = ResourcePoolManager(...)
trainer = RayPPOTrainer(config=config, tokenizer=..., ...)
trainer.init_workers()
trainer.fit()RayPPOTrainer.__init__() 保存整棵配置:
self.config = config
self.hybrid_engine = config.actor_rollout_ref.hybrid_engine
self.use_reference_policy = need_reference_policy(config)
self.use_rm = need_reward_model(config)
self.use_critic = need_critic(config)所以 trainer 主循环读到的是完整的 OmegaConf DictConfig。
配置如何进入 worker
init_workers() 把不同子树传给不同 worker:
actor_rollout_cls = RayClassWithInitArgs(
cls=ActorRolloutRefWorker,
config=self.config.actor_rollout_ref,
distillation_config=self.config.get("distillation"),
role=str(actor_role),
)critic 路径会先转 dataclass,再包装成统一的 TrainingWorkerConfig:
critic_cfg = omega_conf_to_dataclass(self.config.critic)
critic_cfg = TrainingWorkerConfig(
model_type="value_model",
model_config=orig_critic_cfg.model,
engine_config=engine_config,
optimizer_config=orig_critic_cfg.optim,
checkpoint_config=orig_critic_cfg.checkpoint,
)rollout checkpoint engine 也会转 dataclass:
checkpoint_engine_config = omega_conf_to_dataclass(
self.config.actor_rollout_ref.rollout.checkpoint_engine
)_target_ 和 dataclass
很多 YAML 都有 _target_:
actor:
_target_: verl.workers.config.ActorConfig
algorithm:
_target_: verl.trainer.config.AlgoConfigomega_conf_to_dataclass(config) 的规则:
- 如果没传
dataclass_type,配置里必须有_target_,然后用hydra.utils.instantiate()。 - 如果传了
dataclass_type,会先OmegaConf.structured(dataclass_type),再 merge 用户配置,最后OmegaConf.to_object()。
这些 dataclass 都继承 BaseConfig,所以既能像对象一样 cfg.field,也能像 dict 一样 cfg.get("field")。不过 BaseConfig 默认冻结已有字段,除非字段在 _mutable_fields 里。
常见字段和源码落点
| 配置字段 | 源码落点 | 作用 |
|---|---|---|
data.train_files | main_ppo.py:create_rl_dataset() | 训练 parquet 路径 |
data.train_batch_size | dataloader、validate_config() | 每 step prompt 数 |
data.max_prompt_length | dataset、rollout prompt length | prompt padding/truncation 长度 |
data.max_response_length | rollout response length | 生成最大长度 |
algorithm.adv_estimator | need_critic()、compute_advantage() | 决定 GAE/GRPO/RLOO 等路径 |
algorithm.use_kl_in_reward | need_reference_policy()、apply_kl_penalty() | 是否把 KL 从 reward 中扣掉 |
actor_rollout_ref.actor.ppo_mini_batch_size | _update_actor() | actor PPO mini-batch,trainer 会乘 rollout.n |
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu | worker engine config validation | 单卡 micro batch |
actor_rollout_ref.actor.use_kl_loss | need_reference_policy()、actor loss | 是否在 actor loss 里加 KL |
actor_rollout_ref.rollout.name | get_rollout_class() | 选择 vLLM/SGLang/TRTLLM/HF rollout |
actor_rollout_ref.rollout.n | fit().repeat()、_update_actor() | 每 prompt 采样 response 数 |
actor_rollout_ref.rollout.checkpoint_engine.backend | CheckpointEngineManager、worker update_weights() | trainer 到 rollout 的权重同步后端 |
critic.enable / algorithm.adv_estimator | need_critic() | 是否建 critic worker |
reward.reward_model.enable | need_reward_model()、RewardLoopManager | 是否使用模型 reward |
trainer.balance_batch | _balance_batch() | 是否按 token 工作量重排 |
trainer.save_freq | fit() | checkpoint 保存频率 |
trainer.test_freq | fit() / _validate() | validation 频率 |
batch size 名词
| 名称 | 视角 | 例子 |
|---|---|---|
data.train_batch_size | prompt 数 | dataloader 每 step 取多少 prompt |
actor_rollout_ref.rollout.n | 每 prompt response 数 | GRPO 常设为大于 1 |
| 有效 response 数 | train_batch_size * rollout.n | actor/critic 实际看到的样本数 |
actor.ppo_mini_batch_size | PPO 更新 mini-batch | _update_actor() 中会乘 rollout.n |
actor.ppo_micro_batch_size_per_gpu | 单卡 micro batch | 控制显存峰值 |
rollout.max_num_batched_tokens | rollout engine token 调度 | 控制推理吞吐和显存 |
如果 train_batch_size=64 且 rollout.n=8,一次 actor update 面对的是 512 条 response。读指标时也要按 response 数理解。
KL 放在哪里
verl 有两个常见 KL 位置:
- reward-side KL:
algorithm.use_kl_in_reward=True,apply_kl_penalty()写token_level_rewards = token_level_scores - beta * KL。 - actor loss KL:
actor_rollout_ref.actor.use_kl_loss=True,actor loss 内部使用 reference logprob。
两者都可能需要 reference policy。validate_config() 会在两者同时开启时打印 NOTICE。
rollout 配置不要和训练后端混淆
训练后端主要由这些字段决定:
actor_rollout_ref.actor.strategy
critic.strategy
actor_rollout_ref.actor.fsdp_config / megatron / veomni / torchtitanrollout 推理后端主要由这个字段决定:
actor_rollout_ref.rollout.name例如你可以用 FSDP 训练 actor,同时用 vLLM 做 rollout。它们通过 checkpoint engine/weight sync 对接,不是同一个后端。
源码实现怎么读
建议这样读:
- 从
ppo_trainer.yaml的 defaults 开始,画出actor_rollout_ref.actor、actor_rollout_ref.rollout、critic、reward四棵子树。 - 打开
actor/dp_actor.yaml,看它如何 defaults 到actor.yaml和engine/fsdp.yaml。 - 打开
workers/config/actor.py,对照ActorConfig字段和__post_init__()校验。 - 打开
utils/config.py,看validate_config()如何检查 batch size、micro batch 和 reference/critic 条件。 - 回到
ray_trainer.py:init_workers(),看配置子树如何被传入ActorRolloutRefWorker和TrainingWorker。 - 最后回到
ray_trainer.py:fit(),搜索self.config.,把字段和训练行为逐个连起来。
本节参考与延伸阅读
- 源码:
verl/trainer/main_ppo.py,重点读@hydra.main、TaskRunner.run()、validate_config()、RayPPOTrainer(...)。 - 源码:
verl/trainer/config/ppo_trainer.yaml、algorithm.py、config.py、data/legacy_data.yaml、actor/、critic/、reward/、rollout/、engine/、model_engine/。 - 源码:
verl/base_config.py、verl/utils/config.py。 - 源码:
verl/workers/config/actor.py、critic.py、rollout.py、reward.py、engine.py。 - 官方 docs:
docs/examples/config.rst、docs/start/quickstart.rst。 - 外部资料:Hydra 官方文档、OmegaConf 官方文档、HybridFlow: A Flexible and Efficient RLHF Framework, arXiv:2409.19256。