GGUF Quantization Explained: Choosing the Right Format for Local AI
TL;DR
# Check quantization of an Ollama model
ollama show llama3.2:3b --modelfile | grep -i quant
# Inspect a GGUF file directly
python3 -c "from gguf import GGUFReader; r = GGUFReader('model.gguf'); print([kv for kv in r.fields])"
# Or use llama.cpp's built-in info
./llama-quantize --help
# Convert and quantize with llama.cpp
./llama-quantize input.gguf output-Q4_K_M.gguf Q4_K_M
GGUF is the standard file format for running quantized LLMs locally. Quantization reduces model size and VRAM usage by representing weights with fewer bits. The tradeoff is a small reduction in output quality. Choosing the right quantization level depends on your available VRAM, the model size, and your quality requirements.
What Is GGUF
GGUF (GPT-Generated Unified Format) is a binary file format for storing quantized large language models. It was introduced by the llama.cpp project in August 2023 as a successor to the GGML format. GGUF addresses several limitations of GGML:
- Self-contained metadata: Model architecture, tokenizer, and parameters are embedded in the file header. No separate config files needed.
- Extensibility: New metadata fields can be added without breaking backward compatibility.
- Alignment: Data is properly aligned in memory for efficient loading.
- Single-file distribution: One
.gguffile contains everything needed to run inference.
Every model you pull through Ollama is stored internally as GGUF. When you download a model from Hugging Face for use with llama.cpp, you typically download a .gguf file.
GGUF vs GGML
| Feature | GGML (legacy) | GGUF (current) |
|---|---|---|
| Metadata | External files required | Embedded in file |
| Tokenizer | Separate file | Embedded |
| Backward compatibility | Breaking changes common | Versioned, stable |
| Adoption | Deprecated | Standard for llama.cpp, Ollama |
| Memory mapping | Basic | Optimized alignment |
If you encounter .ggml files, they are from older conversions and should be reconverted to GGUF. Most tools no longer support GGML directly.
How Quantization Works
A full-precision (FP32) language model stores each weight as a 32-bit floating-point number. A 7-billion-parameter model at FP32 requires:
7B x 4 bytes = 28 GB
That does not fit in most consumer GPUs. Quantization reduces the bit width of each weight:
- FP16 / BF16: 16 bits per weight. Half the size, negligible quality loss.
- Q8_0: 8 bits per weight. Minor quality loss, significant size reduction.
- Q6_K: 6 bits. Good quality, roughly 44% of FP16 size.
- Q5_K_M: 5 bits. Sweet spot for many use cases.
- Q4_K_M: 4 bits. Most popular for consumer hardware. Noticeable but acceptable quality loss.
- Q4_0: 4 bits, simpler algorithm. Slightly worse than Q4_K_M.
- Q3_K_M: 3 bits. Significant quality loss. Use only when VRAM is extremely limited.
- Q2_K: 2 bits. Severe quality degradation. Not recommended for production use.
The “K” variants (Q4_K_M, Q5_K_S, etc.) use k-quant methods that apply different quantization levels to different layers based on their sensitivity. Attention layers and output layers are quantized less aggressively than feed-forward layers, preserving quality where it matters most.
K-Quant Suffixes
- _S (small): More aggressive quantization. Smaller file, lower quality.
- _M (medium): Balanced. The default recommendation for most users.
- _L (large): Less aggressive. Larger file, better quality.
Quantization Comparison Table (7B Model)
| Quant Type | Bits/Weight | File Size | VRAM (7B) | Quality Retention | Speed vs FP16 |
|---|---|---|---|---|---|
| F16 | 16 | 14.0 GB | ~15 GB | 100% (baseline) | 1.0x |
| Q8_0 | 8 | 7.7 GB | ~9 GB | ~99.5% | 1.2x faster |
| Q6_K | 6 | 5.9 GB | ~7.5 GB | ~99% | 1.3x faster |
| Q5_K_M | 5 | 5.1 GB | ~6.5 GB | ~98% | 1.4x faster |
| Q5_K_S | 5 | 4.8 GB | ~6.2 GB | ~97% | 1.4x faster |
| Q4_K_M | 4 | 4.4 GB | ~5.8 GB | ~96% | 1.5x faster |
| Q4_K_S | 4 | 4.1 GB | ~5.5 GB | ~94% | 1.5x faster |
| Q4_0 | 4 | 3.8 GB | ~5.2 GB | ~93% | 1.6x faster |
| Q3_K_M | 3 | 3.3 GB | ~4.8 GB | ~88% | 1.6x faster |
| Q2_K | 2 | 2.7 GB | ~4.2 GB | ~75% | 1.7x faster |
VRAM figures include approximately 1-1.5 GB overhead for KV cache at 2048 context length. Larger context windows increase VRAM usage significantly.
Quality retention percentages are approximate, based on perplexity benchmarks (lower perplexity = better). Actual perceived quality depends on the task. Coding and math tasks degrade faster than conversational tasks at lower quantization levels.
Choosing the Right Quantization
Decision Framework
Start with Q4_K_M. It is the most widely tested quantization level and offers the best balance of size, speed, and quality for consumer hardware. Move up or down from there based on your situation.
Use Q5_K_M or Q6_K when:
- You have VRAM headroom (12+ GB GPU for a 7B model)
- The task requires precision (coding, math, structured output)
- Quality matters more than speed
- You are running the model as a primary assistant
Use Q4_K_M when:
- Running on 8 GB VRAM (7B models)
- Running on 24 GB VRAM (70B models with Q4_K_M)
- General-purpose chat, summarization, creative writing
Use Q8_0 when:
- You have substantial VRAM (24+ GB for 7B, 80+ GB for 70B)
- Maximum quality is required
- You are benchmarking or evaluating model capabilities
Use Q3_K_M or lower when:
- Fitting a larger model matters more than quality (e.g., 13B at Q3 vs 7B at Q5)
- VRAM is extremely constrained (6 GB GPU)
- The task is simple (classification, yes/no answers, keyword extraction)
Model Size vs Quantization
A common question: is it better to run a larger model at lower quantization or a smaller model at higher quantization?
General rule: a larger model at Q4_K_M usually outperforms a smaller model at Q8_0, assuming both fit in VRAM. A 13B model at Q4_K_M typically produces better results than a 7B at Q8_0. The additional parameters provide more capacity for knowledge and reasoning than the extra precision per weight.
The exception is highly precise tasks (math, code with exact syntax requirements) where quantization noise in larger models can cause more errors than a smaller but more precisely quantized model.
Checking Quantization in Ollama
When you pull a model from the Ollama library, the default tag usually provides a Q4_K_M quantization. To verify:
# Show model details
ollama show llama3.2:3b
Look for the quantization_version and architecture details. For more specifics:
# Show the full modelfile which includes the FROM layer digest
ollama show llama3.2:3b --modelfile
To check what quantization variants are available for a model, check the model page on ollama.com or use:
# List available tags (requires web access)
curl -s https://ollama.com/api/tags/llama3.2 | jq '.tags[].name'
Some models include the quantization in the tag name:
ollama pull llama3.1:8b-instruct-q5_K_M
ollama pull llama3.1:8b-instruct-q8_0
Inspecting GGUF Files Directly
If you have a standalone GGUF file (downloaded from Hugging Face or converted yourself), you can inspect it with the gguf Python package:
pip install gguf
python3 << 'EOF'
from gguf import GGUFReader
reader = GGUFReader("model.Q4_K_M.gguf")
for key in reader.fields:
field = reader.fields[key]
if key in ["general.name", "general.architecture", "general.quantization_version",
"general.file_type", "llama.context_length", "llama.embedding_length"]:
print(f"{key}: {field.parts[-1][0] if field.parts else 'N/A'}")
EOF
Or use llama.cpp’s built-in inspection:
./llama-cli --model model.Q4_K_M.gguf --verbose-prompt -n 1 2>&1 | head -30
This prints model metadata including architecture, context length, and quantization details.
Converting Models to GGUF
To convert a Hugging Face model (safetensors/PyTorch) to GGUF, use the conversion script from llama.cpp:
Prerequisites
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
pip install -r requirements/requirements-convert_hf_to_gguf.txt
Step 1: Convert to FP16 GGUF
python3 convert_hf_to_gguf.py /path/to/huggingface-model/ \
--outfile model-f16.gguf \
--outtype f16
Step 2: Quantize
# Build llama.cpp first
cmake -B build && cmake --build build --config Release -j$(nproc)
# Quantize to Q4_K_M
./build/bin/llama-quantize model-f16.gguf model-Q4_K_M.gguf Q4_K_M
# Quantize to Q5_K_M
./build/bin/llama-quantize model-f16.gguf model-Q5_K_M.gguf Q5_K_M
Step 3: Test
./build/bin/llama-cli -m model-Q4_K_M.gguf -p "Hello, how are you?" -n 100
Step 4: Import into Ollama
Create a Modelfile:
FROM ./model-Q4_K_M.gguf
Then:
ollama create my-model -f Modelfile
ollama run my-model
Quantization and CPU Offloading
When a model does not fully fit in GPU VRAM, Ollama and llama.cpp automatically offload some layers to CPU RAM. Understanding quantization helps optimize this split:
# In llama.cpp, specify GPU layers
./llama-cli -m model.gguf -ngl 20 # 20 layers on GPU, rest on CPU
# In Ollama, GPU offloading is automatic
# Check allocation with:
ollama ps
The PROCESSOR column in ollama ps shows the GPU/CPU split (e.g., “80% GPU / 20% CPU”). Lower quantization means more layers fit on the GPU, reducing the CPU-offloaded portion and improving speed.
Caution: CPU-offloaded layers are significantly slower than GPU layers. A model that is 50% offloaded to CPU will run roughly 3-5x slower than a fully GPU-resident model. It is often better to use a smaller model that fits entirely in VRAM than a larger model that requires heavy CPU offloading.
Perplexity Testing
To measure the actual quality impact of quantization on your specific use case, run a perplexity test with llama.cpp:
./build/bin/llama-perplexity -m model-Q4_K_M.gguf \
-f /path/to/test-text.txt \
--chunks 100
Compare the perplexity score across quantization levels. A difference of less than 0.5 in perplexity is generally imperceptible in real-world use.
Summary
For most self-hosted AI setups on consumer hardware:
- Default choice: Q4_K_M. Works well on 8 GB GPUs for 7B models, 24 GB GPUs for 70B models.
- Quality upgrade: Q5_K_M if you have the VRAM. Measurably better on coding and reasoning tasks.
- Maximum quality: Q8_0 or Q6_K when VRAM is not a constraint.
- Tight VRAM: Q3_K_M as a last resort, but prefer a smaller model at Q4_K_M instead.
- Always prefer _K_M variants over plain Q4_0/Q5_0. The k-quant methods are strictly better.
