Votre appel API se termine. Claude ou GPT-4o renvoie une réponse. Mais quelque part au milieu de votre document de 8 000 mots, il a cessé de faire attention. Non pas parce que le modèle s’est cassé — mais parce que vous avez épuisé la fenêtre de contexte.
La fenêtre de contexte est le nombre maximum de jetons qu’un LLM peut traiter en une seule requête. Claude 3.5 Sonnet gère 200 000 jetons. GPT-4o gère 128 000 jetons. Llama 3 70B gère 8 000 jetons. Dépassez cette limite, votre requête échoue. Restez en dessous mais surchargez trop, l’attention du modèle se dégrade sur le matériel enfoui au milieu — un phénomène appelé problème de « perdu au milieu ».
Ce n’est pas une limitation théorique. Cela casse des systèmes de production réels : des chatbots de support client qui ne peuvent pas se souvenir des premiers échanges de conversation, des pipelines d’analyse de documents qui manquent des sections critiques et des flux de travail de recherche qui s’étouffent sur des PDF.
Comment fonctionne réellement la fenêtre de contexte
Chaque mot, chiffre, signe de ponctuation et espace est converti en jetons avant que le modèle ne le traite. Un jeton ≈ 4 caractères en anglais, mais varie selon la langue et la structure.
Une fenêtre Claude Sonnet de 200 000 jetons se décompose comme suit :
- Invite système : 500 jetons
- Entrée utilisateur (votre document) : 150 000 jetons
- Historique de conversation : 30 000 jetons
- Réservé pour la sortie : 19 500 jetons
Il vous reste 19 500 jetons pour la réponse du modèle. Si vous avez besoin d’une analyse détaillée, c’est suffisant. Si vous avez besoin de plusieurs étapes de raisonnement, vous êtes à la limite.
Les mathématiques sont rigides : jetons d’entrée + jetons de sortie ≤ fenêtre de contexte. Dépassez-la, et la plupart des fournisseurs d’API rejettent la requête avec une erreur 400. Certains services la mettent en file d’attente. Aucun ne la tronque silencieusement.
Le problème de la perte au milieu est réel
En septembre 2023, des chercheurs du MIT ont testé si les LLM utilisaient réellement tout le contexte qu’ils prétendent prendre en charge. Ils ont inséré un fait clé à différentes positions d’un long document et ont demandé au modèle de le récupérer.
Le constat : les modèles obtiennent les meilleurs résultats sur les informations situées au début et à la fin du contexte. Les informations au milieu — positions 40 à 60 % du document — sont traitées avec une précision inférieure de 25 à 35 % par rapport aux mêmes informations au début.
Ce n’est pas spécifiquement un problème de Claude ou de GPT-4o. Cela affecte tous les modèles basés sur des transformeurs. La raison : les modèles d’attention dans les modèles linguistiques pondèrent plus fortement les jetons précédents par défaut, et le modèle « économise » de la capacité pour le résumé et la réponse finaux.
Impact pratique : si votre bot de support client traite une conversation de 5 messages, les premiers messages reçoivent un traitement dégradé. Si votre analyseur de documents traite un PDF de 50 pages, les pages 20 à 30 deviennent invisibles.
Technique 1 : Résumer avant de traiter
Au lieu d’envoyer le document entier, comprimez-le d’abord.
# Mauvaise approche : envoyer le document complet
Utilisateur : « Analysez ce contrat de 30 pages. Quelles sont les obligations clés ? »
[envoyer le contrat complet de 30 pages en entrée]
Le modèle utilise une précieuse fenêtre de contexte sur des sections standard qui n’ont pas d’importance.
# Approche améliorée : processus en deux étapes
Étape 1 : Résumer le document
Invite : « Résumez ce contrat en 500 jetons. Conservez les obligations, les délais et les modalités de paiement. Supprimez le contenu standard. »
[envoyer le contrat complet]
Sortie : résumé de 500 jetons
Étape 2 : Analyser le résumé
Invite : « Sur la base de ce résumé, listez toutes les obligations des contreparties et quelle partie supporte chaque risque. »
[envoyer le résumé de 500 jetons]
Sortie : analyse structurée
Pourquoi cela fonctionne : vous utilisez la fenêtre de contexte lors du premier appel pour extraire le signal, puis vous traitez uniquement le signal lors du second appel. Le second appel est plus rapide, moins cher et plus précis car le modèle travaille avec des informations distillées.
Économies réelles de jetons : un contrat de 50 pages (≈25 000 jetons) devient un résumé de 500 jetons. Votre deuxième appel d’analyse passe de 25 500 jetons à 1 000.
Technique 2 : Diviser et réorganiser l’historique de conversation
Les conversations longues sont le problème de contexte le plus difficile car chaque nouveau message s’ajoute à l’historique. Après 15 échanges, vous avez consommé 8 000 à 15 000 jetons rien que pour la mémoire de conversation.
# Problème : l'historique de conversation gonfle
Tour de conversation 20 :
Système : [invite système d'origine]
Utilisateur : [tour 1]
Assistant : [réponse]
Utilisateur : [tour 2]
Assistant : [réponse]
... [tours 3–19] ...
Utilisateur : [tour 20] <- nouveau message
Assistant : [le modèle répond]
Au tour 20, le modèle a vu plus de 15 échanges non pertinents avant d'atteindre la question actuelle. Au tour 50, le contexte est principalement un poids mort.
Solution : utiliser une approche de réorganisation.
Après chaque 8 à 10 tours, notez chaque message historique par pertinence par rapport au fil de conversation actuel à l'aide d'embeddings ou d'un modèle linguistique léger. Ne conservez que les 5 à 7 tours passés les plus pertinents, plus les 2 tours les plus récents. Jetez le reste.
import openai
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
def prune_conversation_history(history, current_message, max_turns=7):
# Intégrer tous les messages utilisateur passés
past_messages = [h[