🧙 Maestro Yoda Cap. 21 · Open source e HuggingFace

Puntata 227

Puntata 227 — Quantization: GGUF, GPTQ, AWQ

Livello: 🧙 Maestro Yoda · Capitolo 21 · Open source e HuggingFace

Un Llama 70B in FP16 pesa 140 GB. Sul tuo MacBook M3 non ci sta neanche pensandoci. Eppure migliaia di nerd lo fanno girare. Magia? No: aritmetica. Si chiama quantization, e nel 2026 è la differenza tra “demo solo per chi ha una H100” e “demo per chi ha un laptop decente”.

tre versioni della stessa Gioconda — la prima a stampa fine arte (FP16), la seconda Postermania da supermercato (Q8), la terza vignetta da fumetto (Q4). Sotto: “stessa Monnalisa, file 4× più piccolo, sorriso ancora riconoscibile”

Cosa è la quantization

Un modello LLM è una sequenza di matrici (i pesi) di numeri. Di default sono in FP32 (32 bit, ~4 byte ciascuno) o FP16/BF16 (16 bit, 2 byte). Per un modello da N miliardi di parametri:

  • FP32: ~4·N GB.
  • FP16/BF16: ~2·N GB.

Quantization = rappresentare quegli stessi numeri con meno bit (es. 8, 4, 3, 2 bit), accettando un piccolo errore di approssimazione.

Per un 70B:

  • BF16: 140 GB → workstation con 2 GPU.
  • INT8: 70 GB → 1 GPU con 80 GB (A100/H100).
  • INT4: 35-40 GB → 1 GPU 48 GB (A6000 / 4090 24GB con CPU offload) o Mac M3 Max 64 GB.
  • INT3: ~28 GB → 4090 24 GB con CPU swap.
  • INT2: ~18 GB → laptop GPU consumer.

La perplexity degrada un po’, ma fino a INT4 spesso in modo trascurabile per uso pratico.


I 3 formati che dominano nel 2026

GGUF

Formato di llama.cpp (Georgi Gerganov, 2023). Successore di GGML.

  • File .gguf singolo, contiene pesi quantizzati + tokenizer + config.
  • Target: inferenza su CPU/Mac/GPU consumer.
  • Supportato da: llama.cpp, Ollama, LM Studio, Jan, koboldcpp, text-generation-webui.
  • Schemi: Q2_K, Q3_K_S/M/L, Q4_0, Q4_K_S/M, Q5_K_M, Q6_K, Q8_0. Le varianti _K usano “k-quants”, quantization “smart” che dedica più bit ai layer critici.
  • Sweet spot 2026: Q4_K_M = miglior trade-off qualità/dimensione per la maggior parte dei modelli. Q5_K_M se hai spazio. Q8_0 se hai budget e vuoi quasi-FP16.

Esempio reale: Llama-3.1-8B-Instruct

  • BF16: 16 GB
  • Q8_0: 8.5 GB
  • Q4_K_M: 4.9 GB
  • Q3_K_M: 4.0 GB
  • Q2_K: 3.2 GB (qualità sensibilmente peggiore)

GPTQ

Algoritmo di post-training quantization (Frantar et al., 2022). Calibration-based: si usa un piccolo dataset di calibrazione per minimizzare l’errore di reconstruction.

  • Target: inferenza GPU.
  • Supportato da: transformers (via auto-gptq), vLLM, TGI.
  • Schemi tipici: 4-bit GPTQ con groupsize 128.
  • Forza: produce modelli che girano bene su GPU senza unsloth/specializzazioni.
  • Limite: meno popolare di AWQ nei modelli post-2024.

AWQ (Activation-aware Weight Quantization)

Algoritmo Lin et al. (2023, MIT). Identifica i pesi “salient” e li preserva con più bit.

  • Target: inferenza GPU server.
  • Supportato da: vLLM (first-class), transformers via autoawq, TGI.
  • Tipico: 4-bit con groupsize 128.
  • Forza: qualità ottima a 4-bit, throughput più alto di GPTQ su molte GPU.
  • È diventato lo standard de facto per modelli enterprise serviti con vLLM nel 2024-26.

Altri (cenni)

  • bitsandbytes (nf4, int8): semplice da usare in HF transformers, ottimo per LoRA QLoRA in training. Inferenza un po’ più lenta di AWQ/GPTQ.
  • EXL2 (exllamav2): formato GPU-only, qualità ottima, velocissimo. Comunità più piccola.
  • HQQ (Half-Quadratic Quantization): no calibration, veloce da produrre.
  • FP8 (E4M3, E5M2): supportato da H100/MI300/Blackwell. Quasi-FP16 in dimensione ma con throughput più alto su hardware moderno.

Cosa “succede” davvero

Concettualmente:

  1. Prendi una matrice W in FP16.
  2. La dividi in gruppi (es. blocchi di 128 elementi).
  3. Per ogni gruppo calcoli scale e zero_point (e talvolta shift).
  4. Mappi ogni valore al numero intero più vicino nello spazio quantizzato.
  5. Per inferire: W_quant = (W_int - zero_point) * scale, su richiesta o dequantizzando layer per layer.

GPTQ/AWQ aggiungono calibration: passi qualche centinaio di sequenze tipiche, misuri l’errore output → output, e aggiusti la quantization per minimizzarlo.

Per i pesi più “importanti” (es. attention output) si usano scale per gruppi più piccoli o più bit (mixed precision).


Cosa degrada e cosa no

Empiricamente:

SchemaΔ Perplexity vs FP16Δ qualità percepita
Q8_0~0%indistinguibile
Q5_K_M<1%quasi indistinguibile
Q4_K_M1-3%piccola, accettabile
Q3_K_M3-8%percettibile, ancora utile
Q2_K10-25%degrado importante

Eccezioni:

  • Reasoning models (DeepSeek-R1, o-series distill): sensibili a Q3 e sotto. Per loro consigliato Q5+.
  • Coding models: tollerano meglio Q4 (output strutturato).
  • Modelli piccoli (≤3B): degradano più dei grandi. Q4 su un 1B può essere molto rumoroso.
  • Lingue minoritarie: spesso degradano prima dell’inglese (vocabolario rappresentato peggio).

Regola pratica: prova Q4_K_M, valuta su 20 prompt reali. Se non basta, sali. Se basta, fermati.


Dove trovi i modelli quantizzati

Su HuggingFace, accountes specializzati pubblicano versioni quantizzate dei modelli popolari poche ore dopo il rilascio originale:

  • TheBloke — storico (2023-24), molti file GGUF/AWQ/GPTQ; meno attivo nel 2025-26.
  • bartowski — il “TheBloke 2.0”, GGUF aggiornato in tempo reale.
  • mradermacher — GGUF a tutte le quantizzazioni, molto attivo.
  • unsloth — quantizzazioni per fine-tuning (versioni -bnb-4bit).
  • TheBloke, MaziyarPanahi, Qwen team — repo ufficiali GPTQ/AWQ.

Pattern: cerchi “Llama-3.1-8B-Instruct GGUF” su HF, scegli il repo del quantizer di fiducia, scarichi il .gguf con la quantizzazione che ti serve.


Esempio pratico end-to-end

Da BF16 a Q4_K_M GGUF a inferenza locale (5 minuti):

# 1. Scarica il modello base
huggingface-cli download meta-llama/Llama-3.2-3B-Instruct

# 2. Converti in GGUF (richiede llama.cpp)
git clone https://github.com/ggerganov/llama.cpp && cd llama.cpp
python convert_hf_to_gguf.py /path/to/Llama-3.2-3B-Instruct \
  --outfile llama-3.2-3b.f16.gguf

# 3. Quantizza
./llama-quantize llama-3.2-3b.f16.gguf llama-3.2-3b-q4_k_m.gguf Q4_K_M

# 4. Inferenza
./llama-server -m llama-3.2-3b-q4_k_m.gguf -c 8192 --port 8080

Oppure salti tutto e installi Ollama (ollama pull llama3.2:3b-instruct-q4_K_M). Stesso risultato, zero terminal-gym.


Caveat 2026

  1. Quantizzazione ≠ distillation. Quantizzazione comprime gli stessi pesi. Distillation (vedi puntata 219) addestra un modello diverso e più piccolo. Risultati diversi.
  2. Quantization-aware training (QAT) sta diventando comune sui modelli flagship: il modello è addestrato fin dall’inizio considerando che girerà quantizzato. Risultati Q4 quasi indistinguibili da FP16.
  3. FP8 / FP4 nativi (H100/Blackwell, MI300X) consentono quantizzazione durante training, non solo post. Sta diventando lo standard per modelli frontier (es. Llama 4).
  4. Long context degrada di più: a 128k+ token, schemi aggressivi (Q3, Q2) perdono coerenza prima.

Glossario lampo

  • GGUF — formato file binario di llama.cpp, contiene pesi quantizzati + meta + tokenizer in un solo .gguf.
  • K-quants — schemi GGUF “smart” (Q4_K_M, Q5_K_M) che allocano bit in modo non uniforme tra layer per minimizzare degrado.
  • AWQ — quantization GPU-oriented che preserva i pesi “salient” individuati via calibration.
  • GPTQ — concorrente storico di AWQ, basato su minimizzazione errore di reconstruction layer-by-layer.
  • Group size — numero di pesi che condividono uno scale/zero_point. Più piccolo = più qualità + più overhead.

Take-away

Quantization è il motivo per cui un Llama 70B nel 2026 gira sul tuo laptop, non in un datacenter. Senza, l’open source AI sarebbe ancora “guardate cosa farei se avessi 8 H100”. Con, è il motivo per cui Ollama ha milioni di utenti. Q4_K_M è la combinazione che ha democratizzato l’LLM più di qualsiasi altra invenzione recente.


➡️ Prossima puntata: Ollama, LM Studio, vLLM — i runtime locali per far parlare i modelli quantizzati.