# MVP v1.1 计划(Hardening + 多 Workload 可行性验证) 本目录是 `specs/mvp/v1/` 的下一步迭代:在 v1 已经跑通(Ray head + 2 worker,PPO on Ray,持久化落盘)的基础上,把它升级为**可长期回归**的最小系统,并扩展至少一个新 workload 的可行性闭环。 > v1.1 的目标不是做平台服务化(API/队列/多用户)——那是 v2/v3 的工作;v1.1 聚焦“工程化 + 可行性边界验证 + 可观测/可排障基础”。 --- ## 1. v1 基线回顾(已完成) - 拓扑:1 head(无 GPU,CPU/GPU=0)+ 2 worker(各 4 GPU) - 提交方式:必须用 head 上的 `ray job submit` - driver 调度:通过 `worker_node` 自定义资源 + `--entrypoint-resources` 强制 driver 在 worker - 输出:按 `submission_id` 组织到共享目录(NFS) 相关实现参考: - 脚本:`src/mvp/v1/` - 验收动作:`specs/mvp/v1/v1_action.md` - Roadmap:`specs/mvp/mvp_roadmap.md` --- ## 2. v1.1 目标(必须达成) ### 2.1 工程化(Hardening) 1) **JobSpec 标准化(最小)** - 把“提交 job 需要的参数”收敛成结构化文件: - Ray 基础配置(YAML):cluster 地址、entrypoint 资源约束、runtime_env 等 - 训练 JobSpec(YAML):workload 语义与训练参数 - 至少覆盖:`submission_id`、workload 类型、资源需求、共享根路径、模型/数据路径、输出目录、超时、环境变量注入。 - v1.1 实现落点(已在 repo 里提供,SDK 方式): - RayConfig 示例:`src/mvp/v1.1/py/configs/dev.yaml` - JobSpec 示例:`src/mvp/v1.1/py/jobspecs/{ppo,grpo,sft}.yaml` - 提交入口:`src/mvp/v1.1/py/run.py`(在 head 容器内执行,使用 Ray Python SDK 提交) - 设计文档:`specs/mvp/v1.1/sdk_submit_refactor.md` 2) **共享根路径抽象(dev/prod 一致)** - 引入 `SHARED_ROOT` 作为唯一共享根路径: - dev:建议也用 `/private`(docker compose 把宿主机 shared 挂到容器内 `/private`,模拟生产) - prod:固定 `/private`(算力平台容器内 NFS) - 任何代码/脚本不得写死 `/mnt/shared`(允许兼容旧路径但不得作为主路径)。 3) **共享目录分层(新增 `common/` 与 `user/`)** - 在 `datasets/hf/jobs/outputs` 之外,新增一个所有用户可读写的共享区: - `${SHARED_ROOT}/common/`:共享模型/数据/代码快照(多版本 verl / 公共数据) - `${SHARED_ROOT}/user/`:用户自定义代码(例如 `reward_fn_path` 指向这里) - v1.1 默认策略:先假设“所有用户可写”(后续 v3 再做权限与隔离)。 4) **可排障基础** - 每个 job 目录必须有: - `config/`:提交命令、JobSpec 快照、关键 env_vars - `logs/`:Ray job logs + hydra logs(如有) - `checkpoints/`:按 `save_freq` 控制频率(默认每 10 step) - 提供“失败快照”能力:收集 `ray status` / `ray job list` / `ray list nodes` / `ray list actors`(最少其中 2 项)写入 job 目录。 - v1.1 submitter 默认落盘: - `${SHARED_ROOT}/jobs//config/job_spec.json` - `${SHARED_ROOT}/jobs//config/runtime_env.json` - `${SHARED_ROOT}/jobs//config/submit_cmd.txt` - `${SHARED_ROOT}/jobs//logs/ray_job_submit.out` - `${SHARED_ROOT}/jobs//debug/ray_status_{pre,post}.txt` - `${SHARED_ROOT}/jobs//debug/ray_job_list_post.txt` ### 2.2 Workload 扩展(至少新增 1 个) v1.1 需要新增并验收通过两个 workload(都要跑通闭环): - **GRPO on Ray**(推荐优先,复用 PPO 入口,通过算法配置切换) - 基于 `python -m verl.trainer.main_ppo` - 通过配置覆盖:`algorithm.adv_estimator=grpo`(以及必要的 rollout 参数) - **SFT on Ray(Ray-native)** - 入口:`python -m verl.trainer.sft_trainer_ray` - 参考实现:`verl/verl/trainer/sft_trainer_ray.py`(内部会 `ray.init()`) - 需要确保 `ray.init()` 连接已有集群: - 优先:`runtime_env.env_vars.RAY_ADDRESS=auto`(配合 `ray job submit`) - 兜底:在 v1.1 的 launcher 脚本里显式 `ray.init(address="auto")` 再调用 trainer(避免依赖 Ray 的 env var 行为差异) - 重要细节:Ray Job 的 entrypoint(driver)默认不分配 GPU,因此 SFT driver 侧不要强依赖 CUDA: - 推荐:`trainer.device=cpu`(driver 只做 orchestration;训练由 Ray workers 占 GPU) --- ## 3. v1.1 关键设计点 ### 3.1 多版本代码与自定义逻辑(为 v3.1 铺路,但 v1.1 先做最小验证) 已确定优先方案(A):通过 **Ray Job 的 `runtime_env.env_vars`** 注入 `PYTHONPATH`。 - `code_path`(例如 `${SHARED_ROOT}/common/code/verl/`) - 提交 job 时设置: - `runtime_env.env_vars.PYTHONPATH = ":$PYTHONPATH"` 并约定: - `reward_fn_path` 可指向 `${SHARED_ROOT}/user/code/...` 下用户自定义代码 - 与 `code_path` 一样,必须通过 `runtime_env.env_vars` 确保该路径可被 import(例如把 `${SHARED_ROOT}/user/code` 也加入 `PYTHONPATH`) v1.1 中至少做一次“代码覆盖验证”: - 在 code_path 下放一个可识别的 `verl` 版本标识(例如 `verl.__version__` 打印差异) - 提交 job 并在日志中确认 import 的是 code_path 的版本(而不是镜像内默认安装) v1.1 的最小落地方式(已实现): - 提供代码快照脚本:`src/mvp/v1.1/scripts/31_snapshot_verl_code.sh` - 会把 `/workspace/verl`(挂载的 repo)复制到 `${SHARED_ROOT}/common/code/verl//` - 并写入 `${code_path}/mvp_marker.py`,用于在 Ray job logs 中验证“选用的是哪份 code_path” - submitter 会在 entrypoint 前运行 preflight: - 打印 `verl.__file__` 与 `mvp_marker.MARKER` - 由此确认 job 粒度的 PYTHONPATH 生效,且不同 job 可指向不同 `code_path`(多版本共存) ### 3.2 Checkpoint 策略(磁盘保护) - 默认:`save_freq=10`(每 10 step 保存一次) - 对于 step 数已知的短任务(例如 29 steps),可以通过配置把 `save_freq` 调整为 10/15/29(按需求权衡) - 作业目录按 `submission_id` 隔离,方便清理与归档 --- ## 4. v1.1 交付物清单(代码 + 文档) ### 4.1 代码(建议落点) 在 `src/mvp/` 下新增 v1.1 级别的提交器与模板(或在 `src/mvp/v1` 原地演进但要保持 v1 可回归): - `src/mvp/v1.1/` - `docker-compose.yaml`(与 v1 互不干扰的容器名/网络名) - `scripts/`(Ray 启动/prepare 保留 bash;submit 通过 SDK 工具执行) - `py/`(工程化提交层:YAML + Ray Python SDK) - `py/configs/`(Ray 基础配置) - `py/jobspecs/`(训练 JobSpec) - `py/run.py`(入口) 此外,为了对齐 dev 环境约束(远程机固定目录): - 远程机目录必须新增:`argus@h1:/home2/argus/infra/mvp/v1.1/` - 该目录内需包含 v1.1 的全部内容(compose + scripts + README),可由本 repo 的 `src/mvp/v1.1/` 同步过去 ### 4.2 文档 - `specs/mvp/v1.1/v1.1_action.md`:开发、部署、测试、验收流程(可复现) - 更新 `specs/mvp/mvp_roadmap.md`:保持路线图与落地一致(按需) --- ## 5. v1.1 验收标准(DoD) ### 5.1 Hardening DoD - [ ] 所有提交均由 head 执行 `ray job submit`,且显式 `--submission-id=` - [ ] 共享根路径由 `SHARED_ROOT` 控制(dev/prod 可切换),脚本无硬编码 - [ ] 每个 job 的输出目录为:`${SHARED_ROOT}/jobs//` - [ ] checkpoint 不会“每 step 保存”导致爆盘:默认 `save_freq=10` - [ ] job 失败时,`${SHARED_ROOT}/jobs//config/` 中有足够信息定位(命令、env、ray 状态快照) - [ ] v1.1 测试前会清理 v1 的遗留容器/进程(避免端口、容器名、Ray session 干扰) ### 5.2 Workload DoD(GRPO + SFT 都必须) GRPO(必须): - [ ] `algorithm.adv_estimator=grpo` 的 job 可提交并进入 RUNNING - [ ] job 能跑完最小训练步数(可设 `total_epochs=1` 或 `total_training_steps`) - [ ] 输出目录内有日志与至少 1 次 checkpoint(或明确不保存并说明原因) SFT(必须): - [ ] `sft_trainer_ray` 可连接集群并跑到至少 1 个 step(推荐最小训练步数/epoch) - [ ] 输出目录与 checkpoint 策略同 v1.1 规范(落盘到 `${SHARED_ROOT}/jobs//...`)