GGUF 모델 포맷

llama.cpp 기반 로컬 LLM 모델 포맷의 구조, 양자화, 변환 워크플로 상세 가이드

업데이트 안내: 모델/요금/버전/정책 등 시점에 민감한 정보는 변동될 수 있습니다. 최신 내용은 공식 문서를 확인하세요.

개요

Ollama는 GGUF (Georgi Gerganov Unified Format) 파일 형식을 사용합니다. GGUF는 Georgi Gerganov가 개발한 llama.cpp 프로젝트의 핵심 모델 포맷으로, 로컬 환경에서 LLM을 효율적으로 실행하기 위해 설계되었습니다. 현재 Ollama, LM Studio, llama.cpp, GPT4All 등 대부분의 로컬 LLM 런타임이 GGUF를 표준 포맷으로 채택하고 있습니다.

📜 GGUF의 탄생 배경

초기 llama.cpp는 GGML (Georgi Gerganov Machine Learning) 포맷을 사용했습니다. GGML은 모델 가중치만 저장하고, 토크나이저와 메타데이터는 별도 파일로 관리해야 했습니다. 2023년 8월, 이러한 한계를 극복하기 위해 GGUF가 등장했습니다. GGUF는 모델 가중치, 토크나이저, 하이퍼파라미터, 아키텍처 정보를 단일 파일에 모두 포함하여 모델 배포와 관리를 획기적으로 단순화했습니다.

GGML (구 포맷) 2023년 이전 model.bin — 가중치만 저장 tokenizer.model — 별도 파일 params.json — 별도 파일 ❌ 파일 누락 위험 ❌ 버전 불일치 문제 진화 GGUF (현재 표준) 2023년 8월~ model.gguf (단일 파일) ✅ 가중치 (텐서 데이터) ✅ 토크나이저 ✅ 하이퍼파라미터 ✅ 아키텍처 메타데이터 ✅ 자기 완결적, 이식성 극대 ✅ 확장 가능한 KV 메타데이터

GGML에서 GGUF로의 진화: 분산된 파일 → 단일 자기 완결적 파일

포맷 구조와 양자화

GGUF 버전 히스토리

GGUF는 출시 이후 지속적으로 발전해왔습니다. 각 버전은 하위 호환성을 유지하면서 새로운 기능을 추가합니다.

2023년 3월 GGML 시대 (구 포맷) llama.cpp 첫 릴리스. 가중치 전용 바이너리. 토크나이저/설정은 별도 파일. 모델 간 호환성 문제 빈발 2023년 8월 GGUF v1 — 최초 릴리스 • 단일 파일에 모든 정보 포함 (가중치 + 토크나이저 + 메타데이터) • Key-Value 메타데이터 시스템 도입 • Magic Number 검증 (0x46475547) 2023년 9월 GGUF v2 — 토크나이저 개선 • 64비트 데이터 오프셋 지원 (대형 모델 >4GB 텐서 데이터 대응) • 토크나이저 메타데이터 구조 표준화 • 문자열 인코딩 UTF-8 표준화 2023년 10월~현재 GGUF v3 — 현재 표준 ★ • 빅 엔디안(Big-Endian) 지원 (크로스 플랫폼 완전 호환) • K-quant 양자화 타입 (Q4_K_M, Q5_K_S 등) • i-quant 도입 (IQ4_XS, IQ3_XXS) • 파일 분할(Split) 지원 • 텐서 정렬(alignment) 커스터마이징

GGUF 포맷 버전 타임라인: GGML → v1 → v2 → v3 (현재 표준)

GGUF 파일 내부 구조

GGUF 파일은 바이너리 포맷으로, 정해진 구조에 따라 순차적으로 데이터를 배치합니다. 모든 정보가 하나의 파일에 포함되므로 별도의 설정 파일 없이 모델을 로드할 수 있습니다.

model.gguf ① Magic Number 0x46475547 ("GGUF" in Little-Endian) 4 bytes ② Header (헤더) • version: GGUF 버전 (현재 v3) • tensor_count / metadata_kv_count ~20 bytes ③ Metadata KV Pairs (메타데이터) • general.architecture: "llama" / "mistral" / ... • general.name: 모델 이름 • llama.context_length: 컨텍스트 길이 • tokenizer.ggml.model: 토크나이저 종류 • quantization_version: 양자화 정보 ... 가변 크기 ④ Tensor Info (텐서 정보) • 각 텐서의 이름, 차원, 데이터 타입, 오프셋 • 예: "blk.0.attn_q.weight" [4096, 4096] Q4_0 가변 크기 정렬 패딩 (기본 32바이트 정렬) ⑤ Tensor Data (실제 가중치 데이터) 파일의 대부분

GGUF 파일 바이너리 레이아웃: Magic → Header → Metadata → Tensor Info → Tensor Data

GGUF의 핵심 설계 원칙은 자기 설명적(self-describing) 구조입니다. 파일 자체에 모델을 로드하는 데 필요한 모든 정보가 담겨 있으므로, 외부 설정 파일이나 코드 없이도 모델의 아키텍처, 양자화 방식, 토크나이저 종류를 파악할 수 있습니다.

# GGUF 파일 정보 확인 (llama.cpp 도구)
# gguf-dump: 메타데이터와 텐서 구조를 출력
$ python3 -c "
from gguf import GGUFReader
reader = GGUFReader('model.gguf')
print(f'GGUF Version: {reader.header.version}')
print(f'Tensor Count: {reader.header.tensor_count}')
print(f'Metadata KV Count: {reader.header.metadata_kv_count}')
for kv in reader.fields.values():
    print(f'  {kv.name}: {kv.data}')
"

# 출력 예시
GGUF Version: 3
Tensor Count: 291
Metadata KV Count: 23
  general.architecture: llama
  general.name: Llama 3.2 3B Instruct
  llama.context_length: 131072
  llama.embedding_length: 3072
  llama.block_count: 28
  llama.attention.head_count: 24
  tokenizer.ggml.model: gpt2
  general.quantization_version: 2

바이너리 헤더 Hex Dump

실제 GGUF 파일의 첫 바이트를 살펴보면 포맷의 구조를 직접 확인할 수 있습니다. 아래는 hexdump 명령으로 확인한 GGUF v3 파일의 헤더 영역입니다.

# GGUF 파일 헤더 Hex Dump 확인
$ hexdump -C model.gguf | head -n 4

00000000  47 47 55 46  03 00 00 00  17 00 00 00  00 00 00 00  |GGUF............|
00000010  23 01 00 00  00 00 00 00  14 00 00 00  00 00 00 00  |#...............|
         ╰─┬────────╯ ╰─┬────────╯ ╰─┬────────────────────╯ ╰─┬────────────────────╯
     Magic Number   Version=3    tensor_count=23(0x17)    metadata_kv_count=291(0x123)

# 상세 구조 해설
Offset  0x00-0x03: 47 47 55 46"GGUF" (ASCII, Little-Endian)
Offset  0x04-0x07: 03 00 00 00 → version = 3 (uint32_t LE)
Offset  0x08-0x0F: 17 00 00 00 00 00 00 00 → tensor_count = 23 (uint64_t LE)
Offset  0x10-0x17: 23 01 00 00 00 00 00 00 → metadata_kv_count = 291 (uint64_t LE)

# 파일 전체 구조 오프셋 확인
$ python3 -c "
import struct
with open('model.gguf', 'rb') as f:
    magic = f.read(4)
    version = struct.unpack('<I', f.read(4))[0]
    n_tensors = struct.unpack('<Q', f.read(8))[0]
    n_kv = struct.unpack('<Q', f.read(8))[0]
    print(f'Magic: {magic}')
    print(f'Version: {version}')
    print(f'Tensors: {n_tensors}')
    print(f'KV pairs: {n_kv}')
"
Magic: b'GGUF'
Version: 3
Tensors: 23
KV pairs: 291
💡 GGUF Magic Number

GGUF 파일은 반드시 0x47475546 ("GGUF"의 ASCII) 매직 넘버로 시작합니다. 빅 엔디안 시스템에서는 0x47475546이 그대로, 리틀 엔디안에서도 0x46554747이 아닌 동일한 바이트 순서(47 47 55 46)를 사용합니다. 이를 통해 파일의 엔디안을 감지합니다. 만약 첫 4바이트가 46 55 47 47이면 빅 엔디안 GGUF로 판별합니다.

메타데이터 KV 상세

GGUF 메타데이터는 Key-Value 쌍으로 구성됩니다. 키는 네임스페이스 규칙(general.*, {arch}.*, tokenizer.*)을 따릅니다.

네임스페이스 주요 키 설명
general.* architecture, name, author, license, description 모델 기본 정보 (아키텍처 종류, 이름, 라이선스 등)
{arch}.* context_length, embedding_length, block_count, attention.head_count 아키텍처별 하이퍼파라미터 (llama.*, mistral.*, phi.* 등)
tokenizer.* ggml.model, ggml.tokens, ggml.scores, ggml.bos_token_id 토크나이저 종류, 어휘, 특수 토큰 ID
quantize.* imatrix.file, imatrix.dataset 양자화에 사용된 중요도 행렬(importance matrix) 정보

메타데이터 값 타입

GGUF 메타데이터의 각 Key-Value 쌍에서 Value는 다음 타입 중 하나를 가집니다. 이 타입 시스템 덕분에 메타데이터를 파싱할 때 별도의 스키마 파일이 필요 없습니다.

타입 ID 타입명 크기 사용 예
0UINT81B불리언 플래그
1INT81B-
2UINT162B-
3INT162B-
4UINT324Bcontext_length, head_count
5INT324B-
6FLOAT324Brope_freq_base, layer_norm_eps
7BOOL1B-
8STRING가변architecture, name, license
9ARRAY가변tokenizer.ggml.tokens (어휘 목록)
10UINT648B-
11INT648B-
12FLOAT648B-

지원 아키텍처

general.architecture 키는 모델의 아키텍처 종류를 지정합니다. GGUF는 현재 다양한 Transformer 변형 아키텍처를 지원하며, 지속적으로 확장되고 있습니다.

아키텍처 ID 대표 모델 설명
llamaLlama 2/3, Mistral, Yi, Qwen2가장 보편적. RoPE + GQA/MHA 기반 디코더
falconFalcon 7B/40B/180BMulti-query attention 기반
gpt2GPT-2원조 GPT 아키텍처
gptjGPT-J 6BRotary embedding + parallel attention
gptneoxGPT-NeoX, PythiaEleutherAI 계열
mptMPT 7B/30BALiBi attention, FlashAttention
baichuanBaichuan 7B/13B중국어 특화
starcoderStarCoder, StarCoder2코드 생성 특화
phi2Phi-2, Phi-3Microsoft 소형 고효율 모델
gemmaGemma, Gemma 2Google 오픈 웨이트 모델
command-rCommand R/R+Cohere RAG 특화 모델
qwen2Qwen2, Qwen2.5Alibaba 다국어 모델
deepseek2DeepSeek-V2/V3MoE (Mixture of Experts) 아키텍처
GGUF 범용 포맷 Llama 계열 Llama3, Mistral, Yi Qwen2, CodeLlama 가장 많이 사용 ★ Falcon 7B / 40B / 180B GPT 계열 GPT-2, J, NeoX Phi Phi-2, Phi-3 StarCoder 코드 생성 특화 Gemma Google 오픈 웨이트 DeepSeek MoE V2 / V3 (MoE 구조) MPT ALiBi attention Baichuan 중국어 특화

GGUF가 지원하는 다양한 아키텍처: 하나의 포맷으로 수십 종의 모델을 통합

GGUF 지원 데이터 타입

GGUF는 원본 부동소수점부터 극도로 압축된 양자화 타입까지 다양한 데이터 타입을 지원합니다. 각 타입은 메모리 효율추론 품질 사이의 트레이드오프를 제공합니다.

타입 비트/가중치 블록 크기 설명
F32 32-bit - 원본 정밀도. 학습/변환 중간 단계에서 사용
F16 16-bit - 반정밀도. 원본에 가까운 품질, GPU 추론 최적
BF16 16-bit - Brain Float16. 넓은 지수 범위, 학습에 유리
Q8_0 8-bit 32 8비트 양자화. 품질 손실 최소, 크기 50% 감소
Q5_K_M 5-bit 32 K-quant (중요도 기반). 품질/크기 균형 우수
Q4_K_M 4-bit 32 가장 널리 사용. 실용적 품질, 크기 75% 감소
Q4_0 4-bit 32 기본 4비트. K-quant보다 단순하지만 빠름
Q3_K_M 3-bit 32 3비트. 리소스 제한 환경에서 사용
Q2_K 2-bit 32 2비트. 극한 압축, 품질 저하 주의
IQ4_XS ~4-bit 256 i-quant (중요도 행렬). 같은 비트에서 더 높은 품질
IQ3_XXS ~3-bit 256 i-quant 극압축. 연구/실험용
💡 양자화 명명 규칙
  • Q{n}_0: 기본(legacy) 양자화 — 단순하고 빠르지만 품질 낮음
  • Q{n}_K_S / Q{n}_K_M / Q{n}_K_L: K-quant — 레이어별 중요도 기반 양자화 (S=Small, M=Medium, L=Large). _M이 가장 일반적
  • IQ{n}_*: i-quant — 중요도 행렬(imatrix)을 사용하여 더 정교한 양자화. 같은 비트에서 Q보다 높은 품질

블록 양자화 동작 원리

GGUF의 양자화는 블록 단위로 작동합니다. 가중치를 작은 블록(보통 32개씩)으로 나누고, 각 블록마다 스케일 팩터양자화된 정수 값을 저장합니다. 추론 시에는 역양자화(dequantization)하여 부동소수점으로 복원합니다.

Q4_0 블록 양자화 과정 (32개 가중치 → 1블록) ① 원본 FP16 가중치 (32개, 64 bytes) [0.0312, -0.1523, 0.2148, -0.0078, 0.1875, -0.3242, 0.0547, 0.1094, ...] × 32개 각 값: 16-bit 부동소수점 (2 bytes × 32 = 64 bytes) 양자화 ② 양자화 과정 1. 블록 내 최대 절댓값(absmax) 계산: max(|values|) = 0.3242 2. 스케일 팩터(scale) 산출: scale = absmax / 7 = 0.04632 (4비트: -8~7 범위) 3. 각 값을 양자화: q[i] = round(value[i] / scale) + 8 → 4비트 정수 (0~15) 예: 0.0312 / 0.04632 ≈ 0.67 → round → 1 + 8 = 9, -0.3242 / 0.04632 ≈ -7.0 → round → -7 + 8 = 1 ③ 저장 형태 (총 18 bytes — 64 bytes → 18 bytes, 72% 절약) [scale: FP16 2bytes] [q0q1: 4bit×2=1byte] [q2q3: 1byte] ... [q30q31: 1byte] 스케일 팩터(2B) + 양자화 값(4bit × 32 = 16B) = 18 bytes/block 역양자화 ④ 역양자화 (추론 시) value[i] = (q[i] - 8) × scale → [0.0463, -0.1389, 0.2316, -0.0000, 0.1852, -0.3242, ...]

Q4_0 블록 양자화: 32개 FP16 가중치(64B) → 스케일+양자화값(18B)으로 72% 압축

양자화 기법 심화 비교

GGUF는 세 가지 주요 양자화 패밀리를 지원합니다. 각 기법은 정밀도와 성능의 트레이드오프가 다릅니다.

Legacy Quant Q4_0, Q5_0, Q8_0 단일 스케일 팩터/블록 모든 레이어 동일 처리 장점: ⚡ 가장 빠른 양자화/추론 ⚡ 구현 단순 단점: ❌ 품질 상대적 낮음 ❌ 이상치 가중치에 취약 속도 우선 시 선택 K-Quant ★ 추천 Q4_K_S/M/L, Q5_K_M, Q6_K 슈퍼블록 + 서브블록 구조 레이어별 중요도 차등 할당 장점: ✅ 최적의 품질/크기 균형 ✅ 중요 레이어는 높은 정밀도 단점: ⚠️ Legacy보다 약간 느림 ⚠️ 양자화 시간 약간 더 소요 대부분의 경우 최선 i-Quant (imatrix) IQ4_XS, IQ3_XXS, IQ2_XXS 중요도 행렬 기반 양자화 가중치별 중요도 측정 후 처리 장점: ✅ 동일 비트에서 최고 품질 ✅ 극압축에서도 합리적 품질 단점: ❌ 캘리브레이션 데이터 필요 ❌ 양자화 시간 크게 증가 극압축 필요 시 선택

세 가지 양자화 기법 비교: Legacy(속도) vs K-Quant(균형, 추천) vs i-Quant(품질)

모델 크기별 양자화 벤치마크

실제 모델에 양자화를 적용했을 때의 파일 크기와 품질(Perplexity) 변화입니다. Perplexity(PPL)는 낮을수록 좋으며, 언어 모델이 텍스트를 얼마나 잘 예측하는지를 나타냅니다.

양자화 7B 크기 7B PPL 13B 크기 13B PPL 70B 크기 70B PPL
F16 13.5 GB 5.59 25.0 GB 5.09 131 GB 3.32
Q8_0 7.2 GB 5.60 13.3 GB 5.09 69.4 GB 3.32
Q6_K 5.5 GB 5.60 10.3 GB 5.10 53.7 GB 3.33
Q5_K_M 4.8 GB 5.63 9.0 GB 5.11 46.7 GB 3.34
Q4_K_M 4.1 GB 5.68 7.6 GB 5.14 39.6 GB 3.36
Q4_0 3.8 GB 5.77 7.0 GB 5.20 36.2 GB 3.39
IQ4_XS 3.7 GB 5.66 6.8 GB 5.12 35.0 GB 3.35
Q3_K_M 3.3 GB 5.93 6.1 GB 5.30 31.7 GB 3.45
IQ3_XXS 2.7 GB 5.85 4.9 GB 5.24 25.6 GB 3.41
Q2_K 2.5 GB 6.79 4.7 GB 5.79 24.6 GB 3.72
7B 모델 — 양자화별 크기 vs 품질 (Perplexity) PPL (낮을수록 좋음) 파일 크기 (GB) 5.5 5.7 5.9 6.1 2GB 4GB 6GB 8GB 10GB 14GB F16 Q8_0 Q5_K_M Q4_K_M ★ IQ4_XS Q4_0 Q3_K_M IQ3_XXS Q2_K (6.79) Sweet Spot

7B 모델 양자화 트레이드오프: Q4_K_M이 크기 대비 품질의 최적점(Sweet Spot)

💡 양자화 선택 실전 가이드
  • 품질 최우선: Q8_0 — PPL 손실 거의 없음, F16 대비 47% 크기 절감
  • 최적 균형 (추천): Q4_K_M — PPL 약 1.6% 증가, 크기 70% 절감. 대부분의 작업에서 체감 차이 없음
  • 극한 압축: IQ4_XS — Q4_K_M보다 작으면서 비슷한 품질 (imatrix 필요)
  • RAM 극히 부족: IQ3_XXS 또는 Q2_K — 품질 저하 감수. 테스트 후 사용 권장
  • 모델이 클수록 양자화 영향 작음 — 70B Q4_K_M은 7B F16보다 품질이 높음

다른 모델 포맷과의 비교

GGUF llama.cpp ✅ CPU 추론 최적 ✅ 단일 파일 ✅ 양자화 내장 ✅ mmap 지원 ✅ 메타데이터 용도: 로컬 추론 Ollama, LM Studio GPT4All 로컬 LLM 표준 SafeTensors Hugging Face ✅ GPU 학습 최적 ✅ 안전한 로딩 ❌ 양자화 없음 ✅ mmap 지원 ⚠️ 제한적 메타 용도: 학습/파인튜닝 HuggingFace Hub Transformers HF 생태계 표준 PyTorch .pt / .bin ✅ GPU 학습 최적 ❌ pickle 보안 위험 ❌ 양자화 없음 ❌ mmap 불가 ❌ 메타데이터 없음 용도: 연구/학습 PyTorch 네이티브 레거시 호환 레거시 포맷 ONNX Open Neural Network ✅ 크로스 프레임워크 ✅ 최적화 런타임 ⚠️ 제한적 양자화 ✅ mmap 지원 ✅ 연산 그래프 포함 용도: 프로덕션 배포 DirectML, ONNX RT Edge 디바이스 배포 최적화

주요 모델 포맷 비교: GGUF는 로컬 CPU/GPU 추론에 최적화된 포맷

비교 항목 GGUF SafeTensors PyTorch (.pt) ONNX
주요 용도 로컬 추론 학습/배포 연구/학습 프로덕션 배포
양자화 2~8비트 내장 미지원 미지원 제한적
CPU 추론 최적화됨 비효율적 비효율적 보통
GPU 추론 지원 (부분 오프로드) 최적 최적 지원
메모리 매핑 ✅ mmap ✅ mmap
보안 안전 (바이너리) 안전 ⚠️ pickle 위험 안전
메타데이터 풍부 (KV 쌍) 제한적 없음 연산 그래프
단일 파일 ⚠️ (분할 가능) ⚠️ (분할 가능)
변환 난이도 쉬움 (llama.cpp) 쉬움 기본 포맷 보통

메모리 매핑(mmap)과 GGUF

GGUF가 빠르게 모델을 로드할 수 있는 핵심 비결은 메모리 매핑(mmap)입니다. 일반적인 파일 로딩은 디스크→RAM 전체 복사가 필요하지만, mmap은 운영체제의 가상 메모리 시스템을 활용하여 파일을 직접 메모리 공간에 매핑합니다.

일반 로딩 (read) 디스크 model.gguf (4GB) 전체 복사 RAM 4GB 전부 점유 ⏱ 로딩 수초~수십초 / RAM 전부 사용 mmap 로딩 (GGUF) 디스크 model.gguf (4GB) 필요한 페이지만 가상 메모리 필요 분만 RAM 사용 ⚡ 즉시 로딩 / RAM 절약 / OS 캐시 활용 mmap 장점 요약 • 로딩 시간: 수초 → 거의 즉시 (메모리 매핑만 설정) • 여러 프로세스가 같은 모델 파일을 공유 가능 (메모리 절약) • OS가 자동으로 자주 쓰는 부분을 RAM에 캐시

일반 파일 로딩 vs mmap: GGUF는 mmap을 통해 즉시 로딩과 메모리 공유를 실현

GPU 오프로딩 (Partial Offload)

GGUF 기반 추론 엔진(llama.cpp, Ollama)은 모델의 레이어를 GPU와 CPU에 분산하여 배치할 수 있습니다. 이를 GPU 오프로딩이라 하며, VRAM이 모델 전체를 수용하지 못할 때 핵심적인 기능입니다. --n-gpu-layers (줄여서 -ngl) 파라미터로 GPU에 올릴 레이어 수를 지정합니다.

28-Layer 모델의 GPU 오프로딩 시나리오 CPU Only -ngl 0 CPU (RAM) Layer 0~27 (전체 28층) 4.1 GB RAM 느림 (1x) Partial Offload -ngl 20 GPU (VRAM) Layer 0~19 2.9 GB VRAM CPU (RAM) Layer 20~27 1.2 GB RAM 보통 (3~5x) Full GPU ★ -ngl 99 (전체) GPU (VRAM) Layer 0~27 (전체 28층) 4.1 GB VRAM 최고속 (10~20x) VRAM 필요량 (Q4_K_M 기준) 3B → ~2 GB 7B → ~4 GB 13B → ~8 GB 34B → ~20 GB 70B → ~40 GB 일반 GPU별 권장 8GB → 7B 풀 GPU 12GB → 13B 풀 GPU 24GB → 34B 풀 GPU 48GB → 70B 풀 GPU KV 캐시 추가 필요 (컨텍스트 길이에 비례)

GPU 오프로딩 시나리오: CPU Only → Partial → Full GPU (속도 10~20배 차이)

# Ollama에서 GPU 레이어 수 지정
OLLAMA_NUM_GPU_LAYERS=20 ollama run llama3.2:3b

# llama.cpp 직접 사용 시
./llama-cli -m model.gguf -ngl 99  # 전체 GPU 오프로드
./llama-cli -m model.gguf -ngl 20  # 20개 레이어만 GPU
./llama-cli -m model.gguf -ngl 0   # CPU 전용 (GPU 미사용)

# VRAM 사용량 실시간 모니터링
watch -n 1 nvidia-smi  # NVIDIA GPU
# macOS: 활성 상태 보기 → GPU 히스토리

GGUF 변환 워크플로

Hugging Face의 SafeTensors/PyTorch 모델을 GGUF로 변환하는 과정입니다. llama.cpp 프로젝트의 convert_hf_to_gguf.py 스크립트를 사용합니다.

# 1. llama.cpp 클론 및 빌드
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
pip install -r requirements.txt

# 2. Hugging Face 모델을 GGUF F16으로 변환
python convert_hf_to_gguf.py \
  /path/to/hf-model \
  --outfile model-f16.gguf \
  --outtype f16

# 3. 양자화 적용 (F16 → Q4_K_M)
./llama-quantize model-f16.gguf model-q4km.gguf Q4_K_M

# 중요도 행렬(imatrix) 기반 양자화 (더 높은 품질)
# 먼저 imatrix 생성
./llama-imatrix \
  -m model-f16.gguf \
  -f calibration-data.txt \
  -o imatrix.dat

# imatrix를 사용한 양자화
./llama-quantize \
  --imatrix imatrix.dat \
  model-f16.gguf \
  model-iq4xs.gguf IQ4_XS
HF 모델 .safetensors / .bin + config.json convert_hf GGUF (F16) 원본 품질 유지 ~13GB (7B 모델) quantize GGUF (Q4_K_M) 양자화 적용 ~4GB (7B 모델) ollama create Ollama ollama run 로컬 추론 실행 HuggingFace → F16 변환 → 양자화 → 로컬 실행 총 소요 시간: 수분 ~ 수십분 (모델 크기에 따라)

GGUF 변환 파이프라인: HuggingFace 모델 → F16 → 양자화 → Ollama 실행

GGUF 핵심 특징 요약

특징 설명
단일 파일 모델 가중치, 토크나이저, 하이퍼파라미터, 아키텍처 메타데이터를 하나의 .gguf 파일로 패키징. 파일 하나만 옮기면 모델 이동 완료
다양한 양자화 Q2_K ~ Q8_0, IQ 시리즈 등 10가지 이상의 양자화 레벨 내장 지원. K-quant, i-quant 등 고급 양자화 기법 포함
메모리 매핑 mmap을 통한 즉시 로딩, 멀티 프로세스 메모리 공유, OS 레벨 캐싱 자동 활용
자기 설명적 확장 가능한 KV 메타데이터로 모델의 모든 정보를 파일 자체에서 확인 가능. 외부 설정 파일 불필요
크로스 플랫폼 Windows, Linux, macOS (ARM/x86) 모두 지원. 엔디안 표준화로 플랫폼 간 바이너리 호환
확장성 버전 관리 시스템으로 하위 호환성 유지. 새로운 양자화 타입이나 메타데이터 추가 시 기존 파일과 호환
광범위한 지원 Ollama, LM Studio, llama.cpp, GPT4All, KoboldCpp, text-generation-webui 등 대부분의 로컬 LLM 도구가 지원

GGUF Split — 대용량 모델 분할

70B 이상의 대형 모델은 단일 GGUF 파일이 수십 GB에 달합니다. 일부 파일 시스템(FAT32 등)은 4GB 제한이 있고, 대용량 파일 전송 시 문제가 될 수 있습니다. GGUF v3부터 파일 분할(Split)을 공식 지원합니다.

# GGUF 파일 분할 (llama.cpp 도구)
./llama-gguf-split --split-max-size 8G model-70b-q4km.gguf model-70b-q4km

# 결과: 분할된 파일들
model-70b-q4km-00001-of-00005.gguf  # 8GB
model-70b-q4km-00002-of-00005.gguf  # 8GB
model-70b-q4km-00003-of-00005.gguf  # 8GB
model-70b-q4km-00004-of-00005.gguf  # 8GB
model-70b-q4km-00005-of-00005.gguf  # 나머지

# 분할된 파일 다시 병합
./llama-gguf-split --merge model-70b-q4km-00001-of-00005.gguf merged-model.gguf

# Ollama는 분할 파일도 직접 사용 가능
# Modelfile에서 첫 번째 파일만 지정하면 나머지를 자동 탐지
FROM ./model-70b-q4km-00001-of-00005.gguf

Transformer 블록과 GGUF 텐서 매핑

GGUF 파일 내부의 텐서 이름은 Transformer 아키텍처의 각 구성 요소에 직접 매핑됩니다. 텐서 이름을 이해하면 모델의 구조를 파일 레벨에서 파악할 수 있습니다.

Llama 아키텍처 — GGUF 텐서 이름 매핑 token_embd.weight [vocab_size × embed_dim] — 토큰 임베딩 × N blocks (blk.{i}.*) 예: blk.0.*, blk.1.*, ... blk.{i}.attn_norm.weight RMSNorm Self-Attention attn_q.weight attn_k.weight attn_v.weight attn_output.weight — [embed_dim × embed_dim] Query/Key/Value Output proj blk.{i}.ffn_norm.weight RMSNorm Feed-Forward (SwiGLU) ffn_gate.weight ffn_up.weight ffn_down.weight — [embed_dim × ff_dim] Gate + Up proj Down proj output_norm.weight → output.weight [embed_dim] RMSNorm → [vocab_size × embed_dim] 출력 헤드

Llama 아키텍처의 GGUF 텐서 이름: blk.{i}.attn_q/k/v, ffn_gate/up/down 등

# GGUF 파일의 텐서 목록 확인
$ python3 -c "
from gguf import GGUFReader
reader = GGUFReader('llama-3.2-3b-q4km.gguf')
for tensor in reader.tensors:
    dims = ' × '.join(str(d) for d in tensor.shape)
    print(f'{tensor.name:40s} [{dims}] {tensor.tensor_type.name}')
"

# 출력 예시 (Llama 3.2 3B)
token_embd.weight                        [128256 × 3072] Q4_K
blk.0.attn_norm.weight                   [3072] F32
blk.0.attn_q.weight                      [3072 × 3072] Q4_K
blk.0.attn_k.weight                      [3072 × 1024] Q4_K
blk.0.attn_v.weight                      [3072 × 1024] Q6_K
blk.0.attn_output.weight                 [3072 × 3072] Q4_K
blk.0.ffn_norm.weight                    [3072] F32
blk.0.ffn_gate.weight                    [3072 × 8192] Q4_K
blk.0.ffn_up.weight                      [3072 × 8192] Q4_K
blk.0.ffn_down.weight                    [8192 × 3072] Q6_K
... (blk.1 ~ blk.27 동일 패턴 반복)
output_norm.weight                       [3072] F32
output.weight                            [128256 × 3072] Q6_K
📌 K-quant의 차등 양자화

위 출력에서 attn_v.weightffn_down.weightQ6_K(6비트)로, 나머지는 Q4_K(4비트)로 양자화된 것을 볼 수 있습니다. 이것이 K-quant의 핵심 — 모델 품질에 민감한 텐서는 높은 정밀도를, 덜 민감한 텐서는 낮은 정밀도를 적용하여 전체 품질을 유지하면서 크기를 줄입니다. _norm.weight는 항상 F32로 유지되는데, 정규화 파라미터는 극히 작은 크기이면서 품질에 큰 영향을 주기 때문입니다.

HuggingFace에서 GGUF 모델 찾기

HuggingFace Hub에서 GGUF 모델을 효율적으로 찾고 올바른 양자화 버전을 선택하는 방법입니다.

# HuggingFace Hub에서 GGUF 모델 검색
# https://huggingface.co/models?library=gguf

# 주요 GGUF 양자화 제공자
# ① bartowski — 가장 활발한 GGUF 변환자, imatrix 적용
# ② unsloth  — Llama/Mistral 계열 최적화 변환
# ③ mmnga    — 일본어/다국어 모델 GGUF 변환

# huggingface-cli로 직접 다운로드
pip install huggingface-hub
huggingface-cli download \
  bartowski/Llama-3.2-3B-Instruct-GGUF \
  --include "*Q4_K_M.gguf" \
  --local-dir ./models

# 특정 양자화만 골라서 다운로드 (와일드카드)
huggingface-cli download \
  bartowski/Qwen2.5-7B-Instruct-GGUF \
  --include "*Q5_K_M.gguf" \
  --local-dir ./models

# Ollama에서 직접 Hugging Face GGUF 사용 (v0.4+)
ollama run hf.co/bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M
💡 GGUF 모델 선택 체크리스트
  • 모델 이름에 "-GGUF"가 붙은 리포지토리를 찾으세요 (예: Llama-3.2-3B-Instruct-GGUF)
  • imatrix 적용 여부 확인 — README에 "importance matrix" 언급이 있으면 더 높은 품질
  • 양자화 선택 기준: VRAM/RAM 여유에 맞는 파일 크기 확인 후, Q4_K_M부터 시작
  • 파일명 규칙: 모델명-Q{비트}_{방식}_{크기}.gguf (예: model-Q4_K_M.gguf)
  • 최신 변환자 선호: bartowski, unsloth 등 활발히 활동하는 변환자의 모델이 최신 llama.cpp와 호환될 가능성이 높음

GGUF 생태계 도구 모음

도구 설명 주요 명령/용도
llama-quantize F16/F32 GGUF를 양자화 llama-quantize model-f16.gguf model-q4km.gguf Q4_K_M
llama-imatrix 중요도 행렬(imatrix) 생성 llama-imatrix -m model.gguf -f calib.txt -o imatrix.dat
llama-gguf-split GGUF 파일 분할/병합 llama-gguf-split --split-max-size 8G model.gguf out
convert_hf_to_gguf.py HuggingFace → GGUF 변환 python convert_hf_to_gguf.py /path/to/model --outtype f16
gguf-py (Python) GGUF 파일 읽기/쓰기 라이브러리 pip install ggufGGUFReader, GGUFWriter
llama-cli GGUF 모델 CLI 추론 llama-cli -m model.gguf -p "Hello" -ngl 99
llama-server GGUF 모델 HTTP 서버 (OpenAI 호환) llama-server -m model.gguf --port 8080 -ngl 99
llama-perplexity 모델 품질 벤치마크 (PPL 측정) llama-perplexity -m model.gguf -f wikitext-2-raw/wiki.test.raw
GGUF 생태계 전체 워크플로 소스 모델 HuggingFace SafeTensors PyTorch (.pt) GGML (레거시) 직접 학습/파인튜닝 변환 도구 convert_hf_to_gguf llama-quantize llama-imatrix llama-gguf-split .gguf 단일 파일 포맷 가중치 + 메타데이터 + 토크나이저 gguf-py로 읽기/쓰기 Ollama ollama run / serve LM Studio GUI 기반 로컬 추론 llama.cpp (CLI/Server) llama-cli / llama-server GPT4All KoboldCpp 외부 앱 통합 (OpenAI 호환 API 경유) Continue.dev Aider Open WebUI LangChain 커스텀 앱 REST API (http://localhost:11434) → /api/generate, /api/chat, /v1/chat/completions GGUF 모델 하나로 CLI, GUI, API, 외부 앱까지 — 완전한 로컬 AI 스택 구축

GGUF 생태계: 소스 모델 → 변환 → .gguf → 다양한 런타임 → 외부 앱 통합

GGUF 자주 묻는 질문 (FAQ)

질문 답변
GGUF와 GGML의 차이는? GGML은 가중치만 저장하는 구 포맷. GGUF는 토크나이저, 메타데이터까지 단일 파일에 포함하는 후속 포맷. 2023년 8월 이후 GGML은 폐기되었으며 모든 도구가 GGUF로 전환
Q4_K_M과 Q4_0의 차이는? Q4_0은 모든 레이어를 동일하게 4비트로 양자화. Q4_K_M은 중요한 레이어(attention value, ffn_down 등)를 6비트로 유지하여 같은 비트에서 더 높은 품질 제공. 파일 크기는 Q4_K_M이 약 8% 큼
양자화하면 모델이 "멍청해"지나? Q4_K_M 기준으로 Perplexity 증가는 약 1~2%에 불과. 대부분의 일상 작업(코드 생성, 대화, 요약)에서 체감 차이 거의 없음. 단, Q2_K 이하에서는 눈에 띄는 품질 저하 발생
GPU가 없어도 되나? 가능. GGUF의 핵심 장점이 CPU 추론 최적화. 양자화된 4비트 모델은 CPU에서도 충분히 사용 가능. 단, GPU를 사용하면 10~20배 빠름
GGUF를 직접 파인튜닝할 수 있나? 불가. GGUF는 추론 전용 포맷. 파인튜닝은 SafeTensors/PyTorch 형태로 수행 후 GGUF로 변환해야 함. LoRA 어댑터는 별도 적용 가능
최대 지원 모델 크기는? 이론적 제한 없음 (64비트 오프셋). 실무적으로 405B (Llama 3.1 405B) 모델까지 GGUF로 변환·실행 사례 있음. 파일 분할(Split)로 대용량 처리
SafeTensors와 GGUF 중 뭘 받아야? 로컬에서 Ollama/LM Studio로 추론하려면 GGUF. HuggingFace Transformers로 학습/파인튜닝하려면 SafeTensors. 둘 다 필요하면 SafeTensors 받아서 GGUF로 변환
imatrix(i-quant) 꼭 필요한가? Q4_K_M 이상에서는 거의 차이 없음. IQ3_XXS, IQ2_XXS 등 극압축 양자화에서만 의미 있는 품질 차이 발생. 캘리브레이션 데이터셋이 필요하여 추가 작업 소요

실무 팁

  • GGUF 모델은 Q4_K_M 양자화가 대부분의 용도에서 최적의 품질/크기 균형을 제공합니다.
  • GPU VRAM이 부족하면 -ngl 옵션으로 일부 레이어만 GPU에 올리세요.
  • HuggingFace에서 GGUF 모델을 받을 때는 bartowski, unsloth 등 활발한 변환자의 모델을 선택하세요.