Distinction entre ReAct Memory et Conversation Memory
Dans un agent conversationnel basé sur `ReActAgent` de `llama_index`, il est essentiel de distinguer deux types de mémoire bien distincts. Cette séparation permet de structurer proprement l’architecture des traitements et d’éviter toute confusion entre raisonnement interne et historique utilisateur.
ReAct Memory : mémoire de raisonnement
Également appelée "Mémoire ReAct".
Définition : mémoire temporaire utilisée pendant le traitement d’une requête unique.
Contenu :
– La question de l’utilisateur
– Les `Thoughts` (raisonnements internes)
– Les `Actions` (outils appelés)
– Les `Observations` (résultats des actions)
– La `Final Answer`
Cycle de vie : réinitialisée à chaque nouvelle question.
Stockage : dans `state["intermediate_steps"]` ou `AgentChatResponse.intermediate_steps`.
Remarque : cette mémoire est volatile et ne doit pas être confondue avec l’historique de conversation.
Conversation Memory : mémoire de conversation
Également appelée "Mémoire conversationnelle", "Chat memory", "History".
Définition : mémoire persistante des échanges utilisateur ↔ assistant, gérée par l’application appelante.
Contenu :
– Les messages de l’utilisateur (`role="user"`)
– Les réponses de l’agent (`role="assistant"`)
Cycle de vie : maintenue entre les requêtes, sauvegardée par l’application (fichier, base, buffer).
Stockage : via un objet comme `ChatMemoryBuffer`, ou une base externe. L’instance est souvent nommée "chat_memory".
Utilisation : pour injecter du contexte dans les prompts, suivre le fil de la discussion, ou adapter les réponses.
Comparaison synthétique
| Type de mémoire | Portée | Contenu | Persistée | Gérée par |
| ReAct Memory | Intra-requête | Thoughts, actions, obs | Non | ReActAgent |
| Conversation Memory | Inter-requête | Messages utilisateur ↔ assistant | Oui | Application |
Nos bonnes pratiques
– Utiliser le bon vocabulaire pour le nommage des fonctions et des variables.
– Ne jamais injecter les `intermediate_steps` dans le prompt utilisateur.
– Gérer la mémoire de conversation séparément, via un buffer ou une base.
– Injecter dynamiquement les derniers tours dans le prompt si besoin de contexte.
– Encapsuler les accès mémoire dans des méthodes dédiées (`get_history`, `update_memory`, etc.).
– Tracer les deux types de mémoire indépendamment pour audit ou debug.
Faut-il persister la ReAct Memory ?
Dans la logique ReAct classique, la mémoire de raisonnement est temporaire : elle est reconstruite à chaque requête, puis oubliée. Cela garantit un raisonnement frais et indépendant.
Mais dans certains cas — comme une série de questions sur un même objet — il peut être judicieux de persister certains résultats intermédiaires pour éviter des appels redondants à des outils.
Cas typique : résolution d’entité
Supposons que l’on pose plusieurs questions sur une entité nommée "Acme Corp". À chaque tour, ReAct doit :
– Identifier l’entité
– Résoudre son ID via un outil
– Appeler un outil avec cet ID qui retournera les données de l’entité
Sans mémoire persistante, l’agent répète ces étapes à chaque tour.
Stratégie : extraire et stocker les résultats utiles
Il faut inspecter les `intermediate_steps` après chaque appel, et en extraire les données pertinentes
Puis injecter ce contexte dans la requête suivante :
Conclusion
La ReAct Memory n’est pas conçue pour être persistée dans son ensemble — mais certains résultats extraits peuvent l’être, pour optimiser les performances et enrichir le contexte. Il suffit de les transférer dans une mémoire de travail (`state["context"]`) ou un outil à cache, selon l’architecture.
Mais il ne faut pas l’intégrer dans Conversation Memory , sous peine de joindre au prompt utilisateur des résultats hors contexte.