GGUF / GGML (llama.cpp)#

TL;DR — GGUF (GPT-Generated Unified Format) est le format de fichier standard pour distribuer des LLMs quantifiés. Développé par Georgi Gerganov pour llama.cpp, il offre des dizaines de niveaux de quantification (de 2 à 8 bits) et tourne sur n'importe quelle plateforme — du CPU laptop au GPU datacenter.


Qu'est-ce que GGUF ? (expliqué pour un néophyte)#

Un modèle de langage « normal » (comme Llama-2-70B en FP16) pèse ~140 GB. Pour le faire tourner chez toi, il te faut des GPU coûteux.

GGUF est un format de fichier qui compresse ce modèle à ~20-40 GB en réduisant la précision des poids à 2-8 bits. Le moteur llama.cpp sait lire ces fichiers et faire de l'inférence — sans GPU si nécessaire, juste sur ton CPU.

flowchart LR A["Modèle original FP16
Llama-2-70B
~140 GB
16 bits/poids
GPU requis"] A -->|"quantification"| B["Modèle GGUF Q4_K_M
Llama-2-70B
~40 GB
~4.5 bits/poids
CPU ou GPU ok"]

C'est devenu le standard de facto pour distribuer des modèles open-source : Hugging Face, Ollama, LM Studio — tous utilisent GGUF.


GGML → GGUF : l'évolution#

GGML GGUF
Période 2023 (début) Août 2023 →
Structure Format ad hoc, parsing fragile Format key-value structuré et extensible
Extensibilité Casser le format à chaque changement Métadonnées typées, backward-compatible
Statut Déprécié Actif et recommandé

GGUF a remplacé GGML car le premier format nécessitait de recompiler llama.cpp à chaque changement de structure. GGUF utilise un système de paires clé-valeur typées qui permet d'ajouter des métadonnées sans casser la compatibilité.


Les quant types : tableau complet#

Le grand force de GGUF est la variété de ses types de quantification. Trois familles principales :

Types Legacy (uniformes par bloc de 32)#

Quantification uniforme simple. Rapide, pas de calibration, mais qualité limitée aux bas bits.

K-quants (importance-aware, bloc de 256)#

Quantification par blocs de 256 avec scale factors à précision variable. Les suffixes _S, _M, _L indiquent le compromis taille/qualité.

I-quants (importance matrix)#

Utilisent une matrice d'importance (calibration) pour guider la quantification. Meilleure qualité à bas bitrate (2-3 bits).

Tableau de référence#

Type Bits/poids Taille relative Famille Notes
Q2_K ~2.6 ~19% K-quants Minimum viable, perte notable
Q3_K_S ~2.9 ~21% K-quants
Q3_K_M ~3.1 ~23% K-quants Bon ratio pour petits modèles
Q3_K_L ~3.3 ~24% K-quants
Q4_0 4.0 ~28% Legacy Le plus rapide, qualité correcte
Q4_1 4.5 ~31% Legacy Avec zero-point, meilleur que Q4_0
Q4_K_S ~4.1 ~29% K-quants
Q4_K_M ~4.8 ~34% K-quants ★ Sweet spot — recommandé
Q5_0 5.0 ~35% Legacy
Q5_1 5.5 ~38% Legacy
Q5_K_S ~5.1 ~36% K-quants
Q5_K_M ~5.5 ~38% K-quants Très haute qualité
Q6_K ~6.6 ~45% K-quants Quasi-lossless
Q8_0 8.5 ~57% Legacy Lossless pratique
IQ2_XXS ~2.0 ~14% I-quants Extrême, nécessite importance matrix
IQ2_XS ~2.2 ~16% I-quants
IQ2_S ~2.4 ~17% I-quants
IQ3_XXS ~3.0 ~21% I-quants
IQ3_XS ~3.2 ~23% I-quants
IQ3_S ~3.4 ~24% I-quants
IQ4_XS ~4.2 ~29% I-quants Compétitif avec Q4_K_M
IQ4_NL ~4.5 ~31% I-quants Non-linear, bonne qualité
F16 16.0 ~100% N/A FP16 natif (pas de quantification)

Règle empirique : Q4_K_M est le sweet spot universel — meilleur compromis qualité/taille pour la majorité des modèles. Si tu as de la RAM, monte à Q5_K_M ou Q6_K. Si tu es très limité, descends à Q3_K_M ou les I-quants.

Visualisation du trade-off#

xychart-beta title "Qualité vs Taille de fichier" x-axis ["IQ2", "Q2_K", "Q3_K_M", "Q4_0", "Q4_K_M", "Q5_K_M", "Q6_K", "Q8_0", "F16"] y-axis "Qualité" 0 --> 100 line [10, 20, 35, 50, 55, 75, 85, 90, 100]

Q4_K_M est le sweet spot — meilleur compromis qualité/taille pour la majorité des modèles.


Architecture llama.cpp#

Pourquoi llama.cpp est devenu le standard#

flowchart TD F["Fichier .gguf
(modèle quantifié)"] F --> C["llama.cpp core
(C/C++ pur, ~0 dep)"] C --> B1["Backend CPU
(SIMD AVX2/NEON/AVX512)"] C --> B2["Backend GPU
(CUDA / ROCm)"] C --> B3["Backend GPU
(Metal / Vulkan)"] B1 --> D1["Laptop CPU
Raspberry Pi
Edge devices"] B2 --> D2["Serveur NVIDIA
AMD"] B3 --> D3["Mac M1/M2/M3
iPhone / iPad
Android"]

Atouts clés :

  1. Zéro dépendance — C/C++ pur, compile partout (laptop, serveur, mobile, edge)
  2. CPU inference — pas besoin de GPU ! SIMD (AVX2, AVX-512, ARM NEON) pour la vitesse
  3. Multi-backend — CUDA, Metal, Vulkan, OpenCL, ROCm, SYCL
  4. Portabilité absolue — tourne sur Mac, Linux, Windows, Android, iOS
  5. Écosystème riche — Ollama, LM Studio, KoboldCpp, text-generation-webui
  6. Single-file — tout le modèle dans un seul fichier .gguf (poids + tokenizer + métadonnées)
  7. Pas de calibration pour les types legacy et K-quants

Structure interne d'un fichier GGUF#

block-beta columns 1 block:H["Header GGUF
• Magic number: GGUF
• Version du format
• Nombre de tenseurs
• Nombre de paires clé-valeur"] block:K["Métadonnées (KV)
• general.name = Llama-2-70B
• llama.context_length = 4096
• tokenizer.ggml.model = llama
• quantization_type = Q4_K_M"] block:T["Données des tenseurs
• token_embd.weight [Q4_K_M]
• blk.0.attn_q.weight [Q4_K_M]
• blk.0.attn_k.weight [Q4_K_M]
• ...
• output.weight [Q6_K]"] block:TK["Données du tokenizer
• Vocabulaire
• BPE merges
• Tokens spéciaux"] H --> K --> T --> TK

Le format KV permet à n'importe quelle application de lire les métadonnées sans connaître la structure interne du modèle.

Le format KV permet à n'importe quelle application de lire les métadonnées sans connaître la structure interne du modèle.


Exemple pratique#

Installation de llama.cpp#

# Cloner et compiler (avec support CUDA optionnel)
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp

# CPU seulement (le plus simple)
make -j$(nproc)

# Avec CUDA
make GGML_CUDA=1 -j$(nproc)

# Avec Metal (macOS)
make GGML_METAL=1 -j$(nproc)

Conversion d'un modèle HF vers GGUF#

# 1. Télécharger un modèle au format Hugging Face
huggingface-cli download meta-llama/Llama-2-7B-hf --local-dir ./llama-7b

# 2. Convertir en GGUF (format FP16 d'abord)
python convert_hf_to_gguf.py ./llama-7b --outfile llama-7b-fp16.gguf

# 3. Quantifier en Q4_K_M (le sweet spot)
./llama-quantize llama-7b-fp16.gguf llama-7b-q4_k_m.gguf Q4_K_M

# Autres quant types populiers :
./llama-quantize llama-7b-fp16.gguf llama-7b-q5_k_m.gguf Q5_K_M   # haute qualité
./llama-quantize llama-7b-fp16.gguf llama-7b-q8_0.gguf   Q8_0     # quasi-lossless
./llama-quantize llama-7b-fp16.gguf llama-7b-q2_k.gguf   Q2_K     # minimum viable
./llama-quantize llama-7b-fp16.gguf llama-7b-iq3_s.gguf  IQ3_S    # bas bit intelligent

Inférence avec llama.cpp#

# Mode interactif (chat)
./llama-cli \
    -m llama-7b-q4_k_m.gguf \
    -p "Explique la quantification en une phrase :" \
    -n 200 \
    --temp 0.7

# Mode serveur (API compatible OpenAI)
./llama-server \
    -m llama-7b-q4_k_m.gguf \
    --host 0.0.0.0 --port 8080 \
    -c 4096 \
    -ngl 33          # nombre de couches offloadées sur GPU (-1 = tout)

# Appel API
curl http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama-7b",
    "messages": [{"role": "user", "content": "Bonjour !"}],
    "temperature": 0.7
  }'

Avec Ollama (le plus simple)#

# Installer Ollama
curl -fsSL https://ollama.com/install.sh | sh

# Lancer un modèle (télécharge automatiquement le GGUF Q4_K_M)
ollama run llama3.1:8b

# Lister les modèles disponibles
ollama list

# Modèle avec quant type spécifique
ollama pull llama3.1:8b-q5_K_M

Via Python (llama-cpp-python)#

from llama_cpp import Llama

# Charger le modèle GGUF
llm = Llama(
    model_path="llama-7b-q4_k_m.gguf",
    n_ctx=4096,           # Contexte
    n_gpu_layers=-1,      # -1 = offload tout sur GPU si dispo
    verbose=False,
)

# Génération
response = llm(
    "Qu'est-ce que la quantification NF4 ?",
    max_tokens=200,
    temperature=0.7,
    stop=["\n\n"],
)
print(response["choices"][0]["text"])

Avantages et inconvénients#

✅ Avantages#

  • Déploiement universel — CPU, GPU, mobile, edge, navigateur (WASM)
  • Pas besoin de GPU — inférence CPU viable avec SIMD
  • Large choix de quant types — du 2-bit au lossless
  • Single-file — un .gguf contient tout
  • Écosystème mature — Ollama, LM Studio, countless GUIs
  • Pas de calibration pour les types legacy et K-quants
  • Format extensible — backward-compatible

⚠️ Inconvénients#

  • Pas un papier académique — documentation sur GitHub/wiki uniquement
  • Moins optimisé que GPTQ/AWQ pour GPU pur (kernels moins spécialisés)
  • I-quants nécessitent une matrice d'importance (calibration)
  • Performance CPU limitée pour les très grands modèles (>70B)
  • Choix de quant type peut être déroutant pour un débutant

Quel quant type choisir ?#

flowchart TD A["Tu veux utiliser un modèle GGUF.
Quel type choisir ?"] --> B{"Beaucoup de RAM/VRAM ?"} B -->|"OUI"| C["Q6_K ou Q8_0
(quasi-lossless)"] B -->|"NON"| D{"Meilleure qualité possible ?"} D -->|"OUI"| E["Q5_K_M
(excellent ratio)"] D -->|"NON"| F{"Meilleur compromis standard ?"} F -->|"OUI"| G["★ Q4_K_M ★
(recommandé par défaut)"] F -->|"NON"| H{"Très limité en mémoire ?"} H -->|"Modèle > 30B"| I["Q3_K_M
(acceptable)"] H -->|"Modèle ≤ 13B"| J["IQ3_S ou IQ4_XS
(intelligent)"] H -->|"Minimum absolu"| K["Q2_K ou IQ2_XXS
(perte notable mais fonctionnel)"]

Références#

ia llm quantification gguf ggml llama-cpp cpu-inference edge ollama