# MVP v3.0 迭代总结(Ray + SFTPGo + API + WebUI) 本文总结 v3.0 迭代最终落地的功能、架构、运行方式、验收点与已知限制,便于后续评审、交接与继续迭代。 相关更详细文档: - `specs/mvp/v3.0/v3.0_design.md` - `specs/mvp/v3.0/v3.0_api.md` - `specs/mvp/v3.0/v3.0_dev_plan.md` - `specs/mvp/v3.0/v3.0_acceptance.md` - `specs/mvp/v3.0/v3.0_progress.md` --- ## 1. 目标与范围 v3.0 作为“第一版可发布”的最小闭环,主要新增: - **WebUI**:最小可用的人机界面(登录、任务提交与查看、数据入口、管理员入口)。 - **用户管理**:基于内部 token 的用户体系(admin 与普通用户),支持创建用户与签发 token。 - **数据管理入口(SFTPGo)**:用户通过 SFTP/WebClient 上传下载自己的数据;同时暴露只读的共享数据/缓存目录(common)用于复用。 - **保持训练闭环**:仍通过 Ray Job 提交到集群执行(PPO/GRPO/SFT 三类 workload 都验证)。 明确不做(本迭代保持最小): - 不支持用户自定义训练代码(TaskSpec 的 `code_path` 固定走 common 下的 verl snapshot 策略)。 - 不做复杂资源排队优化/多集群/多租隔离策略(目前隔离粒度主要在用户 jobs 目录层)。 --- ## 2. 系统架构(最终形态) 核心组件: - **Ray 集群(容器)** - `argus-ray-head`:head 节点(无 GPU/不跑训练),提供 Ray Dashboard 与 Job Server。 - `argus-ray-worker-0/1`:worker 节点(有 GPU),承载训练任务。 - worker 以 “stateless + watchdog 自动连接 head” 的方式加入集群。 - **API Server(运行在 head 容器内)** - 读取 YAML 配置(dev/prod),维护任务队列(sqlite),并周期性调度将任务提交到 Ray。 - 同时承载 WebUI(`/ui`)。 - **SFTPGo(容器)** - 提供 SFTP(端口 `2022`)与 Web Client/Admin(端口 `8081` 映射到容器 8080)。 - 用户 home 为 `/private/users/`,默认可读写。 - 额外提供 `/common/*` 共享只读入口(见第 4 节)。 - **共享存储(NFS/GPFS 等挂载到容器内 `/private`)** - `/private/common`:共享缓存(hf、datasets、models、db、logs 等)。 - `/private/users/`:用户隔离目录(jobs/datasets/models/code/trash 等)。 --- ## 3. 任务与调度(Task / Ray Job) ### 3.1 Task(平台概念) - 用户向 API 提交 TaskSpec(YAML),平台分配 `task_id`(可读、包含用户名)。 - `task_id` 对应内部状态机与重试逻辑;底层每次提交 Ray Job 会产生 attempt 与 `ray_submission_id`。 ### 3.2 Ray Job(Ray 概念) - 真正执行训练的 driver 通过 Ray Job 运行在集群 worker 上(避免 head 承载训练)。 - head 节点通过 `--num-cpus=0` / 自定义资源等策略避免调度到 head。 ### 3.3 VERL 资源预检查的处理 - VERL 在创建资源池时会做 fail-fast 资源预检查(如“可用 GPU 不足”直接报错退出)。 - v3.0 延续 v2.x 的策略:服务端识别失败原因并按策略重试/回退(具体见 scheduler 实现与 v2.5/3.0 文档)。 --- ## 4. 数据管理(SFTPGo)与 common 只读目录 ### 4.1 用户目录(读写) - 用户通过 SFTP/WebClient 访问自己的 home:`/private/users/` - 目录结构(至少):`datasets/ models/ code/ jobs/ trash/ common/` ### 4.2 common 只读(方案 A:Virtual Folder) 本迭代采用 SFTPGo 的 Virtual Folder + 路径权限覆盖,实现用户可读共享目录但不可写。 最终对外暴露为: - `/common/datasets`(只读) - **mapped_path 指向真实目录 `/private/datasets`**(避免 `/private/common/datasets` 中大量 symlink 导致的 WebClient “权限不足/越界”问题) - `/common/hf`(只读) - mapped_path 指向 `/private/hf` 备注: - `/private/common/datasets` 内部存在 symlink(如 `gsm8k -> /private/datasets/gsm8k`),如果虚拟目录映射到 symlink 根目录,SFTPGo 会把 symlink 跳转视为“逃逸 root”,导致点击进入时报权限不足;因此选择直接映射到真实目录根。 --- ## 5. WebUI(最小可用) 入口: - `/ui/login`:粘贴 token(存 browser `localStorage`) - `/ui/tasks`:任务列表(Running/Pending/Completed),Completed 支持分页 - `/ui/tasks/new`:提交任务(PPO/GRPO/SFT 三套样例可一键填充) - `/ui/data`:展示当前用户名、支持重置 SFTPGo 密码并复制;提供跳转到 SFTPGo WebClient;提示 FileZilla 等客户端用法 - `/ui/admin`:管理员入口(创建用户、签发 token、用户列表) - 导航栏提供 Ray Dashboard 快捷跳转(当前 IP 的 `:8265`) 关于 admin 页面权限: - admin 页面本身可访问,但其数据请求必须携带 admin token;否则会在页面内显示 401/403/错误信息(满足“需要先提供 admin token 才能看到内容”)。 --- ## 6. API(v3.0 新增/强化点) 核心接口(节选): - 认证: - Bearer token:`MVP_INTERNAL_TOKEN`(admin)或用户 token(由 admin 签发) - 用户管理(admin): - `POST /api/v2/users` 创建用户(并初始化用户目录) - `GET /api/v2/users` 获取用户列表(包含最新 token、创建/更新时间等) - `POST /api/v2/users/{user_id}/tokens` 签发用户 token - 任务: - `POST /api/v2/tasks` 提交 TaskSpec(YAML) - `GET /api/v2/tasks` 任务列表(支持 states/limit/offset,用于 Completed 分页) - `GET /api/v2/tasks/{task_id}`、`POST /api/v2/tasks/{task_id}:cancel`、`GET /api/v2/tasks/{task_id}/logs` - `GET /api/v2/queue`(运行中/待调度概览) - 数据/SFTP: - `GET /api/v2/me` 返回用户路径信息、SFTP 连接信息,并 best-effort 对齐 SFTPGo 用户配置 - `POST /api/v2/me/sftp:reset_password` 用户自助重置 SFTPGo 密码(一次性返回明文) 安全取舍说明(当前为内网/开发优先): - 为了 Admin WebUI “可查看并复制 token”,数据库持久化存储了 `token_plain`(明文 token)。 - 这在生产场景通常不建议;未来可改为只展示“重置/重新签发”而不回显明文,或只回显一次。 --- ## 7. 持久化与清理 - 任务队列:sqlite(WAL 模式) - SFTPGo:自带 sqlite db(容器挂载持久化目录) - Jobs 目录清理策略(服务端 janitor): - job 结束后 3 天移动到回收目录(trash) - 回收目录再保留 7 天后删除 --- ## 8. 运行方式与脚本 开发/验收脚本: - `src/mvp/scripts/run_all_v30_api.sh`:端到端拉起(Ray + SFTPGo + API),并通过 API 提交 PPO/GRPO/SFT,等待完成并验收 - 其他脚本用于启动/停止 API、准备数据与模型、探测服务就绪等(详见 scripts 目录与 README) 典型端到端(示例参数): - `MVP_INTERNAL_TOKEN=my-dev-token` - `SFTPGO_ADMIN_PASSWORD=my-dev-sftpgo-admin` - 支持 `RESET_DB/RESET_SFTPGO` 用于测试环境重置 --- ## 9. 验证结果(已跑通) 在 `argus@h1` 环境中已完成端到端验证: - Ray 集群可用(head + 2 worker) - API server + WebUI 可用 - SFTPGo(admin + 普通用户)可用 - 通过 API 连续提交 PPO/GRPO/SFT 三种任务均能完成(SUCCEEDED) - 用户可以登录 SFTPGo WebClient/SFTP,访问自己的目录,并访问 `/common/datasets`、`/common/hf` 的只读内容 同时本地单测通过: - pytest 全绿 - 覆盖率阈值 >= 90% --- ## 10. 已知限制 & 后续可改进 - WebUI 当前为最小版,交互与权限提示仍偏“工程化”而非产品化(后续可增强错误提示、搜索筛选、任务详情聚合等)。 - token 明文持久化仅适合内网/开发场景;生产建议改为一次性展示或支持撤销/轮换策略。 - SFTPGo 虚拟目录目前保留了历史遗留映射(例如 `/common/models` 可能残留),后续可在升级脚本中做一次性清理与迁移。