La fenêtre de contexte, une ressource finie
Ce que voit le modèle, et rien d'autre
Un LLM est sans état : entre deux appels, il ne garde rien. Tout ce qu'il « sait » de votre utilisateur, de la conversation ou de vos documents, il le lit dans la requête du moment. Cette requête (consignes système, historique, documents, question) s'appelle le contexte, et sa taille maximale est la fenêtre de contexte, mesurée en tokens (des morceaux de mots ; en français, comptez grossièrement 4 caractères par token).
flowchart TB
subgraph FEN["Fenêtre de contexte (une requête)"]
S["Consignes système"]
F["Faits sur l'utilisateur"]
R["Résumé de la conversation"]
H["Derniers échanges"]
D["Documents"]
Q["Question"]
end
FEN --> M["Modèle"] --> A["Réponse"]
M -.->|"rien n'est gardé"| X["Appel suivant : tout est à renvoyer"]
Le context engineering consiste à décider, pour chaque appel, ce qui entre dans cette fenêtre.
Pourquoi ne pas tout y mettre ?
gemini-3.5-flash accepte 1 048 576 tokens en entrée (valeur lue le 2026-10-15 avec client.models.get). C'est énorme, et c'est un piège pour trois raisons :
| Coût | Ce qui se passe | Ordre de grandeur |
|---|---|---|
| Argent | chaque token d'entrée est facturé, à chaque appel | un historique de 10 000 tokens renvoyé 50 fois = 500 000 tokens facturés |
| Latence | le modèle doit lire tout le contexte avant de répondre | plus le contexte est long, plus le premier mot tarde |
| Qualité | une information noyée au milieu d'un long contexte est moins bien exploitée | voir « Lost in the Middle » (références) |
L'article Lost in the Middle (Liu et al., 2023) a montré, sur les modèles de l'époque, que la performance est souvent meilleure quand l'information utile est au début ou à la fin du contexte qu'au milieu. Les modèles récents s'en sortent mieux, mais le principe reste : un contexte encombré est un contexte où l'essentiel se perd.
Pourquoi un assistant oublie-t-il votre prénom d'une session à l'autre ?
Le modèle ne garde rien entre deux appels. Se souvenir, c'est la responsabilité de votre application : stocker l'information et la remettre dans le contexte au bon moment.
Mesurer avant d'optimiser
Deux outils :
client.models.count_tokens(model=..., contents=...): le nombre exact de tokens avant d'appeler ;response.usage_metadata: ce qui a été réellement consommé (prompt_token_count,cached_content_token_count,candidates_token_count).
doc = catalogue.document()
print(f"Document : {len(doc)} caractères, "
f"{c.models.count_tokens(model=MODEL, contents=doc).total_tokens} tokens")Dans le projet, assistant.py garde aussi prompt_token_count de chaque réponse, pour comparer les stratégies de contexte sur les mêmes questions.
Résultat obtenu
Mesures réelles du 2026-10-15 :
Document : 23042 caractères, 8149 tokens # catalogue fictif de 160 produits
# Même question « Dans quelle équipe suis-je ? », trois stratégies (moyenne sur 10 questions)
sans_memoire : tokens d'entrée moyens 95
historique_complet : tokens d'entrée moyens 591
memoire : tokens d'entrée moyens 159Recoller toute la première conversation coûte presque 4 fois plus de tokens que rappeler 4 faits ciblés, alors que la conversation n'avait que 10 messages. Avec 200 messages, l'écart se compterait en dizaines de milliers de tokens par question.
Un assistant renvoie tout l'historique (8 000 tokens) à chaque message. Un utilisateur envoie 30 messages dans la journée. Combien de tokens d'historique sont facturés ?
L'historique est renvoyé à chaque appel : 30 × 8 000 = 240 000 tokens (et même plus, puisqu'il grossit à chaque message). C'est pour cela qu'on résume, qu'on sélectionne et qu'on met en cache.
Exercice : l'inventaire du contexte
Prenez une application LLM que vous connaissez (ou l'assistant de cette formation). Listez chaque bloc de son contexte, estimez sa taille en tokens, et classez-le : stable (identique d'un appel à l'autre), par utilisateur, par message.
Voir la solution
Pour l'assistant Atelier :
| Bloc | Taille estimée | Nature |
|---|---|---|
| Consignes système | environ 80 tokens | stable |
| Faits rappelés (4 au plus) | environ 60 tokens | par utilisateur et par message |
| Résumé glissant | 0 à 160 tokens | par conversation |
| Derniers échanges (6 au plus) | 100 à 600 tokens | par conversation |
| Question | 10 à 50 tokens | par message |
Ce classement guide la suite : le stable va en tête (il peut profiter du cache), le par message à la fin, et ce qui grossit sans limite (l'historique) doit être résumé.
Je sais faire
- Expliquer pourquoi un LLM est sans état et ce que cela implique pour la mémoire
- Citer les trois coûts d'un contexte long (argent, latence, qualité)
- Compter les tokens avant un appel et lire
usage_metadataaprès - Faire l'inventaire des blocs d'un contexte et les classer par stabilité