8.7 KiB
8.7 KiB
MVP v3.5(精简版)开发计划(TDD)
目标:在 v3.0 已有能力基础上,仅新增两项能力:
- Advanced TaskSpec(自定义 command)
- Custom Reward(方式 A:用户自己在 command 里写
custom_reward_function.*)设计依据:
specs/mvp/v3.5/v3.5_design.md(本计划不再扩展 scope)。
0. 范围与约束
0.1 In scope
- 新增
kind: advanced的 TaskSpec:用户提供command,平台做$HOME宏替换与 best-effort 校验,再提交 Ray Job。 - Custom Reward:平台仅做 reward path 校验(方式 A),不新增结构化字段。
$HOME/common/*路径语义支持(关键):用户在 SFTPGo/WebClient 看到的路径能被训练进程正确读取。
0.2 Out of scope(本轮不做)
- 自定义 verl 版本/代码路径(多版本共存)
- 断点续训(resume from checkpoint)
- IB/RoCEv2/NCCL 专项支持
- Model Serving
- Node management 改造(v3.0 的 stateless head/worker/watchdog/supervisor 机制保持不变)
0.3 关键路径映射(必须保持一致)
说明:SFTPGo 的
$HOME/common/...是 virtual folder,训练进程看不到该虚拟路径。
提交 Advanced command 前必须展开/映射:
$HOME/common/datasets→/private/datasets(只读语义)$HOME/common/hf→/private/hf(只读语义)- 其余
$HOME→/private/users/<user_id>
并且为兼容历史用法(v3.0):
- Basic TaskSpec 仍接受
/private/common/datasets/...、/private/common/hf/...(不强制迁移)。
1. 测试策略(TDD)
1.1 单元测试优先级
- 解析与兼容:
kind: advanced能解析;无kind仍按 Basic 解析,旧用法不破坏。 - 宏替换正确性:
$HOME/$HOME/common/*映射严格按约定展开。 - best-effort 校验:拒绝明显危险/跨用户路径;对 reward path 做 allowlist。
- 提交链路:Scheduler 能识别 Advanced spec 并调用对应的提交方法,确保 submission_id/目录规范不变。
- WebUI/API:New Task 模板与
/spec展示完整 resolved spec(包含展开后的 command)。
1.2 本地运行方式
- 复用已有
.venv,执行:.venv/bin/python -m pytest - 若环境没有 pip,使用 uv 的方式参考 v3.0 约定(不在本计划重复)。
2. 里程碑划分(每个里程碑可独立验证)
约定:每个里程碑先写测试(失败),再实现代码使测试通过;里程碑结束跑一遍
pytest。
M1 — TaskSpec 模型与解析(兼容优先)
目标
- 引入 AdvancedTaskSpec 数据结构与 union parser,同时保证 v3.0 Basic 行为不变。
新增/修改(建议位置)
src/mvp/py/argus/ray/models.py- 新增
AdvancedTaskSpec - 新增
parse_taskspec(obj: dict) -> JobSpec | AdvancedTaskSpec - 兼容策略:缺省
kind→ 走JobSpec.from_dict
- 新增
测试(先写)
src/mvp/py/tests/test_models.pytest_parse_taskspec_basic_no_kind_compat()test_parse_taskspec_advanced_smoke()test_parse_taskspec_advanced_requires_command_nnodes_gpus()
验收
pytest -q通过;旧测试不修改或仅做最小必要更新。
M2 — Advanced command 展开与校验(核心能力)
目标
- 实现 command 展开(含
$HOME/common/*映射)与 best-effort 强约束校验。
实现点(建议新增模块)
src/mvp/py/argus/service/command_expand.py(或放在argus/service/validation.py)expand_advanced_command(user_id: str, command: str) -> strvalidate_advanced_command(user_id: str, expanded_command: str) -> None(失败抛ValueError)
强约束(与设计文档一致)
- 必须包含
python3且包含-m verl.trainer.(否则 400) - 禁止出现
/private/users/<other>/...(跨用户路径) - 若检测到
data.train_files=/data.val_files=:- 只允许
/private/users/<me>/datasets/...或/private/datasets/... - (兼容)允许
/private/common/datasets/...(旧路径)
- 只允许
- 若检测到
custom_reward_function.path=:- 只允许
/private/users/<me>/code/...(展开后校验)
- 只允许
测试(先写)
- 新增:
src/mvp/py/tests/test_advanced_command.pytest_expand_maps_home_common_datasets_to_private_datasets()test_expand_maps_home_common_hf_to_private_hf()test_expand_maps_home_to_private_users()test_validate_rejects_cross_user_paths()test_validate_requires_verl_trainer_entry()test_validate_allows_reward_path_under_user_code()test_validate_rejects_reward_path_outside_user_code()
验收
- 单测覆盖映射/校验的正反例;错误信息可读(用于 API 400 detail)。
M3 — Ray 提交链路支持 Advanced(Builder/Tool/Scheduler)
目标
- Advanced spec 能进入 scheduler 队列并提交为 Ray job(driver 仍落 worker)。
代码改动点(建议)
src/mvp/py/argus/ray/builders.py- 新增
build_advanced_argv(command: str):返回["bash","-lc", expanded_command]
- 新增
src/mvp/py/argus/ray/ray_job_tool.py- 新增
submit_advanced(...)(或统一成内部 submit plan) - runtime_env:继续注入公共 verl code path(本轮不支持用户自定义 verl 代码)
- 可选:把
/private/users/<user>/code加入PYTHONPATH,提升 reward 代码import体验
- 新增
src/mvp/py/argus/service/scheduler.py- 使用
parse_taskspec分流 Basic/Advanced - Advanced 调用
tool.submit_advanced(...)
- 使用
测试(先写)
src/mvp/py/tests/test_builders.pytest_build_advanced_argv_uses_bash_lc()
src/mvp/py/tests/test_scheduler.py- 新增一个
kind: advanced的任务,断言 scheduler 调用了submit_advanced - 断言 job_dir/submission_id 规则不变(仍按
/private/users/<user>/jobs/<sid>)
- 新增一个
src/mvp/py/tests/test_ray_job_tool.py- 断言 advanced 提交时 entrypoint 是 driver_entrypoint +
bash -lc ...
- 断言 advanced 提交时 entrypoint 是 driver_entrypoint +
验收
- 单测跑通;Scheduler tick 能完成 Advanced 任务从 QUEUED → SUBMITTED(mock Ray)。
M4 — API & WebUI(最小功能闭环)
目标
- WebUI/HTTP API 能提交 Advanced Task,并在详情页看到 resolved spec(含完整 command)。
API 改动点
src/mvp/py/argus/service/app.pyPOST /api/v2/tasks:支持kind: advanced- 保存 raw YAML(保持与 Basic 一致)
- 对 Advanced:展开 command + 校验(失败返回 400)
GET /api/v2/tasks/{task_id}/spec:- 返回 resolved spec(建议同时返回 raw + expanded,或 YAML 中直接给 expanded)
WebUI 改动点
src/mvp/py/argus/service/ui.py- New Task 页面新增 Advanced 模板(含中文注释)
- 文案强调共享目录:
$HOME/common/datasets、$HOME/common/hf
测试(先写)
src/mvp/py/tests/test_app.pytest_create_task_advanced_ok()(最小 valid command)test_create_task_advanced_rejects_invalid_command()test_task_spec_endpoint_includes_expanded_command()
src/mvp/py/tests/test_ui.py- 断言页面包含 Advanced 示例块
验收
pytest通过;浏览器可提交 Advanced YAML 并看到 expanded command。
M5 — 端到端验证(远端 argus@h1)
目标
- 在真实 Ray cluster + VERL 环境下验证 Advanced 与 Custom Reward(方式 A)。
步骤(手工验收脚本化可选)
- 启动 v3.0/v3.5 统一的 compose + API(沿用现有
run_all脚本体系) - 用户(如
alice)通过 SFTP 上传 reward 代码到:$HOME/code/reward.py(真实路径/private/users/alice/code/reward.py)
- 通过 WebUI 或 curl 提交 Advanced task:
command中包含:custom_reward_function.path=$HOME/code/reward.pycustom_reward_function.name=compute_scoredata.train_files=$HOME/common/datasets/gsm8k/train.parquetdata.val_files=$HOME/common/datasets/gsm8k/test.parquet
- 检查:
- 任务状态从 QUEUED → RUNNING → SUCCEEDED/FAILED(有日志)
- driver 不在 head 上跑(dashboard 验证)
- 日志出现 “custom reward” 生效的提示(按 VERL 实际日志关键字确认)
- 回归:提交 Basic ppo/grpo/sft 任务仍可运行(确保兼容性)
验收
- Advanced task 能跑至少若干 step,且 reward 注入生效。
- Basic 任务兼容不回退。
3. 风险点与边界(明确写进 PR/变更说明)
- Advanced command 只做 best-effort 校验,不做完整 shell AST 解析;复杂命令可能存在漏检/误判(后续可扩展)。
$HOME/common/*是“用户侧语义”,服务层必须映射到真实路径,否则训练必然 FileNotFound。- 校验策略(强约束)如果后续要允许非 VERL 命令,需要调整规则并补测试(本轮默认拒绝)。