File size: 7,798 Bytes
212761d
c5862cd
 
212761d
c5862cd
 
212761d
 
c5862cd
212761d
2fcbb3b
212761d
 
2fcbb3b
 
 
 
 
 
 
c5862cd
212761d
2fcbb3b
 
c5862cd
2fcbb3b
 
 
 
 
 
 
 
 
 
 
 
c5862cd
2fcbb3b
c5862cd
 
2fcbb3b
 
 
 
 
 
 
 
 
 
 
 
 
c5862cd
2fcbb3b
 
 
 
 
212761d
2fcbb3b
 
212761d
 
2fcbb3b
212761d
2fcbb3b
212761d
 
 
 
 
 
 
 
c5862cd
212761d
 
 
 
2fcbb3b
212761d
 
 
 
 
c5862cd
212761d
2fcbb3b
 
212761d
c5862cd
 
 
 
 
 
212761d
c5862cd
 
 
 
 
 
 
 
 
 
 
 
2fcbb3b
212761d
 
2fcbb3b
212761d
2fcbb3b
c5862cd
2fcbb3b
 
 
 
c5862cd
2fcbb3b
 
 
 
 
 
 
c5862cd
 
 
2fcbb3b
 
 
 
 
c5862cd
2fcbb3b
 
 
 
 
 
 
 
 
 
 
 
 
 
c5862cd
 
 
 
212761d
 
2fcbb3b
212761d
2fcbb3b
 
212761d
2fcbb3b
212761d
 
2fcbb3b
212761d
 
 
 
c5862cd
212761d
2fcbb3b
 
 
 
212761d
c5862cd
2fcbb3b
 
 
 
f49e1ba
2fcbb3b
c5862cd
 
 
212761d
 
2fcbb3b
212761d
 
2fcbb3b
c5862cd
 
212761d
 
2fcbb3b
212761d
2fcbb3b
212761d
2fcbb3b
212761d
2fcbb3b
 
 
 
c5862cd
212761d
 
 
 
2fcbb3b
212761d
 
2fcbb3b
212761d
2fcbb3b
c5862cd
212761d
2fcbb3b
 
c5862cd
2fcbb3b
c5862cd
212761d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#!/bin/bash
# Khudi AI v2 β€” On-start script (v3 - ALL FIXES APPLIED)
# All issues from v1 + v2.1 addressed

# Don't use 'set -e' - we want to handle errors gracefully
# instead of exiting on first failure

echo "============================================"
echo "πŸ‡΅πŸ‡° Khudi AI v2 β€” SAFE TRAINING (v3)"
echo "============================================"
echo "Start: $(date)"

# ============================================================
# FIX 1: Initialize IDLE_COUNT before health check
# ============================================================
IDLE_COUNT=0

# ============================================================
# SAFETY: 14-hour auto-shutdown
# ============================================================
( sleep 50400 && echo "⏰ 14 HOUR TIMEOUT" && pkill -9 -f "python train_v2" ) &
TIMEOUT_PID=$!

# ============================================================
# SAFETY: Health check (only after training starts)
# ============================================================
start_health_check() {
    while true; do
        sleep 300
        GPU_UTIL=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits 2>/dev/null || echo "0")
        echo "[HEALTH] $(date) GPU: ${GPU_UTIL}% idle_count=$IDLE_COUNT"
        if [ "${GPU_UTIL:-0}" -lt 5 ]; then
            IDLE_COUNT=$((IDLE_COUNT + 1))
            if [ "$IDLE_COUNT" -gt 12 ]; then
                echo "[HEALTH] GPU idle 60+ min - EMERGENCY EXIT"
                # Save what we have
                if [ -d /workspace/khudi-v2-output/checkpoints ]; then
                    LATEST=$(ls /workspace/khudi-v2-output/checkpoints/ 2>/dev/null | grep checkpoint- | sort -V | tail -1)
                    if [ -n "$LATEST" ]; then
                        echo "Saving $LATEST to HF..."
                        HF_TOKEN="$HF_TOKEN_VALUE" python -c "
from huggingface_hub import HfApi
import os
api = HfApi()
api.upload_folder(
    folder_path='/workspace/khudi-v2-output/checkpoints/$LATEST',
    repo_id='ZaoKing/khudi-ai-v2',
    repo_type='model',
    commit_message='EMERGENCY: $LATEST - health check timeout'
)
print('Saved $LATEST to HF')
" 2>&1
                    fi
                fi
                pkill -9 -f "python train_v2" 2>/dev/null
                kill -9 $TIMEOUT_PID 2>/dev/null
                exit 2
            fi
        else
            IDLE_COUNT=0
        fi
    done
}

# ============================================================
# Step 1: Install packages
# ============================================================
echo "[1/8] Installing packages..."
pip install -q --no-cache-dir \
    "transformers==4.45.0" \
    "datasets==2.20.0" \
    "peft==0.11.0" \
    "trl==0.10.0" \
    "accelerate==0.34.0" \
    "bitsandbytes==0.43.3" \
    "huggingface_hub==0.25.0" \
    "sentencepiece" "protobuf" 2>&1 | tail -3 || echo "  ⚠️ Some packages may have failed"

# ============================================================
# Step 2: Setup directories
# ============================================================
echo "[2/8] Setting up dirs..."
mkdir -p /workspace
cd /workspace
mkdir -p khudi-v2-output/checkpoints khudi-v2-output/hf_cache

# ============================================================
# Step 3: Download train script from HF
# ============================================================
echo "[3/8] Downloading training scripts from HF..."
HF_TOKEN_VALUE="HF_TOKEN_PLACEHOLDER"

# FIX: Add retry logic
download_with_retry() {
    local url="$1"
    local output="$2"
    local max_retries=3
    local retry=0

    while [ $retry -lt $max_retries ]; do
        if wget -q --header="Authorization: Bearer $HF_TOKEN_VALUE" -O "$output" "$url" && [ -s "$output" ]; then
            return 0
        fi
        retry=$((retry + 1))
        echo "  Retry $retry/$max_retries for $output..."
        sleep 5
    done
    return 1
}

if ! download_with_retry "https://huggingface.co/ZaoKing/khudi-ai-v2/resolve/main/train_v2.py" "train_v2.py"; then
    echo "❌ FATAL: Could not download train_v2.py"
    exit 1
fi
echo "  βœ… train_v2.py downloaded: $(wc -l < train_v2.py) lines"

# ============================================================
# Step 4: Download v2 dataset (4 chunks)
# ============================================================
echo "[4/8] Downloading v2 dataset (4 chunks)..."
for i in 0 1 2 3; do
    echo "  Downloading chunk $i..."
    if ! download_with_retry "https://huggingface.co/ZaoKing/khudi-ai-v2/resolve/main/data/v2_chunk_$i.jsonl" "v2_chunk_$i.jsonl"; then
        echo "  ❌ FATAL: Could not download chunk $i"
        exit 1
    fi
done

# Combine chunks
cat v2_chunk_0.jsonl v2_chunk_1.jsonl v2_chunk_2.jsonl v2_chunk_3.jsonl > v2_data.jsonl
TOTAL=$(wc -l < v2_data.jsonl)
SIZE=$(ls -lh v2_data.jsonl | awk '{print $5}')
echo "  βœ… Combined: $TOTAL samples ($SIZE)"

# ============================================================
# Step 5: Quick data validation
# ============================================================
echo "[5/8] Validating data..."
HF_TOKEN="$HF_TOKEN_VALUE" python -c "
import json
count = 0
errors = 0
with open('/workspace/v2_data.jsonl') as f:
    for line in f:
        try:
            item = json.loads(line)
            if 'messages' not in item:
                errors += 1
                continue
            count += 1
        except:
            errors += 1
print(f'Valid: {count}, Errors: {errors}')
if count < 1000:
    print('FATAL: Not enough valid samples!')
    exit(1)
" || { echo "❌ Data validation failed"; exit 1; }

# ============================================================
# Step 6: Check for resume checkpoint
# ============================================================
echo "[6/8] Checking for resume checkpoints..."
if [ -d khudi-v2-output/checkpoints ] && [ "$(ls -A khudi-v2-output/checkpoints 2>/dev/null)" ]; then
    LATEST=$(ls khudi-v2-output/checkpoints/ | grep checkpoint- | sort -V | tail -1)
    echo "  βœ… Found checkpoint: $LATEST - will resume"
    RESUME_FLAG="--resume_from_checkpoint"
else
    echo "  No checkpoints - starting fresh"
    RESUME_FLAG=""
fi

# ============================================================
# Step 7: Start training
# ============================================================
echo "[7/8] Starting health check + training..."
start_health_check &
HEALTH_PID=$!
echo "  Health check PID: $HEALTH_PID"

# Export ALL required env vars
export HF_TOKEN="$HF_TOKEN_VALUE"
export HUGGINGFACE_HUB_TOKEN="$HF_TOKEN_VALUE"
export DATA_PATH="/workspace/v2_data.jsonl"
export OUTPUT_DIR="/workspace/khudi-v2-output"
export MODEL_NAME="Qwen/Qwen3.5-9B"

# FIX: Pass --epochs 1 explicitly
cd /workspace
python train_v2.py $RESUME_FLAG --epochs 1 2>&1

TRAIN_EXIT=$?
echo "Training exit: $TRAIN_EXIT"
echo "End: $(date)"

# Stop health check
kill $HEALTH_PID 2>/dev/null || true
kill $TIMEOUT_PID 2>/dev/null || true

# ============================================================
# Step 8: Final status
# ============================================================
echo "[8/8] Final status..."
if [ $TRAIN_EXIT -eq 0 ]; then
    echo "βœ… Training completed"
else
    echo "⚠️ Training had issues - exit $TRAIN_EXIT"
fi

# Upload final log
HF_TOKEN="$HF_TOKEN_VALUE" python -c "
from huggingface_hub import HfApi
api = HfApi()
api.upload_file(
    path_or_fileobj='/workspace/train.log',
    path_in_repo='train_v2_$(date +%Y%m%d_%H%M%S).log',
    repo_id='ZaoKing/khudi-ai-v2',
    repo_type='model',
    commit_message='Training log v2'
)
print('Log uploaded')
" 2>&1 || echo "  Log upload failed"

# Stop instance
echo "Stopping instance..."
pkill -9 -f "python train_v2" 2>/dev/null || true
sleep 2
sudo shutdown -h now 2>/dev/null || shutdown -h now 2>/dev/null || true
echo "Script complete"