# PR #2236 完整报告

- 仓库：`THUDM/slime`
- 标题：fix: don't overwrite an explicitly set --start-rollout-id
- 合并时间：2026-08-12 13:50
- 原文链接：http://prhub.com.cn/THUDM/slime/pull/2236

---

# 执行摘要

- 一句话：修复校验覆写显式 --start-rollout-id 参数的问题
- 推荐动作：值得快速审阅，属于典型的参数覆盖 bugfix，修改直观且测试覆盖良好。可关注参数校验的既定设计，以及后续是否有类似被无条件覆盖的 fallback 参数。

# 功能与动机

PR body 明确指出 `--start-rollout-id` 文档将其定义为 fallback：若未设置，则继续训练时尝试从 `--load` 加载步数，否则设为 0 表示从头训练。但 `slime_validate_args` 在两个分支中均无条件赋值 0，恰好覆盖了用户显式指定的值。当训练不恢复 Megatron checkpoint 时，显式传入的 `--start-rollout-id` 是唯一指定起点的方式，却被静默丢弃，导致 `train.py` 从 `range(0, num_rollout)` 开始。

# 实现拆解

1. **变更入口**：`slime/utils/arguments.py` 中的 `slime_validate_args` 函数。在 `if not load_is_megatron:` 分支内，将原先无条件执行的 `args.start_rollout_id = 0` 改为 `if args.start_rollout_id is None: args.start_rollout_id = 0`，确保仅在用户未显式指定时填充默认值。
2. **测试配套**：在 `tests/test_megatron_argument_validation.py` 中新增两个测试函数，均使用 `pytest.mark.parametrize("megatron_to_hf_mode", ["raw", "bridge"])` 覆盖两种模式：
 - `test_slime_validate_args_preserves_explicit_start_rollout_id`：传入 `start_rollout_id=100`，校验后仍为 100。
 - `test_slime_validate_args_defaults_start_rollout_id_to_zero`：传入 `None`，校验后为 0。
3. **影响**：修复后，`create_actor_model` 中的 `if args.start_rollout_id is None:` 分支逻辑保持不变，仅当用户未设置时由后面的代码填充，行为与文档一致。

关键文件：
- `slime/utils/arguments.py`（模块 参数校验；类别 source；类型 core-logic；符号 slime_validate_args）: 核心修复文件，修改了参数校验逻辑，防止覆盖显式设置的 --start-rollout-id。
- `tests/test_megatron_argument_validation.py`（模块 测试；类别 test；类型 test-coverage；符号 test_slime_validate_args_preserves_explicit_start_rollout_id, test_slime_validate_args_defaults_start_rollout_id_to_zero）: 新增针对 start_rollout_id 保留与默认的测试，验证修复正确性。

关键符号：slime_validate_args

## 关键源码片段

### `slime/utils/arguments.py`

核心修复文件，修改了参数校验逻辑，防止覆盖显式设置的 --start-rollout-id。

```python
# slime/utils/arguments.py 中 slime_validate_args 相关分支

    if not load_is_megatron:
        args.no_load_optim = True
        args.no_load_rng = True
        args.finetune = True
        if not load_is_hf:
            args.load = args.ref_load
        if args.ref_ckpt_step is not None:
            args.ckpt_step = args.ref_ckpt_step
        # 仅当用户未显式设置 start_rollout_id 时，才回退为 0
        # 这样显式传入的值不会被静默覆盖
        if args.start_rollout_id is None:
            args.start_rollout_id = 0

```

# 评论区精华

PR 无 review 评论和讨论。

- 暂无高价值评论线程

# 风险与影响

- 风险：本次修改仅将 `args.start_rollout_id = 0` 改为条件赋值，逻辑简单，风险极低。但需注意：如果某些调用方依赖 `slime_validate_args` 强制将 `start_rollout_id` 置为 0（例如在非 checkpoint 恢复场景下必须从头开始），此改动可能改变其行为。不过如 PR body 所述，`create_actor_model` 仅在值为 `None` 时才设置，因此原始行为保留，且文档表明参数本意即为 fallback，因此风险可控。
- 影响：影响范围限于参数校验逻辑，修复了显式指定 `--start-rollout-id` 时被覆盖的问题，确保用户能准确控制训练起点。对用户而言，避免了静默重训的错误；对系统而言，无性能或安全影响。影响程度中等，主要提升参数语义的正确性。
- 风险标记：参数校验覆盖风险 , 潜在行为变化

# 关联脉络

- PR #2213 Fix tau-bench token deltas for reasoning templates: 同为参数校验相关的 bugfix，虽文件不同但涉及训练步数与 rollouts 逻辑。
- PR #2249 Remove --train-memory-margin-bytes: 同样修改参数校验逻辑，可参考其对参数处理的一致性。