Le Labo AI
LLMs : mécanique interne de la prédiction de token à l'échelle

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

11 min3 niveaux disponibles

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éthodePrécision perdueCompressionCas d'usage
FP16référence1xTraining, serving haut de gamme
INT8 (LLM.int8)~1%2xServing standard
GPTQ INT4~2-3%4xEdge, coût réduit
AWQ INT4~1.5%4xMeilleur 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.

Articles liés