Prhub

#1907 Fix p2p profile's rotary_base not reaching the model script it configures

原始 PR 作者 fzyzcjy 合并时间 2026-08-09 18:47 文件变更 11 提交数 14 评论 1 代码增减 +87 / -11

执行摘要

修复 P2P profile 的 rotary_base 未到达模型脚本的问题

该 PR 是追踪 Issue #1837「refactoring and enhancements」下的第 13 项子任务。PR 标题直接点出问题:p2p profile 的 rotary_base 没有到达它配置的模型脚本。测试注释也明确说明了根因:"The knob has to survive into the shell that expands MODEL_ARGS, not only into ray's runtime env"——即模型脚本在 source 时读取环境变量来决定 --rotary-base,而此前 rotary_base 只存在于 ray runtime env 中,shell 展开 MODEL_ARGS 时根本看不到它,导致实际训练参数与 profile 声明不一致(例如 Qwen3-235B-A22B-Instruct-2507 声明的 5000000 可能静默丢失)。

值得精读。这个 PR 展示了一个最小但完整的“配置到达真实命令行”修复闭环:把单点配置抽成两个纯函数,用真实 bash 展开而非 mock 来测试,并以快照防回归。对编写启动脚本、命令构造工具或示例类代码的工程师有直接借鉴意义。重点阅读 build_model_args_command 中“先设变量再 source”的构造方式,以及测试中“测试真实命令而不是逻辑副本”的策略。

讨论亮点

该 PR 的 review 讨论非常少:only 审核者 yueming-yuan 直接 Approve,未留下任何文字评论,说明变更被认为没有阻塞性问题。Issue 上仅有一条 gemini-code-assist[bot] 的公告(GitHub 上的 Gemini Code Assist 已停止 review 活动),不构成有效审查意见。整体决策由作者 fzyzcjy 主导,依托快照测试作为行为契约。

实现拆解

第 1 步:定位根因

examples/infra_features/p2p_weight_transfer/run.pycmd_run 中,cfg.rotary_base 此前只被写入 ray job 的 runtime env(env_vars["MODEL_ARGS_ROTARY_BASE"]),而真正携带模型参数的 shell 命令是 source "scripts/models/{model_type}.sh" && ray job submit ... ${MODEL_ARGS[@]}。模型脚本在 source 时才能决定 --rotary-base 的值,但该环境变量在 source 那一刻并不存在于 shell 中,于是实际参数与 profile 声明脱节。

第 2 步:抽出统一构造逻辑

新增两个函数,让两处注入点共用同一数据源:

  • build_model_args_env(cfg) -> dict[str, str]:把 cfg.rotary_base 映射为 {"MODEL_ARGS_ROTARY_BASE": str(value)}None 时返回空字典;
  • build_model_args_command(cfg) -> str:用 shlex.quote 把键值对拼成 VAR=value 前缀,再接 source ".../scripts/models/{model_type}.sh",保证变量在 source 时就位。

cmd_run 中对应修改:runtime env 改用 env_vars.update(model_args_env),提交命令改用 build_model_args_command(cfg);同时把 import shlex 从提交分支内提升到模块顶层,删除原先重复的内联逻辑。

第 3 步:新增单元测试

新增 tests/fast/examples/infra_features/p2p_weight_transfer/test_run.py(含 3 个空 __init__.py 包保证 pytest 可发现):

  • importlib 直接加载 run.py 为模块,避免复制逻辑;
  • expand_model_args 辅助函数把 build_model_args_command 的返回值交给真实 /bin/bash 执行,再 printf 打印 "${MODEL_ARGS[@]}",测试的是 run.py 真实命令而非逻辑副本;
  • 用例覆盖:不固定 rotary_base 的 profile 不注入任何覆盖(Qwen3-4B)、固定值的 profile 生成正确的 MODEL_ARGS_ROTARY_BASE(Qwen3-235B-A22B-Instruct-2507)、参数化验证 3 个固定值的 profile 展开出的 --rotary-base 与声明一致、以及所有 profile 都能展开成非空且以 -- 开头的 argv(防止模型脚本改名后提交无效作业)。

第 4 步:更新快照

tests/snapshots/launch_scripts/self_executing/examples/infra_features/p2p_weight_transfer/run.py/run/ 下 6 个快照(GLM-4.5-Air、Qwen3-235B-A22B-Instruct-2507、Qwen3-30B-A3B 各自的 broadcast/p2p 模式)在命令行中新增 MODEL_ARGS_ROTARY_BASE=<值> 前缀,并同步更新 runtime env JSON,保持快照测试绿色。

第 5 步:合并验证

14 个 commit 中 12 个属于 #1837 系列其余子任务(typo 修复、shell harness、快照基建、base64 payload 等),最后一个 merge commit 与 main 对齐,最终由 yueming-yuan 批准合并。

文件 模块 状态 重要度
examples/infra_features/p2p_weight_transfer/run.py 示例运行 modified 7.08
tests/fast/examples/infra_features/p2p_weight_transfer/test_run.py 示例测试 added 7.01
tests/fast/examples/__init__.py 测试结构 added 3.11
tests/fast/examples/infra_features/__init__.py 测试结构 added 3.11
tests/fast/examples/infra_features/p2p_weight_transfer/__init__.py 测试结构 added 3.11
tests/snapshots/launch_scripts/self_executing/examples/infra_features/p2p_weight_transfer/run.py/run/GLM-4.5-Air/broadcast.txt 快照测试 modified 1.89
tests/snapshots/launch_scripts/self_executing/examples/infra_features/p2p_weight_transfer/run.py/run/GLM-4.5-Air/p2p.txt 快照测试 modified 1.89
tests/snapshots/launch_scripts/self_executing/examples/infra_features/p2p_weight_transfer/run.py/run/Qwen3-235B-A22B-Instruct-2507/broadcast.txt 快照测试 modified 1.89
tests/snapshots/launch_scripts/self_executing/examples/infra_features/p2p_weight_transfer/run.py/run/Qwen3-235B-A22B-Instruct-2507/p2p.txt 快照测试 modified 1.89
tests/snapshots/launch_scripts/self_executing/examples/infra_features/p2p_weight_transfer/run.py/run/Qwen3-30B-A3B/broadcast.txt 快照测试 modified 1.89

关键符号

build_model_args_env build_model_args_command expand_model_args test_model_args_env_is_empty_when_the_profile_pins_no_rotary_base test_model_args_env_carries_the_rotary_base_a_profile_pins test_a_pinned_rotary_base_reaches_the_expanded_model_args test_every_profile_expands_to_a_usable_argv

关键源码片段

examples/infra_features/p2p_weight_transfer/run.py core-logic

核心修复文件:新增 build_model_args_env / build_model_args_command,把 rotary_base 注入 source 前的 shell 环境,解决 profile 参数无法到达模型脚本的问题。

# examples/infra_features/p2p_weight_transfer/run.py(节选)
import shlex # 新增:构建 shell 片段时需要对值做引用
​
​
def build_model_args_env(cfg: RunConfig) -> dict[str, str]:
    """把 profile 中的 rotary_base 统一转成模型脚本读取的 MODEL_ARGS_* 环境变量。    返回空字典表示该 profile 不固定 rotary_base,避免向两个注入点
    传递错误的覆盖值。
    """
    if cfg.rotary_base is None:
        return {}
    return {"MODEL_ARGS_ROTARY_BASE": str(cfg.rotary_base)}
​
​
def build_model_args_command(cfg: RunConfig) -> str:
    """生成一个 shell 片段:先设置 MODEL_ARGS_*,再 source 模型脚本。    修复前 rotary_base 只写入 ray runtime env,模型脚本在 shell 中展开
    ${MODEL_ARGS[@]} 时读不到它,导致 --rotary-base 与 profile 声明不符。
    shlex.quote 用于防止值中的特殊字符破坏命令结构。
    """
    prefix = "".join(f"{name}={shlex.quote(value)} " for name, value in build_model_args_env(cfg).items())
    return f'{prefix}source "{MILES_ROOT}/scripts/models/{cfg.model_type}.sh"'
​
​
# cmd_run 中两个使用点(节选):runtime env 与提交命令共用同一来源
model_args_env = build_model_args_env(cfg)
model_args_source = build_model_args_command(cfg)
# ...
env_vars.update(model_args_env) # ray 作业进程可见
runtime_env_json = json.dumps({"env_vars": env_vars})
# ...
run_cmd(
    f"{model_args_source} && "
    f"ray job submit --address='http://127.0.0.1:8265' "
    f"--runtime-env-json='{runtime_env_json}' "
    f'-- python3 "{MILES_ROOT}/train.py" '
    f"${{MODEL_ARGS[@]}} " # 此刻已能看到 MODEL_ARGS_ROTARY_BASE
    f"{args_str}",
    check=False,
)

评论区精华

reviewer 直接批准,无文字评论 other

yueming-yuan 对 PR 给出 APPROVED,未留下任何文字评论;Issue 上仅有 gemini-code-assist[bot] 的废弃公告(GitHub 上的 Gemini Code Assist 已停止 review 活动)。

结论:变更被认为不存在阻塞性问题,直接批准并合并。 · 已解决

风险与影响

  • 配置注入双点同步:rotary_base 现在同时注入 shell 前缀和 ray runtime env,两处共用 build_model_args_env 单一数据源,短时间不会漂移;但未来若新增其他 MODEL_ARGS_* 键,必须同步在该函数注册,否则会出现注入缺失。
  • 快照依赖 bash 具体行为:快照测试和 expand_model_args 显式使用 /bin/bash,若执行环境 shell 语义不同会直接失败;这是显式保护而非隐患,但意味着修改模型脚本时必须同步重录快照。
  • 示例级修复影响面有限:改动仅涉及 examples/infra_features/p2p_weight_transfer/run.py 及对应测试/快照,不影响 miles/ 核心库或 CI 门禁。风险集中在 P2P 权重传输示例复现正确性。
  • 测试进程副作用:fast 测试通过 importlib 加载 run.py,若该文件今后引入重依赖或顶层副作用,可能拖慢 fast 套件或造成 pytest 导入异常。
  • 用户(示例使用者):P2P 权重传输示例中 Qwen3-235B-A22B-Instruct-2507(rotary_base=5000000)、Qwen3-30B-A3B(1000000)、GLM-4.5-Air(1000000)等模型现在会真正以 profile 声明的 rotary base 训练,不再静默使用默认值。
  • 工程影响:为 #1837 推进的“启动脚本命令快照 + 模型参数展开”链条补齐关键一环;后续 #1908-#1911 都复用同一展开/快照路径,本 PR 是这条链路的行为基准之一。
  • 团队影响:新增一个测试目录(tests/fast/examples/...),不改变现有测试运行方式,fast 套件自动发现新用例。
配置注入双点同步风险 快照依赖 bash 具体行为 示例级修复不影响核心库

关联 Issue

#1837 Tracking issue for refactoring and enhancements

完整报告

参与讨论