From 1eb850423c7453d29e595fee1f35416d01ddc06b Mon Sep 17 00:00:00 2001 From: Luna Date: Tue, 3 Mar 2026 21:40:44 +0100 Subject: [PATCH] global memories --- .env.example | 2 ++ README.md | 1 + src/config.js | 1 + src/prompt.js | 2 +- 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 417f2e4..28147a8 100644 --- a/.env.example +++ b/.env.example @@ -17,6 +17,8 @@ SHORT_TERM_LIMIT=12 ENABLE_SHORT_TERM_SUMMARY=true # Number of short-term turns before an automatic summary request (default 12) SUMMARY_TRIGGER_TURNS=12 +# Enable global memory retrieval by default (set to false to scope per user) +ENABLE_GLOBAL_MEMORIES=true ENABLE_WEB_SEARCH=true OPENAI_API_KEY=your_openai_api_key # Memory retrieval cooldown (ms) before the same long-term entry can be reused diff --git a/README.md b/README.md index 8cd0caf..c7466fc 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,7 @@ okay - **Importance scoring:** Messages mentioning intent words ("plan", "remember", etc.), showing length, or emotional weight receive higher scores. When the store exceeds its cap, the lowest-importance/oldest memories are pruned. You can also call `pruneLowImportanceMemories()` manually if needed. - **Pattern-aware long-term recall:** Long-term memory is only queried when Nova detects a recall cue (`remember`, `do you know`, `we talked`, `refresh my memory`, etc.). When a cue fires, she fetches the top cosine-similar memories but only keeps the ones whose score meets `MEMORY_RECALL_SIMILARITY_THRESHOLD` (default 0.62); otherwise the conversation stays anchored on the short-term buffer and summary. This keeps memory-driven context from popping up during casual chat unless you explicitly ask for it. + - **Global recall:** `ENABLE_GLOBAL_MEMORIES` is true by default, so Nova now considers every user’s long-term memories (tagged with their `user_id`) whenever she runs recall logic. Set it to `false` only if you need strict per-user isolation again. - **What gets embedded:** After every user→bot turn, `recordInteraction()` (see [src/memory.js](src/memory.js)) bundles the pair, scores its importance, asks OpenAI for an embedding, and stores `{ content, embedding, importance, timestamp }` inside the SQLite tables. - **Why so many numbers:** Cosine similarity needs raw vectors to compare new thoughts to past ones. When a fresh message arrives, `retrieveRelevantMemories()` embeds it too, calculates cosine similarity against every stored vector, adds a small importance boost, and returns the top five memories to inject into the system prompt. - **Memory cooldown:** `MEMORY_COOLDOWN_MS` (defaults to 180000 ms) keeps a long-term memory out of the retrieval window for a few minutes after it was just used so Nova has to pull fresh context before repeating herself, while still falling back automatically if there isn’t anything new to surface. diff --git a/src/config.js b/src/config.js index 28811c5..dab6fc5 100644 --- a/src/config.js +++ b/src/config.js @@ -53,6 +53,7 @@ export const config = { : 0.62, memoryRecallTriggerPatterns, relevantMemoryCount: 3, + enableGlobalMemories: process.env.ENABLE_GLOBAL_MEMORIES !== 'false', longTermFetchLimit: 120, // Optional local dashboard that runs alongside the bot. Enable with // `ENABLE_DASHBOARD=true` and customize port with `DASHBOARD_PORT`. diff --git a/src/prompt.js b/src/prompt.js index 10f9c88..e0ca3f5 100644 --- a/src/prompt.js +++ b/src/prompt.js @@ -93,8 +93,8 @@ export async function buildPrompt(userId, incomingText, options = {}) { blockedSearchTerm = null, searchOutage = null, context: providedContext = null, - useGlobalMemories = false, userName = null, + useGlobalMemories = config.enableGlobalMemories, includeMemories = false, similarityThreshold = null, } = options;