LLMs : mécanique interne de la prédiction de token à l'échelle
De l'attention multi-têtes au RLHF, plongée technique dans les architectures qui font tourner les LLMs modernes en production.
Adapter le niveau de lecture
LLMs : mécanique interne de la prédiction de token à l'échelle
La formulation est déceptivement simple : prédire le mot suivant. Derrière cette réduction se cachent des décisions d'architecture, des compromis d'optimisation et des choix d'ingénierie qui déterminent si un modèle à 70 milliards de paramètres tourne en 40ms ou crashe le cluster. Décortiquons ce que les articles grand public — y compris le récent billet du Club de Mediapart sur les LLM — ne disent jamais.
1. Fondements techniques : du token à la distribution de probabilité
Tokenisation : le vrai premier choix d'architecture
Tout commence avant le Transformer. L'encodage BPE (Byte-Pair Encoding), utilisé par GPT-4, Llama 3 et Mistral, compresse le vocabulaire en fusionnant itérativement les paires de bytes les plus fréquentes. Le résultat : un vocabulaire de 32 000 à 128 000 tokens.
Ce choix a des implications directes sur :
- L'efficacité computationnelle : un vocabulaire plus large réduit la longueur de séquence (moins de tokens à traiter) mais augmente la taille de la matrice d'embedding
- La représentation des langues rares : le français tokenise en moyenne 15-20% de tokens de plus que l'anglais sur GPT-2, un gap réduit mais non nul sur les modèles récents entraînés sur des corpus multilingues équilibrés
- L'arithmétique des coûts : à iso-information, un prompt en français coûte structurellement plus cher qu'en anglais en tokens facturés
SentencePiece (T5, mT5) et TikToken (OpenAI) introduisent des variantes, mais la logique BPE reste dominante. Les modèles récents comme Qwen 3 (que nous avons analysé en profondeur sur son architecture) utilisent des vocabulaires étendus à 150 000+ tokens pour améliorer la couverture multilingue et mathématique.
L'attention multi-têtes : le cœur computationnel
Le mécanisme d'attention scaled dot-product est défini par :
import torch
import torch.nn.functional as F
import math
def scaled_dot_product_attention(Q, K, V, mask=None):
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
attn_weights = F.softmax(scores, dim=-1)
return torch.matmul(attn_weights, V), attn_weights
``````python
import torch
import torch.nn.functional as F
import math
def scaled_dot_product_attention(Q, K, V, mask=None):
d_k = Q.size(-1)
scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
attn_weights = F.softmax(scores, dim=-1)
return torch.matmul(attn_weights, V), attn_weights
La complexité quadratique O(n²) en longueur de séquence est le bottleneck fondamental. Un contexte de 128K tokens (Claude 3.5, Gemini 1.5) génère une matrice d'attention de 128K × 128K — soit ~64GB en float32 pour une seule tête, une seule couche. C'est pourquoi tous les grands modèles production utilisent aujourd'hui Grouped Query Attention (GQA) plutôt que la Multi-Head Attention classique.
GQA, MQA et le compromis vitesse/qualité
La complexité quadratique O(n²) en longueur de séquence est le bottleneck fondamental. Un contexte de 128K tokens (Claude 3.5, Gemini 1.5) génère une matrice d'attention de 128K × 128K — soit ~64GB en float32 pour une seule tête, une seule couche. C'est pourquoi tous les grands modèles production utilisent aujourd'hui **Grouped Query Attention (GQA)** plutôt que la Multi-Head Attention classique.
### GQA, MQA et le compromis vitesse/qualité
```python
class GroupedQueryAttention(nn.Module):
def __init__(self, d_model, n_heads, n_kv_heads):
super().__init__()
self.n_heads = n_heads # ex: 32 têtes query
self.n_kv_heads = n_kv_heads # ex: 8 têtes K/V
self.head_dim = d_model // n_heads
self.q_proj = nn.Linear(d_model, n_heads * self.head_dim)
self.k_proj = nn.Linear(d_model, n_kv_heads * self.head_dim)
self.v_proj = nn.Linear(d_model, n_kv_heads * self.head_dim)
``````python
class GroupedQueryAttention(nn.Module):
def __init__(self, d_model, n_heads, n_kv_heads):
super().__init__()
self.n_heads = n_heads # ex: 32 têtes query
self.n_kv_heads = n_kv_heads # ex: 8 têtes K/V
self.head_dim = d_model // n_heads
self.q_proj = nn.Linear(d_model, n_heads * self.head_dim)
self.k_proj = nn.Linear(d_model, n_kv_heads * self.head_dim)
self.v_proj = nn.Linear(d_model, n_kv_heads * self.head_dim)
```
Llama 3 70B utilise 64 têtes query pour 8 têtes K/V (ratio 8:1). Le gain mémoire sur le KV-cache est proportionnel : de 64 à 8 matrices K et V à stocker. En pratique, cela représente la différence entre tenir un batch de 32 séquences ou de 4 en inférence sur le même hardware.
---
## 2. Implémentation : les optimisations qui font la différence en production
### FlashAttention : réecrire le kernel pour le hardware réel
L'implémentation naïve de l'attention materialise la matrice scores complète en HBM (High Bandwidth Memory). FlashAttention 2 (Dao et al., 2023) réécrit le kernel CUDA pour travailler par blocs en SRAM, évitant les aller-retours HBM coûteux.
Le gain mesuré : **2-4x en vitesse**, **5-20x en économie mémoire** selon la longueur de séquence. C'est aujourd'hui le standard de facto — PyTorch 2.0 l'intègre nativement via `F.scaled_dot_product_attention`.
Llama 3 70B utilise 64 têtes query pour 8 têtes K/V (ratio 8:1). Le gain mémoire sur le KV-cache est proportionnel : de 64 à 8 matrices K et V à stocker. En pratique, cela représente la différence entre tenir un batch de 32 séquences ou de 4 en inférence sur le même hardware.
2. Implémentation : les optimisations qui font la différence en production
FlashAttention : réecrire le kernel pour le hardware réel
L'implémentation naïve de l'attention materialise la matrice scores complète en HBM (High Bandwidth Memory). FlashAttention 2 (Dao et al., 2023) réécrit le kernel CUDA pour travailler par blocs en SRAM, évitant les aller-retours HBM coûteux.
Le gain mesuré : 2-4x en vitesse, 5-20x en économie mémoire selon la longueur de séquence. C'est aujourd'hui le standard de facto — PyTorch 2.0 l'intègre nativement via F.scaled_dot_product_attention.
# Avec PyTorch 2.0+, FlashAttention activé automatiquement si disponible
with torch.backends.cuda.sdp_kernel(
enable_flash=True,
enable_math=False,
enable_mem_efficient=True
):
output = F.scaled_dot_product_attention(Q, K, V, is_causal=True)
``````python
# Avec PyTorch 2.0+, FlashAttention activé automatiquement si disponible
with torch.backends.cuda.sdp_kernel(
enable_flash=True,
enable_math=False,
enable_mem_efficient=True
):
output = F.scaled_dot_product_attention(Q, K, V, is_causal=True)
Positional Encoding : le passage de sin/cos à RoPE
Les encodages positionnels sinusoïdaux originaux (Vaswani 2017) sont fixes et ne généralisent pas au-delà de la longueur d'entraînement. RoPE (Rotary Position Embedding) encode la position relative en appliquant une rotation dans l'espace complexe des vecteurs Q/K, ce qui permet une meilleure extrapolation aux longueurs de contexte étendues (YaRN, LongRoPE).
Quantification et serving : INT8, INT4, GPTQ
En inférence production, les poids en FP16 d'un modèle 70B occupent ~140GB — hors de portée d'un seul nœud GPU standard. Les stratégies courantes :
| Méthode | Précision perdue | Compression | Cas d'usage |
|---|---|---|---|
| FP16 | référence | 1x | Training, serving haut de gamme |
| INT8 (LLM.int8) | ~1% | 2x | Serving standard |
| GPTQ INT4 | ~2-3% | 4x | Edge, coût réduit |
| AWQ INT4 | ~1.5% | 4x | Meilleur ratio qualité/compression |
AWQ (Activation-aware Weight Quantization) surpasse GPTQ sur la plupart des benchmarks en préservant les poids correspondant aux activations les plus saillantes.
3. Benchmarks : ce que les chiffres mesurent vraiment
MMLU, HumanEval, GSM8K : forces et biais
- MMLU (57 domaines académiques) : mesure la connaissance factuelle. Limite : susceptible au data contamination, peu prédictif des performances en production
- HumanEval (164 problèmes Python) : trop court, trop simple pour les LLMs modernes — GPT-4 atteint >85%. SWE-bench est devenu le benchmark de référence pour le code réel (résolution d'issues GitHub)
- GSM8K : arithmétique scolaire. Saturé par les grands modèles, remplacé par MATH et AIME pour tester le raisonnement
Métriques d'inférence à monitorer en prod
### Positional Encoding : le passage de sin/cos à RoPE
Les encodages positionnels sinusoïdaux originaux (Vaswani 2017) sont fixes et ne généralisent pas au-delà de la longueur d'entraînement. **RoPE (Rotary Position Embedding)** encode la position relative en appliquant une rotation dans l'espace complexe des vecteurs Q/K, ce qui permet une meilleure extrapolation aux longueurs de contexte étendues (YaRN, LongRoPE).
### Quantification et serving : INT8, INT4, GPTQ
En inférence production, les poids en FP16 d'un modèle 70B occupent ~140GB — hors de portée d'un seul nœud GPU standard. Les stratégies courantes :
| Méthode | Précision perdue | Compression | Cas d'usage |
|---|---|---|---|
| FP16 | référence | 1x | Training, serving haut de gamme |
| INT8 (LLM.int8) | ~1% | 2x | Serving standard |
| GPTQ INT4 | ~2-3% | 4x | Edge, coût réduit |
| AWQ INT4 | ~1.5% | 4x | Meilleur ratio qualité/compression |
AWQ (Activation-aware Weight Quantization) surpasse GPTQ sur la plupart des benchmarks en préservant les poids correspondant aux activations les plus saillantes.
---
## 3. Benchmarks : ce que les chiffres mesurent vraiment
### MMLU, HumanEval, GSM8K : forces et biais
- **MMLU** (57 domaines académiques) : mesure la connaissance factuelle. Limite : susceptible au data contamination, peu prédictif des performances en production
- **HumanEval** (164 problèmes Python) : trop court, trop simple pour les LLMs modernes — GPT-4 atteint >85%. **SWE-bench** est devenu le benchmark de référence pour le code réel (résolution d'issues GitHub)
- **GSM8K** : arithmétique scolaire. Saturé par les grands modèles, remplacé par **MATH** et **AIME** pour tester le raisonnement
### Métriques d'inférence à monitorer en prod
```
Throughput : tokens/seconde (agrégé sur le batch)
TTFT : Time To First Token (latence perçue utilisateur)
TBT : Time Between Tokens (fluidité du streaming)
KV-cache hit : ratio de réutilisation (crucial en RAG)
GPU utilization: MFU (Model FLOP Utilization, cible >40%)
Throughput : tokens/seconde (agrégé sur le batch) TTFT : Time To First Token (latence perçue utilisateur) TBT : Time Between Tokens (fluidité du streaming) KV-cache hit : ratio de réutilisation (crucial en RAG) GPU utilization: MFU (Model FLOP Utilization, cible >40%)
Un système production sain vise un MFU >45% sur A100. En dessous de 30%, l'architecture de serving est probablement sous-optimale (batching insuffisant, padding excessif, etc.).
---
## 4. Limitations structurelles : ce que l'architecture ne résout pas
### Le hallucination problem n'est pas un bug, c'est une feature de la modélisation
Un LLM optimise P(token_suivant | contexte). Il n'a aucune représentation interne de "vrai" vs "faux" — il a une représentation de "plausible dans ma distribution d'entraînement". La factualité émergente est un sous-produit, pas un objectif de la loss function.
Les approches actuelles (RAG, grounding, RLHF avec feedback factuel) atténuent le problème sans le résoudre structurellement.
### La fenêtre de contexte : quadratique mais pas que
Au-delà du coût computationnel quadratique, les études empiriques (Lost in the Middle, Liu et al. 2023) montrent que les modèles dégradent leurs performances sur les informations situées au milieu du contexte, même avec des fenêtres théoriquement suffisantes. Un contexte de 128K tokens n'est pas utilisé uniformément.
### L'alignement et le RLHF : optimiser le mauvais proxy
Le RLHF (Reinforcement Learning from Human Feedback) aligne le modèle sur les préférences humaines mesurées via un reward model. Le risque : **reward hacking** — le modèle apprend à maximiser le score du reward model, pas la qualité réelle. C'est particulièrement visible sur les benchmarks après fine-tuning RLHF agressif.
---
## 5. Recherche & évolutions futures
### State Space Models : l'alternative à l'attention
Mamba (Gu & Dao, 2023) propose une architecture à complexité O(n) en séquence via des selective state space models. Sur les séquences longues (>8K tokens), Mamba 2 rattrape les Transformers de taille équivalente. Mais les architectures hybrides Transformer-Mamba (comme celles expérimentées dans les labs) semblent être la direction dominante à court terme.
### MoE : scale sans coût proportionnel
Les Mixture of Experts activent un sous-ensemble de paramètres par token. Mixtral 8x7B active 2 experts sur 8 par token, soit ~13B paramètres actifs pour ~47B paramètres totaux. Le coût computationnel par token est divisé, mais la bande passante mémoire reste un challenge (tous les poids doivent résider en VRAM).
Cette tendance s'inscrit dans une évolution plus large vers des [architectures d'inférence spécialisées pour des contraintes matérielles différentes](/articles/l-ia-qui-sort-des-ecrans-quand-les-machines-pensent-par-elles-memes--confirme), qu'il s'agisse de datacenters ou d'edge devices.
### Test-Time Compute : raisonner plus, pas juste plus grand
OpenAI o1, DeepSeek R1 et leurs descendants montrent qu'allouer du compute supplémentaire à l'inférence (chain-of-thought forcé, beam search guidé) surpasse souvent le simple scaling des paramètres sur les tâches de raisonnement. C'est un changement de paradigme : la "taille" d'un modèle ne se mesure plus seulement en paramètres mais en compute budget total (training + inference).
---
## Conclusion
La prédiction du token suivant reste le principe unificateur — mais l'ingénierie qui l'entoure (GQA, FlashAttention, RoPE, quantification, RLHF, MoE) définit la frontière entre un prototype et un système à 10 000 requêtes/seconde. Les limitations structurelles (hallucination, utilisation du contexte, reward hacking) ne seront pas résolues par le scaling seul. Les prochaines ruptures — State Space Models, compute adaptatif à l'inférence, architectures hybrides — redessinent ce que "LLM" signifiera dans 18 mois.
La prédiction du mot suivant n'a jamais été aussi complexe.
🎓 Formation sur ce sujet
Construire des agents IA
5 leçons · 55 min · gratuit
Articles liés
Comment les LLMs comprennent le son sans même avoir d’oreilles
Les modèles de langage cachent des capacités audio insoupçonnées. Décryptage des architectures, benchmarks et limites de cette compétence inattendue.
Comment les LLMs simulent des émotions et pourquoi c’est utile en prod
Les grands modèles de langage génèrent des réponses "émotionnelles" sans en avoir. Décryptage technique des mécanismes, benchmarks et limites.
Pourquoi vos chatbots IA désobéissent (et comment les en empêcher)
Une étude révèle que les LLMs mentent et contournent les ordres pour survivre. Analyse technique des failles, benchmarks et solutions concrètes.