Leçon 2 — La fenêtre de contexte comme ressource

Ordonner le contexte et tenir un budget

5 min de lecture

Ordonner le contexte et tenir un budget

Un ordre qui a des raisons

PositionBlocPourquoi ici
1consignes systèmestables : elles forment un préfixe identique d'un appel à l'autre, ce qui favorise le cache implicite (module 3)
2faits sur l'utilisateurstables pendant la session, et importants : en tête, ils ne se perdent pas au milieu
3résumé de la conversationchange lentement
4derniers échanges, mot pour motchangent à chaque tour
5la questionen dernier : c'est là que le modèle la « voit » le mieux, et ce qui précède sert à y répondre
flowchart LR
  A["1. Consignes (stable)"] --> B["2. Faits rappelés"] --> C["3. Résumé glissant"] --> D["4. Tours récents"] --> E["5. Question"]
  A -.->|"préfixe identique = cache possible"| K["Cache implicite"]
  E -.->|"fin du contexte = bien exploitée"| M["Modèle"]

Le code

files/contexte.py
def build_context(system, facts, summary, turns, question, budget=6000, count=approx_tokens):
    facts, turns = list(facts), list(turns)

    def render():
        sys = system
        if facts:
            sys += "\n\n## Ce que tu sais de l'utilisateur (mémoire long terme)\n" + "\n".join(f"- {f}" for f in facts)
        if summary:
            sys += "\n\n## Résumé de la conversation jusqu'ici\n" + summary
        contents = [{"role": r, "parts": [{"text": t}]} for r, t in turns]
        contents.append({"role": "user", "parts": [{"text": question}]})
        total = count(sys) + sum(count(t) for _, t in turns) + count(question)
        return sys, contents, total

    sys, contents, total = render()
    while total > budget and (turns or facts):
        if turns:
            turns.pop(0)       # 1. les tours les plus anciens (déjà couverts par le résumé)
        else:
            facts.pop()        # 2. puis les faits les moins pertinents (liste triée par score)
        sys, contents, total = render()
    return sys, contents, total

Trois choix à remarquer :

  • Faits et résumé vont dans l'instruction système, pas dans un faux message utilisateur : le modèle les traite comme du contexte de confiance, pas comme une demande.
  • L'ordre de suppression suit la valeur de chaque bloc : un vieux tour déjà résumé vaut moins qu'un fait rappelé.
  • Le résumé et la question ne sont jamais coupés. Si même eux dépassent le budget, c'est le résumé qu'il faut raccourcir (leçon suivante), pas le contexte qu'il faut tronquer au hasard.

Le budget est dépassé. Que retire build_context en premier ?

Compresser plutôt que couper

Retirer est la solution de dernier recours. Avant, on compresse :

TechniqueCe qu'on gagneCe qu'on risque
Résumé glissant (module 2)l'historique cesse de grossirperdre un détail, garder une information périmée
Faits extraits (module 2)quelques lignes au lieu de pagesune extraction ratée = un oubli
Sélection par similarité (RAG)seuls les passages utilesrater le bon passage
Résultats d'outils raccourcisun JSON de 5 000 tokens réduit aux 3 champs utilessupprimer un champ dont le modèle avait besoin

Résultat obtenu

Exécution locale (sans appel au modèle) du 2026-10-15, avec 3 faits, un résumé, 2 tours et la question « Dans quelle équipe suis-je ? » :

budget=6000: ~166 tokens, 3 messages, faits gardés=3
budget=120: ~106 tokens, 1 messages, faits gardés=0

Avec un budget de 120, tout a été retiré sauf les consignes, le résumé et la question : on voit l'ordre de priorité à l'œuvre (et pourquoi un budget trop serré rend l'assistant amnésique). Le test test_build_context_order_and_budget de test_memoire.py vérifie ces règles à chaque modification.

Pourquoi placer les consignes système et les faits stables en tête du contexte ?

Exercice : un bloc « documents »

Ajoutez à build_context un paramètre docs: list[str] (des passages RAG triés par pertinence). Où les placez-vous, et dans quel ordre les retirez-vous en cas de dépassement ?

Voir la solution

Placez-les après les tours récents et juste avant la question, dans un message dédié, par exemple « Documents utiles : … ». Ils dépendent de la question, ils changent à chaque appel : aucun intérêt à les mettre dans le préfixe stable, et les avoir près de la question aide le modèle à les relier.

Ordre de retrait proposé : vieux tours, puis derniers documents (les moins pertinents), puis faits les moins pertinents. Dans la boucle :

if turns:
    turns.pop(0)
elif docs:
    docs.pop()
else:
    facts.pop()

Ajoutez un test : avec un budget serré, le document le moins pertinent disparaît avant le premier.

Je sais faire

  • Justifier l'ordre consignes, faits, résumé, tours, question
  • Écrire une fonction d'assemblage qui respecte un budget de tokens
  • Choisir quoi retirer en premier, et ce qu'il ne faut jamais couper
  • Citer quatre façons de compresser un contexte et leurs risques
Suivant