Pular para conteúdo

Capítulo 2.2 — Quantização e compressão de modelos: de 4-bit ao deployment real

🎯 Objetivo

Cobrir quantização com nível suficiente para decidir entre laboratório/local e produção enterprise. O foco não é treinar quantização, mas entender o que muda em memória, throughput, qualidade, kernel e hardware quando um modelo deixa FP16 e cai para INT8/INT4.

🧠 Conceito principal

Quantização troca precisão numérica por redução de tamanho e custo de operação. Em LLMs, as três operações dominantes são matmul, attention e normalização. Quantizar reduz o tamanho dos pesos e, eventualmente, das ativações; o ganho real depende de o kernel suportar a operação no novo formato.

🧮 Formatos e onde aparecem

Formato Bits Uso típico Hardware necessário
FP32 32 Treino padrão, baselines, comparação CPU/GPU geral
TF32 19 (acumulação) Treino com Tensor Cores (NVIDIA Ampere+) A100, H100
FP16 16 Treino com mixed precision, inferência GPU V100+
BF16 16 Treino estável (range ~ FP32), inferência A100/H100, TPU
FP8 (E4M3/E5M2) 8 Inferência/treino moderno em GPUs novas H100/H200, MI300, Trainium
INT8 8 Inferência quantizada (W8A8 ou W8A16) GPU/CPU/edge amplos
INT4 / NF4 4 Inferência quantizada e QLoRA GPU recente, llama.cpp, MLC, GGUF
INT3 / INT2 3, 2 Pesquisa, formatos GGUF "agressivos" Variável; perda comum

🧠 Inferência vs fine-tuning quantizado

São dois problemas diferentes:

  • Quantização para inferência - reduzir custo/memória ao servir. Família GPTQ, AWQ, SmoothQuant, formatos GGUF/AWQ/EXL2, kernels do TensorRT-LLM, vLLM, llama.cpp.
  • Quantização durante fine-tuning - manter o modelo base em baixa precisão e treinar adapters (LoRA) em precisão maior. O exemplo canônico é QLoRA com NF4 + double quantization + paged optimizers.

A confusão entre os dois costuma aparecer em discussões "QLoRA é melhor que GPTQ?" - são técnicas para problemas diferentes (treino vs serving).

🧪 Métodos principais

Post-Training Quantization (PTQ)

  • GPTQ - quantização camada-a-camada usando aproximação de segunda ordem do erro de reconstrução; tipicamente INT4 ou INT3 só nos pesos. Bom equilíbrio qualidade/custo para serving. (Frantar et al., 2022).
  • AWQ (Activation-aware Weight Quantization) - preserva canais "salientes" (alta magnitude de ativação) e quantiza o resto com agressividade. Costuma manter melhor qualidade que round-to-nearest e é amigável a kernels otimizados. (Lin et al., 2023).
  • SmoothQuant - redistribui dificuldade de quantização entre pesos e ativações via reescala; permite W8A8.
  • GGUF (llama.cpp) - formato de arquivo + variantes de quantização (Q4_K_M, Q5_K_M, Q8_0, IQ-quants etc.) populares em execução local CPU/GPU mista. Bom para laboratório e dev local.

Quantization-Aware Training (QAT)

Treina (ou continua treinando) já considerando o ruído de quantização. Custo de engenharia maior, qualidade tipicamente melhor que PTQ em formatos agressivos.

bitsandbytes

Biblioteca Python amplamente usada para carregar modelos em 8-bit (LLM.int8) e 4-bit (NF4) com Hugging Face Transformers. Foco em pesquisa, prototipagem e fine-tuning. Não é o caminho típico para serving de baixa latência em produção em larga escala - para isso, prefira kernels do vLLM, TensorRT-LLM ou implementações nativas do framework de serving.

QLoRA

Combina (a) modelo base congelado em NF4 (4-bit "NormalFloat", distribuição informacionalmente otimizada para pesos próximos a normal); (b) double quantization dos próprios constantes de quantização; (c) paged optimizers para suportar picos de memória; (d) adapters LoRA em BF16. Resultado: fine-tunar modelos grandes em GPUs únicas com qualidade próxima a full FT em muitos cenários.

⚖️ Trade-offs

Eixo Realidade
VRAM Quase sempre cai com quantização. INT4 reduz pesos em ~4x vs FP16.
Throughput Nem sempre aumenta. Depende de existir kernel quantizado eficiente para o hardware. Em hardware moderno com FP16 já bem otimizado, INT4 sem kernel adequado pode ser mais lento.
Latência (TTFT) Pode melhorar pelo menor tráfego de pesos via memory bandwidth, principal gargalo do decode.
Qualidade Modelos grandes (>30B) toleram INT4 razoavelmente. Modelos pequenos (≤7B) sofrem mais, especialmente em raciocínio multi-step e tool calling.
Compatibilidade FP8/INT4 exigem hardware e kernels específicos. Mover entre stacks (Transformers, vLLM, TGI, TensorRT-LLM, llama.cpp) frequentemente quebra.
Determinismo Quantização aumenta variação numérica; reproducibilidade fica mais frágil.
Tool calling / structured output Modelos quantizados agressivamente podem degradar mais em seguir schemas e em raciocínio passo-a-passo do que em respostas livres.

🏗️ Como isso aparece em produção

  • Laboratório / dev local - INT4 via GGUF + llama.cpp ou via bitsandbytes resolve, com modelos rodando em laptops. Aceita perda; objetivo é experimentação.
  • Self-hosting enterprise - geralmente FP16/BF16 ou FP8 em GPUs recentes; AWQ/GPTQ INT4 quando o ganho de densidade compensa a perda mensurável. Sempre com eval set comparativo entre versões.
  • API providers - abstrai o leitor. Cliente vê apenas modelo + preço; quantização é responsabilidade do provedor.
  • Edge / on-device - INT4/INT3, MLC, llama.cpp, mlx, formatos GGUF; qualidade é negociada explicitamente.

🚨 Modos de falha

  • Adotar quantização agressiva por causa de "ganho de VRAM" sem medir throughput real no hardware-alvo.
  • Avaliar quantização apenas com perplexity em benchmarks gerais; ignorar task-specific degradation em tool calling, JSON output e RAG.
  • Trocar de framework (ex.: bitsandbytes -> vLLM) sem reavaliar qualidade.
  • Quantizar modelo pequeno que já estava no limite.
  • Misturar adapters de QLoRA treinados em uma versão de NF4 com base quantizada em outra biblioteca.

🛡️ Controles e mitigações

  • Manter eval set fixo (golden + adversarial + tool calling + structured output) para comparar FP16 vs INT8 vs INT4.
  • Medir, no hardware-alvo: TTFT, TPOT, throughput de tokens/s, p95, custo por sucesso.
  • Versionar model_id + quant_scheme + framework_version no tracing.
  • Fixar versões de kernel/biblioteca via lock files.
  • Adotar canary com sombra (shadow inference) antes de promover modelo quantizado.

📈 Métricas

  • Memória de pesos: params × bits_per_param / 8.
  • Perplexity (quando aplicável) em corpus de domínio.
  • Task success rate por categoria.
  • Hallucination rate vs baseline FP16.
  • Tool call accuracy e schema validity rate (especialmente para 4-bit).
  • Tokens/s (decode) e TTFT (prefill).
  • Custo por sucesso, não apenas custo por chamada.

🧪 Distillation (revisão curta)

Modelo "student" aprende a imitar "teacher" (rótulos, logits, comportamento em traces reais). Diferentemente de quantização, distillation altera a arquitetura/tamanho, não apenas a precisão numérica.

Padrões úteis:

  • Distilar modelo grande para um modelo menor para uma tarefa específica.
  • Distilar comportamento (formato, estilo) e deixar conhecimento factual em RAG.
  • Combinar distillation + quantização para reduzir custo agregado.

🧪 Fine-tuning (revisão curta)

  • Full fine-tuning - atualiza todos os pesos. Caro, exige dataset significativo, pipeline de eval, governança.
  • LoRA - adapters de baixo posto sobre camadas selecionadas. Mantém o base congelado.
  • QLoRA - LoRA sobre base 4-bit (NF4); permite fine-tune de modelos grandes em hardware modesto.
  • Adapter / Prefix / IA³ / DoRA - variações com diferentes trade-offs de parâmetros e qualidade.
  • Instruction tuning / SFT - treino supervisionado em pares instrução-resposta.
  • Preference tuning (DPO, KTO, ORPO etc.) - alinhar comportamento a preferências; mais delicado e fora do escopo deste livro.

⚠️ Quando NÃO usar fine-tuning

  • Para adicionar conhecimento factual mutável - prefira RAG.
  • Para impor regra de negócio - prefira policy-as-code.
  • Para um único requisito de formato - prefira structured outputs.
  • Para "ensinar a usar tools" sem dataset estruturado e eval - quase sempre não vale a pena; ajuste descrição, exemplos e harness.

📌 Checklist

  • [ ] Eval set comparativo entre formatos (FP16/INT8/INT4) está pronto?
  • [ ] Métricas de tool calling e structured output foram medidas, não só perplexity?
  • [ ] Foi medido throughput real no hardware-alvo, e não só VRAM teórica?
  • [ ] O framework de serving suporta o formato de forma estável?
  • [ ] Existe plano de rollback para versão FP16?
  • [ ] Adapters de fine-tuning estão versionados junto com a base?

🧰 Exemplos práticos relacionados (planejados)

  • EX-LLM-07 - comparação FP16 vs INT8 vs INT4 (GPTQ/AWQ) com eval set de tool calling e JSON output.
  • EX-LLM-08 - QLoRA mínimo com Hugging Face + bitsandbytes em modelo pequeno para estilo, mantendo conhecimento em RAG.

📚 Referências