File size: 7,969 Bytes
75b8dbb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770f650
75b8dbb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Automated Remote Orchestrator for Cham-DBNet on Lightning AI Studio.
Manages:
1. Phase 1 (CPU): Git clone, dependencies install, dataset generation (12,000 pages, 50% tight lines).
2. Phase 2 (H100 Switch): Switch machine to NVIDIA H100 (80GB VRAM SXM5).
3. Phase 3 (Training & Monitoring): Launch PaddleOCR DBNet distributed training, stream log metrics.
4. Phase 4 (Export & Download): Export lightweight inference model, package ZIP, download locally.
5. Phase 5 (Auto Stop): Stop Studio immediately to prevent credit consumption.
"""

import os
import sys
import time
from lightning_sdk import Studio, Machine

if sys.stdout and sys.stdout.encoding != 'utf-8':
    try:
        sys.stdout.reconfigure(encoding='utf-8')
    except AttributeError:
        pass

def log(msg):
    timestamp = time.strftime("%H:%M:%S")
    print(f"[{timestamp}] {msg}", flush=True)

def main():
    log("=================================================================")
    log("🚀 KHỞI ĐỘNG REMOTE ORCHESTRATOR TRÊN LIGHTNING AI")
    log("=================================================================")

    studio = Studio(name="cham-det-h100", teamspace="phucsd", org="phucsd-org")
    log(f"Trạng thái Studio hiện tại: {studio.status} (Machine: {studio.machine})")

    # PHASE 1: CPU SETUP & DATASET GENERATION
    log("\n📦 --- PHASE 1: THIẾT LẬP MÔI TRƯỜNG & SINH DỮ LIỆU TRÊN CPU (0 CREDIT) ---")
    
    setup_cmds = [
        # 1. Clone or Pull Cham-OCR
        "if [ ! -d 'Cham-OCR' ]; then git clone https://github.com/phucsd/Cham-OCR.git; else cd Cham-OCR && git pull origin main && cd ..; fi",
        # 2. Clone PaddleOCR inside Cham-OCR/ocr-training if not exists
        "cd /teamspace/studios/this_studio/Cham-OCR/ocr-training && if [ ! -d 'PaddleOCR' ]; then git clone -b release/2.7 https://github.com/PaddlePaddle/PaddleOCR.git; fi",
        # 3. Download fonts
        "cd /teamspace/studios/this_studio/Cham-OCR/ocr-training && mkdir -p data/fonts && wget -q -nc -O data/fonts/NotoSansCham-Regular.ttf https://raw.githubusercontent.com/googlefonts/noto-fonts/main/hinted/ttf/NotoSansCham/NotoSansCham-Regular.ttf && wget -q -nc -O data/fonts/NotoSansCham-Bold.ttf https://raw.githubusercontent.com/googlefonts/noto-fonts/main/hinted/ttf/NotoSansCham/NotoSansCham-Bold.ttf",
        # 4. Download pretrained weights
        "cd /teamspace/studios/this_studio/Cham-OCR/ocr-training && mkdir -p PaddleOCR/pretrain_models && wget -q -nc -O PaddleOCR/pretrain_models/PPLCNetV3_x0_75_ocr_det.pdparams https://paddleocr.bj.bcebos.com/pretrained/PPLCNetV3_x0_75_ocr_det.pdparams",
        # 5. Install general pip dependencies
        "pip install -q pyclipper shapely imgaug lmdb attrdict pillow opencv-python pyyaml",
    ]

    for cmd in setup_cmds:
        log(f"Đang thực thi: {cmd[:70]}...")
        out = studio.run(cmd)
        if out.strip():
            log(f"   -> {out.strip()[:200]}")

    log("✅ Thiết lập mã nguồn, phông chữ và pretrained model hoàn tất!")

    # 6. Generate dataset on CPU
    log("⚙️ Bắt đầu sinh 12,000 trang huấn luyện và 1,200 trang kiểm thử (50% cự ly siêu hẹp 3-10px)...")
    gen_cmd = "cd /teamspace/studios/this_studio/Cham-OCR/ocr-training && python3 scripts/generate_detector_data_v2.py --num_train 12000 --num_val 1200 --output_dir PaddleOCR/data/detector_v2 --workers 8"
    out = studio.run(gen_cmd)
    log("Kết quả sinh dữ liệu:")
    for line in out.strip().splitlines()[-6:]:
        log(f"   {line}")

    # Copy config
    studio.run("cd /teamspace/studios/this_studio/Cham-OCR/ocr-training && mkdir -p PaddleOCR/configs/det && cp configs/det/ch_PP-OCRv4_det_h100.yml PaddleOCR/configs/det/")
    log("✅ Bộ dữ liệu và cấu hình H100 đã sẵn sàng!")

    # PHASE 2: SWITCH MACHINE TO H100
    log("\n🔥 --- PHASE 2: CHUYỂN ĐỔI PHẦN CỨNG SANG GPU NVIDIA H100 (80GB VRAM) ---")
    log("Đang gửi lệnh switch_machine sang H100...")
    studio.switch_machine(Machine.H100)
    log(f"Trạng thái sau khi chuyển: {studio.status} (Machine: {studio.machine})")

    # Install paddlepaddle-gpu for Hopper/CUDA
    log("📦 Cài đặt PaddlePaddle GPU bản CUDA 11.8/12.x tối ưu H100...")
    studio.run("pip install -q paddlepaddle-gpu -i https://www.paddlepaddle.org.cn/packages/stable/cu118/")
    gpu_info = studio.run("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader")
    log(f"🔥 GPU đã nhận diện: {gpu_info.strip()}")

    # PHASE 3: LAUNCH TRAINING WITH BACKGROUND MONITORING
    log("\n🚀 --- PHASE 3: KHỞI CHẠY HUẤN LUYỆN CHAM-DBNET TRÊN H100 ---")
    train_script = """cd /teamspace/studios/this_studio/Cham-OCR/ocr-training/PaddleOCR && nohup python3 -m paddle.distributed.launch --gpus '0' tools/train.py -c configs/det/ch_PP-OCRv4_det_h100.yml > train.log 2>&1 &"""
    studio.run(train_script)
    log("✅ Lệnh huấn luyện đã kích hoạt chạy ngầm (background) an toàn trên H100!")

    # MONITORING LOOP
    log("📊 Bắt đầu vòng lặp theo dõi liên tục tiến trình huấn luyện...")
    prev_log_tail = ""
    idle_count = 0
    start_time = time.time()

    while True:
        time.sleep(15)
        # Check if process is still running
        ps_out = studio.run("ps aux | grep tools/train.py | grep -v grep | wc -l")
        is_running = int(ps_out.strip() or "0") > 0
        
        # Read log tail
        try:
            log_tail = studio.run("cd /teamspace/studios/this_studio/Cham-OCR/ocr-training/PaddleOCR && tail -n 8 train.log")
            if log_tail.strip() != prev_log_tail:
                prev_log_tail = log_tail.strip()
                log("--- Cập nhật tiến trình mới nhất ---")
                for l in log_tail.strip().splitlines()[-4:]:
                    log(f"   {l}")
        except Exception as e:
            log(f"Không thể đọc log: {e}")

        elapsed_mins = (time.time() - start_time) / 60
        if not is_running:
            log(f"\n🎉 Tiến trình huấn luyện đã kết thúc sau {elapsed_mins:.1f} phút!")
            break

    # PHASE 4: EXPORT MODEL & DOWNLOAD
    log("\n📦 --- PHASE 4: XUẤT MÔ HÌNH INFERENCE & ĐÓNG GÓI ---")
    export_cmd = """cd /teamspace/studios/this_studio/Cham-OCR/ocr-training/PaddleOCR && \
BEST_MODEL="output/ch_PP-OCRv4_det_cham_h100/best_accuracy" && \
if [ ! -f "${BEST_MODEL}.pdparams" ]; then BEST_MODEL="output/ch_PP-OCRv4_det_cham_h100/latest"; fi && \
python3 tools/export_model.py -c configs/det/ch_PP-OCRv4_det_h100.yml -o Global.pretrained_model=${BEST_MODEL} Global.save_inference_dir=../output/ch_PP-OCRv4_det_cham_infer && \
cd ../output && zip -r ../cham_dbnet_v1_infer.zip ch_PP-OCRv4_det_cham_infer/"""
    
    out = studio.run(export_cmd)
    log("Kết quả đóng gói:")
    for l in out.strip().splitlines()[-5:]:
        log(f"   {l}")

    # Download file to local workspace
    local_zip_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "cham_dbnet_v1_infer.zip")
    log(f"⬇️ Đang tải tệp mô hình về máy local: {local_zip_path}...")
    studio.download_file("Cham-OCR/ocr-training/cham_dbnet_v1_infer.zip", local_zip_path)
    log(f"✅ Đã tải thành công tệp mô hình ({os.path.getsize(local_zip_path) / (1024*1024):.2f} MB)!")

    # PHASE 5: STOP STUDIO TO SAVE CREDITS
    log("\n🛑 --- PHASE 5: TỰ ĐỘNG DỪNG STUDIO ĐỂ BẢO VỆ CREDIT ---")
    studio.stop()
    log("✅ Studio đã được DỪNG (STOPPED) an toàn! Không còn tiêu tốn bất kỳ credit nào.")
    log("=================================================================")
    log("🎊 HOÀN THÀNH TOÀN BỘ QUY TRÌNH HUẤN LUYỆN CHAM-DBNET TRÊN H100!")
    log("=================================================================")

if __name__ == '__main__':
    main()