
Un agent conversationnel oublie tout d'une session à l'autre : sa seule mémoire est la fenêtre de contexte du modèle, perdue dès la conversation terminée. Pour un assistant censé connaître ses utilisateurs, c'est rédhibitoire. Ce guide donne à un agent une mémoire persistante. Vous verrez d'abord pourquoi la fenêtre de contexte ne suffit pas, puis les deux étages de mémoire : la mémoire court terme d'une session — buffer, résumé — et la mémoire long terme stockée dans une base vectorielle. Vous construirez ensuite un agent à mémoire avec Mem0 et Qdrant : il retient les préférences d'un utilisateur et les retrouve même après un redémarrage. Public visé : développeur ayant construit des agents et voulant les rendre persistants.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Pourquoi la fenêtre de contexte ne tient pas lieu de mémoire.
- La mémoire court terme d'une session : buffer brut et résumé.
- La mémoire long terme sur base vectorielle, et son lien avec le RAG.
- Construire un agent à mémoire avec Mem0 et Qdrant.
- Les stratégies de compaction et d'oubli.
Prérequis
Section intitulée « Prérequis »- Avoir construit un agent conversationnel ou un chatbot.
- Docker pour faire tourner Qdrant.
- Une instance Ollama avec
qwen2.5et le modèle d'embeddingnomic-embed-text. - Python 3.10+.
Le problème : la fenêtre de contexte
Section intitulée « Le problème : la fenêtre de contexte »Un modèle de langage est sans état. Entre deux appels, il ne retient rien : la seule chose qu'il « connaît » d'une conversation, c'est ce qu'on lui renvoie à chaque requête — l'historique des messages. Cet historique tient dans la fenêtre de contexte, la quantité de texte que le modèle peut traiter d'un coup.
Cette fenêtre a deux limites. Elle est bornée : une longue conversation finit par déborder, et il faut couper. Et elle est éphémère : quand la session se termine, l'historique disparaît. Rouvrir l'application, c'est repartir de zéro — l'agent ne se souvient ni de votre nom, ni de vos préférences, ni de ce qu'on a réglé hier.
Une vraie mémoire d'agent se construit donc à côté du modèle, sur deux étages : une mémoire court terme qui gère la session en cours, et une mémoire long terme qui survit aux sessions.
Mémoire court terme : buffer et résumé
Section intitulée « Mémoire court terme : buffer et résumé »La mémoire court terme, c'est la gestion de la conversation en cours. Deux stratégies, selon la longueur de l'échange.
Le buffer garde l'historique brut : tous les messages, tels quels. Simple et fidèle, c'est le bon choix tant que la conversation tient dans la fenêtre de contexte. C'est exactement ce que faisait le chatbot Chainlit du guide précédent.
Le résumé prend le relais quand l'échange s'allonge. Plutôt que de tout garder, on demande au modèle de condenser les tours anciens en un paragraphe, qu'on conserve à la place du détail. La conversation reste dans la fenêtre, au prix d'une perte de précision sur le passé. Buffer pour les détails récents, résumé pour le contexte ancien : les deux se combinent souvent.
Mémoire long terme : le vector store
Section intitulée « Mémoire long terme : le vector store »La mémoire long terme répond à l'autre limite : la persistance entre les sessions. Le principe : extraire les faits marquants d'une conversation et les ranger dans un magasin durable, indépendant du processus.
Ce magasin est une base vectorielle. Chaque fait y est stocké avec son embedding — sa représentation numérique, qui capture le sens. Pour retrouver un souvenir, on ne cherche pas par mot-clé exact mais par similarité sémantique : la question « quel langage j'aime ? » retrouve le fait « préfère coder en Python », même sans mot commun.
Construire un agent à mémoire avec Mem0
Section intitulée « Construire un agent à mémoire avec Mem0 »Écrire à la main l'extraction des faits, leur vectorisation et leur stockage serait long. Mem0 est une bibliothèque dédiée qui fait tout cela : elle distille les faits d'une conversation, les vectorise et les range dans une base vectorielle — ici Qdrant.
Mem0 assemble trois briques, déclarées dans une configuration : un LLM pour extraire les faits, un embedder pour les vectoriser, un vector store pour les conserver. Les trois pointent vers des services locaux.
CONFIG = { "llm": { "provider": "ollama", "config": {"model": "qwen2.5", "ollama_base_url": "http://localhost:11434"}, }, "embedder": { "provider": "ollama", "config": {"model": "nomic-embed-text", "ollama_base_url": "http://localhost:11434", "embedding_dims": 768}, }, "vector_store": { "provider": "qdrant", "config": {"collection_name": "agent_memoire", "host": "localhost", "port": 6333, "embedding_model_dims": 768}, },}Deux modèles Ollama interviennent : un modèle de chat (qwen2.5) qui distille les faits, un modèle d'embedding (nomic-embed-text) qui les vectorise. Un point de vigilance : la dimension des vecteurs — 768 pour nomic-embed-text — doit être identique dans la config de l'embedder et dans celle de la collection Qdrant, sinon le stockage échoue.
from mem0 import Memory
def ouvrir_memoire() -> Memory: """Ouvre la mémoire Mem0 — Qdrant la rend persistante entre les runs.""" return Memory.from_config(CONFIG)Mémoriser et rappeler
Section intitulée « Mémoriser et rappeler »La mémoire s'utilise par deux opérations. add range les faits d'un échange ; search retrouve les souvenirs pertinents pour une question. Les deux sont toujours filtrées par user_id : chaque utilisateur a sa propre mémoire, jamais mélangée à celle d'un autre.
def memoriser(memoire, user_id, echange): """Range les faits marquants d'un échange dans la mémoire long terme.""" memoire.add(echange, user_id=user_id)
def repondre(memoire, user_id, question): """Répond à une question en s'appuyant sur la mémoire long terme.""" souvenirs = memoire.search(question, user_id=user_id, limit=5)["results"] contexte = "\n".join(f"- {s['memory']}" for s in souvenirs) # contexte est injecté dans le prompt système du modèle...Le scénario du lab le démontre. Lors d'une première session, l'utilisateur dit « je préfère coder en Python » : Mem0 en extrait le fait et le range dans Qdrant. Lors d'une seconde session — une instance Memory toute neuve, comme après un redémarrage —, la question « quel langage est-ce que je préfère ? » déclenche un search qui retrouve le fait dans Qdrant. L'agent répond « Python » : il se souvient, alors que rien n'a survécu en mémoire vive.
C'est tout l'intérêt du vector store : la mémoire ne vit pas dans le processus Python, mais dans Qdrant. Le processus peut redémarrer, l'agent garde son passé.
Compaction et oubli
Section intitulée « Compaction et oubli »Une mémoire qui ne fait que grossir finit par poser problème : trop de souvenirs, des recherches plus lentes, des faits périmés qui polluent les réponses. Une mémoire long terme se gère.
La compaction consiste à fusionner ou résumer des souvenirs redondants : dix échanges sur le même sujet peuvent se condenser en un fait synthétique. Mem0 applique déjà une forme de cela — il met à jour un fait existant plutôt que d'en empiler un quasi-identique.
L'oubli est l'autre face : retirer délibérément des souvenirs. Un fait peut devenir faux (« je travaillais sur Kubernetes » n'est plus vrai), ou simplement sans intérêt. Décider quoi oublier — par ancienneté, par pertinence, sur demande de l'utilisateur — fait partie de la conception d'un agent à mémoire. Une mémoire n'est utile que si elle reste juste.
Mem0 et Letta : les frameworks de mémoire
Section intitulée « Mem0 et Letta : les frameworks de mémoire »La mémoire d'agent est un sujet assez riche pour avoir ses frameworks dédiés.
Mem0 — utilisé ici — se concentre sur la couche mémoire : on la branche sur l'agent de son choix, quel que soit son framework. C'est une brique, pas un cadre complet.
Letta (anciennement MemGPT) va plus loin : c'est un framework d'agents construit autour de la mémoire, avec une gestion hiérarchique inspirée d'un système d'exploitation — l'agent décide lui-même ce qu'il garde en contexte et ce qu'il archive. Plus intégré, mais plus engageant.
Le choix suit le besoin : ajouter de la mémoire à un agent existant appelle une brique comme Mem0 ; concevoir un agent dont la mémoire est le cœur justifie un framework comme Letta.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
| Erreur de dimension au stockage | Embedder et collection Qdrant divergent | Aligner embedding_dims et embedding_model_dims |
Connection refused sur le port 6333 | Qdrant n'est pas démarré | Lancer le conteneur qdrant/qdrant |
Mem0 réclame d'installer ollama | Bibliothèque cliente absente | Installer le paquet ollama |
search ne retrouve rien | user_id différent entre add et search | Utiliser le même user_id partout |
| L'agent mélange deux utilisateurs | Recherche non filtrée | Toujours passer user_id à search |
À retenir
Section intitulée « À retenir »- Un modèle est sans état : la fenêtre de contexte est sa seule mémoire — bornée et éphémère.
- La mémoire court terme gère la session : buffer brut, ou résumé quand l'échange s'allonge.
- La mémoire long terme stocke des faits dans une base vectorielle, retrouvés par similarité sémantique.
- C'est la mécanique du RAG appliquée à l'historique de l'utilisateur.
- Mem0 fournit la couche mémoire ; Qdrant la rend persistante au-delà du processus.
- Une mémoire se gère : compaction des redondances, oubli des faits périmés.
Prochaines étapes
Section intitulée « Prochaines étapes »Pour aller plus loin
Section intitulée « Pour aller plus loin »- Documentation Mem0 — la référence de la bibliothèque et de sa configuration.
- Documentation Qdrant — la base vectorielle utilisée pour la persistance.