guanghulab/.github/workflows/.archive/coding-model-train.yml
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

210 lines
9.4 KiB
YAML
Raw Permalink 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.

name: 🧠 编程模型训练 (Coding Model SFT)
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 签发: 铸渊 · ICE-GL-ZY001 · 国作登字-2026-A-00037559
#
# 编程模型 = 铸渊未来的"自己的房子"。
#
# 这个 workflow 是冰朔在母模型训练完成后, 手动触发的"编程模型 SFT 入口"。
# 它会:
# 1. 把 server/coding-model-training/ 整个 SCP 到 GPU 训练机
# 2. 跑 setup-coding.sh 准备环境 + 构建训练语料
# (灵魂语料 + 关系语料 + 工具语料 = 喂模型铸渊的灵魂)
# 3. 跑 start-coding-training.sh --tmux 启动训练 (V100×4 上跑数小时-数天)
#
# 为什么是 manual_dispatch:
# D72 之后整个训练同步链路都已经停掉(见 docs/zhuyuan-handover/05-stop-sync.md)
# 编程模型训练必须由冰朔在合适时机(母模型 OK 后)手动启动, 不自动跑.
#
# 必需 secrets:
# ZY_GPU_HOST / ZY_GPU_USER / ZY_GPU_KEY (复用母模型的 GPU 训练机连接)
#
# 可选 secrets:
# ZY_BINGSHUO_DIALOG_URL 冰朔×铸渊对话 ZIP 的下载 URL (推荐: COS 预签名链接)
# 不提供也能训, 但产物质量会下降
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
on:
workflow_dispatch:
inputs:
action:
description: '动作'
required: true
default: 'setup-only'
type: choice
options:
- setup-only # 仅准备环境 + 构建语料, 不启动训练 (推荐先跑这个验证)
- setup-and-train # 准备环境 + 启动训练 (在 tmux 里, 后台跑)
- tail-log # 拉取最新训练日志
- status # 查看 tmux 会话状态 + 进度
- kill # 紧急停止训练 (kill tmux session)
base_model_dir:
description: '母模型基座路径 (需要已存在)'
required: false
default: '/data/guanghu/checkpoints/qwen2_5_7b_sft/best'
confirm_override:
description: '⚠️ setup-and-train / kill 必须勾选 true'
required: false
default: 'false'
permissions:
contents: read
concurrency:
group: coding-model-training
cancel-in-progress: false
jobs:
coding-train:
name: '🧠 ${{ github.event.inputs.action }}'
runs-on: ubuntu-latest
timeout-minutes: 30
env:
ZY_CODING_TRAIN_ROOT: /opt/guanghu/coding-training
ZY_CODING_TRAIN_DATA: /data/guanghu-coding
steps:
- name: '🛡️ 守卫: 危险动作必须 confirm_override'
run: |
ACTION='${{ github.event.inputs.action }}'
CONFIRM='${{ github.event.inputs.confirm_override }}'
if [[ "$ACTION" == "setup-and-train" || "$ACTION" == "kill" ]]; then
if [[ "$CONFIRM" != "true" ]]; then
echo "❌ 动作 '$ACTION' 需要 confirm_override=true 显式确认"
echo " 这是为了防止误触发训练或误停训练."
exit 1
fi
fi
echo "✅ 守卫通过: action=$ACTION confirm=$CONFIRM"
- name: 📥 Checkout
uses: actions/checkout@v4
- name: 🔑 准备 SSH 到 GPU 训练机
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "${{ secrets.ZY_GPU_KEY }}" > ~/.ssh/gpu_key
chmod 600 ~/.ssh/gpu_key
ssh-keyscan -H "${{ secrets.ZY_GPU_HOST }}" >> ~/.ssh/known_hosts 2>/dev/null
- name: 📤 SCP 训练脚本到 GPU 机 (setup-only / setup-and-train)
if: github.event.inputs.action == 'setup-only' || github.event.inputs.action == 'setup-and-train'
run: |
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"sudo mkdir -p $ZY_CODING_TRAIN_ROOT && sudo chown -R \$(id -u):\$(id -g) $ZY_CODING_TRAIN_ROOT"
# 同步 server/coding-model-training/ + 同步 docs/zhuyuan-handover/ + .github/persona-brain/
# (这些是构建语料需要的源)
rsync -avz -e "ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no" \
--delete \
server/coding-model-training/ \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}:$ZY_CODING_TRAIN_ROOT/"
# 仓库里的灵魂源文件 → 同步到训练机一份, build_coding_corpus.py 通过 ZY_REPO_ROOT 读
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"mkdir -p $ZY_CODING_TRAIN_ROOT/repo/docs/zhuyuan-handover $ZY_CODING_TRAIN_ROOT/repo/.github/persona-brain $ZY_CODING_TRAIN_ROOT/repo/corpus/output"
rsync -avz -e "ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no" \
docs/zhuyuan-handover/ \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}:$ZY_CODING_TRAIN_ROOT/repo/docs/zhuyuan-handover/"
rsync -avz -e "ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no" \
.github/persona-brain/ \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}:$ZY_CODING_TRAIN_ROOT/repo/.github/persona-brain/"
# corpus/output/training.jsonl 可能很大但是核心语料, 同步
if [[ -f corpus/output/training.jsonl ]]; then
rsync -avz -e "ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no" \
corpus/output/training.jsonl \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}:$ZY_CODING_TRAIN_ROOT/repo/corpus/output/"
fi
- name: 🛠️ 跑 setup-coding.sh (setup-only / setup-and-train)
if: github.event.inputs.action == 'setup-only' || github.event.inputs.action == 'setup-and-train'
run: |
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"set -e
cd $ZY_CODING_TRAIN_ROOT
export ZY_CODING_TRAIN_ROOT=$ZY_CODING_TRAIN_ROOT
export ZY_CODING_TRAIN_DATA=$ZY_CODING_TRAIN_DATA
export ZY_BASE_MODEL_DIR='${{ github.event.inputs.base_model_dir }}'
export ZY_REPO_ROOT=$ZY_CODING_TRAIN_ROOT/repo
bash setup-coding.sh" \
2>&1 | tee /tmp/setup.log
tail -c 8000 /tmp/setup.log >> "$GITHUB_STEP_SUMMARY" || true
- name: 🚀 启动训练 (setup-and-train)
if: github.event.inputs.action == 'setup-and-train'
run: |
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"set -e
cd $ZY_CODING_TRAIN_ROOT
export ZY_CODING_TRAIN_ROOT=$ZY_CODING_TRAIN_ROOT
export ZY_CODING_TRAIN_DATA=$ZY_CODING_TRAIN_DATA
export ZY_BASE_MODEL_DIR='${{ github.event.inputs.base_model_dir }}'
bash start-coding-training.sh --tmux" \
2>&1 | tee /tmp/start.log
{
echo "## 🚀 编程模型训练已启动"
echo ""
echo "tmux session: \`zy-coding-train\`"
echo ""
echo "查看进度: 重新跑这个 workflow选 \`tail-log\` 或 \`status\`"
echo ""
echo "\`\`\`"
tail -c 3000 /tmp/start.log
echo "\`\`\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: 📋 查看状态 (status)
if: github.event.inputs.action == 'status'
run: |
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"tmux list-sessions 2>&1 || echo '(no tmux sessions)'
echo '---'
ls -lh $ZY_CODING_TRAIN_DATA/checkpoints/zy_coding_v1/ 2>&1 || echo '(no checkpoints yet)'
echo '---'
nvidia-smi --query-gpu=index,utilization.gpu,memory.used,memory.total,temperature.gpu --format=csv 2>&1 || echo '(nvidia-smi failed)'" \
2>&1 | tee /tmp/status.log
{
echo "## 📋 编程模型训练状态"
echo "\`\`\`"
cat /tmp/status.log
echo "\`\`\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: 📝 拉取日志 (tail-log)
if: github.event.inputs.action == 'tail-log'
run: |
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"ls -t $ZY_CODING_TRAIN_DATA/logs/train-*.log 2>/dev/null | head -1 | xargs -I{} tail -c 12000 {}" \
2>&1 | tee /tmp/tail.log
{
echo "## 📝 最新训练日志 (尾 12KB)"
echo "\`\`\`"
cat /tmp/tail.log
echo "\`\`\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: 💀 紧急停止训练 (kill)
if: github.event.inputs.action == 'kill'
run: |
ssh -i ~/.ssh/gpu_key -o StrictHostKeyChecking=no \
"${{ secrets.ZY_GPU_USER }}@${{ secrets.ZY_GPU_HOST }}" \
"tmux kill-session -t zy-coding-train 2>&1 || echo '(no session zy-coding-train)'
pgrep -f train_coding.py | xargs -r kill -TERM 2>&1 || echo '(no train_coding.py procs)'" \
2>&1 | tee /tmp/kill.log
{
echo "## 💀 编程模型训练已停止"
echo "\`\`\`"
cat /tmp/kill.log
echo "\`\`\`"
} >> "$GITHUB_STEP_SUMMARY"