La récupération bat toujours une fenêtre d'1M tokens pour votre base de code
Il y a quelques semaines, je déboguais un bug d'authentification dans un projet personnel — un backend TypeScript, une centaine quarante de fichiers, confortablement sous le million de tokens. J'avais devant moi un modèle à 1M tokens, alors j'ai pris le chemin de la facilité : j'ai fourré tout le répertoire src/ dans un seul prompt et demandé à l'agent de trouver où le token de session était rafraîchi et pourquoi ce n'était parfois pas le cas.
Il a tout lu. Ça m'a coûté une petite fortune en tokens d'entrée pour ce seul tour. Et il a désigné en toute confiance un helper refreshToken qui semblait correct — mais qui était le mauvais. Il y en avait deux, dans des modules différents, et celui qu'il avait choisi n'était pas sur le chemin d'exécution qui se déclenchait. Je lui avais fourni toute la botte de foin, et il avait attrapé une aiguille plausible qui s'y trouvait en plein milieu.
J'ai ensuite fermé cette session, ouvert une nouvelle avec le même modèle, et le laissé travailler de la manière habituelle : lister l'arbre, faire un grep de refreshToken, lire les trois fichiers correspondants, suivre les imports. Il a trouvé le vrai bug en environ un quart des tokens et un tiers du temps réel. Même modèle. Même dépôt. La différence tenait entièrement à la façon dont je lui avais fourni le code.
En bref : pour une vraie base de code, tout déverser dans une énorme fenêtre de contexte est généralement le pire choix — non pas parce que la fenêtre est trop petite, mais parce que les modèles deviennent mesurément moins fiables à mesure qu'on la remplit, et le code est le pire cas d'entrée pour cet échec. La récupération ciblée — grep, indexation des symboles, lecture consciente des dépendances — gagne sur le coût, la latence et la précision pour la plupart des tâches de code. Le contexte long gagne dans quelques cas spécifiques, et je vous donnerai la règle à la fin.
Le chiffre de la fenêtre est réel ; la partie utilisable ne l'est pas
D'abord, la partie qui est vraie : les grands chiffres existent. En juin 2026, les trois principaux modèles de codage — Claude Opus 4.8, GPT-5.5 et Gemini 3.1 Pro — proposent tous une fenêtre d'1M tokens, et plus de treize modèles frontier hébergés annoncent 1M ou plus (comparaison de fenêtres de contexte de Morph). Anthropic et OpenAI ont même supprimé le supplément pour contexte long, si bien que la facturation se fait maintenant au même tarif par token sur toute la fenêtre.
Le problème, c'est que annoncé et utilisable sont deux chiffres différents. Les tests de rappel indépendants en 2026 continuent de montrer que la capacité effective se situe bien en deçà du chiffre indiqué — un bilan estime la capacité de contexte effective à environ 50–65 % du nominal, et signale des scores MRCR multi-aiguilles qui s'effondrent dans la seconde moitié de la fenêtre : Gemini 3.1 Pro maintient ~84,9 % de rappel dans la bande 128K–256K et s'écrase à 26,3 % dans la bande 512K–1M (analyse « context window lie » de CodingFleet). Traitez les pourcentages exacts comme indicatifs — ce sont des chiffres de benchmarks de fournisseurs, pas une étude contrôlée — mais la forme est cohérente partout : le rappel baisse bien avant que la fenêtre ne soit pleine.
Cette baisse a un nom et une trajectoire de recherche, et elle importe davantage pour le code que pour presque tout autre domaine.
Pourquoi le code est le pire cas d'entrée pour une fenêtre pleine
Deux effets bien répliqués jouent contre vous quand vous entassez un dépôt dans un seul prompt.
Perdu au milieu. L'article de Liu et al. (publié dans TACL) a montré que la précision du modèle est une fonction en U selon l'endroit où se trouve l'information pertinente : maximale quand elle est au début ou à la fin du contexte, et se dégradant de plus de 30 % quand elle est enfouie au milieu — et cela s'est vérifié sur six familles de modèles pour la QA multi-documents et la récupération clé-valeur. Une base de code, c'est précisément « de l'information pertinente au milieu ». La fonction dont vous avez besoin est rarement le premier ou le dernier fichier que vous avez collé.
Pourrissement du contexte. L'étude 2025 de Chroma a testé 18 modèles frontier — Claude Opus 4 / Sonnet 4 / 3.7 / 3.5 / Haiku 3.5, OpenAI o3 et la famille GPT-4.1, Gemini 2.5 Pro/Flash, et trois tailles de Qwen3 — et a constaté que les performances baissent à mesure que la longueur de l'entrée augmente, même sur des tâches triviales comme trouver une chaîne ou répliquer des mots répétés (rapport « Context Rot » de Chroma). La découverte qui devrait mettre mal à l'aise tout développeur d'agents de code : sur la tâche LongMemEval, tous les modèles ont fait moins bien avec l'historique complet de ~113k tokens qu'avec un extrait ciblé de ~300 tokens du même contenu pertinent. Plus de tokens du bon contenu, présentés en masse, ont obtenu un score inférieur à une petite sélection soigneusement choisie.
Il y a un détail dans ce rapport qui est presque drôle quand on écrit du code : les modèles ont obtenu de moins bons résultats quand la botte de foin « préserv[ait] un flux logique d'idées » que quand elle était mélangée. Un dépôt est structuré de la façon la plus logique possible — imports, graphes d'appels, définitions de types, modules ordonnés. Vous donnez au modèle exactement la forme d'entrée qu'il gère le plus mal.
Et le code punit l'échec plus durement que la prose. Si un chatbot rate une phrase d'un long document, il donne une réponse un peu plus vague. Si un agent de code rate la vraie définition de refreshToken, il écrit du code qui appelle une méthode inexistante ou corrige la mauvaise fonction — et il le fait avec confiance. Comme le soulignait une analyse de la récupération par agents : « le mode d'échec du RAG dans les contextes de codage est silencieux et cumulatif » (MindStudio). Une mauvaise récupération ne génère pas d'erreur. Elle est mise en production.
Ce que « récupération » signifie pour le code (ce ne sont surtout pas des embeddings)
Quand les gens entendent « récupération », ils imaginent une base de données vectorielle. Pour le code, les agents qui passent vraiment en production — Claude Code, Cursor, Devin — ne commencent généralement pas par là. Ils naviguent comme le ferait un développeur expérimenté : regarder l'arbre de fichiers, faire un grep d'un symbole, lire les fichiers spécifiques qui correspondent, suivre la chaîne d'imports (MindStudio). L'outil de recherche principal de Claude Code est ripgrep — correspondance de texte exacte, rapide, avec numéros de ligne, qui fonctionne sur n'importe quel dépôt sans prétraitement.
Il y a une bonne raison pour laquelle les vecteurs ne sont pas la méthode par défaut pour le code, et ce n'est pas de la nostalgie. Un cadre utile est celui des trois couches, à escalader uniquement quand nécessaire (recherche de code pour les agents IA) :
- Lexicale (ripgrep) : correspondance exacte, millisecondes, gitignore-aware. Votre option par défaut.
- Structurelle (ast-grep) : correspondance de motifs AST — « trouver toutes les fonctions async », « tous les catch-and-rethrow » — des choses que regex ne peut pas exprimer proprement. Passez à cette couche quand la requête porte sur la forme, pas sur des chaînes.
- Sémantique (embeddings / repo-map) : requêtes conceptuelles en langage naturel. Dernier recours.
Pourquoi la sémantique est-elle le dernier recours et non le premier ? Parce que les requêtes qu'un agent de code génère réellement sont courtes et ont la forme de symboles — auth flow, user service, refreshToken — et c'est précisément le format qui fait échouer la recherche par embeddings. Le benchmark CoREB a trouvé que les requêtes courtes par mots-clés « font s'effondrer presque tous les modèles sémantiques testés à un nDCG@10 proche de zéro ». Les embeddings capturent la similarité de sens ; le code est un graphe de dépendances, d'imports et de définitions de types, et la similarité n'est pas la relation que vous interrogez. Deux fonctions peuvent être sémantiquement quasi identiques et structurellement sans rapport ; celle dont vous avez besoin est celle sur le chemin d'appel, pas celle qui se lit de façon similaire.
Ça ne rend pas l'indexation sémantique inutile — ça en fait un outil spécialisé. Quand elle mérite sa place, les bonnes implémentations n'embedent pas des fenêtres de texte arbitraires. Elles parsent avec tree-sitter en unités réelles — fonctions, classes, interfaces avec leurs docstrings intacts — gardent ces morceaux entiers, et associent la similarité vectorielle à la correspondance de mots-clés BM25 plus des outils de graphe d'appels pour le traçage des dépendances et l'analyse du rayon de souffle (opencode-codebase-index). C'est tout le jeu pour la récupération de code : découpage conscient des dépendances aux limites des symboles avec repli sur les mots-clés — pas « découpe le fichier toutes les 512 tokens et espère le meilleur ».
Les calculs de coût et de latence que personne ne fait
Mettez la précision de côté un instant et regardez juste la facture. Disons qu'un dépôt moyen fait 600K tokens. Le déverser dans un seul tour signifie payer 600K tokens d'entrée à chaque tour de la conversation sauf si vous gérez soigneusement le cache — et même avec le cache, vous supportez la latence du modèle qui porte son attention sur tout cela. Un passage de récupération envoie à la place l'arbre (quelques Ko), un résultat de grep (quelques centaines de tokens) et peut-être quatre fichiers que vous lisez vraiment (~15K tokens). Ce n'est pas une différence d'arrondi ; c'est un à deux ordres de grandeur par tour, multiplié par chaque tour d'une session de débogage.
La latence suit la même courbe. Un modèle raisonnant sur 600K tokens est plus lent au premier token et globalement que le même modèle raisonnant sur 18K. Dans une boucle interactive où vous faites vingt tours pour traquer un bug, ça s'accumule en minutes d'attente inutile. La récupération garde chaque tour petit, donc chaque tour est rapide, donc la boucle reste serrée.
Et il y a un coût plus discret : le budget d'attention. Chaque fichier non pertinent dans la fenêtre est un élément distrayant, et Chroma a montré que ces éléments traînent la précision vers le bas de façon mesurable — un élément distrayant a nui, quatre l'ont amplifié. Un dépôt complet en contexte représente des milliers d'éléments distrayants pour n'importe quelle question. Vous ne payez pas seulement plus pour être plus lent ; vous payez plus pour être plus lent et plus imprécis.
Quand le contexte long gagne vraiment
Ce n'est pas « toujours la récupération ». Il existe une vraie zone où tout déverser est le bon choix, et elle est définie par la taille du dépôt et la forme de la tâche, pas par la taille de la fenêtre pour laquelle vous payez.
Le contexte long gagne quand :
- Tout le dépôt tient vraiment avec de la marge — disons moins de ~150K tokens, bien à l'intérieur du front à haute précision de la fenêtre — et la tâche nécessite un raisonnement inter-fichiers difficile à récupérer par morceaux. Un petit dépôt où tout compte est exactement le cas que la récupération over-complique.
- Vous avez besoin d'un raisonnement sur un fichier entier ou un module entier en une seule passe — un seul gros fichier à refactoriser entièrement, une lecture de sécurité de haut en bas d'un module, une revue architecturale où le modèle doit tenir les relations en vue en même temps. La récupération fragmente ça ; le contexte le préserve.
- C'est une passe unique en lecture seule, pas une boucle itérative. Un seul appel « révise cette PR » ou « résume comment ce service fonctionne » amortit le coût sur un seul tour. L'économie qui tue le contexte long — payer la fenêtre entière à chaque tour — ne mord pas quand il n'y en a qu'un.
La récupération gagne partout ailleurs, ce qui en pratique représente la majeure partie du travail : tout dépôt trop grand pour tenir confortablement, tout ce qui est itératif, tout ce où vous avez besoin d'une définition spécifique plutôt que d'une compréhension générale, et tout ce où une mauvaise récupération silencieuse déploierait du code cassé.
Une règle approximative que j'utilise vraiment : si la partie pertinente de la tâche est plus petite que le dépôt, récupérez. Si la tâche est tout le dépôt et que le dépôt tient dans les premiers ~15 % de la fenêtre, chargez-le. La plupart du temps, la partie est plus petite que le dépôt.
La conclusion
La fenêtre d'1M tokens est une vraie capacité, et ça vaut la peine d'exploiter la tarification sans supplément pour les travaux pour lesquels elle est adaptée — revues en une passe de code qui tient, raisonnement sur un module entier, le dépôt petit occasionnel où tout est pertinent. Mais ce n'est pas un substitut à savoir où vit votre code. Pour un agent de code qui fonctionne, la pile ennuyeuse — lister l'arbre, faire un grep du symbole, lire les quatre fichiers qui ont correspondu, suivre les imports, escalader vers l'AST ou les embeddings uniquement quand la recherche par mots-clés revient vide — est moins chère, plus rapide et plus précise que l'impressionnante. Le grand chiffre sur la fiche technique est une option, pas une instruction. La plupart du temps, ne la remplissez pas.
