argus-cluster/specs/mvp/v3.5/v3.5_dev_plan.md

8.7 KiB
Raw Blame History

MVP v3.5精简版开发计划TDD

目标:在 v3.0 已有能力基础上,仅新增两项能力:

  1. Advanced TaskSpec自定义 command
  2. 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 单元测试优先级

  1. 解析与兼容kind: advanced 能解析;无 kind 仍按 Basic 解析,旧用法不破坏。
  2. 宏替换正确性$HOME / $HOME/common/* 映射严格按约定展开。
  3. best-effort 校验:拒绝明显危险/跨用户路径;对 reward path 做 allowlist。
  4. 提交链路Scheduler 能识别 Advanced spec 并调用对应的提交方法,确保 submission_id/目录规范不变。
  5. WebUI/APINew 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.py
    • test_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) -> str
    • validate_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.py
    • test_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 提交链路支持 AdvancedBuilder/Tool/Scheduler

目标

  • Advanced spec 能进入 scheduler 队列并提交为 Ray jobdriver 仍落 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.py
    • test_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 ...

验收

  • 单测跑通Scheduler tick 能完成 Advanced 任务从 QUEUED → SUBMITTEDmock Ray

M4 — API & WebUI最小功能闭环

目标

  • WebUI/HTTP API 能提交 Advanced Task并在详情页看到 resolved spec含完整 command

API 改动点

  • src/mvp/py/argus/service/app.py
    • POST /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.py
    • test_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

步骤(手工验收脚本化可选)

  1. 启动 v3.0/v3.5 统一的 compose + API沿用现有 run_all 脚本体系)
  2. 用户(如 alice)通过 SFTP 上传 reward 代码到:
    • $HOME/code/reward.py(真实路径 /private/users/alice/code/reward.py
  3. 通过 WebUI 或 curl 提交 Advanced task
    • command 中包含:
      • custom_reward_function.path=$HOME/code/reward.py
      • custom_reward_function.name=compute_score
      • data.train_files=$HOME/common/datasets/gsm8k/train.parquet
      • data.val_files=$HOME/common/datasets/gsm8k/test.parquet
  4. 检查:
    • 任务状态从 QUEUED → RUNNING → SUCCEEDED/FAILED有日志
    • driver 不在 head 上跑dashboard 验证)
    • 日志出现 “custom reward” 生效的提示(按 VERL 实际日志关键字确认)
  5. 回归:提交 Basic ppo/grpo/sft 任务仍可运行(确保兼容性)

验收

  • Advanced task 能跑至少若干 step且 reward 注入生效。
  • Basic 任务兼容不回退。

3. 风险点与边界(明确写进 PR/变更说明)

  • Advanced command 只做 best-effort 校验,不做完整 shell AST 解析;复杂命令可能存在漏检/误判(后续可扩展)。
  • $HOME/common/* 是“用户侧语义”,服务层必须映射到真实路径,否则训练必然 FileNotFound。
  • 校验策略(强约束)如果后续要允许非 VERL 命令,需要调整规则并补测试(本轮默认拒绝)。