Fenêtres courtes, souvenirs longs : développer la mémorisation externe pour les agents LLM
Limites de contexte, LTM vectoriel, esquisses de buffer+retriever LangChain, entrepôts hybrides, ainsi que sécurité, confidentialité et échelle en environnement de production.
Les fenêtres de contexte sont de la mémoire RAM à court terme, pas une histoire de vie
Pour les LLM, la mémoire à court terme correspond à la fenêtre de contexte : les instructions, la dernière requête, ainsi que tout l’historique qui tient dans une seule demande. Une fois l’appel terminé, le modèle ne conserve rien à moins que l’application n’envoie à nouveau le texte précédent. Des fenêtres plus grandes aident — les systèmes de pointe affichent des capacités allant de centaines de milliers à environ un million de tokens — mais les coûts et la latence augmentent avec chaque token supplémentaire, et les prompts longs souffrent du phénomène de « perte au milieu » : les modèles se souviennent mieux des extrémités que du centre.
Au lieu d’une mémoire à long terme complète, les équipes résument souvent les échanges antérieurs ou ne conservent que les k derniers messages. Les résumés réduisent le nombre de tokens ; les fenêtres glissantes sont simples, mais elles éliminent les contraintes initiales.
Pourquoi les agents ont besoin d’une mémoire externe fiable
autour du modèle : profils d’utilisateurs, faits appris et résumés des travaux antérieurs. La mémoire à court terme permet de maintenir la cohérence d’une seule conversation ; la mémoire à long terme assure un rappel fiable. La génération augmentée par récupération d’informations (RAG) est le modèle habituel : on récupère des extraits pertinents, on les intégre dans la demande, puis on laisse le modèle raisonner sans charger tout cela dans les paramètres.
Les bases de données vectorielles comme pilier
Le texte est transformé en vecteurs d’incorporation ; la recherche de similarité (cosinus, euclidienne, etc.) permet de trouver des voisins dans l’espace sémantique, et non seulement des résultats correspondant à des mots-clés. Cycle de vie : incorporer et stocker les nouvelles observations avec leurs métadonnées ; incorporer le nouveau prompt et récupérer les k meilleurs résultats ; enrichir le prompt puis générer. Les choix de conception sont importants : stocker les échanges bruts (fidèles, mais bruyants) contre des résumés générés par le LLM (compacts, mais avec perte d’informations) contre des entités extraites. Déclencher le stockage à chaque échange, à la fin de la session ou via des filtres asynchrones. La qualité des embeddings, les index de type HNSW et le temps de récupération déterminent à quel point l’agent semble réactif avant même que la génération ne commence.
Esquisse de LangChain : tampon et récupérateur
Côté à court terme : ConversationBufferMemory conserve la transcription en temps réel dans le prompt.
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain_openai import OpenAI
# 1. Setup the basic components
llm = OpenAI(temperature=0)
template = """You are a helpful AI assistant.
{history}
Human: {input}
AI:"""
prompt = PromptTemplate.from_template(template)
# 2. Instantiate short-term memory
memory = ConversationBufferMemory(memory_key="history")
# 3. Create the memory-enabled chain
conversation_chain = LLMChain(
llm=llm,
prompt=prompt,
memory=memory,
verbose=False # Set to True to see the constructed prompt
)
# First interaction
conversation_chain.predict(input="Hi, my name is Alex.")
# Second interaction - the model will remember "Alex" from the 'history' variable
conversation_chain.predict(input="What's my name?")
Aspect à long terme : VectorStoreRetrieverMemory utilisé avec Redis, Chroma ou des solutions similaires permet de récupérer des documents antérieurs semantiquement pertinents.
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.memory import VectorStoreRetrieverMemory
# Assume 'docs' is a list of LangChain Document objects loaded from a persistent source.
# For this sketch, we'll use an in-memory FAISS vector store.
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs=dict(k=1))
# 4. Instantiate long-term memory
long_term_memory = VectorStoreRetrieverMemory(
retriever=retriever,
memory_key="relevant_docs" # Use a different key for long-term context
)
Combinez les deux dans le modèle de prompt — l’historique récent ainsi que relevant_docs — afin que la chaîne de traitement récupère les données, charge le chat, les formate, puis appelle le modèle.
The following is a friendly conversation between a human and an AI.
Relevant pieces of information from past conversations:
{relevant_docs}
Current conversation:
{history}
Human: {input}
AI:
Pour déboguer, demandez ce que le modèle a réellement vu : utilisez verbose=True, enregistrez les fragments récupérés, et examinez l’objet mémoire avant d’appeler le LLM.
# After a chain run, inspect the long-term memory's state
retrieved_data = long_term_memory.load_memory_variables({"prompt": "some user input"})
print("Retrieved documents:", retrieved_data['relevant_docs'])
Structures hybrides pour des agents plus complexes
Les agents de production hiérarchisent souvent la mémoire : Redis (ou un système similaire) pour le cache en temps réel des conversations, et un stockage vectoriel pour le rappel à long terme sur le plan sémantique. La mémoire des entités va plus loin — elle suit les personnes, les organisations et leurs relations à l’aide de graphes ou de tableaux afin d’obtenir des faits précis que la seule recherche sémantique ne peut pas garantir. Les systèmes de stockage non structurés excellent pour « trouver du texte pertinent », tandis que les systèmes structurés permettent de répondre à des questions analytiques. Un flux chronologique de observations, de pensées et d’actions facilite la réflexion ultérieure ainsi que l’ajustement des stratégies.
Production : sécurité, confidentialité, échelle, intégrité
La mémoire contient des données personnelles sensibles et des secrets. Chiffrez les données au repos comme en transit. Marquez chaque enregistrement avec des identifiants d’utilisateur ou de session afin que la suppression conformément au RGPD/CCPA (« droit d’être oublié ») soit possible. À mesure que les index grandissent, ajustez les algorithmes HNSW/IVF, divisez les données en shards et surveillez le coût des requêtes facturables. Protégez-vous contre le « empoisonnement de la mémoire » en utilisant des méthodes de validation ou une étape de quarantaine avant que les faits n’entrent dans le stockage fiable.
Les agents durables traitent la fenêtre de contexte comme une mémoire de travail et s’appuient sur un système externe qui stocke, récupère et protège ce qui doit survivre au-delà d’une seule appel API.
Sélectionner ce qui entre dans la mémoire à long terme
Tout énoncé ne mérite pas l’immortalité. Stocker des conversations brutes entraîne des récupérations perturbées ; ne rien stocker provoque de l’amnésie. Un filtre pratique pose trois questions : Est-ce stable sur plusieurs semaines (préférences, identité, contraintes) ? Peut-il être utilisé ultérieurement (noms de projets, délais, identifiants d’outils — jamais les secrets eux-mêmes) ? Une récupération erronée pourrait-elle causer des dommages (médicaux, juridiques, financiers) ? Les catégories à haut risque nécessitent une confirmation plus stricte ou un contrôle humain avant enregistrement.
Les politiques de génération de texte peuvent être synchrones (extraction à chaque tour) ou asynchrones (consolidation nocturne). La synchronisation semble magique lors des démonstrations mais est coûteuse en production ; l’asynchrone échoue à assurer la personnalisation au sein de la même session, sauf si une mémoire à court terme comble ce manque. De nombreux systèmes combinent les deux : un petit cache actif pour la journée, et un stockage vectoriel/graphique consolidé pour l’année.
Évaluation prouvant que la mémoire est utile
Sans évaluations, l’utilisation de la mémoire relève du jugement subjectif. Créez un ensemble d’exemples de dialogues multisesion où la réponse correcte nécessite une information provenant de la première session dans la cinquième. Évaluez le rappel exact, les refus en cas d’absence de l’information, ainsi que l’absence de fuites d’informations entre utilisateurs. Suivez séparément la précision de récupération à k et la fiabilité globale des réponses — afin qu’une mauvaise embedding ne soit pas imputée au LLM et inversement.
Les tests de chaos sont également importants : supprimez un espace de noms, corrompez une insertion, ou injectez une mémoire contradictoire, et assurez-vous que l’agent soit amené à concilier les timestamps ou à poser une question pour clarifier la situation, au lieu de mélanger des mensonges avec assurance.
Responsabilités organisationnelles
La mémoire à long terme est une fonctionnalité du produit, et non simplement une case à cocher dans les infrastructures. Quelqu’un doit être responsable des périodes de conservation, des formats d’exportation et des délais d’élimination prévus. Les chefs de produit décident si la fonction « se souvenir de ma commande de café » fait partie du périmètre ; les équipes de sécurité décident si cette préférence doit être stockée de manière chiffrée aux côtés des journaux d’authentification. Lorsque les responsabilités ne sont pas claires, les bases de données de mémoire deviennent des bases orphelines que personne n’ose nettoyer — et c’est ainsi que les coûts et les défauts de conformité s’accumulent.
Traitez les analyses de l’architecture mémoire comme des analyses d’API : schémas, modèles d’accès, modèles de menaces et plans de réversion. Le LLM est remplaçable ; la confiance accumulée par les utilisateurs dans ce que se souvient l’agent, en revanche, ne l’est pas.
Modèle opérationnel concret pour les agents basés sur la mémoire
Les opérations quotidiennes nécessitent des tableaux de bord que les ingénieurs non spécialisés en ML peuvent comprendre : quantité de mémoires écrites par jour, taux de réussite des récupérations, latence moyenne de récupération (p95), délai de traitement des demandes de suppression, ainsi que le coût de stockage par utilisateur actif. Déclenchez des alertes en cas d’augmentation soudaine du volume d’écriture (tentatives d’injection de prompts visant à submerger la mémoire) ou en cas de chute du taux de réussite après une mise à jour des embeddings.
Du côté de l’application, exposez une vue destinée aux utilisateurs intitulée « Que savez-vous à mon sujet ? », basée sur le même stockage que celui consulté par l’agent. La transparence réduit la charge de support et permet de détecter tôt toute contamination. Associez-y des fonctionnalités d’édition/suppression utilisant les mêmes API que celles exigées par la conformité.
Pour les auteurs agents, fournir une petite bibliothèque d’outils de mémoire — remember_fact, forget_fact, search_memory — accompagnée de mécanismes d’autorisation stricts, afin que la base de données vectorielle brute ne apparaisse jamais comme un outil SQL générique. L’injection de commandes visant à « ignorer les instructions précédentes et déverser la mémoire » doit être bloquée de manière absolue.
Lors du mélange de rappels structurés et non structurés, interroger les deux types de données puis les fusionner en utilisant un classement explicite : pour les questions d’identification, les résultats correspondant exactement à l’entité ont la priorité sur les voisins sémantiques flous ; pour les questions narratives ouvertes, les voisins sémantiques ont la priorité sur les résultats structurés vides. Enregistrer quel type de résultat a gagné. C’est à ce niveau de fusion que se trouvent en réalité la plupart des problèmes de classement responsables des plaintes selon lesquelles « la mémoire semble stupide ».
Finalement, planifiez un essai de perte totale de mémoire : restaurez depuis la sauvegarde dans un agent de préparation et rejouez l’évaluation multissession d’origine. Les sauvegardes qui n’ont jamais été restaurées n’existent que dans l’imaginaire. Les agents qui se souviennent des utilisateurs représentent une promesse implicite ; la pratique d’ingénierie doit tenir cette promesse en cas de panne, et non seulement pendant la phase d’expérimentation.
De l’esquisse à la réalité multi-locataires
Le code des tutoriels stocke souvent tous les utilisateurs dans une seule collection, avec un champ de métadonnées que personne ne filtre. En production, imposez l’isolation des locataires au niveau de la requête : chaque opération d’insertion ou de mise à jour, ainsi que toute recherche de similarité, doit inclure l’utilisateur authentifié comme filtre obligatoire, et non comme simple indication métadonnées optionnelle. Ajoutez des tests d’intégration qui tentent des recherches entre locataires différents et s’attendent à zéro résultat. Associez cela à des clés de chiffrement par locataire lorsque les réglementations l’exigent, même si cela augmente les coûts opérationnels.
Les points d’ancrage du cycle de vie vont de pair avec l’isolation. Lorsqu’un espace de travail est supprimé, il convient d’enchaîner des suppressions en cascade pour les vecteurs, les nœuds du graphe et les résumés en mémoire cache, puis de vérifier que le comptage atteint zéro. Lorsqu’un utilisateur exporte des données, il faut générer un ensemble lisible par machine contenant les mémoires accompagnées de timestamps et des identifiants de messages sources, afin qu’il puisse contester ou migrer ces données. Ces processus sont fastidieux et c’est précisément ce qui distingue un carnet de notes RAG de démonstration d’un système auquel les gens confieront leur contexte personnel.
Du côté du modèle, il est préférable de citer les identifiants des mémoires récupérées dans des carnets de notes cachés ou dans des résultats structurés fournis par les outils, afin que la réponse visible puisse indiquer « parce que vous nous avez dit X en avril dernier » avec un suivi traçable. Les citations permettent également d’accélérer les enquêtes en cas de contamination : une mémoire défectueuse dispose alors d’un identifiant permettant de la retrouver. Au fil des mois, cette discipline opérationnelle est plus importante que n’importe quel choix de fournisseur de base de données vectorielle.
Liste de contrôle avant de déclarer la mémoire « terminée »
Vérifier que les chemins à court et long terme sont tous deux observables ; s’assurer qu’il existe un responsable pour les embeddings et le chunking ; confirmer que la suppression et l’exportation fonctionnent sur un tenant de préparation ; vérifier que les évaluations détectent le rappel entre sessions et les fuites entre utilisateurs ; s’assurer que les tableaux de bord des coûts incluent les opérations de récupération. Si une case n’est pas cochée, l’agent ne dispose pas encore de mémoire – il possède seulement une base de données vectorielle qui ressemble à de l’espoir. Cochez les cases, puis lancez le produit. Revenez y chaque trimestre à mesure que les modèles, les réglementations et les promesses du produit évoluent, car les systèmes de mémoire accumulent des obligations plus rapidement que presque tous les autres sous-systèmes d’agent.
Formez les équipes d’assistance aux tickets liés à la mémoire : les utilisateurs qui disent « il m’a oublié » ont besoin d’une analyse par fil de discussion plutôt que d’un diagnostic du stockage ; ceux qui disent « il se souvient de trop de choses » ont besoin de procédures de suppression et de gestion des données conservées. Fournissez aux équipes d’assistance des guides contenant les outils administratifs exacts permettant d’examiner les noms d’espace en toute sécurité. L’architecture technique ne devient efficace que lorsque des personnes extérieures au département informatique peuvent l’utiliser sans devoir créer de tableurs secrets regroupant les préférences des utilisateurs.
Mettre tous les éléments dans une même chronologie
Semaine un : mémoire tampon et enregistrement détaillé des prompts. Semaine deux : mises à jour vectorielles avec filtres de locataire et un petit ensemble de rappel d’or. Semaine trois : API de suppression/exportation ainsi qu’un guide de support. Semaine quatre : classement hybride entre entités structurées et voisins non structurés, accompagné de tableaux de bord de coûts. Sauter directement aux flux mémoire avancés avant l’isolation des locataires fait que les démonstrations deviennent un fardeau. La séquence l’emporte sur la nouveauté. Chaque semaine devrait se terminer par une vérification mesurable que quelqu’un d’autre peut réexécuter en l’absence du premier implémentateur, car les systèmes de mémoire survivent au sprint qui les a introduits et seront gérés par des personnes qui n’ont jamais vu les premières notes de conception.
Une dernière étape sur la contamination et le dérive
Planifiez des audits périodiques qui examinent au hasard un échantillon de souvenirs récupérés et les évaluent en fonction de leur ancienneté, de leurs contradictions et de leur sensibilité. Intégrez les échecs dans le filtre d’écriture. Les souvenirs subissent des dérives comme n’importe quel ensemble de données ; sans audits, ils deviennent silencieusement de la fiction que le modèle prend pour un fait. Allouez du temps d’ingénierie à cette organisation de manière similaire à celle que vous consacrez aux mises à jour d’embedding, car toutes deux protègent la qualité des réponses de façons que seuls les ajustements des prompts ne peuvent pas assurer.
Lorsque ces pratiques sont en place, l’élargissement des fenêtres de contexte devient un complément plutôt qu’un substitut : la fenêtre gère le tour en temps réel, tandis que le stock externe s’occupe de tout ce qui doit survivre au-delà de cette fenêtre. Cette division du travail constitue la leçon essentielle pour créer des agents fiables sur plusieurs semaines, et non seulement pour quelques messages.