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

234 lines
7.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# FRANKENSTALLM 프로젝트 완료 보고서
- **작성일**: 2026-03-10
- **상태**: Phase 1~4 전체 완료, HuggingFace 배포 완료
- **모델 배포**: https://huggingface.co/pathcosmos/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단계)
```
Phase 1: Pretrain ──────── 57,000 steps, loss 1.466 ✅ 완료
Phase 2: SFT v2 ──────── 25,500 steps, val_loss 1.8851 ✅ 완료
Phase 3: ORPO ──────── 9,997 steps, eval_loss 1.625 ✅ 완료
Phase 4: GGUF 변환·배포 ─ HuggingFace + Ollama ✅ 완료
```
---
## 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중 패치로 해결:
1. `torch.nan_to_num()` 클램핑
2. `log_softmax` 수치 안정화
3. `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. 주요 기술적 교훈
1. **SFT만으로는 반복 문제 미해결** — ORPO가 greedy 반복률 72.97% → 30.89%로 감소
2. **rep_penalty=1.2가 핵심** — sampling 시 반복 0% 달성
3. **byte_fallback 필수** — SentencePiece 토크나이저는 반드시 `byte_fallback=True` 설정
4. **TRL ORPO NaN 버그** — 라이브러리 레벨 패치 필요 (3중 방어)
5. **DDP+TE static_graph=False** — Transformer Engine과 DDP 혼용 시 주의
6. **NUMA 매핑** — GPU 0-3/4-7 각각 NUMA node 0/1에 바인딩해야 최적 성능
---
*보고서 작성: 2026-03-10*