Architecture Memory OS : Des paradoxes de raisonnement aux graphes de mémoire hiérarchiques
Les modèles puissants comme o4-mini avec un reasoning_effort élevé rompent la rigidité des schémas lors de l'extraction d'objets structurés. Au lieu de respecter les schémas Pydantic, le modèle se met à « améliorer » la structure : fusion d'objets, modification des champs JSON, et flou des types de concepts. Des tests sur plus de 300 prompts ont révélé une relation inverse : plus de raisonnement entraîne moins de déterminisme.
SGR (Raisonnement guidé par schéma) avec response_format et StrictBase strict (extra='forbid', sans Optional/défaut) résout partiellement le problème, mais le modèle lutte encore contre les contraintes. L'introduction d'un Mappeur sémantique a réduit le reasoning_effort en déplaçant la discipline vers les contrats de données, la validation et le post-traitement.
Résultats :
- Coûts en tokens réduits de 48 % ;
- Qualité d'extraction passée de 5,2 à 7,11 ;
- Traçabilité complète via message_id.
Le validateur vérifie récursivement le schéma JSON : additionalProperties: false, tous les champs dans required. Cela sert de signal central pour la mémoire des agents : l'intelligence du LLM pendant l'extraction est dédiée à l'exécution du schéma, pas à la créativité.
Pourquoi le RAG plat échoue sur les grands ensembles de données et le passage à une mémoire gérée
Le RAG plat brille en démo mais s'effondre sur de gros corpus comme Jocker (3 253 conversations, 24 639 messages) : pas de lignée, pas de sémantique temporelle, ni de règles de mise à jour. La récupération extrait des chunks similaires sans liens source, menant à un Bourbier de graphe — des milliers de nœuds sans granularité (plus de 26 000 dans Jocker avant refactorisation).
La séparation des couches est essentielle :
- Récupération : top-k chunks similaires ;
- Mémoire : objets de connaissance, liens, changements temporels, révisions, dégradation.
Sans cela, le système se réduit à un index de chunks truffé d'hallucinations sur des requêtes complexes.
Ontologie de base : ConceptHypothesis comme citoyen de première classe
Nous partons d'une ontologie de base avec des objets typés et des relations. Fini les entités/summaries lâches, place à ConceptHypothesis :
from pydantic import BaseModel, ConfigDict, Field
from typing import List, Literal, Optional
from datetime import datetime
class StrictBase(BaseModel):
model_config = ConfigDict(extra="forbid")
class EvidenceSpan(StrictBase):
source_id: str
message_id: str
text: str
confidence: float
class ConceptRelation(StrictBase):
target_id: str
relation: Literal["causes", "conflicts_with", "supports", "instance_of", "enables"]
confidence: float
class ConceptHypothesis(StrictBase):
concept_id: str
title: str
type: Literal["behavioral_pattern", "project", "event", "tension", "goal", "belief", "entity"]
description: str
state: Literal["active", "weak", "merged", "split", "archived"]
confidence: float
aliases: List[str]
evidence_spans: List[EvidenceSpan]
relations: List[ConceptRelation]
revision_count: int
first_seen: Optional[datetime]
last_seen: Optional[datetime]
Cet objet porte des spans d'évidence, des relations, une confiance et un compteur de révisions. Le raisonnement temporel (événements, contradictions) est de première classe, pas un sous-produit de chunks.
Contrats de données et staging : SQLite comme source unique de vérité
Les contrats de données verrouillent la structure aux frontières du pipeline. SQLite fait office de source de vérité pour les messages (UUID, texte, rôle, parent_id, timestamp, conversation_id). Graphe Neo4j : nœuds comme Conversation/Message/Segment/Concept/Topic, arêtes comme HAS_MESSAGE/NEXT/CONTAINS_MESSAGE/EVIDENCE_FOR/BELONGS_TO.
La clé est EVIDENCE_FOR : les concepts lient directement à l'évidence au niveau message. Le squelette chronologique NEXT/PREVIOUS accélère l'inférence sans tri en base.
Base de staging (SQLite séparée) conserve les états intermédiaires du pipeline pour une auditabilité totale.
Boucle de mémoire conceptuelle et clustering de sujets
Boucle de mémoire conceptuelle : créer/attacher/raffiner/rejeter — le cycle de gestion d'hypothèses. Clustering de sujets via UMAP + HDBSCAN + Optuna pour des liens pondérés évite la sur-compression et l'explosion de concepts.
LongMemEval et inférence multi-agents stateful
LongMemEval (plus de 100 M de tokens) : 4 phases de debug, Exploration vs Exécution. Multi-agents stateful : Planificateur/Éclaireur/Synthétiseur pour récupération hiérarchique.
Jardinier agentique, invalidation et MCP
Jardinier agentique — pipeline dédié à l'entretien du graphe. Invalidation/réparation pour faits bi-temporels. MCP — interface mémoire souveraine.
Échelle : 106,7 M de tokens, 632 868 unités sémantiques, 2,4 M d'arêtes.
Points clés :
- Un raisonnement élevé casse le SGR ; utilisez un mappeur sémantique et un effort faible ;
- RAG plat → Bourbier de graphe ; exigez des spans d'évidence et une ontologie temporelle ;
- ConceptHypothesis avec Pydantic StrictBase — base pour une compression gérée ;
- SQLite comme source de vérité + Neo4j pour lignée et chronologie ;
- Multi-agents + Jardinier pour une échelle de 100 M+ de tokens.
— Editorial Team
Aucun commentaire pour le moment.