Ollama: Quantização e Otimização de Modelos

Quantização é a dieta do modelo — sacrifique um pouco de precisão, economize metade do espaço, com quase nenhuma perda de qualidade.

💡 Dica: Guia de seleção de nível de Quantização — Q4_K_M oferece o melhor custo-benefício (70% de redução de tamanho, < 5% de perda de qualidade), adequado para cenários mainstream de 8GB VRAM; Q8_0 é quase sem perdas (99%+ de retenção de qualidade), adequado para cenários com VRAM abundante (12GB+) que são sensíveis à precisão (geração de código, raciocínio matemático).

📋 Pré-requisitos: Você deve dominar o seguinte primeiro

1. O Que Você Vai Aprender


2. Uma História Real de Uma Empreendedora SaaS

ℹ️ Info: O Ollama padrão usa Quantização Q4_K_M — esta é a escolha de "melhor custo-benefício," não a escolha de "melhor qualidade." Se você tem VRAM abundante (16GB+), pode tentar Q8_0 para qualidade quase sem perdas; se VRAM é extremamente limitada (4GB), Q3_K_M é um limite inferior melhor que Q2_K.

(1) O Problema: 8GB VRAM Não Consegue Rodar um Modelo 8B

O servidor da Alice tem apenas 8GB VRAM, e o modelo 8B FP16 requer 16GB — não roda. Mas após Quantização Q4_K_M, precisa apenas de 5GB, o que é suficiente. A questão é: quanto qualidade a Quantização sacrifica?

(2) A Solução: Q4_K_M Oferece o Melhor Custo-Benefício

Testes revelaram que Q4_K_M tem menos de 3% de perda de qualidade em cenários de atendimento ao cliente, enquanto reduz o tamanho em 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. Princípios de Quantização em Detalhe

⚠️ Nota: Quantização inevitavelmente sacrifica precisão — Quantização Q2_K tem o menor tamanho mas perda de qualidade notável (retém 80-85%), afetando especialmente tarefas de precisão como geração de código e raciocínio matemático. Apenas recomendado quando VRAM é extremamente limitada (menos de 4GB); caso contrário, Q4_K_M é preferido.

⚠️ Aviso: Quantização Q2_K tem o menor tamanho (modelo 8B apenas ~3GB), mas perda de qualidade notável, especialmente para tarefas de precisão como geração de código e raciocínio matemático. Apenas recomendado quando VRAM é extremamente limitada (menos de 4GB); caso contrário, Q4_K_M é preferido.

(1) De FP16 a Q2_K: Precisão Decrescente

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) Comparação de Níveis de Quantização

Nível de Quantização Largura de Bits Taxa de Compressão Tamanho Modelo 8B Retenção de Qualidade VRAM Adequada
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) Convenção de Nomenclatura K-quant

Sufixo Significado Descrição
_K K-quant Quantização de precisão mista, camadas críticas em precisão mais alta
_S Small Menor tamanho, qualidade mais baixa
_M Medium Tamanho e qualidade equilibrados (recomendado)
_L Large Qualidade mais alta, tamanho maior
💡 Dica: Escolher o sufixo _M oferece o melhor custo-benefício — Q4_K_M é 3% mais qualitativo que Q4_K_S, com apenas 5% a mais de tamanho.

▶ Exemplo 1: Seleção de Quantização Padrão do Ollama

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)

Saída:

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

4. Quantização Embutida do Ollama

(1) Especificando Nível de Quantização no Pull

Método Comando Descrição
Auto-selecionar ollama pull model_name Ollama escolhe a Quantização ótima
Especificar tag ollama pull model_name:q4_K_M Especificar nível de Quantização

(2) Tags de Quantização Disponíveis

Tag Quantização Caso de Uso
q4_K_M Precisão mista 4-bit Recomendação geral
q5_K_M Precisão mista 5-bit Qualidade mais alta
q8_0 Uniforme 8-bit Quase sem perdas
f16 Original 16-bit Precisão total

▶ Exemplo 2: Baixando Variantes de Quantização Diferentes

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

Saída:

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

5. Importando Quantização Personalizada de Arquivos GGUF

(1) Fontes de Arquivos GGUF

Fonte URL Descrição
HuggingFace huggingface.co Pesquisar por .gguf
TheBloke huggingface.co/TheBloke Coleção de Quantização GGUF
Auto-quantizar llama.cpp convert Usar convert.py

(2) Passos de Importação

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

▶ Exemplo 3: Importar do GGUF do HuggingFace

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"

Saída:

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

6. Avaliação de Qualidade da Quantização

(1) Comparação de Métodos de Avaliação

Método Descrição Caso de Uso
Comparação subjetiva Comparar saídas de diferentes Quantizações para a mesma pergunta Triagem rápida
Benchmark Benchmarks NLP padrão (MMLU/HellaSwag) Avaliação por nível de Quantização
Avaliação de negócio Teste de precisão específico da tarefa Decisão final

(2) Árvore de Decisão VRAM

100%
flowchart TD
    A[VRAM Disponível?] --> B{4 GB ou menos?}
    B -->|Sim| C[Modelo 3B Q4_K_M<br/>ou 8B Q2_K]
    B -->|Não| D{8 GB?}
    D -->|Sim| E[8B Q4_K_M ⭐ Recomendado]
    D -->|Não| F{12-16 GB?}
    F -->|Sim| G[8B Q8_0 ou 13B Q4_K_M]
    F -->|Não| H{24 GB?}
    H -->|Sim| I[70B Q2_K ou 8B FP16]
    H -->|Não| J{48+ GB multi-GPU?}
    J -->|Sim| K[70B Q4_K_M ⭐ Melhor qualidade]

▶ Exemplo 4: Script de Comparação de Qualidade de Quantização

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}")

Saída:

TEXT
# Function defined successfully

▶ Exemplo 5: Recomendação de Quantização por Cenário

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']})")

Saída:

TEXT
# Function defined successfully

7. Exemplo Abrangente: Avaliação de Quantização e Decisão de Implantação

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()}")

❓ Perguntas Frequentes

P: Devo escolher Q4_K_M ou Q4_K_S? R: Prefira Q4_K_M. _M é precisão Medium, 3-5% mais qualitativo que _S (Small), com apenas 5% a mais de tamanho. _M é amplamente reconhecido como o melhor custo-benefício.

P: E se o modelo quantizado ficar "mais burro"? R: Atualize para Q5_K_M ou Q8_0. Se VRAM for insuficiente, um modelo de parâmetros maiores com Quantização baixa (70B Q2_K) pode superar um modelo menor com Quantização alta (8B Q8_0).

P: O Ollama pode quantizar automaticamente? R: Modelos baixados pelo Ollama já são versões pré-quantizadas (geralmente Q4_K_M). Você não pode especificar um nível de Quantização personalizado no pull — deve importar de um arquivo GGUF.

P: Como quantizar um arquivo GGUF eu mesmo? R: Use as ferramentas convert e quantize do llama.cpp. Primeiro converta o modelo para GGUF F16, depois use quantize para especificar o nível. Adequado para usuários avançados; iniciantes devem baixar versões pré-quantizadas.

P: O nível de Quantização afeta a velocidade de Inferência? R: Quantização mais baixa (Q2_K) significa Inferência mais rápida (menos transferência de dados). Mas diferenças de velocidade Q4_K_M e Q8_0 na GPU são tipicamente < 10%. Na CPU, Q4_K_M é visivelmente mais rápido.

P: Modelos de embedding precisam de Quantização? R: Não. Modelos de embedding já são pequenos (nomic-embed-text tem apenas 274MB), e os benefícios de Quantização são negligenciáveis. Mantenha o padrão.


📖 Resumo


📝 Exercícios

  1. Básico (⭐): Baixe duas variantes de Quantização do mesmo modelo (Q4_K_M e Q8_0), use ollama list para comparar tamanhos de arquivo, e compare a qualidade da saída com a mesma pergunta.
  2. Intermediário (⭐⭐): Baixe um arquivo GGUF do HuggingFace, importe-o no Ollama com um Modelfile, e teste que a Inferência funciona corretamente.
  3. Avançado (⭐⭐⭐): Escreva um script de avaliação de Quantização que teste pontuações de qualidade em diferentes níveis de Quantização em um cenário de atendimento ao cliente (5 perguntas padrão), e produza uma tabela de recomendação de Quantização.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%