Prhub

#2356 Replace all the `.sh` launch scripts with `.py` launch script

原始 PR 作者 yueming-yuan 合并时间 2026-08-12 12:51 文件变更 115 提交数 41 评论 4 代码增减 +4931 / -11035

执行摘要

用 Python 启动器全面替换 scripts/ 下全部 shell 启动脚本

PR body 明确指出这是 #1837 中启动器改写任务的一环:模型配置早已迁移到 python(#1910),本 PR 完成启动器本身的迁移。同时清理了三个 shell 遗留怪癖(rl_data 目录不存在、HF_HOME 注入无效、ray start 参数不一致),并借机统一了目录与 GPU 参数约定。

值得精读,推荐顺序:先读 PR body 和 command_utils.py 的 execute_train / ssh_start_ray_workers,再看 run_qwen3_dense.py 的 _Recipe 合并模式与 run_nemotron_3_super_120b_a12b.py 的角色拆分。最大的方法论价值是用“记录-重放快照对比”验证大规模重写语义等价,这种验证方式可复用于其他 bash→python 迁移项目。

讨论亮点
  1. guapisolo 的快照隔离问题(已修复):在 tests/fast/launch_scripts/py_harness.py 上指出 freeze_environment() 只清了 MLP_SOCKET_IFNAME,而四个新启动器也会读 MLP_WORKER_0_HOST,不冻结会导致快照测试随开发机环境漂移;提交 0fa40f7 已把 MLP_WORKER_0_HOST 加入 CLEARED_ENV
  2. Zhichenzzz 对数据集目录统一的建议:在 docs/models/glm/glm4-5.md 评论“we should unify the /root/datasets/rl_data and /root/datasets/”;提交 d584106 统一为 aime-2024 目录。
  3. Zhichenzzz 对 ssh 扇出开关的疑问:在 run_qwen3_next_80b_a3b.py 问“only in this script using this gate”;结论文档说明 join_ray_workers 的额外 gate 用于排除单节点配方,后续提交又统一了四个启动器的开关命名。
  4. Zhichenzzz 对 gpt-oss 后端的确认:在 run_gpt_oss_20b.py 问“the unique one?”,确认 bshd + fused 是该模型 sink attention 在 TE 中唯一可行的组合。

实现拆解

  1. 前置清理与合并基线:分支基于 yueming/script-bugfix,带入了 #2354(删除废弃模型启动器)与 #2355(修复快照冻结的 bug)的改动;再往 main 合入时解决了 DeepSeek V3 文档页、glm4-5 页面等多处冲突。
  2. 用 _Recipe 表合并近重复配方:每个变体的差异化参数收敛为 _Recipe dataclass,ScriptArgs.recipe 属性按 --model-name / --topology 选择。例如 run_qwen3_dense.py 覆盖 6 个 Qwen3/Qwen3.5/Qwen3.6 dense 配方,run_kimi_k2.py 覆盖 Instruct/Thinking,run_qwen3_next_80b_a3b.py 覆盖 4node/single-node 两种拓扑。这消除了逐文件拷贝导致的参数漂移。
  3. 基础设施收敛到 execute_train:所有启动器统一通过 U.execute_train 提交,前导逻辑(环境变量、ray 生命周期、PYTHONPATH、进程清理)由 command_utils 统一管理;新增 U.ssh_start_ray_workers 让四个多节点配方通过 before_ray_job_submit 共享 ssh 扇出逻辑。有意的差异包括:--num-gpus-per-node 总是显式传入,--colocate 时去掉 --rollout-num-gpus,wandb 统一走 get_default_wandb_args
  4. 修正两个 shell 遗留怪癖:GLM-4.5 与 Kimi-K2-Instruct 原本读取不存在的 <data-dir>/rl_data/,现统一为 hf_download_dataset 实际写入的 <data-dir>/aime-2024;gpt-oss 停止注入对 ray workers 无效的 HF_HOME=/workspace/hf_cache
  5. 特殊脚本的处理run_glm45_355b_a32b_8node.py 作为新文件而非合并进 run_glm45_355b_a32b.py(两者是同一模型的不同实验,记录 diff 有 77 处差异);run_nemotron_3_super_120b_a12b.py 用 typer 双命令 train / worker 表达头/worker 角色拆分;Kimi-K2 配方用 MILES_SCRIPT_EXTERNAL_RAY=1 表达外部已起 ray;run_qwen3_4b_npu.sh 因指向错误的 CUDA 启动器且无有效读者而被直接删除。
  6. 测试与文档配套tests/fast/launch_scripts/test_sh_harness.py 改指向幸存的 examples 启动器,移除 6 个 scripts/ 条目并调整发现下限;harness 的 CLEARED_ENV 补充冻结 MLP_SOCKET_IFNAMEMLP_WORKER_0_HOST;约 21 个文档页面改用 python 调用,新增 docs/user-guide/launch-script.md 替代旧的 bash 中心 walkthrough。
文件 模块 状态 重要度
scripts/run_qwen3_dense.py 启动器 added 8.87
scripts/run_glm45_355b_a32b_8node.py 启动器 added 8.89
scripts/run_nemotron_3_super_120b_a12b.py 启动器 added 8.93
scripts/run_qwen3_next_80b_a3b.py 启动器 added 8.98
scripts/run_kimi_k2.py 启动器 added 8.96
scripts/run_qwen3_sft.py 启动器 added 8.65
scripts/amd/run_qwen3_4b.py 启动器 added 8.84
miles/utils/external_utils/command_utils.py 命令工具 modified 6.89
tests/fast/launch_scripts/py_harness.py 测试工具 modified 6.0
docs/user-guide/launch-script.md 文档 added 5.89
docs/user-guide/training-script-walkthrough.md 文档 removed 5.26
scripts/run-qwen3-next-80B-A3B.sh 启动器 removed 5.53

关键符号

execute main ScriptArgs _Recipe recipe ssh_start_ray_workers _wait_for_head_port _wait_for_ray_gpus _execute_train _cluster_env_vars

分析完成后,这里会展示 LLM 生成的相对完整源码片段和详细注释。

评论区精华

快照冻结缺少 MLP_WORKER_0_HOST 导致环境依赖 测试

guapisolo 在 py_harness.py 指出:freeze_environment() 只清了 MLP_SOCKET_IFNAME,而四个新启动器读取 MLP_WORKER_0_HOST 构造 ssh 命令;该变量未冻结时,快照会变成宿主相关,在 MLP 环境必挂。

结论:提交 0fa40f7 将 MLP_WORKER_0_HOST 加入 CLEARED_ENV,并确认 178 个快照全部稳定通过。 · 已解决

rl_data 与数据集目录统一 设计

Zhichenzzz 在 glm4-5.md 评论“we should unify the /root/datasets/rl_data and /root/datasets/”,指向 shell 脚本遗留的错误数据集布局。

结论:提交 d584106 统一为 hf_download_dataset 实际写入的 aime-2024 目录,GLM-4.5 与 Kimi-K2-Instruct 配方及文档全部修正。 · 已解决

join_ray_workers 开关是否只在单一脚本中使用 question

Zhichenzzz 对 run_qwen3_next_80b_a3b.py 发问“only in this script using this gate”,质疑 join ray workers 的额外 gate 是否只出现在个别脚本。

结论:作者澄清:带单节点配方的启动器需要该 gate 防止 ssh 扇出,四个多节点启动器最终统一命名为 join_ray_workers。 · 已解决

gpt-oss 的 bshd + fused 后端是否唯一 question

Zhichenzzz 对 run_gpt_oss_20b.py 问“the unique one?”,核对 sink attention 对 BSHD/SBHD 的限制。

结论:确认该模型在 TE 中只能用 qkv-format bshd + fused 后端,且因此必须用静态 micro-batch。 · 已解决

风险与影响

  1. 删除面大且无法回滚:24 个 shell 启动器被删除,外部书签、内部笔记、旧文档链接可能失效;文档已同步更新但无法覆盖所有使用方。
  2. 快照等价性只覆盖 argv 与 runtime env:验证能防 flag 漂移,但不覆盖真实训练行为;run_glm45_355b_a32b_8node.py 的 20+ NCCL/IB 环境变量若作用于错误进程会影响整机性能,run_nemotron_3_super_120b_a12b.py_wait_for_ray_gpus 在集群未就绪时会等待 10 分钟再提交。
  3. NPU 支持空缺run_qwen3_4b_npu.sh 被删除且无替代,scripts/run_qwen3_4b_npu.py 自身有 /root/model 拼写错误、prepare() 结果未使用等缺陷,需 NPU 硬件验证;NPU 用户按旧路径会直接失败。
  4. 目录与参数默认值变化--model-dir / --data-dir / --output-dir 默认值改为 /root/models/root/datasets/root/shared_data,旧 ${BASE_DIR} 等路径不再内建;依赖集群注入的 msc miles 场景需通过 MILES_SCRIPT_* 覆盖。
  5. ray dashboard 访问变化ray start 不再传 --dashboard-host/--dashboard-port,远程 dashboard 访问方式改变(提交仍走默认 8265)。

对用户而言,所有模型启动入口从 bash 变量风格切换为 typer flags,6 个 Qwen3 dense shell 脚本合并为一个入口;文档和启动方式都需要重新学习。对团队而言,净删除约 11000 行,启动器规则文件(#2357)也开始约束 python 启动器的书写风格,长期降低维护成本。影响范围覆盖 scripts/、miles/utils/external_utils/command_utils.py、tests/fast 快照与 harness、docs 约 21 页,共 115 个文件,是本仓库启动器体系的系统性重构。

115 文件大改动 删除 24 个 shell 启动器 快照验证不覆盖真实训练行为 NPU 启动器空缺 路径默认值变更 ray dashboard 访问变化

关联 Issue

#1837 Tracking issue for refactoring and enhancements
#1910 Replace the model config shell scripts with python

完整报告

参与讨论