FRANKENSTALLM 프로젝트 완료 보고서
1. 프로젝트 개요
8× NVIDIA B200 GPU 위에서 한국어 3B LLM을 처음부터 직접 구현하고 배포까지 완료한 실험 프로젝트.
| 항목 |
내용 |
| 목표 |
한국어에 특화된 3B 파라미터 언어 모델 개발 |
| 접근 |
Pretrain → SFT → ORPO 파인튜닝 → GGUF 변환 → Ollama 배포 |
| 하드웨어 |
8× NVIDIA B200 (183GB VRAM each, 총 ~1.47TB VRAM) |
| 총 학습 기간 |
2026-02-27 ~ 2026-03-09 |
2. 전체 진행 요약 (4단계)
3. Phase 1 — 사전학습 (Pretrain)
| 항목 |
값 |
| 총 학습 스텝 |
57,000 steps |
| 최종 Loss |
1.466 (수렴) |
| 학습 토큰 |
~38.5B tokens |
| 하드웨어 |
8× B200, DDP |
| 처리 속도 |
292K tok/s (MFU 33.5%) |
| Precision |
BF16 / FP8 Tensor Core |
모델 아키텍처
| 항목 |
값 |
| Architecture |
LlamaForCausalLM |
| Hidden size |
2,048 |
| Layers |
24 |
| Attention heads |
16 |
| KV heads |
4 |
| Max position |
4,096 |
| Vocab size |
64,256 (64,000 + 256 byte-fallback) |
주요 이슈 및 해결
- NUMA affinity: GPU 0-3 → NUMA node 0, GPU 4-7 → NUMA node 1 최적 매핑 적용
- FP8 mixed precision: B200 네이티브
torch.float8_e4m3fn 활용
- DDP static_graph=False: Transformer Engine과의 호환성 확보
4. Phase 2 — SFT (지시 학습)
| 항목 |
값 |
| 총 학습 스텝 |
25,500 steps (early stopping) |
| val_loss |
1.8851 |
| 학습률 |
5e-5 |
| Batch size |
4 (grad_accum=8 → effective BS 32) |
| EOS 종료율 |
0% → 60% |
| greedy 반복률 |
60.99% → 72.97% (ORPO 필요 확인) |
SFT 결과
- 지식 보존 우수 (forgetting 0.9% — Base PPL 거의 유지)
- 지시 따르기 일부 학습 (EOS 0% → 60%)
- 반복 문제 미해결 (greedy rep 72.97%) → ORPO 진행 결정
5. Phase 3 — ORPO (선호도 정렬)
HP Sweep (6 configs)
| Config |
beta |
lr |
eval_loss |
pref_acc |
| baseline |
0.25 |
8e-6 |
1.703 |
72.1% |
| fast |
0.25 |
1.2e-5 |
1.693 |
73.8% |
| best ← |
0.25 |
1.2e-5 |
1.693 |
73.8% |
| conserv |
0.15 |
5e-6 |
1.721 |
70.2% |
| aggressive |
0.30 |
1.5e-5 |
1.709 |
72.5% |
본 학습 결과
| 항목 |
값 |
| 스텝 |
9,997 (조기 수렴) |
| eval_loss |
1.7910 → 1.6250 |
| Preference Accuracy |
67.8% → 76.02% |
| Reward Margin |
0.107 → 0.6100 |
| greedy 반복률 |
72.97% → 30.89% (↓42pp) |
| EOS 종료율 |
60% → 67% |
| KoBEST 0-shot |
52.75% |
| PPL forgetting |
최대 4.1% (임계값 15% 이하 ✅) |
10차원 종합 평가
| # |
차원 |
결과 |
| 1 |
Perplexity (지식 보존) |
✅ PASS |
| 2 |
생성 품질 (greedy) |
❌ FAIL (30.89%, 목표 <5%) |
| 3 |
한국어 벤치마크 KoBEST |
❌ FAIL (52.75%, 목표 >55%) |
| 4 |
영어 벤치마크 |
❌ FAIL |
| 5 |
Calibration |
✅ PASS (67.99%) |
| 6 |
SFT Chat 능력 |
✅ PASS |
| 7 |
Preference Accuracy |
✅ PASS (76.02%) |
| 8 |
Reward Margins |
✅ PASS (0.6100) |
| 9 |
Parameter Sensitivity |
✅ PASS |
| 10 |
SFT→ORPO 개선 |
✅ PASS |
| 종합 |
7/10 PASS |
정량 스코어 63.7/100 |
주요 이슈 해결: TRL ORPO NaN 버그
TRL 라이브러리의 ORPO 구현에서 chosen_logps가 nan이 되는 버그를 3중 패치로 해결:
torch.nan_to_num() 클램핑
log_softmax 수치 안정화
inf 마스킹
6. Phase 4 — GGUF 변환 & 배포
byte-fallback 문제 해결 (v2)
| 항목 |
내용 |
| 문제 |
SentencePiece Unigram 토크나이저에 byte_fallback 미적용 |
| 증상 |
\n 등 미등록 문자 입력 시 llama.cpp 크래시 |
| 해결 |
256개 byte-fallback 토큰 추가, 임베딩 64000→64256 리사이즈 |
| 검증 |
\n 포함 프롬프트 Ollama 처리 확인 (크래시 없음) |
변환 결과
| 파일 |
크기 |
설명 |
frankenstallm-3b-f16.gguf |
6.0G |
v1 f16 (ORPO, 원본) |
frankenstallm-3b-Q8_0.gguf |
3.2G |
v1 Q8_0 |
frankenstallm-3b-Q4_K_M.gguf |
1.9G |
v1 Q4_K_M |
frankenstallm-3b-v2-f16.gguf |
2.3G |
v2 f16 (byte-fallback 수정) |
frankenstallm-3b-v2-Q8_0.gguf |
1.2G |
v2 Q8_0 |
frankenstallm-3b-v2-Q4_K_M.gguf |
757M |
v2 Q4_K_M ← 권장 |
Ollama 배포 벤치마크
| 항목 |
값 |
| 모델명 |
frankenstallm-3b-v2:Q4_K_M |
| 테스트 수 |
35 (자동 20 + 수동 15) |
| 자동 채점 평균 |
46.7 |
| 평균 TPS |
142.5 tok/s |
| 평균 TTFT |
16.7 ms |
| korean_nlu |
100.0 |
| reasoning |
50.0 |
| knowledge |
75.0 |
| instruction_following |
66.7 |
최적 샘플링 파라미터
ORPO eval grid 실측 최적값 (t0.7_rep1.2):
| 파라미터 |
값 |
비고 |
| temperature |
0.7 |
창의성/일관성 균형점 |
| repeat_penalty |
1.2 |
greedy 반복 0%로 억제 |
| top_p |
0.9 |
nucleus sampling |
| top_k |
50 |
|
| num_predict |
512 |
|
| num_ctx |
4096 |
|
7. HuggingFace 배포 현황 (2026-03-10)
URL: https://huggingface.co/pathcosmos/frankenstallm
업로드 완료 파일
| 경로 |
내용 |
model.safetensors |
4.76GB — v2 ORPO 베스트 체크포인트 |
config.json, tokenizer.json 등 |
HF 모델 설정 파일 |
sampling_config.json |
검증된 샘플링 파라미터 |
gguf/frankenstallm-3b-v2-Q4_K_M.gguf |
757M ← 권장 |
gguf/frankenstallm-3b-v2-Q8_0.gguf |
1.2G |
gguf/frankenstallm-3b-v2-f16.gguf |
2.3G |
gguf/frankenstallm-3b-Q4_K_M.gguf |
1.9G |
gguf/frankenstallm-3b-Q8_0.gguf |
3.2G |
gguf/frankenstallm-3b-f16.gguf |
6.0G |
gguf/Modelfile.3b-v2-Q4_K_M 등 |
Ollama Modelfile 6종 |
8. 하드웨어 환경
| 항목 |
사양 |
| GPU |
8× NVIDIA B200 |
| VRAM |
183GB HBM3e/GPU (~1.47TB total) |
| FP8 Tensor Core |
2,250 TFLOPS/GPU |
| NVLink |
5.0 NV18, 900 GB/s bidirectional |
| CPU |
2× AMD EPYC 9365 (Zen 5), 72코어 |
| RAM |
2.21TB DDR5 |
| CUDA |
13.1 / Driver 580.95.05 |
| PyTorch |
nv25.12 커스텀 빌드 (B200 최적화) |
| FlashAttention |
2.7.4 |
| NCCL |
2.28.9 |
9. 주요 기술적 교훈
- SFT만으로는 반복 문제 미해결 — ORPO가 greedy 반복률 72.97% → 30.89%로 감소
- rep_penalty=1.2가 핵심 — sampling 시 반복 0% 달성
- byte_fallback 필수 — SentencePiece 토크나이저는 반드시
byte_fallback=True 설정
- TRL ORPO NaN 버그 — 라이브러리 레벨 패치 필요 (3중 방어)
- DDP+TE static_graph=False — Transformer Engine과 DDP 혼용 시 주의
- NUMA 매핑 — GPU 0-3/4-7 각각 NUMA node 0/1에 바인딩해야 최적 성능
보고서 작성: 2026-03-10