Memory Search and Management ============================ This page describes how Synthetic Heart looks up stored memories, prepares them for the prompt, and manages memory-related context during prompt construction. This is a developer-focused explanation of the internal memory pipeline, not the public `memory_search` action plugin. How memory search is triggered ----------------------------- Memory search in the JSON prompt builder is triggered by tags extracted from the incoming message text. - `core.prompt_engine.build_json_prompt()` extracts tags from `message.text`. - Tags are expanded with `core.synth_tagging.expand_tags()`. - If expanded tags exist, `core.synth_core_memory.search_memories()` is called. The prompt builder passes: - `tags=expanded_tags` - `limit=max(1, mem_limit)` where `mem_limit` is derived from `CONTEXT_VERBOSITY`. - `include_chat=True` so the search may also include recent chat history hits. Search pipeline and query behavior ---------------------------------- `core.synth_core_memory.search_memories()` performs a unified search across three sources: 1. `memories` table 2. `ai_diary` table 3. `chat_history_cache` table (only when `include_chat=True`) Search rules: - Tag searches use `JSON_CONTAINS(tags, %s)` for the `memories` and `ai_diary` tables. - Keyword searches use SQL `LIKE` on text fields. - Chat history search also uses `LIKE` on cached message text. - A large internal `pool_limit` is used to prefetch extra results before deduplication. Result normalization: - Each hit is returned as a normalized dictionary: `{"source", "id", "timestamp", "snippet", "tags"}`. - Snippets are truncated to 400 characters for prompt efficiency. - Tags are deserialized from stored JSON where available. - Chat history hits use an empty `tags` list. Deduplication and ordering -------------------------- After collecting hits from all sources, `search_memories()` deduplicates them by `source`, `id`, and snippet prefix. The remaining results are sorted by timestamp descending and trimmed to the requested `limit`. How memories are injected into the prompt ----------------------------------------- Search results are passed back into `build_json_prompt()` as the `memories` argument. `core.history_engine.HistoryEngine.build_context()` is responsible for adding those memory hits into the final `context` section: - `context["memories"]` is included only when `ENABLE_MEMORIES` is enabled. - In normal mode, the number of memories included is capped by `CONTEXT_VERBOSITY`. - In `PROMPT_LITE_MODE`, the cap is lower: `min(verbosity, 2)`. This means the prompt contains a small, curated list of memory recall results alongside chat history and other context contributions. Memory config flags and behavior toggles ---------------------------------------- Key configuration flags affecting memory and history: - `ENABLE_MEMORIES` — whether memory search results are included in prompt context. - `CONTEXT_VERBOSITY` — how many history-like items are allowed in prompt context, including memories. - `UNIFIED_HISTORY` — whether chat streams are merged across interfaces. - `PROMPT_LITE_MODE` — aggressively minimizes prompt size and reduces memory counts. - `ENABLE_HISTORY_CURRENT_CHAT` / `ENABLE_HISTORY_RECENT` — include current chat or recent chat history. - `ENABLE_AI_DIARY` / `AI_DIARY_FULL` — include AI diary entries and control whether full diary content is preserved. - `ENABLE_THOUGHTS` — include separate diary thought summaries. - `ENABLE_TAGS_PLACEHOLDER` — include an empty `tags_placeholder` list for future multi-step or tag-based flows. Memory management internals --------------------------- Synthetic Heart also contains an internal memory save pipeline in `core.synth_core_memory.py`: - `should_remember(user_text, response_text)` decides whether an interaction is worth storing. - `silently_record_memory()` saves the interaction via `core.db.insert_memory()`. - These stored memories are not exposed directly to users; they are an internal recall mechanism. The memory storage path is separate from the prompt search path, but the same `memories` table is used for recall results. Developer notes --------------- - The prompt-side memory search is part of the JSON prompt construction flow, not the same as the `memory_search` plugin action. - The relevant sources are: - `core.prompt_engine.build_json_prompt` - `core.synth_core_memory.search_memories` - `core.history_engine.HistoryEngine.build_context` - Any changes to `context.memories` or memory result normalization should be coordinated with prompt reduction logic in `core.prompt_engine.reduce_prompt_for_llm_limit()`. See also -------- - `docs/prompt_engine_json_prompt.rst` - `core.synth_core_memory.py` - `core.history_engine.py` - `core.prompt_engine.py`