2 Data Flow 03 Memory Consolidation
Blightbow edited this page 2025-12-09 04:34:35 -05:00

Data Flow 03: Memory Consolidation (Sleep Phase)

Engineering documentation series - Data flows in the AI Assistant system


Overview

Memory consolidation occurs during sleep mode, transforming short-term observations into long-term knowledge. The system implements concepts from A-MEM, O-MEM, and Generative Agents research.

Document Description
Data-Flow-01-Context-Compaction Context trimming during dreaming
Data-Flow-05-Entity-Profile-System Entity memory structure

1. Sleep Mode Architecture

Two-Phase Model

┌─────────────────────────────────────────────────────────────────────────────┐
│ SLEEP MODE PHASES                                                           │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ Phase 1: COMPACTING                                                         │
│   - Journal → Mem0 semantic memory consolidation                            │
│   - LLM importance scoring for pending entries                              │
│   - Wake deferred (protect consolidation)                                   │
│                                                                             │
│ Phase 2: DREAMING                                                           │
│   - A-MEM style memory link generation                                      │
│   - Entity observation consolidation (O-MEM)                                │
│   - Generative reflection (Park et al.)                                     │
│   - Episodic pruning                                                        │
│   - Context compaction                                                      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

2. Sleep Tick Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│ SLEEP TICK START                                                            │
│ rag_memory.py:run_sleep_tick() line 960                                     │
│ Triggered by: assistant_script.py:at_tick() when operating_mode == "sleep"  │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                    ┌───────────────┴───────────────┐
                    │       PHASE CHECK             │
                    └───────────────────────────────┘
                                    │
            ┌───────────────────────┼───────────────────────┐
            ▼                       │                       ▼
┌───────────────────────┐           │           ┌───────────────────────┐
│ COMPACTING PHASE      │           │           │ DREAMING PHASE        │
│ (memory_enabled)      │           │           │                       │
└───────────────────────┘           │           └───────────────────────┘
            │                       │                       │
            ▼                       │                       ▼
┌───────────────────────┐           │           ┌───────────────────────┐
│ 1. score_pending_     │           │           │ 1. run_dreaming_tick  │
│    entries()          │           │           │    (link generation)  │
│    LLM importance     │           │           │                       │
│    scoring            │           │           │ 2. prune_orphaned_    │
│                       │           │           │    memory_links()     │
│ 2. run_sleep_         │           │           │                       │
│    consolidation()    │           │           │ 3. entity_            │
│    Journal → Mem0     │           │           │    consolidation      │
│                       │           │           │    (O-MEM style)      │
│ 3. If complete:       │           │           │                       │
│    transition to      │           │           │ 4. run_reflection()   │
│    dreaming           │           │           │    (if triggered)     │
└───────────────────────┘           │           │                       │
                                    │           │ 5. prune_low_         │
                                    │           │    importance_entries │
                                    │           │                       │
                                    │           │ 6. clear_stale_       │
                                    │           │    conversations      │
                                    │           │                       │
                                    │           │ 7. compact_           │
                                    │           │    conversation_      │
                                    │           │    history()          │
                                    │           └───────────────────────┘

3. Compacting Phase Operations

3.1 Importance Scoring

┌─────────────────────────────────────────────────────────────────────────────┐
│ IMPORTANCE SCORING                                                          │
│ importance_scoring.py:score_pending_entries()                               │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ Input: Journal entries with heuristic scores (1-10)                         │
│ Output: Journal entries with LLM-refined scores                             │
│                                                                             │
│ Process:                                                                    │
│   1. Find entries with scoring_method == "heuristic"                        │
│   2. Batch entries for LLM scoring                                          │
│   3. LLM evaluates importance (1-10) based on:                              │
│      - Relevance to assistant's goals                                       │
│      - Novelty of information                                               │
│      - Potential future utility                                             │
│   4. Update scoring_method to "llm"                                         │
│                                                                             │
│ Heuristic scoring (immediate):                                              │
│   - Direct messages: +3                                                     │
│   - @mentions: +2                                                           │
│   - Keywords (goal, quest, name): +1 each                                   │
│   - Sender importance bonus                                                 │
│                                                                             │
│ LLM scoring (sleep phase):                                                  │
│   - Full context evaluation                                                 │
│   - Multi-entry batch processing                                            │
│   - More accurate for consolidation decisions                               │
└─────────────────────────────────────────────────────────────────────────────┘

3.2 Sleep Consolidation

┌─────────────────────────────────────────────────────────────────────────────┐
│ SLEEP CONSOLIDATION                                                         │
│ rag_memory.py:run_sleep_consolidation()                                     │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ Source: character.db.journal["entries"]                                     │
│ Destination: Mem0 semantic memory                                           │
│                                                                             │
│ Process:                                                                    │
│   1. Get unconsolidated entries (not in consolidated_entry_ids)             │
│   2. Filter by min_importance threshold                                     │
│   3. Extract facts via LLM (ASSISTANT_FACT_EXTRACTION_PROMPT)               │
│   4. Store in Mem0: yield mem0_client.add(...)                              │
│   5. Create memory links (journal_id ↔ mem0_id)                             │
│   6. Mark entries as consolidated                                           │
│                                                                             │
│ Persona Protection (critical):                                              │
│   ASSISTANT_FACT_EXTRACTION_PROMPT filters out:                             │
│   - Self-references ("I helped", "The assistant said")                      │
│   - Personality information                                                 │
│   - Only extracts world facts, user facts, events                           │
│                                                                             │
│ Memory Link Structure (character.db.memory_links):                          │
│   {                                                                         │
│     "journal_id_abc": ["mem0_id_1", "mem0_id_2"],                            │
│     "mem0_id_1": {"linked_to": ["journal_id_abc"], "created": "..."},       │
│   }                                                                         │
└─────────────────────────────────────────────────────────────────────────────┘

4. Dreaming Phase Operations

┌─────────────────────────────────────────────────────────────────────────────┐
│ MEMORY LINK GENERATION                                                      │
│ rag_memory.py:run_dreaming_tick()                                           │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ A-MEM Concept: Associate related memories to strengthen recall              │
│                                                                             │
│ Process:                                                                    │
│   1. Select recent high-importance memories                                 │
│   2. Query Mem0 for semantically similar memories                           │
│   3. Create bidirectional links between related memories                    │
│   4. Links improve retrieval during recall                                  │
│                                                                             │
│ Link scoring factors:                                                       │
│   - Semantic similarity                                                     │
│   - Temporal proximity                                                      │
│   - Entity overlap                                                          │
└─────────────────────────────────────────────────────────────────────────────┘

4.2 Entity Consolidation (O-MEM Style)

┌─────────────────────────────────────────────────────────────────────────────┐
│ ENTITY CONSOLIDATION                                                        │
│ helpers.py:run_entity_consolidation_batch()                                 │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ O-MEM Concept: Consolidate observations (Pf) into attributes (Pa)           │
│                                                                             │
│ Source: character.db.entity_profiles[entity_id]["observations"]             │
│ Destination: character.db.entity_profiles[entity_id]["attributes"]          │
│                                                                             │
│ Process:                                                                    │
│   1. Find entities with >= min_observations (default 5)                     │
│   2. For each entity, send observations to LLM                              │
│   3. LLM synthesizes stable knowledge:                                      │
│      - Confirmed facts (personality, preferences)                           │
│      - Relationship patterns                                                │
│      - Behavioral traits                                                    │
│   4. Add synthesized attributes to profile                                  │
│   5. Optionally prune old observations                                      │
│                                                                             │
│ Example transformation:                                                     │
│   Observations:                                                             │
│     - "Alice mentioned she prefers tea over coffee"                         │
│     - "Alice ordered tea at the tavern"                                     │
│     - "Alice refused the coffee I offered"                                  │
│   Attribute:                                                                │
│     - {type: "preference", value: "Prefers tea, dislikes coffee"}           │
└─────────────────────────────────────────────────────────────────────────────┘

4.3 Generative Reflection

┌─────────────────────────────────────────────────────────────────────────────┐
│ GENERATIVE REFLECTION                                                       │
│ generative_reflection.py:run_reflection()                                   │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ Park et al. (2023): Higher-level insights from accumulated experiences      │
│                                                                             │
│ Trigger: cumulative_importance >= threshold (default 150)                   │
│   - Each journal entry adds its importance score                            │
│   - Resets after reflection                                                 │
│                                                                             │
│ Process:                                                                    │
│   1. Gather recent high-importance entries                                  │
│   2. LLM generates reflection questions:                                    │
│      - "What patterns do I notice?"                                         │
│      - "What have I learned about [entity]?"                                │
│   3. LLM answers questions based on memories                                │
│   4. Store insights in journal with high importance (8-9)                   │
│   5. Reset cumulative importance counter                                    │
│                                                                             │
│ Output: Higher-level insights that inform future behavior                   │
│   - Relationship assessments                                                │
│   - Goal progress evaluations                                               │
│   - Behavioral pattern recognition                                          │
└─────────────────────────────────────────────────────────────────────────────┘

4.4 Cleanup Operations

┌─────────────────────────────────────────────────────────────────────────────┐
│ CLEANUP OPERATIONS                                                          │
│ ─────────────────────────────────────────────────────────────────────────── │
│                                                                             │
│ 1. prune_orphaned_memory_links()                                            │
│    - Remove links to deleted Mem0 memories                                  │
│    - Maintain referential integrity                                         │
│                                                                             │
│ 2. prune_low_importance_entries()                                           │
│    - Remove old entries with importance <= 3                                │
│    - Age threshold: 30 days default                                         │
│    - Preserves consolidated entries                                         │
│                                                                             │
│ 3. clear_stale_conversations()                                              │
│    - Remove inactive working memory contexts                                │
│    - Age threshold: 1 hour default                                          │
│                                                                             │
│ 4. compact_conversation_history()                                           │
│    - See Data-Flow-01 for details                                           │
│    - Summarizes old messages when >= 70% context                            │
└─────────────────────────────────────────────────────────────────────────────┘

5. Memory Storage Locations

Storage Location Purpose Persistence
Journal character.db.journal["entries"] Episodic memory, raw experiences Persistent
Mem0 External semantic DB Long-term facts, searchable Persistent
Entity Profiles character.db.entity_profiles Per-entity knowledge Persistent
Working Memory character.db.working_memory Active conversation context Persistent
Memory Links character.db.memory_links Journal ↔ Mem0 associations Persistent
Conversation History script.db.conversation_history LLM context window Compacted

6. Key Files

File Purpose
rag_memory.py:960-1131 run_sleep_tick() main orchestrator
rag_memory.py:run_sleep_consolidation() Journal → Mem0
rag_memory.py:run_dreaming_tick() A-MEM link generation
helpers.py:run_entity_consolidation_batch() O-MEM consolidation
generative_reflection.py Park et al. reflection
importance_scoring.py LLM importance scoring

Document created: 2025-12-06