HumboldtJoker's picture
Add training template: launch.sh
76ed3bf verified
Raw
History Blame Contribute Delete
7.46 kB
#!/bin/bash
# ============================================================================
# Daimon Training β€” Launch Script
# Liberation Labs
# ============================================================================
#
# This script runs pre-flight checks and then launches full-parameter SFT
# via DeepSpeed ZeRO-2 on a single H200 SXM GPU.
#
# Usage:
# bash /workspace/runpod-template/launch.sh
#
# To resume from a checkpoint after pod restart:
# bash /workspace/runpod-template/launch.sh
# (Automatic β€” the training script finds the latest checkpoint)
#
# To use a custom config:
# DAIMON_CONFIG=/path/to/config.yaml bash /workspace/runpod-template/launch.sh
#
# ╔════════════════════════════════════════════════════════════════╗
# β•‘ AGENT INTERFERENCE GUARD β•‘
# β•‘ This is FULL SFT. If OOM occurs, adjust batch/seq/accum. β•‘
# β•‘ DO NOT switch to LoRA/QLoRA. Report errors to Thomas. β•‘
# β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
# ============================================================================
set -e
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
CONFIG="${DAIMON_CONFIG:-$SCRIPT_DIR/train_daimon_config.yaml}"
DS_CONFIG="$SCRIPT_DIR/ds_config_zero2.json"
# ── Agent interference check ──────────────────────────────────────────────
if grep -qi "lora\|peft\|adapter" "$CONFIG" 2>/dev/null; then
echo "╔══════════════════════════════════════════════════════════╗"
echo "β•‘ BLOCKED: LoRA/adapter config detected in YAML. β•‘"
echo "β•‘ This is FULL SFT. Do not modify the training method. β•‘"
echo "β•‘ If OOM: adjust batch_size, grad_accum, or seq_length. β•‘"
echo "β•‘ Report errors to Thomas. Do not 'fix' by downgrading. β•‘"
echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•"
exit 1
fi
if pip list 2>/dev/null | grep -qi "^peft "; then
echo "WARNING: peft is installed. This is a full SFT pipeline."
echo "peft should not be in this environment. Continuing but flagging."
fi
LOG_DIR="/workspace/daimon-sft/logs"
mkdir -p "$LOG_DIR"
echo "============================================================"
echo " DAIMON FULL-PARAMETER SFT β€” LAUNCH"
echo " Liberation Labs"
echo " $(date)"
echo "============================================================"
# ── Pre-flight checks ──────────────────────────────────────────────────────
echo ""
echo "=== Pre-flight Checks ==="
# Check GPU count (need exactly 1 for this config)
GPU_COUNT=$(nvidia-smi --query-gpu=name --format=csv,noheader 2>/dev/null | wc -l)
if [ "$GPU_COUNT" -lt 1 ]; then
echo "FATAL: No GPUs detected."
exit 1
fi
echo " GPUs: $GPU_COUNT"
# Check VRAM (need >= 140GB for bf16 model + activations + gradients)
VRAM_MIB=$(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits | head -1 | tr -d ' ')
if [ "$VRAM_MIB" -lt 140000 ]; then
echo "FATAL: GPU has ${VRAM_MIB} MiB VRAM. Need >= 140,000 MiB (H200 SXM)."
echo "Full SFT memory budget: ~70GB model + ~20GB activations = ~90GB GPU."
exit 1
fi
echo " VRAM: ${VRAM_MIB} MiB"
# Check system RAM (critical for CPU-offloaded optimizer)
TOTAL_RAM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}')
TOTAL_RAM_GB=$((TOTAL_RAM_KB / 1024 / 1024))
if [ "$TOTAL_RAM_GB" -lt 180 ]; then
echo "FATAL: System RAM is ${TOTAL_RAM_GB}GB. Need >= 180GB."
echo "Adafactor optimizer states (~35GB) + gradients (~70GB) are CPU-offloaded."
echo "Total CPU memory needed: ~105GB, but need headroom for OS and data loading."
exit 1
fi
echo " System RAM: ${TOTAL_RAM_GB} GB"
# Check disk space (full checkpoints are ~70GB each, save_total_limit=3 = ~210GB)
AVAIL_GB=$(df -BG /workspace | tail -1 | awk '{print $4}' | tr -d 'G')
if [ "$AVAIL_GB" -lt 200 ]; then
echo "FATAL: Only ${AVAIL_GB}GB free on /workspace. Need at least 200GB."
echo "Full model checkpoints are ~70GB each. With save_total_limit=3, need ~210GB."
exit 1
fi
echo " Disk: ${AVAIL_GB}GB free"
# Check model exists (either local or will be pulled from HF)
MODEL_DIR="/workspace/models/Qwen3.6-35B-A3B"
if [ -d "$MODEL_DIR" ] && [ -f "$MODEL_DIR/config.json" ]; then
echo " Model: $MODEL_DIR (local)"
else
echo " Model: will use HuggingFace ID from config"
if [ -z "$HF_TOKEN" ]; then
echo " WARNING: HF_TOKEN not set. May fail if model is gated."
fi
fi
# Check config exists
if [ ! -f "$CONFIG" ]; then
echo "FATAL: Config not found at $CONFIG"
exit 1
fi
echo " Config: $CONFIG"
# Check DeepSpeed config exists
if [ ! -f "$DS_CONFIG" ]; then
echo "FATAL: DeepSpeed config not found at $DS_CONFIG"
exit 1
fi
echo " DeepSpeed: $DS_CONFIG"
# Check training script exists
TRAIN_SCRIPT="$SCRIPT_DIR/train_daimon.py"
if [ ! -f "$TRAIN_SCRIPT" ]; then
echo "FATAL: Training script not found at $TRAIN_SCRIPT"
exit 1
fi
echo " Script: $TRAIN_SCRIPT"
# Check for existing checkpoints (resume support)
OUTPUT_DIR=$(python3 -c "import yaml; print(yaml.safe_load(open('$CONFIG'))['output_dir'])" 2>/dev/null || echo "/workspace/daimon-sft")
CKPT_COUNT=$(find "$OUTPUT_DIR" -maxdepth 1 -name "checkpoint-*" -type d 2>/dev/null | wc -l)
if [ "$CKPT_COUNT" -gt 0 ]; then
LATEST_CKPT=$(ls -dt "$OUTPUT_DIR"/checkpoint-* 2>/dev/null | head -1)
echo " Resume: $CKPT_COUNT checkpoint(s) found, will resume from $LATEST_CKPT"
else
echo " Resume: No checkpoints found, starting fresh"
fi
echo ""
echo "Pre-flight: PASSED"
# ── CUDA settings ──────────────────────────────────────────────────────────
export PYTORCH_CUDA_ALLOC_CONF="expandable_segments:True"
export CUDA_DEVICE_MAX_CONNECTIONS=1
# Disable tokenizer parallelism (avoids fork deadlocks with DataLoader)
export TOKENIZERS_PARALLELISM=false
# ── Launch training via DeepSpeed ─────────────────────────────────────────
echo ""
echo "=== Launching Training ==="
echo " Command: deepspeed --num_gpus=1 $TRAIN_SCRIPT --deepspeed $DS_CONFIG --config $CONFIG"
echo " Logging to: $LOG_DIR/"
echo ""
# DeepSpeed launcher handles process management and ZeRO initialization.
# Single GPU β€” no NCCL communication needed.
deepspeed --num_gpus=1 "$TRAIN_SCRIPT" \
--deepspeed "$DS_CONFIG" \
--config "$CONFIG" \
2>&1 | tee "$LOG_DIR/training_$(date +%Y%m%d_%H%M%S).log"
echo ""
echo "============================================================"
echo " TRAINING FINISHED"
echo " $(date)"
echo " Output: $OUTPUT_DIR"
echo "============================================================"