# PR #7536 完整报告

- 仓库：`verl-project/verl`
- 标题：[cfg] fix: drop unused ref router replay config
- 合并时间：2026-08-24 15:14
- 原文链接：http://prhub.com.cn/verl-project/verl/pull/7536

---

# 执行摘要

- 一句话：删除残留 ref.router_replay 配置，修复 Hydra dataclass 实例化报错
- 推荐动作：值得花 5 分钟快速阅读，作为“配置 schema 与 dataclass 一致性”的典型案例，建议与 #7466 合并阅读。关注点：(1) verl 用 omega_conf_to_dataclass + Hydra struct 模式实例化配置的机制，多余键会直接抛 TypeError；(2) 顶层死配置键如何分两步（#7466 删 actor 侧、本 PR 删 ref 侧）才清理干净；(3) 是否值得在 CI 增加生成配置与 schema 的一致性校验，防止同类回归。

# 功能与动机

PR #7466 移除 ActorConfig 顶层 router_replay 字段的同时，ref.yaml 仍保留了顶层 ref.router_replay。两者都通过 actor 配置 dataclass 实例化，于是 Hydra 把陈旧字段传给 McoreActorConfig，抛出 TypeError: McoreActorConfig.__init__() got an unexpected keyword argument 'router_replay'。原错误由 PR #7530 的 CI 工单（run 32689421121）复现，PR body 明确指出这是 #7466 引入的 reference configuration incompatibility。深层动机是把 MoE 路由回放配置收敛为单一事实来源，避免用户在无效位置配置造成静默失效或硬报错。

# 实现拆解

1. 删除参考配置死键：verl/trainer/config/ref/ref.yaml 移除文件顶层的 router_replay 配置块（19 行），包括 _target_: verl.workers.config.RouterReplayConfig、mode、record_file、replay_file。该块实例化后即为 actor_rollout_ref.ref.router_replay，是 #7466 删除 actor 侧字段后残留的同构死键。
2. 同步重新生成 4 个扁平配置：_generated_ppo_trainer.yaml（FSDP 通用路径）、_generated_ppo_megatron_trainer.yaml、_generated_ppo_torchtitan_trainer.yaml、_generated_ppo_veomni_trainer.yaml 各删除 actor_rollout_ref.ref 子块下的 router_replay（各 5 行），保证生成文件与源 schema 不漂移。
3. 保留引擎级活动配置：actor_rollout_ref.ref.megatron.router_replay 与 actor_rollout_ref.ref.veomni.router_replay 不动，R2/R3 路由回放能力仍可用，只是入口收敛到引擎配置。
4. 测试与配套：无新增测试、无文档改动。回归验证依赖 CI 配置加载路径（本 PR 的错误来源即是 PR #7530 的 CI 运行），未补充防止同类回归的 schema 一致性测试。

关键文件：
- `verl/trainer/config/ref/ref.yaml`（模块 训练配置；类别 config；类型 configuration）: 修复核心文件：删除顶层 router_replay 死键（19 行），消除 Hydra 将多余字段传给 actor dataclass 导致的 TypeError 根因。
- `verl/trainer/config/_generated_ppo_megatron_trainer.yaml`（模块 训练配置；类别 config；类型 configuration）: 重新生成的扁平配置之一，同步删除 actor_rollout_ref.ref 子块下的 router_replay（5 行），防止生成文件与源 schema 漂移。
- `verl/trainer/config/_generated_ppo_torchtitan_trainer.yaml`（模块 训练配置；类别 config；类型 configuration）: 重新生成的扁平配置之一，删除 ref 块下 router_replay（5 行），TorchTitan 引擎同样受 #7466 回归影响。
- `verl/trainer/config/_generated_ppo_trainer.yaml`（模块 训练配置；类别 config；类型 configuration）: 重新生成的扁平配置之一（FSDP 通用路径），删除 ref 块下 router_replay（5 行），保持与 ref.yaml 一致。
- `verl/trainer/config/_generated_ppo_veomni_trainer.yaml`（模块 训练配置；类别 config；类型 configuration）: 重新生成的扁平配置之一，删除 ref 块下 router_replay（5 行），VeOmni 引擎侧同样收敛到 veomni 引擎级键。

关键符号：未识别

## 关键源码片段

### `verl/trainer/config/ref/ref.yaml`

修复核心文件：删除顶层 router_replay 死键（19 行），消除 Hydra 将多余字段传给 actor dataclass 导致的 TypeError 根因。

```yaml
# —— 修复说明（本 PR）——
# 原文件在此处之后本有一个顶层 router_replay 配置块：
# router_replay:
# _target_: verl.workers.config.RouterReplayConfig
# mode: disabled
# record_file: null
# replay_file: null
# PR #7466 已从 ActorConfig / McoreActorConfig 等 dataclass 移除顶层 router_replay 字段，
# 但 ref.yaml 未同步删除。引用配置用 actor dataclass 实例化时，Hydra 会把多余关键字
# 传给 dataclass，从而抛出：
# TypeError: McoreActorConfig.__init__() got an unexpected keyword argument 'router_replay'
# 因此本 PR 删除该死键，路由回放统一使用引擎级键，例如：
# actor_rollout_ref.ref.megatron.router_replay.mode=R3
# actor_rollout_ref.ref.veomni.router_replay.mode=R3

# verl/trainer/config/ref/ref.yaml —— 变更后（head）局部视图
# 下方为 global_profiler.global_tool_config 的 precision_debugger 段，
# 它是被删 router_replay 块之前的最后一个相邻配置（nsys / npu / torch 等省略）。
global_profiler:
  global_tool_config:
    precision_debugger:
      # 使用 verl.utils.omega_conf_to_dataclass 实例化 dataclass 时必须提供 _target_
      _target_: verl.utils.profiler.config.PrecisionDebuggerToolConfig
      # msprobe 所需 config json 路径，默认继承全局配置
      config_path: ${oc.select:global_profiler.global_tool_config.precision_debugger.config_path,null}
      # 已废弃字段，采样步数请改用 global_profiler.steps
      steps: null
      # 需要采集的 profiler stage 列表
      stages: ${oc.select:global_profiler.global_tool_config.precision_debugger.stages,null}
      # 遇到未知 stage 或 msprobe 缺失时是否直接抛错
      strict: ${oc.select:global_profiler.global_tool_config.precision_debugger.strict,False}

```

# 评论区精华

本 PR 无实质 review 评论：两位 reviewer（tardis-key、wuxibin89）均直接 APPROVE。更有价值的讨论发生在关联 PR #7466 的 review 中，当时结论是：ref.router_replay in ref.yaml is unchanged; this review only asked to drop the actor-level key。这一决策遗漏了“ref 配置同样用 actor dataclass 实例化”的事实，本 PR 正是对该遗漏的补救。可吸取的教训：删除 dataclass 字段时，应全局检索所有会经该 dataclass 实例化的 YAML 配置，包括 reference 配置和 _generated_*.yaml。

- 暂无高价值评论线程

# 风险与影响

- 风险：配置契约变更：actor_rollout_ref.ref.router_replay.* 从“静默无效键”变为 Hydra struct 模式下的显式报错，仍依赖该键的用户脚本必须迁移至 ref.megatron.router_replay / ref.veomni.router_replay，属预期但存在兼容性影响。生成配置同步风险：4 个 _generated_*.yaml 与 ref.yaml 的同步删除依赖手工或生成器执行，repo 中若缺少生成一致性校验，未来新增引擎字段仍可能重演同样回归（本次错误源头即 #7466 只清了 actor 侧、漏了 ref 侧）。覆盖盲区：材料中未见对 docs、examples、experimental/separation 中 ref.router_replay 引用的检索记录，也没有新增测试。总体为低风险纯配置删除，无运行时代码路径变更。
- 影响：用户：修复使用 Megatron / VeOmni / TorchTitan 引擎的 PPO 训练配置在 Hydra struct 模式下的启动崩溃；配置 MoE 路由回放的用户需改用 ref.megatron.router_replay / ref.veomni.router_replay。系统：受 #7466 影响的 CI 配置加载路径恢复健康；_generated_* 配置文件与 ref.yaml 重新对齐，消除“两份真相”。团队：确立“路由回放只存在于引擎级配置”的约定，后续 review 同类清理时需检查全部实例化路径。
- 风险标记：配置契约变更 , 缺少测试覆盖 , 生成配置同步风险

# 关联脉络

- PR #7466 [cfg, megatron, doc] fix: drop unused actor.router_replay in favor of engine config: 本 PR 修复 #7466 移除 ActorConfig 顶层 router_replay 时遗留 ref.yaml 死键导致的 Hydra TypeError 回归；#7466 review 当时明确保留 ref.router_replay，本 PR 是对该决策遗漏的纠正。
- PR #7407 [megatron,veomni] feat: use torch.int16 for routed_experts: router replay 功能线的前序演进，涉及 Megatron/VeOmni 引擎级路由回放改造，与本 PR 保留的 ref.{megatron,veomni}.router_replay 属同一条功能脉络。