Ollama: Model Quantization and Optimization

Quantization is model dieting — sacrifice a little precision, save half the space, with almost no quality loss.

💡 Tip: Quantization level selection guide — Q4_K_M offers the best value (70% size reduction, < 5% quality loss), suitable for mainstream 8GB VRAM scenarios; Q8_0 is nearly lossless (99%+ quality retention), suitable for VRAM-rich (12GB+) scenarios that are precision-sensitive (code generation, mathematical reasoning).

📋 Prerequisites: You should first master the following

1. What You Will Learn


2. A Real Story from a SaaS Entrepreneur

ℹ️ Info: Ollama defaults to Q4_K_M quantization — this is the "best value" choice, not the "best quality" choice. If you have ample VRAM (16GB+), you can try Q8_0 for nearly lossless quality; if VRAM is extremely limited (4GB), Q3_K_M is a better lower bound than Q2_K.

(1) The Pain Point: 8GB VRAM Cannot Run an 8B Model

Alice's server has only 8GB VRAM, and the 8B FP16 model requires 16GB — it won't run. But after Q4_K_M quantization, it only needs 5GB, which is plenty. The question is: how much quality does quantization sacrifice?

(2) The Solution: Q4_K_M Offers the Best Value

Testing revealed that Q4_K_M has less than 3% quality loss in customer service scenarios, while reducing size by 70%:

BASH
# Compare model sizes
ollama show llama3.1:8b        # Q4_K_M: ~5GB
ollama show llama3.1:8b-q8_0   # Q8_0:   ~8GB

3. Quantization Principles in Detail

⚠️ Note: Quantization inevitably sacrifices precision — Q2_K quantization has the smallest size but noticeable quality loss (retains 80-85%), especially affecting precision tasks like code generation and mathematical reasoning. Only recommended when VRAM is extremely limited (under 4GB); otherwise, Q4_K_M is preferred.

⚠️ Warning: Q2_K quantization has the smallest size (8B model only ~3GB), but noticeable quality loss, especially for precision tasks like code generation and mathematical reasoning. Only recommended when VRAM is extremely limited (under 4GB); otherwise, Q4_K_M is preferred.

(1) From FP16 to Q2_K: Decreasing Precision

100%
flowchart LR
    A[FP16<br/>16-bit<br/>16 GB] --> B[Q8_0<br/>8-bit<br/>8 GB]
    B --> C[Q5_K_M<br/>5-bit<br/>5.7 GB]
    C --> D[Q4_K_M<br/>4-bit<br/>5 GB]
    D --> E[Q3_K_M<br/>3-bit<br/>3.8 GB]
    E --> F[Q2_K<br/>2-bit<br/>3 GB]

(2) Quantization Level Comparison

Quantization Level Bit Width Compression Ratio 8B Model Size Quality Retention Suitable VRAM
FP16 16-bit 1x ~16 GB 100% 24 GB+
Q8_0 8-bit 2x ~8 GB 99%+ 12 GB+
Q5_K_M 5-bit 3.2x ~5.7 GB 98% 8 GB+
Q4_K_M 4-bit 3.5x ~5 GB 95-97% 8 GB
Q3_K_M 3-bit 4.5x ~3.8 GB 90-93% 4 GB+
Q2_K 2-bit 6x ~3 GB 80-85% 4 GB

(3) K-quant Naming Convention

Suffix Meaning Description
_K K-quant Mixed-precision quantization, critical layers at higher precision
_S Small Smallest size, lowest quality
_M Medium Balanced size and quality (recommended)
_L Large Higher quality, larger size
💡 Tip: Choosing the _M suffix offers the best value — Q4_K_M is 3% higher quality than Q4_K_S, with only 5% larger size.

▶ Example 1: Ollama Default Quantization Selection

BASH
# Default pull uses optimal quantization (usually Q4_K_M)
ollama pull llama3.1:8b

# Show quantization details
ollama show llama3.1:8b
# Look for: quantization: Q4_K_M

# Compare sizes across quantizations
ollama list | grep llama
# llama3.1:8b          4.9 GB   (Q4_K_M)

Output:

TEXT
NAME                    ID              SIZE    
llama3.2:latest        a80...          2.0 GB  
mistral:latest         61...           4.1 GB

4. Ollama Built-in Quantization

(1) Specifying Quantization Level on Pull

Method Command Description
Auto-select ollama pull model_name Ollama chooses optimal quantization
Specify tag ollama pull model_name:q4_K_M Specify quantization level

(2) Available Quantization Tags

Tag Quantization Use Case
q4_K_M 4-bit mixed precision General recommendation
q5_K_M 5-bit mixed precision Higher quality
q8_0 8-bit uniform Nearly lossless
f16 16-bit original Full precision

▶ Example 2: Pulling Different Quantization Variants

BASH
# Pull specific quantization
ollama pull llama3.1:8b-q4_K_M   # 4-bit, ~5GB
ollama pull llama3.1:8b-q5_K_M   # 5-bit, ~5.7GB
ollama pull llama3.1:8b-q8_0     # 8-bit, ~8GB

# Not all models have all variants
# Check available tags on ollama.com/library/model-name

Output:

TEXT
NAME                    ID              SIZE    
llama3.2:latest        a80...          2.0 GB  
mistral:latest         61...           4.1 GB

5. Importing Custom Quantization from GGUF Files

(1) GGUF File Sources

Source URL Description
HuggingFace huggingface.co Search for .gguf
TheBloke huggingface.co/TheBloke GGUF quantization collection
Self-quantize llama.cpp convert Use convert.py

(2) Import Steps

100%
flowchart LR
    A[Download GGUF] --> B[Create Modelfile<br/>FROM ./model.gguf]
    B --> C[ollama create]
    C --> D[ollama run]

▶ Example 3: Import from HuggingFace GGUF

BASH
# Step 1: Download GGUF file from HuggingFace
wget "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF/resolve/main/mistral-7b-instruct-v0.2.Q4_K_M.gguf"

# Step 2: Create Modelfile
cat > Modelfile <<EOF
FROM ./mistral-7b-instruct-v0.2.Q4_K_M.gguf
SYSTEM You are a helpful AI assistant.
PARAMETER temperature 0.7
PARAMETER num_ctx 4096
TEMPLATE """[INST] {{ if .System }}{{ .System }}{{ end }}
{{ .Prompt }} [/INST]
"""
EOF

# Step 3: Create model in Ollama
ollama create my-mistral -f Modelfile

# Step 4: Run
ollama run my-mistral "Explain quantum computing in simple terms"

Output:

TEXT
I'm a helpful AI assistant running locally on your machine...

6. Quantization Quality Evaluation

(1) Evaluation Method Comparison

Method Description Use Case
Subjective comparison Compare different quantization outputs for the same question Quick screening
Benchmark Standard NLP benchmarks (MMLU/HellaSwag) Quantization-level evaluation
Business evaluation Task-specific accuracy testing Final decision

(2) VRAM Decision Tree

100%
flowchart TD
    A[Available VRAM?] --> B{4 GB or less?}
    B -->|Yes| C[3B model Q4_K_M<br/>or 8B Q2_K]
    B -->|No| D{8 GB?}
    D -->|Yes| E[8B Q4_K_M ⭐ Recommended]
    D -->|No| F{12-16 GB?}
    F -->|Yes| G[8B Q8_0 or 13B Q4_K_M]
    F -->|No| H{24 GB?}
    H -->|Yes| I[70B Q2_K or 8B FP16]
    H -->|No| J{48+ GB multi-GPU?}
    J -->|Yes| K[70B Q4_K_M ⭐ Best quality]

▶ Example 4: Quantization Quality Comparison Script

PYTHON
import ollama
import time
from statistics import mean

def compare_quantizations(model_base: str, quantizations: list[str],
                          test_prompt: str, runs: int = 3):
    """Compare output quality and speed across quantizations."""
    results = {}
    for quant in quantizations:
        model_name = f"{model_base}:{quant}" if ":" not in model_base else model_base
        try:
            # Warm up
            ollama.chat(model=model_name,
                        messages=[{"role": "user", "content": "warm up"}],
                        stream=False)

            speeds = []
            responses = []
            for _ in range(runs):
                start = time.time()
                resp = ollama.chat(
                    model=model_name,
                    messages=[{"role": "user", "content": test_prompt}],
                    stream=False
                )
                elapsed = time.time() - start
                speeds.append(len(resp["message"]["content"]) / elapsed)
                responses.append(resp["message"]["content"])

            results[quant] = {
                "avg_speed": round(mean(speeds), 1),
                "sample_response": responses[0][:200]
            }
        except Exception as e:
            results[quant] = {"error": str(e)}

    return results

# Compare (if you have multiple quantizations pulled)
# results = compare_quantizations(
#     "llama3.1", ["q4_K_M", "q8_0"],
#     "Explain machine learning in 3 sentences"
# )
# for quant, data in results.items():
#     print(f"\n{quant}:")
#     for k, v in data.items():
#         print(f"  {k}: {v}")

Output:

TEXT
# Function defined successfully

▶ Example 5: Scenario-Based Quantization Recommendation

PYTHON
def recommend_quantization(vram_gb: float, use_case: str) -> dict:
    """Recommend optimal quantization based on VRAM and use case."""
    recommendations = {
        "chat": {
            "precision_priority": ("Q8_0", "Best quality, needs more VRAM"),
            "balanced": ("Q4_K_M", "Best quality/size ratio"),
            "size_priority": ("Q3_K_M", "Smallest usable quantization")
        },
        "code": {
            "precision_priority": ("Q8_0", "Code needs high precision"),
            "balanced": ("Q5_K_M", "Good precision for code tasks"),
            "size_priority": ("Q4_K_M", "Minimal quality loss for code")
        },
        "classification": {
            "precision_priority": ("Q5_K_M", "Overkill for classification"),
            "balanced": ("Q4_K_M", "More than enough"),
            "size_priority": ("Q2_K", "Classification is robust to quantization")
        }
    }

    # Determine priority based on VRAM
    if vram_gb >= 12:
        priority = "precision_priority"
    elif vram_gb >= 8:
        priority = "balanced"
    else:
        priority = "size_priority"

    quant, reason = recommendations.get(use_case, recommendations["chat"])[priority]

    # Model size recommendation
    if vram_gb >= 40:
        model_size = "70B"
    elif vram_gb >= 8:
        model_size = "8B"
    else:
        model_size = "3B"

    return {
        "vram_gb": vram_gb,
        "use_case": use_case,
        "priority": priority,
        "quantization": quant,
        "model_size": model_size,
        "reason": reason
    }

# Example usage
for vram in [4, 8, 24]:
    rec = recommend_quantization(vram, "chat")
    print(f"VRAM {vram}GB: {rec['model_size']} {rec['quantization']} ({rec['reason']})")

Output:

TEXT
# Function defined successfully

7. Comprehensive Example: Quantization Evaluation and Deployment Decision

PYTHON
# ============================================
# Comprehensive: Quantization decision engine
# Evaluates quality, speed, and VRAM tradeoffs
# ============================================

import ollama
import time
import json
from pathlib import Path

class QuantizationAdvisor:
    def __init__(self, vram_gb: float, use_case: str = "chat"):
        self.vram_gb = vram_gb
        self.use_case = use_case
        self.results = {}

    def estimate_model_fit(self, params_b: float, quant: str) -> dict:
        """Estimate if a model+quantization fits in available VRAM."""
        quant_bytes = {
            "FP16": 2.0, "Q8_0": 1.0, "Q5_K_M": 0.625,
            "Q4_K_M": 0.5, "Q3_K_M": 0.375, "Q2_K": 0.25
        }
        bytes_per_param = quant_bytes.get(quant, 0.5)
        vram_needed = params_b * bytes_per_param * 1.2  # 20% overhead
        fits = vram_needed <= self.vram_gb
        return {
            "params": f"{params_b}B",
            "quantization": quant,
            "vram_needed_gb": round(vram_needed, 1),
            "vram_available_gb": self.vram_gb,
            "fits": fits,
            "headroom_gb": round(self.vram_gb - vram_needed, 1)
        }

    def generate_recommendations(self) -> list[dict]:
        """Generate all viable model+quantization combinations."""
        models = [
            (3.2, "llama3.2"), (8.0, "llama3.1:8b"), (70.0, "llama3.1:70b")
        ]
        quants = ["Q4_K_M", "Q5_K_M", "Q8_0"]

        viable = []
        for params, name in models:
            for quant in quants:
                fit = self.estimate_model_fit(params, quant)
                if fit["fits"]:
                    viable.append({
                        "model": name,
                        **fit
                    })

        # Sort by params descending (prefer larger model)
        viable.sort(key=lambda x: x["params"], reverse=True)
        return viable

    def best_recommendation(self) -> dict:
        """Return the single best recommendation."""
        viable = self.generate_recommendations()
        if not viable:
            return {"error": "No model fits in available VRAM. Use CPU mode."}

        # Prefer largest model, then highest quantization
        best = viable[0]
        return {
            "recommended_model": best["model"],
            "recommended_quantization": best["quantization"],
            "vram_used": f"{best['vram_needed_gb']}GB",
            "headroom": f"{best['headroom_gb']}GB",
            "reason": f"Largest model that fits {self.vram_gb}GB VRAM with Q4_K_M+"
        }

# Usage
if __name__ == "__main__":
    advisor = QuantizationAdvisor(vram_gb=8, use_case="chat")
    print("=== Quantization Recommendations (8GB VRAM) ===")
    for rec in advisor.generate_recommendations():
        print(f"  {rec['model']} {rec['quantization']}: "
              f"{rec['vram_needed_gb']}GB (headroom: {rec['headroom_gb']}GB)")

    print(f"\nBest: {advisor.best_recommendation()}")

❓ FAQ

Q Should I choose Q4_K_M or Q4_K_S?
A Prefer Q4_K_M. _M is Medium precision, 3-5% higher quality than _S (Small), with only 5% larger size. _M is widely recognized as the best value.
Q What if the quantized model becomes "dumber"?
A Upgrade to Q5_K_M or Q8_0. If VRAM is insufficient, a larger-parameter low-quantization model (70B Q2_K) may outperform a smaller high-quantization model (8B Q8_0).
Q Can Ollama automatically quantize?
A Models pulled by Ollama are already pre-quantized versions (usually Q4_K_M). You cannot specify a custom quantization level at pull time — you must import from a GGUF file.
Q How do I quantize a GGUF file myself?
A Use llama.cpp's convert and quantize tools. First convert the model to GGUF F16, then use quantize to specify the level. Suitable for advanced users; beginners should download pre-quantized versions.
Q Does quantization level affect inference speed?
A Lower quantization (Q2_K) means faster inference (less data transfer). But Q4_K_M and Q8_0 speed differences on GPU are typically < 10%. On CPU, Q4_K_M is noticeably faster.
Q Do embedding models need quantization?
A No. Embedding models are already small (nomic-embed-text is only 274MB), and quantization benefits are negligible. Keep the default.

📖 Summary


📝 Exercises

  1. Basic (⭐): Pull two quantization variants of the same model (Q4_K_M and Q8_0), use ollama list to compare file sizes, and compare output quality with the same question.
  2. Intermediate (⭐⭐): Download a GGUF file from HuggingFace, import it into Ollama with a Modelfile, and test that inference works correctly.
  3. Advanced (⭐⭐⭐): Write a quantization evaluation script that tests quality scores across different quantization levels in a customer service scenario (5 standard questions), and outputs a quantization recommendation table.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏