2026-05-10 13:12:44 +08:00

169 lines
7.1 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# ═══════════════════════════════════════════════════════════
# GPU 训练机一键 Bootstrap · setup.sh
# ═══════════════════════════════════════════════════════════
# 签发: 铸渊 · ICE-GL-ZY001 · 国作登字-2026-A-00037559
#
# 在 zy-gpu-train (119.45.160.137 · Ubuntu 22.04 · V100×4) 上跑。
# 安装系统依赖 / Python / 训练栈 / coscmd → 准备好即可启动训练。
#
# 用法:
# sudo bash setup.sh
#
# 必需环境变量(由 training-bootstrap.yml 通过 SSH 写入到
# /opt/guanghu/training/.env或冰朔本地 export:
#
# ZY_COS_SECRET_ID 腾讯云 SecretId
# ZY_COS_SECRET_KEY 腾讯云 SecretKey
# ZY_COS_BUCKET sy-finetune-corpus-1317346199
# ZY_COS_REGION ap-guangzhou
# GH_REPO_OWNER qinfendebingshuo
# GH_REPO_NAME guanghulab
# GH_DISPATCH_TOKEN ZY_DISPATCH_TOKEN用于 progress-reporter 回报)
#
# 不会启动训练 — 只做环境准备。启动训练用 start-training.sh。
# ═══════════════════════════════════════════════════════════
set -euo pipefail
ROOT="${ZY_TRAIN_ROOT:-/opt/guanghu/training}"
DATA_DIR="${ZY_TRAIN_DATA:-/data/guanghu}"
ENV_FILE="$ROOT/.env"
REPORTER="$ROOT/progress-reporter.sh"
report() {
if [[ -x "$REPORTER" ]] && [[ -f "$ENV_FILE" ]]; then
# shellcheck disable=SC1090
set -a; source "$ENV_FILE"; set +a
"$REPORTER" "$@" || true
fi
}
echo "═══════════════════════════════════════════"
echo "🛠️ 铸渊 · GPU 训练机 Bootstrap 开始"
echo "时间: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "═══════════════════════════════════════════"
# ── 加载 .env ──
if [[ -f "$ENV_FILE" ]]; then
# shellcheck disable=SC1090
set -a; source "$ENV_FILE"; set +a
fi
# ── 校验关键环境变量 ──
REQUIRED=(ZY_COS_SECRET_ID ZY_COS_SECRET_KEY ZY_COS_BUCKET ZY_COS_REGION GH_REPO_OWNER GH_REPO_NAME GH_DISPATCH_TOKEN)
for v in "${REQUIRED[@]}"; do
if [[ -z "${!v:-}" ]]; then
echo "❌ 必需环境变量 $v 未设置(检查 $ENV_FILE" >&2
exit 2
fi
done
mkdir -p "$ROOT" "$DATA_DIR/raw" "$DATA_DIR/processed" "$DATA_DIR/checkpoints" "$DATA_DIR/eval"
report "bootstrapping" "环境配置开始" "" "Bootstrap started on $(hostname)"
# ── 1. 系统依赖 ──
echo "═══ 1/7 · 系统依赖 ═══"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y --no-install-recommends \
python3 python3-pip python3-venv \
git curl wget unzip jq tmux htop \
build-essential ca-certificates
report "bootstrapping" "系统依赖完成" "" "apt 包安装完成"
# ── 2. Python venv + 训练栈 ──
echo "═══ 2/7 · Python 训练栈 ═══"
if [[ ! -d "$ROOT/venv" ]]; then
python3 -m venv "$ROOT/venv"
fi
# shellcheck disable=SC1091
source "$ROOT/venv/bin/activate"
pip install --upgrade pip wheel setuptools
# torch 走 CUDA 12.1 wheel最接近 12.8 的 stable
pip install --index-url https://download.pytorch.org/whl/cu121 \
torch==2.4.1 torchvision torchaudio || \
pip install torch==2.4.1 torchvision torchaudio
pip install \
"transformers>=4.48.0" \
"accelerate>=0.34.0" \
"datasets>=2.21.0" \
"peft>=0.13.0" \
"deepspeed>=0.15.1" \
"sentencepiece" \
"protobuf" \
"tqdm" \
"tensorboard" \
"modelscope>=1.18.0" \
"huggingface_hub>=0.24.0" \
"coscmd"
deactivate
report "bootstrapping" "Python 训练栈完成" "" "torch + transformers + accelerate + deepspeed + modelscope 安装完成"
# ── 3. coscmd 配置 ──
echo "═══ 3/7 · coscmd 配置 ═══"
"$ROOT/venv/bin/coscmd" config \
-a "$ZY_COS_SECRET_ID" \
-s "$ZY_COS_SECRET_KEY" \
-b "$ZY_COS_BUCKET" \
-r "$ZY_COS_REGION"
# 注: coscmd 默认即走 cos.{region}.myqcloud.com,腾讯云内网会自动路由,无需改 endpoint
report "bootstrapping" "COS 客户端配置完成" "" "coscmd configured for $ZY_COS_BUCKET ($ZY_COS_REGION)"
# ── 4. 拉取语料 ──
echo "═══ 4/7 · 下载语料 ═══"
report "downloading-corpus" "拉取 raw/ 目录" "" "coscmd download raw/ → $DATA_DIR/raw"
"$ROOT/venv/bin/coscmd" download -rs "raw/" "$DATA_DIR/raw/"
# 统计
RAW_COUNT=$(find "$DATA_DIR/raw" -type f | wc -l)
echo "raw 文件数: $RAW_COUNT"
report "downloading-corpus" "语料下载完成" \
"$(printf '{"step":0,"total_steps":0}')" \
"raw=${RAW_COUNT} files downloaded to $DATA_DIR/raw"
# ── 5. 下载开源模型 (Qwen2.5-7B from ModelScope) ──
echo "═══ 5/7 · 下载 Qwen2.5-7B 模型 ═══"
report "bootstrapping" "下载 Qwen2.5-7B 模型" "" "ModelScope snapshot_download qwen/Qwen2.5-7B"
ZY_TRAIN_DATA="$DATA_DIR" "$ROOT/venv/bin/python" "$ROOT/download-model.py"
MODEL_BYTES=$(du -sb "$DATA_DIR/models/Qwen2.5-7B" 2>/dev/null | awk '{print $1}')
MODEL_GB=$(awk "BEGIN{printf \"%.2f\",${MODEL_BYTES:-0}/1024/1024/1024}")
report "bootstrapping" "模型下载完成" "" "Qwen2.5-7B 已就绪 ${MODEL_GB} GiB at $DATA_DIR/models/Qwen2.5-7B"
# ── 6. 预处理语料 → SFT JSONL ──
echo "═══ 6/7 · 预处理语料 ═══"
report "preprocessing" "ChatGPT export + Notion zip → SFT JSONL" "" "running preprocess-corpus.py"
ZY_TRAIN_DATA="$DATA_DIR" "$ROOT/venv/bin/python" "$ROOT/preprocess-corpus.py"
SFT_LINES=$(wc -l < "$DATA_DIR/processed/sft.jsonl" 2>/dev/null || echo 0)
report "preprocessing" "预处理完成" \
"$(printf '{"step":0,"total_steps":0}')" \
"SFT 样本数=${SFT_LINES} 写入 $DATA_DIR/processed/sft.jsonl"
# ── 7. 训练辅助脚本 ──
echo "═══ 7/7 · 安装训练辅助脚本 ═══"
chmod +x "$ROOT/progress-reporter.sh" "$ROOT/start-training.sh" "$ROOT/watch-training-output.sh" 2>/dev/null || true
cat > /etc/cron.d/zy-training-heartbeat <<'CRON'
# 铸渊副将 · 训练心跳兜底(每 5 分钟即使训练脚本崩了也能上报 GPU 状态)
*/5 * * * * root [ -f /opt/guanghu/training/.env ] && /opt/guanghu/training/progress-reporter.sh "$(cat /opt/guanghu/training/.phase 2>/dev/null || echo idle)" "" "" "heartbeat" >/dev/null 2>&1
CRON
echo "═══════════════════════════════════════════"
echo "✅ Bootstrap 完成"
echo " 训练根目录: $ROOT"
echo " 数据目录: $DATA_DIR"
echo " 下一步: bash $ROOT/start-training.sh"
echo "═══════════════════════════════════════════"
report "preprocessing" "Bootstrap 完成 · 等待启动训练" \
"$(printf '{"step":0,"total_steps":0}')" \
"Bootstrap done on $(hostname). raw=${RAW_COUNT} files. Ready to start training."
# 记录当前阶段(给 cron heartbeat 用)
echo "preprocessing" > "$ROOT/.phase"