Fonctionnement des LLM
Anatomie et mécanismes internes des grands modèles de langage
Comprendre comment fonctionnent les LLM permet de mieux les utiliser et d'en connaître les limites.
Vue d'ensemble
Un LLM est un Transformer decoder-only entraîné à prédire le token suivant.
┌─────────────────────────────────────────────────────────────┐
│ PIPELINE LLM │
├─────────────────────────────────────────────────────────────┤
│ │
│ Texte → Tokenizer → Embeddings → Transformer → Logits │
│ ↓ │
│ Sampling │
│ ↓ │
│ Next Token │
│ ↓ │
│ Répéter jusqu'à │
│ <end> ou max_tokens │
│ │
└─────────────────────────────────────────────────────────────┘Tokenization
Qu'est-ce qu'un token ?
Un token est l'unité de base que le modèle manipule. Ce n'est pas forcément un mot.
"Bonjour" → 1 token
"anticonstitutionnellement" → 4+ tokens
"GPT-4" → 3 tokens (G, PT, -4)
" " → 1 token (espace)
"🎉" → 1-2 tokensAlgorithmes de tokenization
BPE (Byte Pair Encoding)
Utilisé par GPT, Claude.
1. Commencer avec des caractères individuels
2. Fusionner les paires les plus fréquentes
3. Répéter jusqu'à atteindre la taille de vocabulaire
"lower" + "lower" + "newest"
↓ Après BPE
["low", "er", "low", "er", "new", "est"]WordPiece
Utilisé par BERT.
"playing" → ["play", "##ing"]
Le ## indique une continuationSentencePiece
Fonctionne sur le texte brut (pas de pré-tokenization).
Vocabulaire
| Modèle | Taille vocabulaire |
|---|---|
| GPT-2 | 50,257 |
| GPT-4 | ~100,000 |
| Claude | ~100,000 |
| LLaMA | 32,000 |
Un vocabulaire plus grand = moins de tokens pour le même texte = plus efficace, mais modèle plus gros.
Compter les tokens
import tiktoken
encoder = tiktoken.encoding_for_model("gpt-4")
tokens = encoder.encode("Bonjour, comment allez-vous ?")
print(len(tokens)) # Nombre de tokens
print(tokens) # IDs des tokensRègle empirique : ~4 caractères = 1 token en anglais, ~3 en français.
Embeddings
Chaque token est converti en un vecteur dense de grande dimension.
Token Embeddings
# Vocabulaire de 100k tokens, dimension 4096
embedding_layer = nn.Embedding(100000, 4096)
# Token ID 15496 → Vecteur [4096]
token_id = torch.tensor([15496])
embedding = embedding_layer(token_id)
# Shape: [1, 4096]Positional Embeddings
Les Transformers n'ont pas de notion d'ordre. On ajoute des embeddings de position.
Token Embedding + Position Embedding = Input Embedding
[4096] + [4096] = [4096]Types d'encodage positionnel :
| Type | Modèles | Caractéristique |
|---|---|---|
| Sinusoidal | Transformer original | Fixe, extrapolation limitée |
| Learned | GPT-2, BERT | Appris, limité à max_len |
| RoPE | LLaMA, Mistral | Rotatif, bonne extrapolation |
| ALiBi | BLOOM | Biais d'attention, efficace |
Architecture Transformer
Structure d'un bloc
┌─────────────────────────────────┐
│ TRANSFORMER BLOCK │
├─────────────────────────────────┤
│ │
│ Input │
│ ↓ │
│ LayerNorm │
│ ↓ │
│ Multi-Head Self-Attention │
│ ↓ │
│ + (Residual) │
│ ↓ │
│ LayerNorm │
│ ↓ │
│ Feed Forward (MLP) │
│ ↓ │
│ + (Residual) │
│ ↓ │
│ Output │
│ │
└─────────────────────────────────┘
× N couches (GPT-4: ~120)Paramètres typiques
| Modèle | Couches | Dim | Têtes | FFN Dim |
|---|---|---|---|---|
| GPT-2 Small | 12 | 768 | 12 | 3072 |
| GPT-3 175B | 96 | 12288 | 96 | 49152 |
| LLaMA 7B | 32 | 4096 | 32 | 11008 |
| LLaMA 70B | 80 | 8192 | 64 | 28672 |
Masque causal
Le modèle ne peut voir que les tokens précédents (pas le futur).
Séquence : [Le, chat, dort]
Attention autorisée :
Le chat dort
Le [✓ ✗ ✗ ]
chat [✓ ✓ ✗ ]
dort [✓ ✓ ✓ ]Génération de texte
Processus autorégressif
Prompt: "Le chat"
Étape 1: "Le chat" → modèle → "dort" (probabilité 0.23)
Étape 2: "Le chat dort" → modèle → "sur" (probabilité 0.31)
Étape 3: "Le chat dort sur" → modèle → "le" (probabilité 0.45)
...Stratégies de décodage
Greedy
Toujours choisir le token le plus probable.
next_token = logits.argmax()Problème : Répétitif et peu créatif.
Temperature
Contrôle la "créativité" en modifiant la distribution.
logits = logits / temperature
probs = softmax(logits)
# temperature < 1 : plus déterministe
# temperature > 1 : plus aléatoire
# temperature = 0 : greedyTemperature 0.1 : "Le chat dort sur le canapé."
Temperature 1.0 : "Le chat dort sur le rebord de la fenêtre."
Temperature 2.0 : "Le chat rêve d'aventures galactiques."Top-k Sampling
Ne considère que les k tokens les plus probables.
top_k_logits, top_k_indices = logits.topk(k=50)
probs = softmax(top_k_logits)
next_token = top_k_indices[torch.multinomial(probs, 1)]Top-p (Nucleus) Sampling
Garde les tokens jusqu'à atteindre une probabilité cumulée p.
# Si p=0.9, on garde les tokens représentant 90% de la masse de probabilité
sorted_probs = probs.sort(descending=True)
cumsum = sorted_probs.cumsum()
mask = cumsum <= pParamètres de génération
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000, # Limite de tokens générés
temperature=0.7, # Créativité (0-1)
top_p=0.9, # Nucleus sampling
top_k=50, # Top-k sampling
stop_sequences=["###"], # Arrêter si rencontré
)Entraînement des LLM
Pré-entraînement
Apprentissage non supervisé sur d'immenses corpus de texte.
Objectif : Prédire le token suivant (Causal Language Modeling)
Loss = -log P(token_t | tokens_1...t-1)Données d'entraînement :
- Web (Common Crawl)
- Livres
- Wikipedia
- Code (GitHub)
- Articles scientifiques
- Forums, réseaux sociaux
Compute nécessaire
GPT-3 175B : ~3,640 petaflop/s-days
≈ 1000 GPUs pendant 1 mois
≈ 4.6 millions $ (cloud)
GPT-4 : ~100× GPT-3 (estimé)
≈ 100+ millions $Scaling Laws
Loss ∝ C^(-0.05) où C = compute (FLOPs)
Loi de Chinchilla (2022) :
- Tokens optimaux ≈ 20 × Paramètres
- LLaMA 7B → 140B tokens minimumContexte et mémoire
Fenêtre de contexte
Le modèle ne peut traiter qu'un nombre limité de tokens.
| Modèle | Contexte |
|---|---|
| GPT-3.5 | 4K / 16K |
| GPT-4 | 8K / 32K / 128K |
| Claude 3 | 200K |
| Gemini 1.5 | 1M |
KV Cache
Pour accélérer la génération, on met en cache les Key-Value des tokens précédents.
Sans cache : recalculer attention pour tous les tokens à chaque étape
Avec cache : réutiliser les KV, ne calculer que pour le nouveau token
Mémoire KV Cache = 2 × layers × batch × seq_len × d_model × precisionGestion du contexte long
- Sliding window : ne garder que les N derniers tokens
- Compression : résumer les anciens tokens
- Retrieval : chercher l'info pertinente (RAG)
Représentations internes
Ce que le modèle "comprend"
Les couches successives construisent des représentations de plus en plus abstraites :
Couches 1-10 : Syntaxe, grammaire
Couches 10-30 : Sémantique, sens des mots
Couches 30-60 : Raisonnement, logique
Couches 60+ : Tâches de haut niveauProbing
On peut "sonder" les représentations internes pour voir ce que le modèle encode :
# Extraire les activations d'une couche
hidden_states = model(input_ids, output_hidden_states=True)
layer_20 = hidden_states.hidden_states[20]
# Entraîner un classifieur simple pour détecter
# si le modèle encode une information (ex: sentiment)
probe = nn.Linear(d_model, 2)Résumé
LLM = Tokenizer + Embeddings + Transformer + Sampling
Pipeline :
1. Texte → Tokens (BPE/WordPiece)
2. Tokens → Embeddings + Position
3. Embeddings → N × Transformer Blocks
4. Output → Logits → Softmax → Probabilités
5. Sampling (temperature, top-p, top-k)
6. Répéter jusqu'à fin
Caractéristiques clés :
├── Autorégressif (token par token)
├── Masque causal (ne voit pas le futur)
├── Contexte limité (mais croissant)
└── Pré-entraîné sur texte massif