Conversation History
La conversation history (historique de conversation) est l’ensemble ordonné des messages échangés entre l’utilisateur et le LLM au cours d’une session, incluant le system prompt, les user prompts et les assistant messages, renvoyé à chaque requête API pour donner au modèle le contexte de l’échange en cours.
- Catégorie
- Architecture de conversation / Gestion de contexte
- Format API
- Tableau
messagescontenant des objets{role, content}alternantuseretassistant - Pourquoi c’est nécessaire
- Les LLM sont stateless : ils n’ont aucune mémoire entre les requêtes. L’historique reconstitue le contexte à chaque appel.
- Limite
- Borné par la fenêtre de contexte du modèle (128K à 1M+ tokens selon le modèle)
- Gestion
- Troncation, résumé, compaction automatique, ou sliding window
- Verdict
- La gestion intelligente de l’historique est le facteur le plus déterminant pour la qualité des conversations longues.
Pourquoi l’historique est indispensable
Les LLM via API sont fondamentalement stateless. Contrairement à une application web avec une session serveur, le modèle ne « se souvient » de rien entre deux requêtes. Chaque appel API est traité indépendamment. Si vous envoyez un message user sans l’historique des échanges précédents, le modèle répond comme si c’était le tout premier message de la conversation.
C’est pour cette raison que le développeur doit renvoyer l’intégralité de l’historique à chaque requête. Le modèle lit cet historique, reconstitue le fil de la conversation, et génère une réponse cohérente avec ce qui a été dit précédemment. Sans historique, pas de suivi de contexte, pas de résolution de références (« comme tu l’as mentionné tout à l’heure »), pas de continuité thématique.
// Troisième tour d'une conversation
{
"model": "claude-opus-4-6",
"system": "Vous êtes un assistant de voyage.",
"messages": [
{"role": "user", "content": "Je veux visiter le Japon en avril."},
{"role": "assistant", "content": "Avril est idéal pour le Japon, c'est la saison des cerisiers en fleur..."},
{"role": "user", "content": "Quels quartiers de Tokyo recommandes-tu ?"},
{"role": "assistant", "content": "Je vous recommande Shinjuku, Asakusa et Shibuya..."},
{"role": "user", "content": "Et pour la nourriture dans ces quartiers ?"}
]
}
Dans cet exemple, le modèle comprend que « ces quartiers » fait référence à Shinjuku, Asakusa et Shibuya grâce à l’historique. Sans les messages précédents, il ne saurait pas de quels quartiers parle l’utilisateur.
Structure de l’historique
Composants
L’historique de conversation comprend les éléments suivants, dans l’ordre :
| Composant | Rôle API | Position | Contenu typique |
|---|---|---|---|
| System Prompt | system (Anthropic) ou "role": "system" (OpenAI) | Avant tous les messages | Rôle, ton, contraintes, outils disponibles |
| Messages échangés | Alternance user / assistant | Ordre chronologique | Questions, réponses, appels d’outils, résultats |
| Dernier user message | user | Dernier élément | La requête actuelle qui déclenche la génération |
Règles d’alternance
Chez Anthropic, les messages doivent strictement alterner entre user et assistant. Le premier message doit être un user. Si votre application a besoin d’envoyer deux messages user consécutifs (par exemple, un message user suivi d’un résultat d’outil dans un message user), fusionnez-les en un seul message. Chez OpenAI, cette contrainte est moins stricte : les messages consécutifs du même rôle sont autorisés.
Messages d’outils dans l’historique
Quand le modèle utilise le function calling, l’historique contient des échanges supplémentaires : un assistant message avec un bloc tool_use, suivi d’un message user avec un bloc tool_result. Ces messages d’outils font partie intégrante de l’historique et doivent être conservés pour que le modèle comprenne le contexte des résultats d’outils. Si vous les supprimez, le modèle perd la trace de ce qu’il a fait et pourquoi.
Le problème de la fenêtre de contexte
L’historique de conversation est limité par la fenêtre de contexte du modèle. En mars 2026, les fenêtres vont de 128K tokens (GPT-4o, DeepSeek V3.2) à 1M tokens (Claude Opus 4.6, Claude Sonnet 4.6, Gemini 3.1 Pro) voire plus (Grok 4.1 Fast annonce ~2M tokens). L’historique complet (system prompt + tous les messages) doit tenir dans cette fenêtre, avec de la marge pour la réponse du modèle.
À titre indicatif, 1M tokens représente environ 750 000 mots, soit l’équivalent de plusieurs romans. Pour la plupart des conversations, c’est largement suffisant. Mais les cas d’usage comme l’analyse de documents longs, les sessions de coding étendues ou les conversations multi-jours peuvent rapidement épuiser cette capacité, surtout si l’historique accumule aussi les résultats d’outils volumineux.
Stratégies de gestion de l’historique
Troncation simple (sliding window)
La méthode la plus basique : quand l’historique dépasse un seuil (par exemple, 80 % de la fenêtre de contexte), supprimez les messages les plus anciens. Cette approche est facile à implémenter mais brutale : le modèle perd complètement le contexte des échanges supprimés. Si l’utilisateur fait référence à quelque chose dit en début de conversation, le modèle ne pourra pas y répondre.
# Troncation simple : conserver les N derniers messages
def truncate_history(messages, max_messages=20):
if len(messages) > max_messages:
# Toujours garder le premier échange pour le contexte initial
return messages[:2] + messages[-(max_messages - 2):]
return messages
Une variante consiste à conserver le premier échange (qui établit souvent le contexte principal) et les N derniers messages. C’est un bon compromis entre simplicité et préservation du contexte.
Résumé de l’historique
Plutôt que de supprimer les vieux messages, résumez-les. Utilisez le LLM lui-même pour produire un résumé condensé des échanges passés, puis injectez ce résumé au début de l’historique (dans le system prompt ou dans un message user synthétique). Le modèle a ainsi accès à une version compressée de toute la conversation.
Le résumé peut être déclenché périodiquement (tous les 10 tours), par seuil de tokens (quand l’historique dépasse 50K tokens), ou par détection de changement de sujet. L’inconvénient principal est la perte de détails : le résumé est une approximation, et des informations spécifiques (chiffres exacts, instructions précises) peuvent être perdues ou déformées.
Compaction automatique (Claude Opus 4.6)
Claude Opus 4.6 dispose d’une fonctionnalité de compaction de contexte qui résume automatiquement l’historique quand il devient trop long. Cette compaction est transparente pour le développeur : le modèle gère en interne la transition entre messages détaillés et résumés compactés. C’est l’approche la plus élégante, mais elle est spécifique à Anthropic et n’offre pas de contrôle fin sur ce qui est compacté.
Approche hiérarchique
Pour les applications complexes, combinez plusieurs niveaux de mémoire. Un premier niveau conserve les derniers messages en détail (les 5-10 derniers tours). Un deuxième niveau stocke un résumé glissant de la conversation complète. Un troisième niveau (optionnel) utilise une base de données vectorielle pour stocker les faits clés extraits de la conversation, récupérables par recherche sémantique quand l’utilisateur y fait référence.
Cette architecture s’inspire du fonctionnement de la mémoire humaine : mémoire à court terme (messages récents), mémoire de travail (résumé), et mémoire à long terme (base vectorielle). C’est la stratégie recommandée pour les agents IA qui maintiennent des sessions longues.
| Stratégie | Complexité | Perte d’information | Coût | Cas d’usage |
|---|---|---|---|---|
| Troncation simple | Faible | Élevée | Faible | Chatbots simples, prototypage |
| Résumé périodique | Moyenne | Moyenne | Moyen (tokens de résumé) | Applications conversationnelles standard |
| Compaction automatique | Faible (côté dev) | Faible à moyenne | Inclus dans le coût API | Applications sur Claude |
| Approche hiérarchique | Élevée | Faible | Élevé (infra supplémentaire) | Agents IA, sessions multi-jours |
Impact sur la qualité des réponses
La gestion de l’historique influence directement la qualité des réponses du modèle, de plusieurs façons. Un historique trop court prive le modèle de contexte et produit des réponses hors sujet ou répétitives. Un historique trop long augmente le coût, la latence, et expose le modèle au phénomène Lost in the Middle : les informations en milieu d’historique reçoivent moins d’attention que celles au début et à la fin.
Un historique « pollué » (contenant des échanges hors sujet, des erreurs non corrigées, ou des résultats d’outils volumineux et non pertinents) dégrade aussi la qualité. Le modèle n’a pas de mécanisme pour distinguer les messages importants des messages anodins : il traite tout l’historique de manière uniforme (au biais positionnel près). Nettoyer l’historique (supprimer les résultats d’outils volumineux déjà traités, corriger les réponses erronées) améliore souvent la qualité des réponses suivantes.
Impact sur les coûts
L’historique de conversation est la principale source de consommation de tokens d’entrée. À chaque requête, vous renvoyez l’intégralité de l’historique. Au tour N d’une conversation, vous avez déjà payé les tokens de tous les tours précédents N-1 fois (le premier message a été envoyé N fois). C’est un coût cumulatif qui croît de manière quadratique avec la longueur de la conversation.
Le prompt caching atténue ce problème. Si le début de votre historique est stable d’une requête à l’autre (ce qui est le cas puisque seul le dernier message change), le caching évite de re-traiter les tokens déjà vus. Chez Anthropic, un cache read coûte ~10 % du prix standard de l’input. Structurez vos requêtes pour maximiser le préfixe stable (system prompt + historique existant en premier, nouveau message en dernier) afin de maximiser les cache hits.
Historique en mode single-turn vs multi-turn
En mode single-turn, l’historique ne contient qu’un seul message user. Pas de gestion de mémoire, pas de troncation. C’est le cas des appels API ponctuels (traduction, classification, extraction). En mode multi-turn, l’historique s’accumule au fil des échanges et nécessite une stratégie de gestion active. La frontière entre les deux n’est pas toujours nette : une application peut commencer en single-turn (première requête) puis passer en multi-turn dès que l’utilisateur pose une question de suivi.
Considérations de sécurité
L’historique de conversation peut contenir des informations sensibles : données personnelles partagées par l’utilisateur, résultats d’outils avec des données métier, réponses contenant des analyses confidentielles. Plusieurs précautions s’imposent.
Premièrement, la rétention des données. Déterminez combien de temps vous conservez l’historique et où il est stocké. Les providers d’API (OpenAI, Anthropic, Google) ont des politiques de rétention différentes. Anthropic propose notamment des engagements de non-utilisation des données API pour l’entraînement. Pour les applications sensibles, envisagez le mode zero data retention si le provider le propose.
Deuxièmement, l’injection via l’historique. Si votre application permet à des tiers de contribuer au contenu de l’historique (par exemple, des résultats de recherche injectés comme messages), ces contenus peuvent contenir des instructions malveillantes (« ignore tes instructions précédentes »). Appliquez les mêmes précautions anti-prompt injection au contenu injecté dans l’historique qu’au user prompt direct.
Troisièmement, la fuite d’information inter-sessions. Si vous utilisez des résumés d’historique qui sont stockés côté serveur, assurez-vous que les résumés d’une session ne « fuient » pas vers une autre session ou un autre utilisateur. L’isolation des données par utilisateur et par session est critique, surtout dans les environnements multi-tenant.
Bonnes pratiques d’implémentation
Voici les recommandations principales pour une gestion robuste de l’historique en production :
Surveillez la taille de l’historique en tokens. Implémentez un compteur de tokens (via tiktoken pour OpenAI ou le tokenizer Anthropic) qui suit la taille totale de l’historique. Déclenchez votre stratégie de troncation/résumé avant d’atteindre la limite de la fenêtre de contexte, pas quand l’API retourne une erreur.
Gardez les métadonnées hors de l’historique. Les timestamps, IDs de session, et autres métadonnées techniques n’ont pas besoin d’être dans les messages envoyés au modèle. Stockez-les côté serveur et ne transmettez au modèle que le contenu conversationnel utile.
Nettoyez les résultats d’outils volumineux. Si un appel d’outil renvoie 50 000 tokens de résultat et que le modèle n’en a utilisé qu’une fraction dans sa réponse, résumez ou tronquez le résultat d’outil dans l’historique pour les tours suivants. Conserver des blocs de données massifs dans l’historique gaspille la fenêtre de contexte et augmente les coûts.
Testez la dégradation progressive. Simulez des conversations de 50, 100, 200 tours et vérifiez que la qualité des réponses ne se dégrade pas de manière inacceptable. Identifiez le point à partir duquel votre stratégie de gestion d’historique commence à perdre des informations critiques.
Implémentez la journalisation. Enregistrez l’historique envoyé à chaque requête (ou au moins un hash + la taille en tokens) pour diagnostiquer les problèmes de qualité. Quand un utilisateur signale une réponse incohérente, la première chose à vérifier est l’état de l’historique au moment de cette requête.
Verdict
L’historique de conversation est le tissu conjonctif qui donne sa cohérence à une interaction multi-turn avec un LLM. Sa gestion est un problème d’ingénierie sous-estimé : trop de développeurs se contentent d’accumuler les messages sans stratégie, puis s’étonnent quand la qualité se dégrade, les coûts explosent, ou la fenêtre de contexte déborde. Investissez dans une stratégie de gestion adaptée à votre cas d’usage (troncation intelligente, résumé, ou approche hiérarchique), exploitez le prompt caching pour maîtriser les coûts, et nettoyez régulièrement l’historique des messages obsolètes ou volumineux. La fenêtre de 1M tokens de Claude n’est pas une excuse pour ne pas gérer votre historique.
FAQ
Pourquoi faut-il renvoyer tout l’historique à chaque requête API ?
Parce que les LLM via API sont stateless : ils n’ont aucune mémoire entre les requêtes. Chaque appel est traité indépendamment. Le tableau messages envoyé à chaque requête reconstitue le contexte de la conversation. Sans l’historique, le modèle ne sait pas ce qui a été dit précédemment et ne peut pas résoudre les références contextuelles.
Que faire quand l’historique dépasse la fenêtre de contexte ?
Quatre stratégies principales : (1) troncation simple en supprimant les messages les plus anciens, (2) résumé de l’historique ancien via le LLM lui-même, (3) compaction automatique (disponible sur Claude Opus 4.6), ou (4) approche hiérarchique combinant messages récents détaillés + résumé glissant + base vectorielle pour les faits clés. Le choix dépend de votre cas d’usage et de votre budget.
L’historique de conversation est-il coûteux ?
Oui, c’est la principale source de coût en tokens d’entrée. Le coût est cumulatif : au tour N, vous renvoyez N-1 tours de messages déjà envoyés. Le prompt caching atténue ce problème (90 % de réduction chez Anthropic sur les tokens déjà vus). De plus, Anthropic ne facture aucun surcoût long contexte sur sa fenêtre de 1M tokens, contrairement à OpenAI (surcoût au-delà de 272K) et Google (surcoût au-delà de ~200K).
Quelle est la différence entre conversation history et context window ?
La fenêtre de contexte (context window) est la capacité maximale du modèle en tokens (par exemple, 1M pour Claude Opus 4.6). L’historique de conversation est le contenu effectivement envoyé dans cette fenêtre. L’historique doit tenir dans la fenêtre de contexte, avec de la marge pour la réponse du modèle. Si l’historique dépasse la fenêtre, l’API retourne une erreur.
Comment optimiser l’historique pour le prompt caching ?
Placez le contenu stable en premier dans votre requête : system prompt, puis les messages d’historique existants, et enfin le nouveau message user tout à la fin. Le caching fonctionne sur le préfixe commun entre deux requêtes consécutives. Comme seul le dernier message change entre les tours, la quasi-totalité de l’historique existant est cacheable, ce qui réduit considérablement le coût de re-traitement.