# MVP v1.1（GRPO + SFT on Ray）运行说明

本目录是一套**独立可运行**的 v1.1 交付：使用 1 个 Ray head（不跑训练）+ 2 个 Ray worker（各 4 GPU）在同一宿主机通过 `docker exec` 协调容器，并通过 **head 上的 `ray job submit`** 提交作业，同时强制 driver 落到 worker。

> 远程 dev 环境推荐目录布局：
>
> - `/home2/argus/infra/mvp/`
>   - `shared/`（持久化：datasets/hf/jobs/...）
>   - `verl/`（代码仓库，用于 prepare / snapshot）
>   - `v1.1/`（本目录内容：compose + scripts）

---

## 快速开始（远程机 argus@h1）

在 `/home2/argus/infra/mvp/v1.1/` 下执行：

```bash
./scripts/run_all.sh
```

说明：
- `run_all.sh` 会按顺序提交 `ppo -> grpo -> sft`，并等待每个 job 结束后再提交下一个（避免 8 卡集群并发提交导致 “available GPUs 0” 直接失败）。

等价的“分步执行”：

```bash
./scripts/00_prereq_check.sh
./scripts/03_cleanup_v1_legacy.sh
./scripts/05_ensure_verl_repo.sh
./scripts/01_up.sh
./scripts/20_start_head.sh
./scripts/21_start_workers.sh
./scripts/30_prepare_data_and_model.sh
./scripts/12_install_py_deps.sh
./scripts/44_submit_sdk.sh /workspace/mvp/v1.1/py/configs/dev.yaml /workspace/mvp/v1.1/py/jobspecs/ppo.yaml   # no-wait
./scripts/44_submit_sdk.sh /workspace/mvp/v1.1/py/configs/dev.yaml /workspace/mvp/v1.1/py/jobspecs/grpo.yaml  # no-wait
./scripts/44_submit_sdk.sh /workspace/mvp/v1.1/py/configs/dev.yaml /workspace/mvp/v1.1/py/jobspecs/sft.yaml   # no-wait
./scripts/50_status.sh
```

停止并清理：

```bash
./scripts/02_down.sh
```

---

## 关键约束（必须满足）

- **必须通过 head 执行 `ray job submit`** 提交任务（满足“从 head 提交”要求）。
- **head 不跑训练**：head 以 `--num-cpus=0 --num-gpus=0` 启动；worker 具备自定义资源 `worker_node`；提交时 `--entrypoint-resources='{"worker_node": 1}'` 强制 driver 落 worker。
- **共享路径统一为 `/private`（容器内）**：compose 将宿主机 `../shared` 挂载到容器内 `/private`，对齐生产环境。
- **job 级别 code_path**：训练 JobSpec 中的 `code_path` 指向 `/private/common/code/verl/verl_repo`（由 `scripts/30_prepare_data_and_model.sh` 准备）。

---

## 共享目录（容器内 /private）

- `/private/datasets/`：数据（PPO 的 gsm8k RL parquet、SFT parquet）
- `/private/hf/`：HF 缓存（模型持久化，避免重复下载）
- `/private/jobs/<submission_id>/`：每个 Ray Job 的输出目录（logs/config/debug/checkpoints）
- `/private/common/`：共享区（模型/数据/代码快照）
- `/private/user/`：用户自定义代码（例如 reward_fn）
