Aller au contenu principal

Module 6 — Fenêtre de contexte et gestion de la mémoire

Un LLM ne se souvient pas d'un tour à l'autre. Ce qu'il « sait » d'une conversation ne dépend que de ce qui se trouve dans son invite à l'appel courant. C'est ce texte, mesuré en jetons, qu'on appelle le contexte. Pour notre assistant de support, la question n'est pas académique : un client peut envoyer un historique de tickets, un extrait de CGV, une facture, plus la question elle-même. Faut-il tout mettre dans l'invite ? La réponse est presque toujours non, et ce module explique pourquoi.

La fenêtre de contexte, une contrainte à deux visages

Chaque modèle publie une taille de fenêtre de contexte maximale, exprimée en jetons. Les modèles récents affichent des fenêtres allant de 4 000 à plus de 200 000 jetons.

Modèle représentatif (2026)Contexte maximalContexte utile en pratique
Modèles 7-8 milliards ouverts standard8 000 - 32 0004 000 - 8 000
Modèles ouverts contexte long128 000 - 200 00032 000 - 64 000
Modèles propriétaires haut de gamme200 000 - 1 000 00032 000 - 100 000

L'écart entre le maximum annoncé et le contexte utile est capital. Un modèle peut techniquement lire 200 000 jetons sans erreur, et pourtant s'y comporter de plus en plus mal. La cause tient à un phénomène étudié depuis 2023.

La perte au milieu

Liu et al. (2023) ont montré qu'un LLM, placé face à une information critique enfouie dans un contexte long, la retrouve très bien si elle est au début ou à la fin, mais très mal si elle est au milieu. La courbe de précision en fonction de la position de l'information dessine un U : haute aux extrémités, basse au milieu. Le phénomène s'appelle lost in the middle, ou perte au milieu.

Le mécanisme n'est pas pleinement compris, mais deux facteurs contribuent. D'abord, la position du texte est encodée par des vecteurs qui, aux positions éloignées vues rarement pendant l'entraînement, sont moins bien appris. Ensuite, l'attention se répartit sur toute la séquence : plus il y a de jetons, plus la masse individuelle sur chaque jeton est faible, et l'information critique se noie dans le bruit.

Pour notre assistant, la conséquence pratique est directe. Mettre un historique de vingt messages en tête d'invite puis poser la question à la fin marche mieux que l'inverse, et marche beaucoup mieux qu'un ordre aléatoire.

def construire_invite(historique, contexte_produit, question):
# Ordre optimal : consigne, question au debut, contexte long au milieu,
# rappel de la question a la fin.
return (
"Tu es l'assistant support d'ACME. Reponds en francais, concisement.\n\n"
f"Question du client : {question}\n\n"
"--- Contexte produit ---\n"
f"{contexte_produit}\n"
"--- Historique ---\n"
f"{historique}\n\n"
f"Rappel : la question est '{question}'. Reponse :"
)

Ce simple rappel de la question à la fin gagne systématiquement quelques points d'exactitude sur les jeux de test dès que le contexte dépasse 4 000 jetons.

Le coût du contexte, quadratique en attention

Le calcul de l'attention d'un Transformer est en O(n2)O(n^2) pour une séquence de nn jetons. Doubler le contexte multiplie par quatre le calcul et la mémoire d'attention. La latence perçue par l'utilisateur suit la même loi.

Tpreˊremplissagecn2etTgeˊneˊrationcnm,T_{\text{préremplissage}} \approx c \cdot n^2 \quad \text{et} \quad T_{\text{génération}} \approx c' \cdot n \cdot m,

nn est le nombre de jetons d'invite et mm le nombre de jetons générés. Le préremplissage est la passe qui digère l'invite, sans encore produire de sortie ; il domine le temps de réponse pour les invites longues. La génération est proportionnelle au produit longueur d'invite × longueur de sortie, à cause du cache d'attention consulté à chaque nouveau jeton.

Chiffres concrets pour un modèle de 8 milliards sur A100 :

Longueur d'inviteTemps de préremplissageLatence perçue au premier jeton
1 000 jetons150 ms200 ms
4 000 jetons550 ms620 ms
16 000 jetons3 s3,1 s
64 000 jetons25 sinutilisable en temps réel

Un utilisateur attend rarement plus de trois secondes avant de croire que le service est en panne. Cette contrainte, à elle seule, exclut les contextes très longs pour un assistant interactif — indépendamment de la qualité du modèle.

Trois stratégies pour tenir dans la fenêtre

Une conversation qui dure finit par dépasser toute fenêtre. Trois familles de solutions coexistent.

Fenêtre glissante brute : on garde les nn derniers jetons et on jette le reste. Simple, mais on perd les informations importantes du début de la conversation — le nom du client, sa commande, ses préférences.

Résumé glissant : à chaque nouveau tour, on résume les tours anciens en quelques phrases. Un modèle plus petit ou une passe séparée du même modèle produit le résumé. On conserve ainsi l'essentiel des anciens tours dans une empreinte compacte.

def resumer_conversation(anciens_tours, modele_resume):
consigne = (
"Resume ces echanges client en 3 puces factuelles, "
"sans reformulation, en gardant identifiants et engagements."
)
return modele_resume.generer(consigne + "\n\n" + anciens_tours, max_new_tokens=200)

Mémoire externe : on stocke les tours dans une base de vecteurs et on va chercher les plus pertinents pour chaque nouvelle question. C'est la logique de récupération, prélude à la génération augmentée par récupération (RAG), traitée en détail au cours 18.

StratégieCoûtPerte d'informationCas d'usage
Fenêtre glissantenulforteconversations courtes, sans état
Résumé glissant1 appel LLM par tourmodéréeconversations longues à mémoire vive
Mémoire externeinfrastructurefaiblecorpus stable, plusieurs conversations

Pour notre assistant, la combinaison typique est : mémoire externe pour la base de connaissance produit (CGV, catalogue, procédures) et résumé glissant pour la conversation en cours.

Le cache KV, ce qui rend le contexte long soutenable

Un détail d'implémentation change tout dans l'économie du service. Le Transformer, pendant la génération, calcule des vecteurs clés et valeurs (K et V) pour chaque jeton du passé, et les réutilise à chaque nouveau jeton. Sans cache, chaque nouveau jeton recalculerait tout ; avec cache, on ne recalcule que la nouvelle position.

Meˊmoire du cache=2Lhdteˆtenoctets par valeur,\text{Mémoire du cache} = 2 \cdot L \cdot h \cdot d_{\text{tête}} \cdot n \cdot \text{octets par valeur},

LL est le nombre de couches, hh le nombre de têtes et dteˆted_{\text{tête}} leur dimension. Pour un modèle de 8 milliards en bfloat16 avec 4 000 jetons de contexte, le cache atteint plusieurs gigaoctets : c'est souvent lui qui limite le nombre de requêtes concurrentes tenables sur un GPU, plus que les poids eux-mêmes. Le module 8 y reviendra à propos du service.

Un contexte long n'est pas une base de données

La tentation naturelle, quand on découvre les modèles à 200 000 jetons, est de « tout jeter dedans » — catalogue, documentation, historique complet. Le résultat est presque toujours décevant. Le modèle passe à côté d'informations qu'un simple SQL aurait trouvées, hallucine sur des détails, et coûte quinze fois plus qu'une requête ciblée précédée d'une récupération. La fenêtre longue est utile pour des documents que l'on lit en entier, pas pour remplacer un moteur de recherche.

Récupération et ancrage, l'annonce du cours 18

Le module 7 va montrer qu'une des causes majeures d'hallucination est l'absence de sources dans le contexte. Le cours 18 introduira explicitement la génération augmentée par récupération : indexer un corpus par des embeddings (cours 13), retrouver les passages pertinents au moment de la requête, et les insérer dans l'invite. Ce module 6 pose les bases : le contexte est une ressource rare, il faut l'utiliser à bon escient, et le contenu qui n'y figure pas n'existe pas pour le modèle.

Le budget de jetons est aussi un budget d'attention

Une bonne manière de raisonner : accordez-vous un « budget » de 2 000 à 4 000 jetons pour l'invite, quel que soit le maximum théorique du modèle. Ce budget vous force à hiérarchiser — quelle consigne, quel exemple, quel extrait de document — et donne des réponses plus stables, plus rapides et moins chères qu'un contexte massif de mauvaise qualité.

En résumé

  • La fenêtre de contexte annoncée est un maximum technique ; le contexte utile est nettement plus court à cause de la perte au milieu et du coût quadratique.
  • La perte au milieu est le phénomène par lequel une information au milieu d'un long contexte est moins bien retrouvée qu'aux extrémités ; on la contourne en plaçant les données importantes en tête ou en fin d'invite.
  • Trois stratégies gèrent une conversation qui grandit : fenêtre glissante, résumé glissant, mémoire externe ; on les combine plutôt qu'on ne les oppose.
  • Le cache KV rend la génération soutenable en évitant de recalculer les vecteurs des jetons passés, mais consomme une mémoire proportionnelle au contexte — limite pratique du nombre de requêtes concurrentes.

Module suivant : pourquoi un modèle invente des faits, et quelles parades marchent vraiment.