Aller au contenu
Développement medium

Quantifier un LLM en pratique : GGUF, AWQ, GPTQ, FP8

11 min de lecture

Vous savez pourquoi quantifier un modèle. Ce guide montre comment le faire, et surtout ce que ça change vraiment, mesures à l'appui. Vous allez quantifier un modèle de bout en bout en GGUF pour l'inférence locale, servir des variantes AWQ, GPTQ et FP8 sur GPU, et lire le compromis réel entre taille, vitesse et qualité. Tous les chiffres de ce guide ont été relevés en lab — sur CPU pour la partie GGUF, sur un GPU H100 pour la partie serveur. Public visé : développeur ou ingénieur plateforme à l'aise avec Docker et la ligne de commande.

  • Convertir un modèle Hugging Face en GGUF puis le quantifier vous-même.
  • Mesurer le compromis taille / débit / perplexité d'une quantification.
  • Servir un modèle déjà quantifié en AWQ, GPTQ ou FP8 avec vLLM.
  • Lire le gain VRAM et débit réel de chaque format sur GPU.
  • Choisir le bon format selon votre matériel et votre priorité.

Ce guide suppose acquis le vocabulaire de la quantification — précision, bits par paramètre, formats. Si ces notions sont floues, lisez d'abord Comprendre la quantification des LLM. Il vous faut également :

  • Docker et le plugin Compose.
  • Python 3.12 et git pour la partie conversion GGUF.
  • Un GPU NVIDIA pour la partie serveur (sinon, cette partie reste instructive en lecture).

La partie GGUF se reproduit entièrement sur un poste CPU. La partie GPU a été réalisée sur un H100, mais le principe vaut pour tout GPU récent.

Le pipeline GGUF : convertir et quantifier soi-même

Section intitulée « Le pipeline GGUF : convertir et quantifier soi-même »

Le format GGUF est celui de l'écosystème llama.cpp et Ollama. Le quantifier soi-même se fait en deux temps : convertir le modèle Hugging Face en un GGUF non quantifié (16 bits), puis quantifier ce GGUF vers un format compact. Le modèle de démonstration est Qwen2.5-1.5B-Instruct, assez petit pour que tout le pipeline tienne en quelques minutes.

  1. Récupérer le modèle Hugging Face.

    Téléchargez les fichiers du modèle (poids .safetensors, tokenizer, configs) dans un dossier models/Qwen2.5-1.5B-Instruct/. Le dépôt Qwen/Qwen2.5-1.5B-Instruct est public, aucun compte n'est requis. Vérifiez que model.safetensors pèse bien environ 3,1 Go — un fichier tronqué fera échouer la conversion.

  2. Convertir en GGUF 16 bits.

    La conversion utilise le script convert_hf_to_gguf.py de llama.cpp. Ce script a besoin de dépendances Python (torch, transformers) et de son module interne — clonez donc le dépôt et travaillez dans un environnement virtuel.

    Fenêtre de terminal
    git clone --depth 1 https://github.com/ggml-org/llama.cpp
    cd llama.cpp
    python3 -m venv .venv
    ./.venv/bin/pip install --only-binary=:all: \
    -r requirements/requirements-convert_hf_to_gguf.txt
    ./.venv/bin/python convert_hf_to_gguf.py ../models/Qwen2.5-1.5B-Instruct \
    --outtype f16 --outfile ../models/qwen2.5-1.5b-f16.gguf

    Le fichier qwen2.5-1.5b-f16.gguf obtenu pèse environ 2,9 Gio. C'est la base non quantifiée, qui servira aussi de référence de qualité.

  3. Quantifier vers Q4_K_M, Q5_K_M et Q8_0.

    L'outil llama-quantize transforme le GGUF 16 bits en variantes compactes. Il est inclus dans l'image Docker officielle ghcr.io/ggml-org/llama.cpp:full.

    Fenêtre de terminal
    for Q in Q4_K_M Q5_K_M Q8_0; do
    docker run --rm -v "$PWD/models:/models" \
    --entrypoint /app/llama-quantize \
    ghcr.io/ggml-org/llama.cpp:full \
    /models/qwen2.5-1.5b-f16.gguf /models/qwen2.5-1.5b-$Q.gguf $Q
    done

    En sortie, trois fichiers : le Q8_0 (8 bits), le Q5_K_M (~5,5 bits) et le Q4_K_M (~4,5 bits).

Quantifier sans mesurer n'a pas de sens. Trois outils de llama.cpp suffisent : llama-bench pour le débit, llama-perplexity pour la qualité, et un simple ls -lh pour la taille.

La perplexité mérite un mot. C'est une mesure de la qualité d'un modèle de langage : elle évalue à quel point le modèle est « surpris » par un texte de référence. Plus elle est basse, mieux c'est. Quantifier dégrade légèrement le modèle, donc augmente un peu la perplexité — l'enjeu est de savoir de combien.

Voici les mesures relevées sur Qwen2.5-1.5B, CPU, avec un échantillon du corpus wikitext.

FormatTailleGénérationPerplexitéÉcart de qualité
F162,88 Gio10,5 tok/s9,44référence
Q8_01,53 Gio16,9 tok/s9,46+0,2 %
Q5_K_M1,04 Gio24,2 tok/s9,62+1,9 %
Q4_K_M935 Mio30,8 tok/s10,01+6,0 %

Trois enseignements ressortent. La taille chute fortement : le Q4_K_M divise le modèle par 3,2. La génération accélère à mesure qu'on quantifie — de 10,5 à 30,8 tokens/seconde, soit trois fois plus vite, parce que moins de bits signifie moins de données à déplacer en mémoire. Et la qualité se dégrade peu : le Q8_0 est imperceptible, le Q5_K_M très discret, le Q4_K_M visible mais modéré.

Sur GPU, on quantifie rarement soi-même : on sert un modèle déjà quantifié, publié sur Hugging Face. Trois formats dominent — AWQ et GPTQ (4 bits), FP8 (8 bits) — et vLLM les charge tous. Le modèle de démonstration passe à Qwen2.5-14B-Instruct, une taille où la quantification a un vrai intérêt.

Les variantes AWQ et GPTQ sont des dépôts Hugging Face distincts. vLLM détecte automatiquement la quantification depuis la configuration du modèle.

Fenêtre de terminal
docker run -d --name vllm-quant --runtime nvidia --gpus all --ipc host \
-p 8000:8000 -v hf-cache:/root/.cache/huggingface \
vllm/vllm-openai:latest \
--model Qwen/Qwen2.5-14B-Instruct-AWQ \
--max-model-len 8192 --gpu-memory-utilization 0.90

Remplacez le suffixe -AWQ par -GPTQ-Int4 pour servir la variante GPTQ.

Pour connaître la mémoire réellement occupée par les poids, lisez les logs au démarrage : vLLM affiche une ligne Model loading took X GiB. C'est ce chiffre — et non la VRAM totale, qui inclut le cache — qui mesure le gain de la quantification.

Les quatre variantes ont été servies sur le même H100, avec le même modèle Qwen2.5-14B et le même bench (200 requêtes, débit plafond).

VarianteVRAM des poidsDébit totalLatence (TPOT)
bf16 (référence)27,6 Gio8 354 tok/s74,6 ms
AWQ 4 bits9,5 Gio9 474 tok/s70,1 ms
GPTQ-Int4 4 bits9,4 Gio9 604 tok/s69,4 ms
FP8 8 bits16,1 Gio12 417 tok/s55,8 ms

Le résultat va à l'encontre d'une idée reçue : toutes les variantes quantifiées sont plus rapides que le bf16, pas seulement plus légères. Les formats 4 bits divisent la VRAM des poids par 2,9 et gagnent ~13 à 15 % de débit. Le FP8, lui, est spectaculaire : +49 % de débit par rapport au bf16.

Aucun format n'est universellement supérieur. Le bon choix dépend de votre contrainte principale.

Votre situationFormat conseillé
Inférence locale CPU, usage mono-utilisateurGGUF Q4_K_M — compacité maximale, génération rapide
Inférence locale, la qualité primeGGUF Q5_K_M ou Q8_0
GPU, faire tenir un gros modèle sur peu de VRAMAWQ ou GPTQ — compression par ~3
GPU récent (Tensor Cores FP8), priorité au débitFP8 — débit imbattable
Qualité de référence, VRAM suffisantebf16 — pas de quantification

La règle pratique : commencez par une quantification 4 bits (Q4_K_M en local, AWQ/GPTQ sur GPU). C'est un excellent point de départ. Vous ne reviendrez à une précision supérieure que si vous mesurez une dégradation gênante sur votre cas d'usage.

Les incidents de quantification se résument à quelques causes connues.

SymptômeCause probableSolution
model.safetensors rejeté à la conversionFichier tronqué au téléchargementRe-télécharger ; vérifier la taille avec ls -lh
ModuleNotFoundError au lancement de convert_hf_to_gguf.pyScript lancé hors du dépôt clonéTravailler depuis le dépôt llama.cpp cloné, pas un script isolé
CUDA out of memory en servant le modèle quantifié--max-model-len trop élevéRéduire la longueur de contexte, ou baisser --gpu-memory-utilization
Le FP8 n'accélère pasGPU sans Tensor Cores FP8Utiliser AWQ/GPTQ sur un GPU antérieur à l'architecture Hopper/Ada
Qualité visiblement dégradéeQuantification trop agressive sur un petit modèleMonter en Q5/Q8, ou prendre un modèle plus gros
  • Le pipeline GGUF se fait en deux temps : convertir en 16 bits, puis quantifier vers Q4/Q5/Q8.
  • Quantifier réduit la taille et accélère la génération — ce n'est pas qu'un compromis, c'est souvent un double gain.
  • La perte de qualité reste faible jusqu'à 4 bits ; elle est plus marquée sur les petits modèles.
  • Sur GPU, AWQ et GPTQ compressent le plus (÷2,9 de VRAM) ; le FP8 privilégie le débit.
  • Le FP8 sur H100 gagne +49 % de débit grâce aux Tensor Cores FP8 natifs — un résultat lié au matériel.
  • Choisir un format, c'est choisir sa contrainte prioritaire : VRAM, débit ou qualité.
  • pip install exécute du code : auditer ses sources fait partie du pipeline.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn