Repository navigation
Mina AI Memory System
The Mina AI Memory System provides the AI with long-term conversational memory, enabling it to recall user preferences, facts, and past interactions to create a more personalized and context-aware experience. The system is designed to automatically extract salient information from conversations, store it efficiently, and retrieve it semantically when relevant to a new conversation.
This system utilizes a hybrid storage approach: metadata and conversational context are stored in a MongoDB collection, while semantic vectors for fast retrieval are stored in an Upstash Vector database. User-facing commands allow for viewing and deleting personal memories, ensuring user privacy and control.
Relevant source files
The memory system is primarily driven by the MemoryService, which orchestrates the extraction, storage, and recall processes. It integrates with the AiResponderService to analyze conversations and inject recalled memories back into the AI's prompt context.
The following diagram illustrates the high-level data flow of the memory system.
graph TD
subgraph "User Interaction"
A[User Message]
end
subgraph "AiResponderService"
B[Should Respond?]
C[Handle Message]
D[Recall Memories]
end
subgraph "Memory Lifecycle"
E[Generate AI Response]
F[Extract Memories]
G[Store Memories]
end
subgraph "Data Stores"
H[Upstash Vector]
I[MongoDB 'ai-memory']
end
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
G --> I
The system uses two data stores: MongoDB for persistent metadata and Upstash Vector for semantic search.
All memory metadata is stored in the ai-memory collection in MongoDB. This schema defines the structure of a single memory entry.
Sources: src/database/schemas/AiMemory.ts:5-24
The diagram below shows the entity relationship for the ai-memory schema.
erDiagram
ai-memory {
string userId FK "Index"
string guildId FK "Index"
string memoryType "Enum, Index"
string key
string value
string context
number importance
string vectorId "Unique"
datetime lastAccessedAt "Index"
number accessCount
datetime createdAt
datetime updatedAt
}
The table below details the fields in the ai-memory schema.
| Field | Type | Description | Constraints |
|---|---|---|---|
userId |
String | The Discord user ID this memory belongs to. | Required, Indexed |
guildId |
String | The Discord guild ID where the memory was created. null for DMs. |
Indexed |
memoryType |
String | The category of the memory. | Enum: user, guild, topic. Default: user. Indexed. |
key |
String | A short, descriptive key for the memory (e.g., "Favorite Color"). | Required |
value |
String | The value of the memory (e.g., "Blue"). | Required |
context |
String | A snippet of the conversation that led to this memory's creation. | Default: '' |
importance |
Number | A score from 1-10 indicating the memory's importance. | Default: 5, Min: 1, Max: 10 |
vectorId |
String | The unique identifier for the corresponding vector in Upstash. | Required, Unique |
lastAccessedAt |
Date | Timestamp of the last time this memory was recalled. | Default: Date.now()
|
accessCount |
Number | How many times this memory has been recalled. | Default: 0 |
timestamps |
Boolean | Automatically adds createdAt and updatedAt fields. |
Mongoose option |
Sources: src/database/schemas/AiMemory.ts:5-24
The MemoryService uses Upstash Vector for fast, semantic searching of memories.
- When a memory is stored, its content (
keyandvalue) is converted into a numerical vector (embedding) using google'sembedding-001model. - This vector is stored in upstash, indexed by a unique
vectorid. - When recalling memories, the user's current message is also converted into a vector, which is then used to query upstash for the most semantically similar (i.e., relevant) memory vectors.
Sources: src/services/memoryService.ts:18-32, src/services/memoryService.ts:133-149, src/services/memoryService.ts:192-201
Memories are automatically extracted from conversations that are sufficiently long (at least 5 messages). The AiResponderService triggers this process after generating a response.
This diagram shows the sequence of events for extracting memories from a conversation. Sources: src/services/aiResponder.ts:680-708, src/services/memoryService.ts:49-110
The extractMemories function in MemoryService uses the gemini-flash-latest model with a specific prompt to analyze the last 10 messages of a conversation and return a JSON array of MemoryFact objects.
Once a fact is extracted, the storeMemory function handles saving it to both databases.
-
Generate Embedding: An embedding is created from the fact's
keyandvalueusing theembedding-001model. -
Generate Vector ID: A unique ID is created (e.g.,
mem_<userId>_<guildId>_<timestamp>). - Upsert to Upstash: The vector and associated metadata are saved to the Upstash Vector index.
-
Save to MongoDB: The full memory object, including the
vectorId, is saved to theai-memorycollection. -
Enforce Limits: The system checks if the user has exceeded the
MAX_MEMORIES_PER_USER(50) limit for the given context (guild or DM). If so, the oldest, least important memories are deleted from both MongoDB and Upstash.
Sources: src/services/memoryService.ts:115-184, src/database/schemas/AiMemory.ts:103-124
When a user sends a message, AiResponderService calls memoryService.recallMemories to find relevant information before generating a response.
This flowchart outlines the process of recalling memories to add context to an AI response. Sources: src/services/aiResponder.ts:488-531, src/services/memoryService.ts:189-282
The filtering logic is crucial and respects user privacy settings:
-
combineDmWithServer: If true, memories from both DMs and servers can be recalled together. If false, they are kept separate. -
globalServerMemories: If true (default), memories from any server are recalled. If false, only memories from the current server are considered.
Sources: src/services/memoryService.ts:211-257
The system provides several ways to delete memories:
-
User-Initiated Deletion: The
forgetUserfunction is called by the/mina-ai forget-mecommand handler. It fetches all of a user's memories for a given context, gets theirvectorIds, and deletes them from both Upstash and MongoDB. -
Limit-Based Pruning: The
deleteOldestMemoriesfunction is triggered during storage if a user exceeds theMAX_MEMORIES_PER_USERlimit. It deletes the oldest memories, preserving the most important ones. -
Automatic Pruning: The
pruneOldMemoriesfunction is designed to periodically clean up old, unimportant, and rarely accessed memories (older than 90 days, importance <= 3, access count <= 2).
Sources: src/services/memoryService.ts:287-310, src/handlers/minaai/forget-me.ts:51-54, src/services/memoryService.ts:402-419
Users interact with the memory system primarily through the /mina-ai command and its sub-handlers.
Sources: src/handlers/minaai/main-hub.ts
The memories command, handled by src/handlers/minaai/memories.ts, provides a detailed interface for users to view what Mina remembers about them.
-
Main View (
showMemoriesView):- Displays memories grouped by type (e.g.,
preference,fact,opinion). - Shows a preview of the top 2 memories per type.
- Provides statistics like total memories, total access count, and average importance.
- Includes buttons to navigate to a detailed category view.
- Displays memories grouped by type (e.g.,
-
Category Detail View (
showCategoryDetailView):- Lists all memories for a selected type.
- Supports pagination (up to 2 pages, 5 memories per page).
-
DM Me (
handleDmMe):- If a user has a large number of memories, they can use this button.
- It generates a full, detailed list of all their memories, posts it to a pastebin service (
posttobin), and dms the user a link.
Sources: src/handlers/minaai/memories.ts:30-496
The forget-me option in the settings menu allows a user to permanently delete all memories Mina has about them in the current context (server or DM).
- A confirmation screen is shown to prevent accidental deletion (
showforgetmeconfirmation). - If confirmed,
handleforgetmeconfirmcallsmemoryservice.forgetuser. - It also automatically enables the
ignoremesetting for the user, so the AI will stop interacting with them until they re-enable it.
Sources: src/handlers/minaai/forget-me.ts:17-101
Developers have access to tools for monitoring and managing the AI's memory system.
The /dev mina-ai memory-stats command provides a comprehensive overview of the memory database.
-
Total Memories: Total count of documents in the
ai-memorycollection. - Unique Users/Guilds: Count of distinct users and guilds with stored memories.
-
Breakdown by Type: A count of memories for each
memoryType. - Top Users: A list of users with the most memories.
- Average Importance: The average importance score across all memories.
-
Total Access Count: The sum of
accessCountfor all memories.
This data is retrieved by the getStats method in MemoryService, which aggregates data from the MongoDB collection.
Sources: src/commands/dev/sub/minaAi.ts:284-345, src/services/memoryService.ts:315-381, src/handlers/dev/minaai/handlers.ts:200-230
The Mina AI Memory System is a sophisticated feature that significantly enhances the bot's conversational abilities. By combining the structured storage of MongoDB with the semantic search power of Upstash Vector, it can maintain long-term, contextually relevant memory. The system is built with user privacy in mind, offering clear interfaces for viewing and deleting personal data. Automated extraction and pruning ensure the memory remains relevant and manageable over time, making Mina a more intelligent and engaging companion.