cleaning code

This commit is contained in:
2026-01-13 10:46:43 +08:00
parent ac9c80ed8c
commit 4a5afb7ed7
91 changed files with 1 additions and 13294 deletions

View File

@@ -1,64 +0,0 @@
ray:
# Ray Job server address (head 容器内视角)
address: "http://127.0.0.1:8265"
# 共享根路径(容器内统一 /private,对齐生产)
shared_root: "/private"
# 强制 driver 落 worker(head 不跑训练)
entrypoint_num_cpus: 1
entrypoint_resources:
worker_node: 1
# 所有 job 通用 runtime env
runtime_env:
env_vars:
HF_ENDPOINT: "https://hf-mirror.com"
PYTHONUNBUFFERED: "1"
# v3.7: forbid HuggingFace Hub network access from Ray jobs (use cached snapshots).
HF_HUB_OFFLINE: "1"
# Unify cache dirs so `from_pretrained("org/name")` resolves from the same on-disk cache in offline mode.
HF_HOME: "/private/hf"
HUGGINGFACE_HUB_CACHE: "/private/hf/hub"
TRANSFORMERS_CACHE: "/private/hf/hub"
# v3.0 先不支持 user code 执行
user_code_path: "/private/user/code"
service:
api:
host: "0.0.0.0"
port: 8080
auth:
token_env: "MVP_INTERNAL_TOKEN"
sqlite:
db_path: "/private/common/db/mvp.sqlite3"
scheduler:
tick_s: 5
retry_interval_s: 60
max_running_tasks: 1
tracking:
wandb:
enabled: true
# For dev compose, recommend docker bridge gateway + host published port for stability.
base_url: "http://172.22.0.1:8090"
api_key_env: "WANDB_API_KEY"
project_suffix: "_project"
data:
user_root: "/private/users"
sftpgo:
enabled: true
# Returned to users by GET /api/v2/me. For h1 E2E, usually connect to the host IP.
host: "127.0.0.1"
sftp_port: 2022
# Admin API base should include /api/v2 (SFTPGo OpenAPI server base).
# From head container, access SFTPGo by service name on the compose network.
admin_api_base: "http://argus-sftpgo:8080/api/v2"
admin_user: "admin"
admin_password_env: "SFTPGO_ADMIN_PASSWORD"
retention:
jobs_trash_after_days: 3
jobs_purge_after_days: 7
janitor_interval_s: 3600

View File

@@ -1,118 +0,0 @@
# MVP V1(Ray + VERL PPO)实验脚本
本目录用于在“宿主机 + Docker 容器”环境下,**用宿主机脚本(`docker exec`)**协调启动 Ray 集群,并通过 **`ray job submit`(在 head 提交)**跑通一次 `verl` 的 PPO 训练闭环(`total_epochs=1`),且数据/模型/日志/ckpt 都持久化到宿主机目录。
## 1. 运行环境与拓扑
### 1.1 依赖
- 宿主机:Linux
- 必需工具:`docker`、`docker compose`(Compose v2 插件)、`git`
- GPU:至少 8 张可用 GPU(索引 `0-7`),Docker 的 NVIDIA runtime 可用
### 1.2 集群拓扑(3 个容器)
- `mvp-ray-head`(Ray Head)
- **不挂 GPU**(容器内 `nvidia-smi` 不可用)
- `ray start --head --num-cpus=0 --num-gpus=0`:head 只做控制面,不参与计算调度
- 暴露 dashboard:宿主机端口 `8265`
- `mvp-ray-worker-0`(Ray Worker)
- 4 GPU:`0,1,2,3`
- `ray start ... --resources='{"worker_node": 100}'`
- `mvp-ray-worker-1`(Ray Worker)
- 4 GPU:`4,5,6,7`
- `ray start ... --resources='{"worker_node": 100}'`
**关键点:driver 不在 head**
- 作业通过 head 提交:`ray job submit ...`
- 通过 `--entrypoint-resources='{"worker_node": 1}'` 强制 entrypoint/driver 只能调度到 worker(head 没有该资源)
## 2. 持久化目录(宿主机 <-> 容器)
在宿主机项目根目录(运行脚本时的 `${PWD}`)下使用 `./shared` 做持久化根目录,并 bind mount 到容器内 `/mnt/shared`:
- 宿主机:`./shared`
- 容器:`/mnt/shared`
主要内容:
- 数据集:`/mnt/shared/datasets/gsm8k/`
- HF 缓存:`/mnt/shared/hf/`(脚本会设置 `HF_HOME`,并尽量幂等跳过重复下载)
- 每个 Ray Job 的输出(按 submission id 分目录):
- `/mnt/shared/jobs/<submission_id>/logs/`
- `/mnt/shared/jobs/<submission_id>/checkpoints/`
## 3. 整体流程(代码逻辑)
脚本都在 `src/mvp/v1/scripts/`,整体顺序如下:
1) `00_prereq_check.sh`
- 检查 `docker/docker compose/git`
2) `05_ensure_verl_repo.sh`
- 若项目根目录下没有 `./verl`,自动 `git clone https://github.com/volcengine/verl.git`
3) `01_up.sh`
- 创建持久化目录(`./shared/...`)
- `docker compose up -d` 启动 3 个容器
4) `10_install_verl_editable.sh`
- 在 3 个容器内执行 `pip install -e /workspace/verl`(确保 `python -m verl...` 可用且代码与 `./verl` 同步)
5) `20_start_head.sh`
- 在 `mvp-ray-head` 内启动 Ray head(CPU=0、GPU=0)
6) `21_start_workers.sh`
- 在两个 worker 内启动 Ray worker 加入集群
- 同时给 worker 打 `worker_node` 自定义资源标签
7) `30_prepare_data_and_model.sh`
- 数据集:若 `train.parquet/test.parquet` 已存在则跳过,否则生成
- 模型:使用 HF cache(`HF_HOME=/mnt/shared/hf`),存在则跳过,不存在才下载
8) `40_submit_ppo_epoch1.sh`
- 在 head 容器里执行 `ray job submit`
- 显式指定 `--submission-id=$SUBMISSION_ID`
- 通过 `--entrypoint-resources='{"worker_node": 1}'` 强制 driver 在 worker
- 训练参数:
- `trainer.total_epochs=1`
- `trainer.total_training_steps=29`(GSM8K 该配置下对应 29 steps)
- `trainer.save_freq=10`(每 10 step 保存一次 checkpoint,避免磁盘爆炸)
- `trainer.default_local_dir=/mnt/shared/jobs/$SUBMISSION_ID/checkpoints`
- `hydra.run.dir=/mnt/shared/jobs/$SUBMISSION_ID/logs/hydra`
9) `50_status.sh`
- 打印 `ray status` / `ray job list` / `ray job status` / `ray job logs | tail`
## 4. 运行方法
### 4.1 一键执行
在项目根目录执行:
- `./src/mvp/v1/scripts/run_all.sh`
### 4.2 分步执行(推荐)
按顺序执行:
- `./src/mvp/v1/scripts/01_up.sh`
- `./src/mvp/v1/scripts/10_install_verl_editable.sh`
- `./src/mvp/v1/scripts/20_start_head.sh`
- `./src/mvp/v1/scripts/21_start_workers.sh`
- `./src/mvp/v1/scripts/30_prepare_data_and_model.sh`
- `SUBMISSION_ID=ppo_h20_8g_$(date +%Y%m%d_%H%M%S) ./src/mvp/v1/scripts/40_submit_ppo_epoch1.sh`
- `./src/mvp/v1/scripts/50_status.sh`
### 4.3 查看与停止
- Dashboard:`http://<宿主机IP>:8265`
- 列出作业(在 head 容器内):
- `docker exec mvp-ray-head bash -lc "ray job list --address=http://127.0.0.1:8265"`
- 停止某个 submission id:
- `docker exec mvp-ray-head bash -lc "ray job stop --address=http://127.0.0.1:8265 <submission_id>"`
### 4.4 清理
- 停止并删除容器:`./src/mvp/v1/scripts/02_down.sh`
- 清理输出(谨慎,数据量可能很大):删除 `./shared/jobs/<submission_id>/`
## 5. 常见坑
- **不传 `--submission-id` 会导致“输出目录难以等于 submission id”**:因为 hydra/ckpt 目录需要在提交前确定。当前脚本会显式传 `--submission-id=$SUBMISSION_ID`,并使用同名目录。
- **checkpoint 太大**:PPO 的 checkpoint 非常占空间。当前脚本默认 `save_freq=10`,如仍过大,可调大 `save_freq` 或减少保存内容/频率。
更多分步操作与验收标准见:`specs/mvp/v1_action.md`

File diff suppressed because it is too large Load Diff

View File

@@ -1,86 +0,0 @@
version: "3.8"
services:
ray_head:
image: verlai/verl:sgl055.latest
container_name: mvp-ray-head
command: sleep infinity
ports:
- "8265:8265"
volumes:
- ./verl:/workspace/verl
- ./shared:/mnt/shared
shm_size: "10g"
ulimits:
nofile:
soft: 65536
hard: 65536
cap_add:
- SYS_ADMIN
- SYS_PTRACE
networks:
- mvp-ray-net
environment:
HF_HOME: "/mnt/shared/hf"
HUGGINGFACE_HUB_CACHE: "/mnt/shared/hf/hub"
TRANSFORMERS_CACHE: "/mnt/shared/hf/transformers"
HF_ENDPOINT: "https://hf-mirror.com"
PYTHONUNBUFFERED: "1"
ray_worker_0:
image: verlai/verl:sgl055.latest
container_name: mvp-ray-worker-0
command: sleep infinity
volumes:
- ./verl:/workspace/verl
- ./shared:/mnt/shared
shm_size: "10g"
ulimits:
nofile:
soft: 65536
hard: 65536
cap_add:
- SYS_ADMIN
- SYS_PTRACE
networks:
- mvp-ray-net
runtime: nvidia
environment:
NVIDIA_VISIBLE_DEVICES: "0,1,2,3"
NVIDIA_DRIVER_CAPABILITIES: "all"
HF_HOME: "/mnt/shared/hf"
HUGGINGFACE_HUB_CACHE: "/mnt/shared/hf/hub"
TRANSFORMERS_CACHE: "/mnt/shared/hf/transformers"
HF_ENDPOINT: "https://hf-mirror.com"
PYTHONUNBUFFERED: "1"
ray_worker_1:
image: verlai/verl:sgl055.latest
container_name: mvp-ray-worker-1
command: sleep infinity
volumes:
- ./verl:/workspace/verl
- ./shared:/mnt/shared
shm_size: "10g"
ulimits:
nofile:
soft: 65536
hard: 65536
cap_add:
- SYS_ADMIN
- SYS_PTRACE
networks:
- mvp-ray-net
runtime: nvidia
environment:
NVIDIA_VISIBLE_DEVICES: "4,5,6,7"
NVIDIA_DRIVER_CAPABILITIES: "all"
HF_HOME: "/mnt/shared/hf"
HUGGINGFACE_HUB_CACHE: "/mnt/shared/hf/hub"
TRANSFORMERS_CACHE: "/mnt/shared/hf/transformers"
HF_ENDPOINT: "https://hf-mirror.com"
PYTHONUNBUFFERED: "1"
networks:
mvp-ray-net:
driver: bridge

View File

@@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
require_cmd docker
require_cmd git
if ! docker compose version >/dev/null 2>&1; then
echo "docker compose plugin not available; please install docker compose v2" >&2
exit 1
fi
echo "OK: docker + docker compose + git"

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
"${SCRIPT_DIR}/00_prereq_check.sh"
"${SCRIPT_DIR}/05_ensure_verl_repo.sh"
mkdir -p \
"${ROOT_DIR}/shared/hf" \
"${ROOT_DIR}/shared/datasets" \
"${ROOT_DIR}/shared/jobs" \
"${ROOT_DIR}/shared/outputs" \
"${ROOT_DIR}/shared/ray"
dc up -d
dc ps

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
dc down

View File

@@ -1,19 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
VERL_DIR="${ROOT_DIR}/verl"
if [[ -d "${VERL_DIR}/.git" ]]; then
echo "OK: verl repo exists: ${VERL_DIR}"
exit 0
fi
echo "verl repo not found at ${VERL_DIR}; cloning..."
rm -rf "${VERL_DIR}"
git clone https://github.com/volcengine/verl.git "${VERL_DIR}"
echo "OK: cloned verl -> ${VERL_DIR}"

View File

@@ -1,22 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
install_one() {
local name="$1"
echo "[${name}] ensure verl importable"
if ! dexec "${name}" python3 -c "import verl; print(verl.__file__)" >/dev/null 2>&1; then
echo "[${name}] verl not importable; installing editable from /workspace/verl"
dexec "${name}" bash -lc "pip install -e /workspace/verl"
else
echo "[${name}] verl import OK"
fi
}
install_one "${HEAD_CONTAINER}"
install_one "${WORKER0_CONTAINER}"
install_one "${WORKER1_CONTAINER}"

View File

@@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
echo "[head] ray stop (ignore errors)"
dexec "${HEAD_CONTAINER}" bash -lc "ray stop --force || true"
echo "[head] ray start (CPU=0, GPU=0 to prevent scheduling on head)"
HEAD_IP="$(container_ip "${HEAD_CONTAINER}")"
echo "[head] container ip: ${HEAD_IP}"
dexec "${HEAD_CONTAINER}" bash -lc "ray start --head --node-ip-address=${HEAD_IP} --dashboard-host=0.0.0.0 --dashboard-port=8265 --port=6379 --num-cpus=0 --num-gpus=0"
echo "[head] ray status"
dexec "${HEAD_CONTAINER}" bash -lc "ray status || true"

View File

@@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
start_worker() {
local name="$1"
local node_ip
node_ip="$(container_ip "${name}")"
echo "[${name}] ray stop (ignore errors)"
dexec "${name}" bash -lc "ray stop --force || true"
local head_ip
head_ip="$(container_ip "${HEAD_CONTAINER}")"
echo "[${name}] container ip: ${node_ip}"
echo "[${name}] ray start -> join ${head_ip}:6379 (num_gpus=4, resources worker_node=100)"
dexec "${name}" bash -lc "ray start --node-ip-address=${node_ip} --address=${head_ip}:6379 --num-gpus=4 --resources='{\"worker_node\": 100}'"
}
start_worker "${WORKER0_CONTAINER}"
start_worker "${WORKER1_CONTAINER}"
echo "[head] waiting for workers to register"
for _ in $(seq 1 30); do
if dexec "${HEAD_CONTAINER}" bash -lc "ray status" | grep -q "Active:"; then
break
fi
sleep 2
done
dexec "${HEAD_CONTAINER}" bash -lc "ray status || true"

View File

@@ -1,37 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
DATA_DIR="/mnt/shared/datasets/gsm8k"
MODEL_ID="Qwen/Qwen2.5-0.5B-Instruct"
echo "[head] prepare dataset (idempotent) -> ${DATA_DIR}"
dexec "${HEAD_CONTAINER}" bash -lc "mkdir -p ${DATA_DIR} && if [[ -f ${DATA_DIR}/train.parquet && -f ${DATA_DIR}/test.parquet ]]; then echo 'dataset_exists: skip'; else python3 /workspace/verl/examples/data_preprocess/gsm8k.py --local_save_dir ${DATA_DIR}; fi"
echo "[head] ensure model cached to persistent HF_HOME (idempotent) -> ${MODEL_ID}"
PY_CODE="$(cat <<'PY'
import os
model_id = os.environ["MODEL_ID"]
hf_home = os.environ.get("HF_HOME", "/mnt/shared/hf")
os.environ.setdefault("HF_HOME", hf_home)
os.environ.setdefault("HUGGINGFACE_HUB_CACHE", os.path.join(hf_home, "hub"))
os.environ.setdefault("TRANSFORMERS_CACHE", os.path.join(hf_home, "transformers"))
from huggingface_hub import snapshot_download
try:
snapshot_download(repo_id=model_id, local_files_only=True)
print("model_cache_exists: skip", model_id)
except Exception:
print("model_cache_missing: downloading", model_id)
snapshot_download(repo_id=model_id)
print("model_cached_ok:", model_id)
PY
)"
printf "%s\n" "${PY_CODE}" | dexec "${HEAD_CONTAINER}" bash -lc "MODEL_ID='${MODEL_ID}' python3 -"

View File

@@ -1,70 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
SUBMISSION_ID="${SUBMISSION_ID:-mvp_ppo_$(timestamp)_$RANDOM}"
# 为了让“输出目录 = submission id”,默认把 JOB_TAG 也设成 SUBMISSION_ID(可手动覆盖)。
JOB_TAG="${JOB_TAG:-${SUBMISSION_ID}}"
JOB_DIR="/mnt/shared/jobs/${SUBMISSION_ID}"
MODEL_ID="Qwen/Qwen2.5-0.5B-Instruct"
TRAIN_FILE="/mnt/shared/datasets/gsm8k/train.parquet"
VAL_FILE="/mnt/shared/datasets/gsm8k/test.parquet"
echo "[head] create job dir: ${JOB_DIR}"
dexec "${HEAD_CONTAINER}" bash -lc "mkdir -p ${JOB_DIR}/logs ${JOB_DIR}/checkpoints ${JOB_DIR}/config"
SUBMIT_CMD="python3 -m verl.trainer.main_ppo \
data.train_files=${TRAIN_FILE} \
data.val_files=${VAL_FILE} \
data.train_batch_size=256 \
data.max_prompt_length=512 \
data.max_response_length=512 \
actor_rollout_ref.model.path=${MODEL_ID} \
actor_rollout_ref.actor.optim.lr=1e-6 \
actor_rollout_ref.actor.ppo_mini_batch_size=64 \
actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=4 \
actor_rollout_ref.rollout.name=sglang \
actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=8 \
actor_rollout_ref.rollout.tensor_model_parallel_size=1 \
actor_rollout_ref.rollout.gpu_memory_utilization=0.4 \
actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=4 \
critic.optim.lr=1e-5 \
critic.model.path=${MODEL_ID} \
critic.ppo_micro_batch_size_per_gpu=4 \
algorithm.kl_ctrl.kl_coef=0.001 \
trainer.logger=console \
trainer.val_before_train=False \
trainer.n_gpus_per_node=4 \
trainer.nnodes=2 \
trainer.save_freq=10 \
trainer.test_freq=29 \
trainer.total_epochs=1 \
trainer.total_training_steps=29 \
trainer.resume_mode=disable \
trainer.default_local_dir=${JOB_DIR}/checkpoints \
+ray_kwargs.ray_init.address=auto \
hydra.run.dir=${JOB_DIR}/logs/hydra"
printf "%s\n" "${SUBMIT_CMD}" | dexec "${HEAD_CONTAINER}" bash -lc "cat > ${JOB_DIR}/config/submit_cmd.txt"
echo "[head] submit PPO via ray job submit (force driver on worker via entrypoint resources)"
SUBMIT_OUT="$(dexec "${HEAD_CONTAINER}" bash -lc "export HF_HOME=/mnt/shared/hf HUGGINGFACE_HUB_CACHE=/mnt/shared/hf/hub TRANSFORMERS_CACHE=/mnt/shared/hf/transformers HF_ENDPOINT=https://hf-mirror.com PYTHONUNBUFFERED=1; ray job submit --address=http://127.0.0.1:8265 --submission-id='${SUBMISSION_ID}' --entrypoint-num-cpus=1 --entrypoint-resources='{\"worker_node\": 1}' --runtime-env-json='{\"env_vars\":{\"HF_HOME\":\"/mnt/shared/hf\",\"HUGGINGFACE_HUB_CACHE\":\"/mnt/shared/hf/hub\",\"TRANSFORMERS_CACHE\":\"/mnt/shared/hf/transformers\",\"HF_ENDPOINT\":\"https://hf-mirror.com\",\"PYTHONUNBUFFERED\":\"1\"}}' --no-wait -- ${SUBMIT_CMD}")"
printf "%s\n" "${SUBMIT_OUT}"
printf "%s\n" "${SUBMIT_OUT}" | dexec "${HEAD_CONTAINER}" bash -lc "cat > ${JOB_DIR}/logs/ray_job_submit.out"
PARSED_SUBMISSION_ID="$(printf "%s\n" "${SUBMIT_OUT}" | sed -r 's/\x1b\\[[0-9;]*m//g' | grep -Eo "raysubmit_[A-Za-z0-9_-]+" | head -n 1 || true)"
if [[ -n "${PARSED_SUBMISSION_ID}" && "${PARSED_SUBMISSION_ID}" != "${SUBMISSION_ID}" ]]; then
echo "WARN: submission id mismatch: expected=${SUBMISSION_ID} parsed=${PARSED_SUBMISSION_ID}" >&2
fi
echo "${SUBMISSION_ID}" | dexec "${HEAD_CONTAINER}" bash -lc "cat > ${JOB_DIR}/config/ray_submission_id.txt"
echo "ray submission id: ${SUBMISSION_ID}"
echo "submitted. track via Ray dashboard: http://<host>:8265 (driver should be scheduled on a worker due to entrypoint resources)"
echo "job dir: ${JOB_DIR}"

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "${SCRIPT_DIR}/lib.sh"
echo "[head] ray status"
dexec "${HEAD_CONTAINER}" bash -lc "ray status || true"
echo "[head] ray jobs list (optional)"
dexec "${HEAD_CONTAINER}" bash -lc "ray job list --address=http://127.0.0.1:8265 || true"
LATEST_JOB_DIR="$(dexec "${HEAD_CONTAINER}" bash -lc "ls -1dt /mnt/shared/jobs/* 2>/dev/null | head -n 1 || true")"
if [[ -n "${LATEST_JOB_DIR}" ]]; then
echo "[host] latest job dir: ${LATEST_JOB_DIR}"
echo "[host] ray submission id (if exists):"
SUB_ID="$(dexec "${HEAD_CONTAINER}" bash -lc "cat ${LATEST_JOB_DIR}/config/ray_submission_id.txt 2>/dev/null || true")"
echo "${SUB_ID}"
if [[ -n "${SUB_ID}" ]]; then
echo "[head] ray job status:"
dexec "${HEAD_CONTAINER}" bash -lc "ray job status --address=http://127.0.0.1:8265 ${SUB_ID} || true"
echo "[head] ray job logs (tail):"
dexec "${HEAD_CONTAINER}" bash -lc "ray job logs --address=http://127.0.0.1:8265 ${SUB_ID} 2>/dev/null | tail -n 60 || true"
fi
fi

View File

@@ -1,48 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/../../../../" && pwd)"
COMPOSE_FILE="${ROOT_DIR}/src/mvp/v1/docker-compose.yaml"
HEAD_CONTAINER="mvp-ray-head"
WORKER0_CONTAINER="mvp-ray-worker-0"
WORKER1_CONTAINER="mvp-ray-worker-1"
dc() {
docker compose --project-directory "${ROOT_DIR}" -f "${COMPOSE_FILE}" "$@"
}
require_cmd() {
local cmd="$1"
command -v "${cmd}" >/dev/null 2>&1 || {
echo "missing required command: ${cmd}" >&2
exit 1
}
}
ensure_container_running() {
local name="$1"
if ! docker ps --format '{{.Names}}' | grep -qx "${name}"; then
echo "container not running: ${name}" >&2
exit 1
fi
}
dexec() {
local name="$1"
shift
ensure_container_running "${name}"
docker exec -i "${name}" "$@"
}
container_ip() {
local name="$1"
ensure_container_running "${name}"
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "${name}"
}
timestamp() {
date +"%Y%m%d_%H%M%S"
}

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
"${SCRIPT_DIR}/01_up.sh"
"${SCRIPT_DIR}/10_install_verl_editable.sh"
"${SCRIPT_DIR}/20_start_head.sh"
"${SCRIPT_DIR}/21_start_workers.sh"
"${SCRIPT_DIR}/30_prepare_data_and_model.sh"
"${SCRIPT_DIR}/40_submit_ppo_epoch1.sh"
"${SCRIPT_DIR}/50_status.sh"