Files
frankenstallm/source/eval/plan/MASTER_PLAN.md
ModelHub XC d4abdb70fa 初始化项目,由ModelHub XC社区提供模型
Model: pathcosmos/frankenstallm
Source: Original Platform
2026-07-14 04:21:16 +08:00

18 KiB
Raw Permalink Blame History

🗺️ MASTER PLAN: 한국어 LLM 1B 재학습 → 3B → 배포

작성일: 2026-02-27
프로젝트: /PROJECT/0325120031_A/ghong/taketimes/llm-bang/
결정: Restart (base checkpoint에서 클린 재학습)
총 예상 기간: ~35시간 (1B: 3시간 → 3B pretrain: 26시간 → 3B SFT+평가: 6시간)


📊 전체 타임라인 한눈에 보기

Phase 0  ██░░░░░░░░░░░░░░░░░░░░░░  30분    데이터/코드 준비
Phase 1  ████░░░░░░░░░░░░░░░░░░░░  40분    1B SFT 재학습
Phase 2  ██████░░░░░░░░░░░░░░░░░░  2시간   1B 평가
         ────── 여기서 판단 ──────
Phase 3A ████████░░░░░░░░░░░░░░░░  3-5시간  (조건부) 1B 추가 개선
Phase 3B ████████████████████████  26시간   3B 사전학습
Phase 4  ████░░░░░░░░░░░░░░░░░░░░  2시간   3B SFT
Phase 5  ██████░░░░░░░░░░░░░░░░░░  4시간   평가 & 배포

Phase 0: 재학습 직전 준비 (오늘, ~30분)

체크리스트

☐ 0-1. 데이터 재생성 (~20분)

cd /PROJECT/0325120031_A/ghong/taketimes/llm-bang

# prepare_sft_data.py 재실행 (강화 필터 + 수정된 가중치)
python data/prepare_sft_data.py \
    --output_dir data/sft_v2/ \
    --val_split 0.1

확인 사항:

  • 필터링 후 120K-135K 샘플 남아야 함 (기존 159K에서 저품질 제거)
  • </s> 리터럴 113건, Q/A 마커 ~550건, 자체반복 57건 제거 확인
  • OpenOrca 가중치: 5.0 → 2.0으로 감소 확인
  • Val split: ~12-13K 샘플 (10%)
  • 짧은 output (<80자) 제거 확인
# 결과 확인
wc -l data/sft_v2/train.jsonl data/sft_v2/val.jsonl
# 예상: train ~108K-120K, val ~12K-13K

완료 기준: train 100K+ 샘플, val 10K+ 샘플. 제거된 샘플 spot check 시 실제 저품질.

☐ 0-2. sft_dataset.py 수정 확인 (~5분)

이미 수정된 항목 확인:

수정 사항 파일 확인
Dynamic padding 실제 작동 data/sft_dataset.py __getitem__ ☐ 패딩 없이 실제 길이 텐서 반환
EOS 보존 data/sft_dataset.py L130-134 response_ids[:allowed-1] + [eos_id]
Collate fn data/sft_dataset.py dynamic_collate_fn ☐ 배치별 가변 패딩
# 핵심 코드 확인
grep -n "allowed_response" data/sft_dataset.py
grep -n "eos_token_id" data/sft_dataset.py
grep -n "torch.full" data/sft_dataset.py  # 4096 고정 패딩 없어야 함

☐ 0-3. launch_sft.sh 수정 (~5분)

# 변경할 값들:
# RUN_NAME=korean_1b_sft_v2
# SFT_DATA=data/sft_v2/train.jsonl
# VAL_DATA=data/sft_v2/val.jsonl
# MAX_STEPS=10000  (3-4 epoch, 기존 5000에서 증가)
# WARMUP_STEPS=300  (3%)

cp scripts/launch_sft.sh scripts/launch_sft_v2.sh
# 편집 후 diff 확인

☐ 0-4. Sanity Check (~5분)

# 100 steps만 빠르게 돌려서 파이프라인 정상 확인
bash scripts/launch_sft_v2.sh --max_steps 100

# 확인:
# - Loss가 2.0-2.5 범위에서 시작하는가? ✅
# - 배치 내 시퀀스 길이가 가변적인가? (로그에서 확인) ✅
# - Val loss가 출력되는가? ✅
# - OOM 없는가? ✅

완료 기준: 100 steps 에러 없이 완료, loss 합리적 범위, val loss 출력 확인.


Phase 1: 1B SFT 재학습 (오늘, ~40분)

실행 명령어

cd /PROJECT/0325120031_A/ghong/taketimes/llm-bang

RUN_NAME=korean_1b_sft_v2 \
BASE_CHECKPOINT=checkpoints/korean_1b_fp8_run1/checkpoint-0034000 \
SFT_DATA=data/sft_v2/train.jsonl \
VAL_DATA=data/sft_v2/val.jsonl \
MAX_STEPS=10000 \
WARMUP_STEPS=300 \
LR=2.0e-5 \
bash scripts/launch_sft.sh

모니터링

실시간 로그:

tail -f checkpoints/korean_1b_sft_v2/train.log

TensorBoard:

tensorboard --logdir checkpoints/korean_1b_sft_v2/tensorboard --port 6007

핵심 수치:

수치 정상 범위 경고 즉시 중단
Train Loss 시작 2.0-2.5, 최종 <1.90 >2.5 at step 500+ >3.0 (발산)
Val Loss Train의 1.0-1.1배 Train의 1.2배 Train 대비 계속 상승 (과적합)
GNorm 0.8-1.5 >2.0 >5.0 (gradient 폭발)
학습 속도 기존 대비 2x+ (dynamic padding 효과) 기존과 비슷 기존보다 느림

체크포인트 관찰:

  • Step 500: 파이프라인 안정성 확인
  • Step 2500: 중간 지점, loss 추세 확인
  • Step 5000: 기존 학습과 비교 (loss < 1.97이어야 함)
  • Step 7500: 수렴 여부 확인
  • Step 10000: 최종

성공 기준

지표 목표 실패 기준
Final Train Loss < 1.90 > 2.00
Final Val Loss < 2.00 Train 대비 1.2배 초과
Val Loss 추세 하강 or 안정 3연속 상승 (과적합)
학습 시간 ~40-60분 >2시간 (dynamic padding 미작동)

실패 시 대응

상황 원인 추정 대응
Loss 발산 (>3.0) LR 과다 or 데이터 버그 LR=1e-5로 재시도
OOM 배치 크기 과다 BATCH_SIZE=2로 감소
Loss 정체 (step 2000+ 변화 없음) LR 부족 or 데이터 문제 데이터 점검, LR=3e-5 시도
Val Loss 발산 (과적합) Epoch 과다 Early stop at best val checkpoint
학습 속도 기존과 같음 Dynamic padding 미작동 sft_dataset.py 재점검

Phase 2: 1B SFT 평가 (~2시간)

평가 순서

2-1. 반복률 측정 (30분)

# 올바른 포맷(<|user|>/<|assistant|>)으로 생성 테스트
python eval/test_generation_params.py \
    --checkpoint checkpoints/korean_1b_sft_v2/checkpoint-0010000

# 다양한 rep_penalty 테스트
# rep_penalty=1.0 (없음): 목표 <10%
# rep_penalty=1.1:        목표 <3%
# rep_penalty=1.2:        목표 <1%

2-2. 생성 품질 주관 평가 (30분)

python eval/generate.py \
    --checkpoint checkpoints/korean_1b_sft_v2/checkpoint-0010000 \
    --prompts_file eval/test_prompts.txt \
    --temperature 0.8 --top_p 0.9

체크: 한국어 자연스러움, instruction following, EOS 정상 종료

2-3. 공식 벤치마크 (1시간)

# ko_ifeval
lm_eval --model hf \
    --model_args pretrained=checkpoints/korean_1b_sft_v2/checkpoint-0010000,dtype=bfloat16 \
    --tasks ko_ifeval \
    --device cuda:0 \
    --output_path eval/results/sft_v2_ko_ifeval.json

# ko_winogrande (선택)
lm_eval --model hf \
    --model_args pretrained=checkpoints/korean_1b_sft_v2/checkpoint-0010000,dtype=bfloat16 \
    --tasks ko_winogrande \
    --device cuda:0 \
    --output_path eval/results/sft_v2_ko_winogrande.json

판단 기준 & 분기

                    [Phase 2 평가 결과]
                          │
    ┌─────────────────────┼─────────────────────┐
    │                     │                     │
  ✅ PASS              ⚠️ PARTIAL            ❌ FAIL
 반복률<5%            반복률 5-15%          반복률>15%
 ko_ifeval>25%       ko_ifeval 15-25%      ko_ifeval<15%
    │                     │                     │
    ▼                     ▼                     ▼
 Phase 3B             Phase 3A              원인 분석
 (3B 전환)          (추가 개선)           (데이터/코드 재검토)

상세 기준:

지표 Pass ⚠️ 추가 조정 재학습
반복률 (rep_penalty 없이) <10% 10-20% >20%
반복률 (rep_penalty=1.1) <5% 5-15% >15%
ko_ifeval >25% 15-25% <15%
EOS 정상 종료율 >85% 60-85% <60%

Phase 3A: 1B 추가 개선 (조건부, ~3-5시간)

Phase 2 결과가 ⚠️ PARTIAL일 때만 진입

옵션 A: ORPO 학습 (~3시간)

Preference Data 준비 (1시간)

# 한국어 preference 데이터 다운로드
python -c "
from datasets import load_dataset
# 옵션 1: ko_Ultrafeedback (60K, 일반 도메인)
ds = load_dataset('maywell/ko_Ultrafeedback')
# 옵션 2: 자체 생성 (현재 모델로 rejected 생성)
"

자체 생성 방법:

  1. 현재 SFT 모델로 동일 프롬프트에 여러 번 생성
  2. 반복/저품질 출력 → rejected
  3. 깨끗한 데이터의 정답 → chosen
  4. ~10K-20K 쌍 생성

ORPO 학습 (1.5시간)

from trl import ORPOConfig, ORPOTrainer

config = ORPOConfig(
    learning_rate=5e-7,
    num_train_epochs=1,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=2,
    beta=0.1,  # ORPO coefficient
)
trainer = ORPOTrainer(model, config, train_dataset=preference_data)
trainer.train()

평가 (30분)

  • 반복률 재측정: 목표 <5% (rep_penalty=1.1)
  • ko_ifeval 재측정: 목표 >20%

옵션 B: 추가 SFT (데이터 보강, ~5시간)

추가 데이터 수집 (2시간)

from datasets import load_dataset

# 고품질 한국어 데이터 추가
datasets = {
    "hPark/orca-ko": 200_000,          # 고품질 합성
    "nayohan/llama3-instruct-ko-dataset": 58_000,  # Llama3 한국어
    "FreedomIntelligence/evol-instruct-korean": 70_000,  # GPT-4 생성
}
# 기존 120K + 추가 ~300K → 필터 후 ~350K

재학습 (2시간)

# 증가된 데이터로 재학습
RUN_NAME=korean_1b_sft_v3 \
SFT_DATA=data/sft_v3/train.jsonl \
MAX_STEPS=15000 \
bash scripts/launch_sft.sh

Phase 3A 성공 기준

지표 목표
반복률 (rep_penalty=1.1) <5%
ko_ifeval >20%

실패 시: 1B 한계 인정, Phase 3B (3B 전환)로 바로 이동.


Phase 3B: 3B 사전학습 (Phase 2 통과 후, ~26시간)

3B 모델 아키텍처

파라미터 1B (현재) 3B (목표) 비고
d_model 2048 2560 ~1.25x
n_layers 24 32 ~1.33x
n_heads 16 32 2x
n_kv_heads (GQA) 4 8 2x
d_ffn 5472 6912 ~1.26x
vocab_size 64000 64000 동일
max_seq_len 4096 4096 동일
총 파라미터 1.19B ~3.0B ~2.5x

설정 파일 작성

# configs/korean_3b_fp8.yaml 작성
cat > configs/korean_3b_fp8.yaml << 'EOF'
model:
  d_model: 2560
  n_layers: 32
  n_heads: 32
  n_kv_heads: 8
  d_ffn: 6912
  vocab_size: 64000
  max_seq_len: 4096
  rope_theta: 500000

training:
  lr: 3.0e-4
  min_lr: 3.0e-5
  warmup_steps: 2000
  max_steps: 100000
  batch_size: 4
  grad_accum: 4
  weight_decay: 0.1
  use_fp8: true

data:
  sources:
    - cc100_ko
    - culturax_ko
    - existing_pretrain
EOF

사전학습 데이터

소스 토큰 수 상태
CulturaX ko 24.8B 보유
cc100 ko (재수집) ~65-100B ⚠️ 재수집 필요 (노이즈 필터링)
기존 pretrain 데이터 ~8.9B 보유
추가 수집 (나무위키, 뉴스 등) ~20-50B 선택적
합계 ~120-180B Chinchilla 60B 최소 충족

데이터 준비 명령어:

# cc100 재수집 + 품질 필터링
python scripts/download_cc100_ko.py --quality_filter --dedup
# MinHash dedup + perplexity filter
python scripts/quality_filter.py --input data/pretrain/ --max_ppl 1000

학습 실행

# 3B pretrain 시작 (8× B200, ~26시간)
bash scripts/run_pretrain.sh --config configs/korean_3b_fp8.yaml

# 예상 처리 속도: ~1.6M tok/s (8× B200)
# 150B tokens / 1.6M tok/s ≈ 26시간

모니터링

# 로그 확인
tail -f checkpoints/korean_3b_fp8/train.log

# 중간 체크포인트에서 base 품질 확인 (step 10000마다)
python eval/perplexity.py --checkpoint checkpoints/korean_3b_fp8/checkpoint-0010000

성공 기준: PPL < 10 (한국어 텍스트), loss 지속 하강


Phase 4: 3B SFT (~2시간)

1B에서 배운 교훈 전부 적용

교훈 적용
Dynamic padding 작동 확인 sft_dataset.py 수정 완료, 그대로 사용
EOS 보존 동일 코드
Val split 필수 10% split
3-4 epoch MAX_STEPS 계산하여 설정
OpenOrca 과다 가중치 방지 2.0x 이하
데이터 품질 필터링 Phase 0에서 생성한 클린 데이터 사용
올바른 프롬프트 포맷 <|user|>/<|assistant|>

실행

RUN_NAME=korean_3b_sft \
BASE_CHECKPOINT=checkpoints/korean_3b_fp8/checkpoint-BEST \
SFT_DATA=data/sft_v2/train.jsonl \
VAL_DATA=data/sft_v2/val.jsonl \
MAX_STEPS=10000 \
LR=2.0e-5 \
WARMUP_STEPS=300 \
bash scripts/launch_sft.sh

예상 시간: ~2시간 (3B는 1B 대비 ~2.5x 느림)

성공 기준

지표 목표
Train Loss < 1.85
Val Loss Train의 1.1배 이내
반복률 (rep_penalty 없이) < 10%
반복률 (rep_penalty=1.1) < 3%

Phase 5: 평가 및 배포 (~4시간)

5-1. 전체 벤치마크 (~2시간)

# ko_ifeval
lm_eval --model hf \
    --model_args pretrained=checkpoints/korean_3b_sft/checkpoint-BEST,dtype=bfloat16 \
    --tasks ko_ifeval --device cuda:0

# ko_winogrande
lm_eval --model hf \
    --model_args pretrained=checkpoints/korean_3b_sft/checkpoint-BEST,dtype=bfloat16 \
    --tasks ko_winogrande --device cuda:0

# KoBEST (선택)
lm_eval --model hf \
    --model_args pretrained=checkpoints/korean_3b_sft/checkpoint-BEST,dtype=bfloat16 \
    --tasks kobest_boolq,kobest_copa,kobest_wic,kobest_hellaswag,kobest_sentineg \
    --device cuda:0

3B 목표 수치:

벤치마크 1B 예상 3B 목표
ko_ifeval 20-30% 35-45%
ko_winogrande 53-58% 60-68%
KoBEST (avg) 55-60% 65-75%
반복률 <5% <3%

5-2. HuggingFace Hub 업로드 (~1시간)

# HF 포맷 변환
python scripts/convert_to_hf.py \
    --checkpoint checkpoints/korean_3b_sft/checkpoint-BEST \
    --output_dir hf_models/korean-3b-instruct

# Model card 작성
cat > hf_models/korean-3b-instruct/README.md << 'EOF'
---
language: ko
license: apache-2.0
tags:
  - korean
  - llm
  - instruction-tuning
---
# Korean 3B Instruct
...벤치마크 결과, 사용법 등...
EOF

# 업로드
huggingface-cli upload ghong/korean-3b-instruct hf_models/korean-3b-instruct

5-3. vLLM 서빙 설정 (~1시간)

# vLLM 서버 시작
python -m vllm.entrypoints.openai.api_server \
    --model hf_models/korean-3b-instruct \
    --dtype bfloat16 \
    --tensor-parallel-size 1 \
    --max-model-len 4096 \
    --port 8000

# 테스트
curl http://localhost:8000/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "korean-3b-instruct",
        "messages": [{"role": "user", "content": "한국의 수도는?"}],
        "temperature": 0.7
    }'

FP8 서빙 (B200 최적):

python -m vllm.entrypoints.openai.api_server \
    --model hf_models/korean-3b-instruct \
    --quantization fp8 \
    --tensor-parallel-size 1 \
    --max-model-len 4096

GGUF 변환 (Ollama/로컬 배포):

bash scripts/convert_to_gguf.sh checkpoints/korean_3b_sft/checkpoint-BEST
# Ollama Modelfile 작성 후
ollama create korean-3b -f Modelfile

📋 Phase별 요약 테이블

Phase 소요 시간 필요한 것 성공 기준 실패 시
0: 준비 30분 prepare_sft_data.py, sft_dataset.py 수정 클린 데이터 120K+, sanity 100steps 통과 코드 디버그
1: 1B SFT 40분 8×B200, 클린 데이터, 수정된 코드 Loss<1.90, ValLoss 안정 LR 조정 or 데이터 재점검
2: 1B 평가 2시간 lm-eval-harness, 평가 스크립트 반복률<5%, ko_ifeval>25% Phase 3A
3A: 추가개선 3-5시간 Preference 데이터, ORPO/추가 SFT 반복률<5% 달성 1B 한계 인정→3B
3B: 3B PT 26시간 150B+ 토큰, configs/korean_3b_fp8.yaml PPL<10, loss 하강 데이터 추가 or 아키텍처 조정
4: 3B SFT 2시간 Phase 0의 클린 데이터 재사용 Loss<1.85, 반복률<3% LR/epoch 조정
5: 배포 4시간 HF 계정, vLLM ko_ifeval>35%, 서빙 정상 모델 개선 후 재배포

🔥 오늘 당장 시작할 첫 번째 명령어

cd /PROJECT/0325120031_A/ghong/taketimes/llm-bang
python data/prepare_sft_data.py --output_dir data/sft_v2/ --val_split 0.1

이 명령어 하나로 Phase 0의 가장 중요한 작업(클린 데이터 생성)이 시작된다.


가장 중요한 판단 포인트

1차 판단: Phase 1 완료 후 (Step 10000)

  • Val Loss가 Train Loss의 1.2배 이상? → 과적합. Best checkpoint 사용.
  • Train Loss > 2.0? → 무언가 잘못됨. 코드/데이터 재점검.

2차 판단: Phase 2 평가 후 (가장 중요!)

  • 반복률 <5% AND ko_ifeval >25%? 3B 전환 (Phase 3B)
  • 반복률 5-15%?⚠️ ORPO 시도 (Phase 3A)
  • 반복률 >15%? 원인 분석. 데이터/코드 재검토.

3차 판단: Phase 3B 중간 (3B pretrain step 50000)

  • Loss 하강 멈춤? → 데이터 품질 문제. 필터링 강화.
  • PPL > 15? → 데이터 부족. 추가 수집 필요.

🛡️ 리스크 매트릭스

리스크 확률 영향 예방/대응
Dynamic padding 여전히 미작동 10% 높음 (속도 3-8x 낭비) Sanity check에서 배치 길이 확인
데이터 필터링 과다 (100K 미만) 15% 중간 필터 기준 완화 (80자→50자)
1B 재학습 후에도 반복 >15% 15% 중간 ORPO or 3B 전환
3B pretrain 중 OOM 10% 높음 batch_size 줄이기, gradient checkpointing
cc100 재수집 시간 초과 20% 낮음 CulturaX만으로 시작 (24.8B)
디스크 공간 부족 5% 높음 현재 19TB 가용, 충분

"40분 아끼려고 기술 부채를 안고 가지 마라. 3시간 투자해서 깨끗한 기반을 만들어라."

이 문서는 각 Phase 완료 시 결과로 업데이트할 것.