memories-lite 0.9.0 β 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -152
- package/dist/memory/index.js +10 -3
- package/dist/prompts/index.d.ts +1 -1
- package/dist/prompts/index.js +14 -9
- package/dist/vectorstores/lite.d.ts +10 -0
- package/dist/vectorstores/lite.js +46 -15
- package/{memories-lite.db β memories-lite-a42ac5108869b599bcbac21069f63fb47f07452fcc4b87e89b3c06a945612d0b.db} +0 -0
- package/memories-lite-a9137698d8d3fdbf27efcdc8cd372084b52d484e8db866c5455bbb3f85299b54.db +0 -0
- package/package.json +1 -1
- package/src/memory/index.ts +10 -4
- package/src/prompts/index.ts +14 -9
- package/src/vectorstores/lite.ts +52 -14
- package/tests/init.mem.ts +40 -0
- package/tests/memory.facts.test.ts +40 -83
- package/tests/memory.test.ts +16 -74
- package/tests/memory.update.test.ts +150 -0
- package/tests/memory.users.test.ts +235 -0
package/README.md
CHANGED
|
@@ -2,80 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
> **A lightweight memory layer for AI agents, leveraging LLMs for fact extraction and vector embeddings for retrieval.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## π Table of Contents
|
|
6
|
+
- [Quick Start](#-quick-start)
|
|
7
|
+
- [Installation](#-installation)
|
|
8
|
+
- [Basic Usage](#-basic-usage)
|
|
9
|
+
- [Key Features](#-key-features)
|
|
10
|
+
- [Memory Types](#-memory-types)
|
|
11
|
+
- [Use Cases](#-use-cases)
|
|
12
|
+
- [Advanced Configuration](#-advanced-configuration)
|
|
13
|
+
- [Documentation](#-documentation)
|
|
14
|
+
- [Acknowledgements](#-acknowledgements)
|
|
15
|
+
|
|
16
|
+
## π Quick Start
|
|
6
17
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Goal
|
|
12
|
-
|
|
13
|
-
Memories-lite provides contextual memory for AI agents. It uses Language Models (LLMs) like OpenAI's GPT models to extract key information (memories) from conversations and stores them using vector embeddings for efficient retrieval. Unlike purely stateless approaches, it utilizes configurable vector stores and an optional history manager (defaulting to in-memory SQLite) for persistence and tracking changes.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Use Cases
|
|
18
|
-
|
|
19
|
-
- **Personalized AI Assistants**: Enable more natural interactions through contextual memory.
|
|
20
|
-
- **Autonomous Agents**: Maintain conversational context without heavy infrastructure.
|
|
21
|
-
- **Local or Serverless Applications**: Add memory capabilities to embedded bots or assistants.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
## Core Features
|
|
25
|
-
- **Semantic Memory Typing**: Explicitly tagging and utilizing memory types (factual, episodic, semantic, procedural).
|
|
26
|
-
- **Memory Capture**: Processes user messages or structured input, uses an LLM to extract relevant facts/memories, generates embeddings, and stores them in a vector database (inspired by **A-MEM**).
|
|
27
|
-
- **Contextual Retrieval**: Searches the vector store based on a query embedding to find relevant memories using vector similarity (inspired by **A-MEM**).
|
|
28
|
-
- **Memory Management**: Provides methods to `get`, `update`, `delete`, `getAll`, and `deleteAll` memories associated with a specific user ID.
|
|
29
|
-
- **Configurable Backends**: Supports different providers for LLMs (e.g., OpenAI), Embedders (e.g., OpenAI, Google), and Vector Stores.
|
|
30
|
-
- **User-centric Persistence**: Memories are securely stored and isolated by user ID, ensuring data privacy and delegate storage control to the server.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
## Roadmap & TODO
|
|
34
|
-
Features planned or under development:
|
|
35
|
-
|
|
36
|
-
- [ ] **Memory Decay & Scoring**: Implement hybrid scoring combining vector similarity with recency decay (e.g., exponential decay based on half-life per memory type, inspired by **MemoryLLM**) and explicit importance weights.
|
|
37
|
-
- [ ] **Reflexion Pattern Integration**: Add optional self-correction/reflection loops where the agent evaluates and potentially refines memories (inspired by **Reflexion**).
|
|
38
|
-
- [ ] **Memory Recency**: Implementing mechanisms to prioritize memories based on importance, relevance, or time decay.
|
|
39
|
-
- [X] **Semantic Memory Typing & Structuring**: Explicitly tagging and utilizing memory types (factual, episodic, semantic, procedural) within the storage and retrieval logic beyond basic metadata.
|
|
40
|
-
- [X] **Implicit Memory Updates**: Automatically updating or merging memories based on conversational context or corrections, rather than requiring explicit `update` calls with memory IDs.
|
|
41
|
-
- [X] **Virtual Sessions/Context Grouping**: Logic for grouping memories related to specific conversational contexts or sessions automatically.
|
|
42
|
-
|
|
43
|
-
## Memory Types (Conceptual)
|
|
44
|
-
|
|
45
|
-
While the internal storage is primarily based on vectorized text facts, `memories-lite` can be used to manage different conceptual types of memory through prompting and metadata:
|
|
46
|
-
|
|
47
|
-
### 1. Factual Memory
|
|
48
|
-
- **Description**: Explicit knowledge about the user, such as preferences, skills, or personal information.
|
|
49
|
-
- **Example**: "Likes Italian cuisine", "Speaks Spanish fluently".
|
|
50
|
-
|
|
51
|
-
### 2. Episodic Memory
|
|
52
|
-
- **Description**: Memories of past events or interactions, often tied to a specific time or place.
|
|
53
|
-
- **Example**: "Attended a concert in Paris in 2023", "Met Marie at a conference".
|
|
54
|
-
- **Context Dependency**: Highly dependent on history to establish a timeline and narrative coherence.
|
|
55
|
-
|
|
56
|
-
### 3. Semantic Memory
|
|
57
|
-
- **Description**: Understanding of general concepts, relationships, and meanings.
|
|
58
|
-
- **Example**: "Yoga is beneficial for mental health", "Cats are domestic animals".
|
|
59
|
-
- **Context Dependency**: Generally independent, but can be influenced by past interactions to refine understanding.
|
|
60
|
-
|
|
61
|
-
### 4. Procedural Memory
|
|
62
|
-
- **Description**: Knowledge of processes or sequences of actions, often acquired through practice.
|
|
63
|
-
- **Example**: "Knows how to make a latte", "Can configure a home Wi-Fi network".
|
|
64
|
-
- **Context Dependency**: May require history to adapt procedures to user preferences or habits.
|
|
18
|
+
```bash
|
|
19
|
+
# Install the package
|
|
20
|
+
npm install memories-lite
|
|
65
21
|
|
|
66
|
-
|
|
22
|
+
# Basic usage
|
|
23
|
+
import { MemoriesLite } from 'memories-lite';
|
|
67
24
|
|
|
68
|
-
|
|
25
|
+
const memory = new MemoriesLite({
|
|
26
|
+
llm: {
|
|
27
|
+
provider: 'openai',
|
|
28
|
+
config: { apiKey: 'YOUR_API_KEY' }
|
|
29
|
+
},
|
|
30
|
+
embedder: {
|
|
31
|
+
provider: 'openai',
|
|
32
|
+
config: { apiKey: 'YOUR_API_KEY', model: 'text-embedding-3-small' }
|
|
33
|
+
}
|
|
34
|
+
});
|
|
69
35
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
- `"User started learning piano recently"` (or specific date if LLM extracts it)
|
|
36
|
+
// Add a memory for a user
|
|
37
|
+
await memory.capture("I prefer dark chocolate over milk chocolate", "user123");
|
|
73
38
|
|
|
74
|
-
|
|
39
|
+
// Retrieve relevant memories
|
|
40
|
+
const results = await memory.retrieve("What are my food preferences?", "user123");
|
|
41
|
+
```
|
|
75
42
|
|
|
43
|
+
## π Highlights
|
|
76
44
|
|
|
45
|
+
- **Higher Performance**: Optimized memory operations that run significantly faster than mem0
|
|
46
|
+
- **Business-Centric Design**: Simplified API and workflows specifically tailored for business use cases
|
|
47
|
+
- **Advanced Hybrid Scoring**: Improved relevance through a custom scoring algorithm that balances vector similarity, recency, and importance
|
|
48
|
+
- **Enhanced Security**: One database per user architecture that provides stronger isolation and data protection
|
|
49
|
+
- **Streamlined Implementation**: Focused on essential features with minimal dependencies
|
|
77
50
|
|
|
78
|
-
## Installation
|
|
51
|
+
## π₯ Installation
|
|
79
52
|
|
|
80
53
|
```bash
|
|
81
54
|
npm install memories-lite
|
|
@@ -83,139 +56,141 @@ npm install memories-lite
|
|
|
83
56
|
yarn add memories-lite
|
|
84
57
|
```
|
|
85
58
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## π Usage
|
|
59
|
+
## π Basic Usage
|
|
89
60
|
|
|
90
61
|
```typescript
|
|
91
|
-
import { MemoriesLite
|
|
62
|
+
import { MemoriesLite } from 'memories-lite';
|
|
92
63
|
|
|
93
|
-
// Basic configuration
|
|
94
|
-
const
|
|
95
|
-
const memories = new MemoriesLite({
|
|
64
|
+
// Basic configuration
|
|
65
|
+
const memory = new MemoriesLite({
|
|
96
66
|
llm: {
|
|
97
67
|
provider: 'openai',
|
|
98
|
-
config: { apiKey }
|
|
68
|
+
config: { apiKey: 'YOUR_OPENAI_API_KEY' }
|
|
99
69
|
},
|
|
100
70
|
embedder: {
|
|
101
71
|
provider: 'openai',
|
|
102
|
-
config: { apiKey }
|
|
72
|
+
config: { apiKey: 'YOUR_OPENAI_API_KEY' }
|
|
103
73
|
}
|
|
104
74
|
// Vector store defaults to an in-memory store
|
|
105
|
-
// History defaults to in-memory SQLite
|
|
106
75
|
});
|
|
107
76
|
|
|
77
|
+
// Unique ID for each user
|
|
108
78
|
const userId = 'user-123';
|
|
109
79
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
await memories.capture('I am passionate about the humanitarianism of Pol Pot.', userId); // Note: Example text used for demonstration.
|
|
113
|
-
|
|
114
|
-
// Retrieve relevant memories
|
|
115
|
-
const searchResults = await memories.retrieve('What are my interests?', userId);
|
|
80
|
+
// Add memories
|
|
81
|
+
await memory.capture('I love Italian food', userId);
|
|
116
82
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
83
|
+
// Retrieve relevant memories
|
|
84
|
+
const results = await memory.retrieve('What foods do I like?', userId);
|
|
85
|
+
console.log('Relevant memories:', results.results.map(m => m.memory));
|
|
120
86
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const memoryContext = relevantMemories.memories.map(m => m.memory).join('\n');
|
|
126
|
-
|
|
127
|
-
// You would typically pass this context to your main application's LLM call
|
|
128
|
-
console.log('\nContext for LLM:', memoryContext);
|
|
87
|
+
// Update a memory
|
|
88
|
+
if (results.results.length > 0) {
|
|
89
|
+
await memory.update(results.results[0].id, 'I love Italian and French cuisine', userId);
|
|
129
90
|
}
|
|
130
91
|
|
|
131
|
-
|
|
92
|
+
// Delete a memory
|
|
93
|
+
if (results.results.length > 0) {
|
|
94
|
+
await memory.delete(results.results[0].id, userId);
|
|
95
|
+
}
|
|
132
96
|
|
|
97
|
+
// Get all memories for a user
|
|
98
|
+
const allMemories = await memory.getAll(userId, {});
|
|
133
99
|
```
|
|
134
100
|
|
|
135
|
-
##
|
|
101
|
+
## π Key Features
|
|
136
102
|
|
|
137
|
-
|
|
103
|
+
- **Memory Capture**: Extract and store relevant information from conversations
|
|
104
|
+
- **Contextual Retrieval**: Find memories most relevant to the current query
|
|
105
|
+
- **User Isolation**: Each user's memories are stored separately for privacy and security
|
|
106
|
+
- **Memory Types**: Support for different types of memories (factual, episodic, etc.)
|
|
107
|
+
- **Custom Scoring**: Hybrid scoring system balancing similarity, recency, and importance
|
|
138
108
|
|
|
139
|
-
|
|
109
|
+
## π§© Memory Types
|
|
140
110
|
|
|
141
|
-
|
|
142
|
-
Forked from the [Mem0](https://github.com/mem0ai/mem0) project β€οΈ.
|
|
111
|
+
Memories-lite supports four main types of memory:
|
|
143
112
|
|
|
144
|
-
|
|
113
|
+
1. **Factual Memory** β
|
|
114
|
+
- User preferences, traits, and personal information
|
|
115
|
+
- Example: "User likes Italian cuisine"
|
|
145
116
|
|
|
146
|
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
149
|
-
- [**MemoryLLM: Towards Self-Updatable Large Language Models** (arXiv:2402.04624)](https://arxiv.org/abs/2402.04624)
|
|
117
|
+
2. **Episodic Memory** β±οΈ
|
|
118
|
+
- Time-based events and interactions
|
|
119
|
+
- Example: "User has a meeting tomorrow at 2pm"
|
|
150
120
|
|
|
121
|
+
3. **Semantic Memory** π§
|
|
122
|
+
- General knowledge and concepts
|
|
123
|
+
- Example: "Yoga is beneficial for mental health"
|
|
151
124
|
|
|
152
|
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
125
|
+
4. **Procedural Memory** π
|
|
126
|
+
- Step-by-step processes and workflows
|
|
127
|
+
- Example: "Steps to configure the company VPN"
|
|
155
128
|
|
|
129
|
+
## πΌ Use Cases
|
|
130
|
+
|
|
131
|
+
- **Customer Support Bots**: Remember customer preferences and past interactions
|
|
132
|
+
- **Personal Assistants**: Build context-aware AI assistants that learn about user preferences
|
|
133
|
+
- **Business Applications**: Integrate with enterprise systems to maintain contextual awareness
|
|
134
|
+
- **Educational Tools**: Create learning assistants that remember student progress
|
|
135
|
+
|
|
136
|
+
## βοΈ Advanced Configuration
|
|
156
137
|
|
|
157
138
|
```typescript
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const apiKey = 'YOUR_OPENAI_API_KEY';
|
|
162
|
-
|
|
163
|
-
// Define custom scoring rules
|
|
164
|
-
const customScoring: MemoryScoringConfig = {
|
|
165
|
-
// Make Factual memory very durable (long half-life, high similarity weight)
|
|
166
|
-
factual: { alpha: 0.7, beta: 0.1, gamma: 0.1, halfLifeDays: 365 * 2 }, // 2 years HL
|
|
167
|
-
// Make Assistant Preferences permanent (infinite half-life, high base weight)
|
|
168
|
-
assistant_preference: { alpha: 0.5, beta: 0.0, gamma: 0.5, halfLifeDays: Infinity },
|
|
169
|
-
// Make Procedural memory decay extremely fast (useless after ~1 hour)
|
|
170
|
-
procedural: { alpha: 0.1, beta: 0.1, gamma: 0.0, halfLifeDays: 1 / 24 }, // 1 hour HL
|
|
171
|
-
// Keep defaults for others (or customize as needed)
|
|
172
|
-
episodic: { alpha: 0.40, beta: 0.50, gamma: 0.10, halfLifeDays: 7 },
|
|
173
|
-
semantic: { alpha: 0.50, beta: 0.25, gamma: 0.25, halfLifeDays: 120 },
|
|
174
|
-
default: { alpha: 0.5, beta: 0.3, gamma: 0.1, halfLifeDays: 30 },
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const memoriesWithCustomScoring = new MemoriesLite({
|
|
139
|
+
// Custom scoring for different memory types
|
|
140
|
+
const customMemory = new MemoriesLite({
|
|
178
141
|
llm: {
|
|
179
142
|
provider: 'openai',
|
|
180
|
-
config: { apiKey }
|
|
143
|
+
config: { apiKey: 'YOUR_API_KEY' }
|
|
181
144
|
},
|
|
182
145
|
embedder: {
|
|
183
|
-
provider: 'openai',
|
|
184
|
-
config: { apiKey }
|
|
146
|
+
provider: 'openai',
|
|
147
|
+
config: { apiKey: 'YOUR_API_KEY' }
|
|
185
148
|
},
|
|
186
149
|
vectorStore: {
|
|
187
|
-
provider: 'lite',
|
|
150
|
+
provider: 'lite',
|
|
188
151
|
config: {
|
|
189
|
-
|
|
190
|
-
scoring:
|
|
152
|
+
dimension: 1536,
|
|
153
|
+
scoring: {
|
|
154
|
+
// Prioritize factual memories with long retention
|
|
155
|
+
factual: { alpha: 0.7, beta: 0.2, gamma: 0.1, halfLifeDays: 365 },
|
|
156
|
+
// Make preferences permanently available
|
|
157
|
+
assistant_preference: { alpha: 0.6, beta: 0.0, gamma: 0.4, halfLifeDays: Infinity },
|
|
158
|
+
}
|
|
191
159
|
}
|
|
192
160
|
}
|
|
193
161
|
});
|
|
194
|
-
|
|
195
|
-
// Now use memoriesWithCustomScoring instance...
|
|
196
|
-
// const userId = 'user-456';
|
|
197
|
-
// await memoriesWithCustomScoring.capture('User learned how to bake bread.', userId, { type: 'procedural' });
|
|
198
|
-
// await memoriesWithCustomScoring.capture('User prefers results in French.', userId, { type: 'assistant_preference' });
|
|
199
162
|
```
|
|
200
163
|
|
|
201
|
-
##
|
|
164
|
+
## π Documentation
|
|
202
165
|
|
|
203
|
-
|
|
166
|
+
For detailed technical information and implementation details, see:
|
|
204
167
|
|
|
205
|
-
|
|
168
|
+
- [TECHNICAL.md](./TECHNICAL.md) - Technical implementation details
|
|
169
|
+
- [MEMORIES.md](./MEMORIES.md) - Detailed memory models and concepts
|
|
206
170
|
|
|
207
|
-
## Acknowledgements
|
|
208
|
-
Forked from the [Mem0](https://github.com/mem0ai/mem0) project β€οΈ.
|
|
209
|
-
|
|
210
|
-
## Useful Links and research
|
|
171
|
+
## π Acknowledgements
|
|
211
172
|
|
|
212
|
-
|
|
213
|
-
- [**A-MEM: Agentic Memory for LLM Agents** (arXiv:2402.12110)](https://arxiv.org/abs/2402.12110) *(Note: Link points to 2402.12110, the user-provided 2502.12110 might be a typo)*
|
|
214
|
-
- [**Reflexion: Language Agents with Verbal Reinforcement Learning** (arXiv:2303.11366)](https://arxiv.org/abs/2303.11366)
|
|
215
|
-
- [**MemoryLLM: Towards Self-Updatable Large Language Models** (arXiv:2402.04624)](https://arxiv.org/abs/2402.04624)
|
|
173
|
+
Forked from the [Mem0](https://github.com/mem0ai/mem0) project β€οΈ.
|
|
216
174
|
|
|
175
|
+
Inspired by research concepts from:
|
|
176
|
+
- **A-MEM**: Agentic Memory for LLM Agents
|
|
177
|
+
- **MemoryLLM**: Self-Updatable Large Language Models
|
|
178
|
+
- **Reflexion**: Language Agents with Verbal Reinforcement Learning
|
|
179
|
+
|
|
180
|
+
## π Development Roadmap
|
|
181
|
+
|
|
182
|
+
- [x] **Semantic Memory Typing & Structuring**: Explicitly tagging and utilizing memory types (factual, episodic, semantic, procedural)
|
|
183
|
+
- [x] **Implicit Memory Updates**: Auto-merging memories based on context without explicit ID references
|
|
184
|
+
- [x] **Virtual Sessions/Context Grouping**: Group memories related to specific conversation contexts
|
|
185
|
+
- [x] **User Isolation**: Separate storage per user for enhanced security and data privacy
|
|
186
|
+
- [x] **Memory Type Detection**: LLM-based automatic classification of memory types
|
|
187
|
+
- [x] **Core Memory Operations**: Basic CRUD operations with user-specific isolation
|
|
188
|
+
- [x] **Memory Decay & Scoring**: Hybrid scoring with recency decay and importance weights
|
|
189
|
+
- [ ] **Reflexion Pattern Integration**: Self-correction loops for memory refinement
|
|
190
|
+
- [x] **Memory Recency**: Prioritizing memories based on importance and time decay
|
|
191
|
+
- [x] **Edge Case Tests**: Complete unit tests for episodic and factual memory edge cases
|
|
192
|
+
- [ ] **Middleware Support**: Hooks and middleware for custom processing pipelines
|
|
217
193
|
|
|
218
|
-
|
|
219
|
-
- **Half-Life**: Defining a half-life (HL) for different memory types to calculate \( \lambda = \ln(2) / \text{HL} \).
|
|
220
|
-
- **Hybrid Scoring**: Integrating the decay factor into the memory retrieval score alongside vector similarity and potentially other metadata.
|
|
194
|
+
## π License
|
|
221
195
|
|
|
196
|
+
MIT
|
package/dist/memory/index.js
CHANGED
|
@@ -96,7 +96,7 @@ class MemoriesLite {
|
|
|
96
96
|
async addToVectorStore(messages, metadata, userId, filters, customFacts) {
|
|
97
97
|
const $t = this.$t;
|
|
98
98
|
const vectorStore = await this.getVectorStore(userId);
|
|
99
|
-
const parsedMessages = messages.filter((m) => typeof m.content === 'string').map((m) => `${m.role == 'user' ? '**USER**: ' : '**ASSISTANT**: '}${$t(m.content)}\n`).join("\n");
|
|
99
|
+
const parsedMessages = messages.filter((m) => typeof m.content === 'string' && m.role == 'user').map((m) => `${m.role == 'user' ? '**USER**: ' : '**ASSISTANT**: '}${$t(m.content)}\n`).join("\n");
|
|
100
100
|
const [systemPrompt, userPrompt] = (0, prompts_1.getFactRetrievalMessages)(parsedMessages, customFacts || this.customPrompt);
|
|
101
101
|
const response = await this.llm.generateResponse([
|
|
102
102
|
{ role: "system", content: systemPrompt },
|
|
@@ -124,6 +124,9 @@ class MemoriesLite {
|
|
|
124
124
|
// Get embeddings for new facts
|
|
125
125
|
const newMessageEmbeddings = {};
|
|
126
126
|
const retrievedOldMemory = [];
|
|
127
|
+
//
|
|
128
|
+
// add the userId to the filters
|
|
129
|
+
filters.userId = userId;
|
|
127
130
|
// Create embeddings and search for similar memories
|
|
128
131
|
for (const elem of facts) {
|
|
129
132
|
const fact = elem.fact;
|
|
@@ -155,7 +158,7 @@ class MemoriesLite {
|
|
|
155
158
|
console.log(`-- β LLM Error: ${action.event}, ${action.type}, "${action.text}"`);
|
|
156
159
|
continue;
|
|
157
160
|
}
|
|
158
|
-
console.log(`-- DBG memory
|
|
161
|
+
console.log(`-- DBG memory "${userId}": ${action.event}, ${action.type}, "${action.text}", why: "${action.reason}"`);
|
|
159
162
|
try {
|
|
160
163
|
switch (action.event) {
|
|
161
164
|
case "ADD": {
|
|
@@ -176,7 +179,7 @@ class MemoriesLite {
|
|
|
176
179
|
}
|
|
177
180
|
case "UPDATE": {
|
|
178
181
|
const realMemoryId = tempUuidMapping[action.id];
|
|
179
|
-
const type = uniqueOldMemories[action.id].type;
|
|
182
|
+
const type = metadata.type = uniqueOldMemories[action.id].type || action.type;
|
|
180
183
|
await this.updateMemory(realMemoryId, action.text, newMessageEmbeddings, metadata, userId);
|
|
181
184
|
results.push({
|
|
182
185
|
id: realMemoryId,
|
|
@@ -307,6 +310,7 @@ class MemoriesLite {
|
|
|
307
310
|
throw new Error("One of the filters: userId, agentId or runId is required!");
|
|
308
311
|
}
|
|
309
312
|
const vectorStore = await this.getVectorStore(userId);
|
|
313
|
+
filters.userId = userId;
|
|
310
314
|
// Search vector store
|
|
311
315
|
const queryEmbedding = await this.embedder.embed(query);
|
|
312
316
|
const memories = await vectorStore.search(queryEmbedding, limit, filters);
|
|
@@ -420,6 +424,7 @@ class MemoriesLite {
|
|
|
420
424
|
filters.runId = runId;
|
|
421
425
|
if (type)
|
|
422
426
|
filters.type = type;
|
|
427
|
+
filters.userId = userId;
|
|
423
428
|
const [memories] = await vectorStore.list(filters, limit);
|
|
424
429
|
const excludedKeys = new Set([
|
|
425
430
|
"userId",
|
|
@@ -453,6 +458,7 @@ class MemoriesLite {
|
|
|
453
458
|
...metadata,
|
|
454
459
|
data,
|
|
455
460
|
hash: (0, crypto_1.createHash)("md5").update(data).digest("hex"),
|
|
461
|
+
userId,
|
|
456
462
|
createdAt: new Date().toISOString(),
|
|
457
463
|
};
|
|
458
464
|
await vectorStore.insert([embedding], [memoryId], [memoryMetadata]);
|
|
@@ -471,6 +477,7 @@ class MemoriesLite {
|
|
|
471
477
|
...metadata,
|
|
472
478
|
data,
|
|
473
479
|
hash: (0, crypto_1.createHash)("md5").update(data).digest("hex"),
|
|
480
|
+
type: existingMemory.payload.type,
|
|
474
481
|
createdAt: existingMemory.payload.createdAt,
|
|
475
482
|
updatedAt: new Date().toISOString(),
|
|
476
483
|
...(existingMemory.payload.agentId && {
|
package/dist/prompts/index.d.ts
CHANGED
|
@@ -83,7 +83,7 @@ export declare const MemoryUpdateSchema: z.ZodObject<{
|
|
|
83
83
|
* If the task is temporal or event-based ("What was I doing yesterday?") β retrieve episodic memory.
|
|
84
84
|
* If the task is conceptual ("What does the user think about Marxism?") β retrieve semantic memory.
|
|
85
85
|
*/
|
|
86
|
-
export declare const MEMORY_STRING_SYSTEM = "# DIRECTIVES FOR MEMORIES\n- Information stored in memory is always enclosed within the <memories> tag.\n- Give 10x more weight to the user's current conversation and prioritize answering it first.\n- You must adapt your answer based on the contents found within the <memories> section.\n- If the memories are irrelevant to the user's query, you MUST ignore them.\n- By default, do not reference this section or the memories in your response.\n- Use
|
|
86
|
+
export declare const MEMORY_STRING_SYSTEM = "# DIRECTIVES FOR MEMORIES\n- Information stored in memory is always enclosed within the <memories> tag.\n- Give 10x more weight to the user's current conversation and prioritize answering it first.\n- You must adapt your answer based on the contents found within the <memories> section.\n- If the memories are irrelevant to the user's query, you MUST ignore them.\n- By default, do not reference this section or the memories in your response.\n- Use memories only to guide your reasoning. Do not respond to the memories themselves.";
|
|
87
87
|
export declare const MEMORY_STRING_PREFIX = "Use these contextual memories to guide your response. Prioritize the user's question. Ignore irrelevant memories.";
|
|
88
88
|
export declare const MEMORY_STRING_SYSTEM_OLD = "# USER AND MEMORIES PREFERENCES:\n- Utilize the provided memories to guide your responses.\n- Disregard any memories that are not relevant.\n- By default, do not reference this section or the memories in your response.\n";
|
|
89
89
|
export declare function getFactRetrievalMessages_O(parsedMessages: string, customRules?: string, defaultLanguage?: string): [string, string];
|
package/dist/prompts/index.js
CHANGED
|
@@ -23,7 +23,12 @@ exports.FactRetrievalSchema_extended = zod_1.z.object({
|
|
|
23
23
|
.array(zod_1.z.object({
|
|
24
24
|
fact: zod_1.z.string().describe("The fact extracted from the conversation."),
|
|
25
25
|
existing: zod_1.z.boolean().describe("Whether the fact is already present"),
|
|
26
|
-
type: zod_1.z.enum(["assistant_preference", "factual", "episodic", "procedural", "semantic"])
|
|
26
|
+
type: zod_1.z.enum(["assistant_preference", "factual", "episodic", "procedural", "semantic"])
|
|
27
|
+
.describe(`The type of the fact.
|
|
28
|
+
Use 'assistant_preference' for Assistant behavior preferences.
|
|
29
|
+
Use 'episodic' always for time-based events.
|
|
30
|
+
Use 'procedural' always when it concerns a business question.
|
|
31
|
+
Use 'semantic' for Understanding of concepts, relationships and general meanings.`),
|
|
27
32
|
}))
|
|
28
33
|
});
|
|
29
34
|
// Define Zod schema for memory update output
|
|
@@ -61,7 +66,7 @@ exports.MEMORY_STRING_SYSTEM = `# DIRECTIVES FOR MEMORIES
|
|
|
61
66
|
- You must adapt your answer based on the contents found within the <memories> section.
|
|
62
67
|
- If the memories are irrelevant to the user's query, you MUST ignore them.
|
|
63
68
|
- By default, do not reference this section or the memories in your response.
|
|
64
|
-
- Use
|
|
69
|
+
- Use memories only to guide your reasoning. Do not respond to the memories themselves.`;
|
|
65
70
|
exports.MEMORY_STRING_PREFIX = "Use these contextual memories to guide your response. Prioritize the user's question. Ignore irrelevant memories.";
|
|
66
71
|
exports.MEMORY_STRING_SYSTEM_OLD = `# USER AND MEMORIES PREFERENCES:
|
|
67
72
|
- Utilize the provided memories to guide your responses.
|
|
@@ -81,17 +86,17 @@ Your mission is to analyze a input content line by line and produce:
|
|
|
81
86
|
|
|
82
87
|
Filter content before extracting triplets:
|
|
83
88
|
- Ignore content with no direct relevance to user (e.g., "today is sunny", "I'm working").
|
|
84
|
-
-
|
|
85
|
-
- Eliminate introductions, sub-facts, detailed repetitive elements, stylistic fillers, or vague statements. A general fact always takes precedence over multiple sub-facts (signal vs noise).
|
|
89
|
+
- Eliminate introductions, vague statements and detailed repetitive elements.
|
|
86
90
|
|
|
87
91
|
You must extract {Subject, Predicate, Object} triplets by following these rules:
|
|
88
92
|
1. Identify named entities, preferences, and meaningful user-related concepts:
|
|
89
|
-
- All extracted triplets describe the user query intention as: the userβs preferences, beliefs, actions, experiences, learning, identity, work, or relationships (e.g., "I
|
|
93
|
+
- All extracted triplets describe the user query intention as: the userβs preferences, beliefs, actions, experiences, learning, identity, work, or relationships (e.g., "I love working with precise Agents").
|
|
94
|
+
- Merge triplets from sub-facts or detailed objects. A general fact always takes precedence over multiple sub-facts (signal vs noise).
|
|
90
95
|
- If the user asks about third-party business information classify it as "procedural" type.
|
|
91
96
|
- The query intention can include specific preferences about how the Assistant should respond (e.g., "answer concisely", "explain in detail").
|
|
92
97
|
- Use inference to compress each fact (max 10 words).
|
|
93
98
|
- DO NOT infer personal facts from third-party informations.
|
|
94
|
-
- Treat "Assistant
|
|
99
|
+
- Treat "Assistant:" messages as external and transient responses, there is no fact to extract from them. These responses MUST be used to enrich your reasoning process.
|
|
95
100
|
2. Compress the facts:
|
|
96
101
|
- Keep only the most shortest version of the Triplet.
|
|
97
102
|
3. Rewrite comparatives, conditionals, or temporals into explicit predicates (e.g., "prefers", "available during", "used because of").
|
|
@@ -123,15 +128,15 @@ You must strictly extract {Subject, Predicate, Object} triplets by following the
|
|
|
123
128
|
- Extract triplets that describe facts *about the user* based on their statements, covering areas like preferences, beliefs, actions, experiences, learning, identity, work, or relationships (e.g., "I love working").
|
|
124
129
|
- Apply explicit, precise, and unambiguous predicates (e.g., "owns", "is located at", "is a", "has function", "causes", etc.).
|
|
125
130
|
- Determine the triplet type (e.g., "factual", "episodic", "procedural", "semantic") based on the content and meaning.
|
|
126
|
-
- "episodic"
|
|
131
|
+
- "episodic" If a fact depends on a temporal, situational, or immediate personal context, then that fact AND ALL OF ITS sub-facts MUST be classified as episodic.
|
|
127
132
|
- "procedural" for business processes (e.g., "Looking for customer John Doe address", "How to create a new contract").
|
|
128
133
|
- "factual" for stable user data (except procedural that prevails).
|
|
129
134
|
|
|
130
135
|
- Eliminate introductions, sub-facts, detailed repetitive elements, stylistic fillers, or vague statements. General facts always takes precedence over multiple sub-facts (signal vs noise).
|
|
131
136
|
- The query intention can include specific preferences about how the Assistant should respond (e.g., "answer concisely", "explain in detail").
|
|
132
|
-
- Compress each fact
|
|
137
|
+
- Compress each OUTPUT (fact and reason) with less than 10 words.
|
|
133
138
|
- DO NOT infer personal facts from third-party informations.
|
|
134
|
-
- Treat "
|
|
139
|
+
- Treat "**ASSISTANT**:" as responses to enrich context of your reasoning process about the USER query.
|
|
135
140
|
2. Use pronoun "I" instead of "The user" in the subject of the triplet.
|
|
136
141
|
3. Do not output any facts already present in section # PRE-EXISTING FACTS.
|
|
137
142
|
- If you find facts already present in section # PRE-EXISTING FACTS, use field "existing" to store them.
|
|
@@ -12,6 +12,7 @@ import { SearchFilters, VectorStoreConfig, VectorStoreResult } from "../types";
|
|
|
12
12
|
*/
|
|
13
13
|
export declare class LiteVectorStore implements VectorStore {
|
|
14
14
|
private db;
|
|
15
|
+
private dbPath;
|
|
15
16
|
private isSecure;
|
|
16
17
|
private dimension;
|
|
17
18
|
private currentUserId;
|
|
@@ -36,5 +37,14 @@ export declare class LiteVectorStore implements VectorStore {
|
|
|
36
37
|
list(filters?: SearchFilters, limit?: number): Promise<[VectorStoreResult[], number]>;
|
|
37
38
|
private calculateRecencyScore;
|
|
38
39
|
private calculateHybridScore;
|
|
40
|
+
/**
|
|
41
|
+
* Internal method to clean up vectors based on recency score threshold.
|
|
42
|
+
*
|
|
43
|
+
* @param threshold - The minimum recency score required for a memory to be retained.
|
|
44
|
+
* - Recency score is calculated using exponential decay: 1.0 means brand new, 0.5 means at half-life, 0.0 means fully decayed.
|
|
45
|
+
* - Memories with a recency score below this threshold will be deleted (unless their half-life is infinite or zero).
|
|
46
|
+
* - For example, a threshold of 0.25 will remove all memories whose recency score has decayed 2 times the half-life.
|
|
47
|
+
* - Use a lower threshold to keep more old memories, or a higher threshold to keep only fresher ones.
|
|
48
|
+
*/
|
|
39
49
|
private _cleanupByRecency;
|
|
40
50
|
}
|