memories-lite 0.10.1 → 0.99.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/dist/config/defaults.js +13 -20
- package/dist/config/manager.js +3 -10
- package/dist/memory/index.d.ts +12 -3
- package/dist/memory/index.js +61 -155
- package/dist/memory/memory.types.d.ts +1 -2
- package/dist/prompts/index.d.ts +53 -17
- package/dist/prompts/index.js +63 -23
- package/dist/types/index.d.ts +40 -234
- package/dist/types/index.js +4 -27
- package/dist/vectorstores/lite.d.ts +1 -0
- package/dist/vectorstores/lite.js +11 -6
- package/memories-lite-a42ac5108869b599bcbac21069f63fb47f07452fcc4b87e89b3c06a945612d0b.db +0 -0
- package/memories-lite-a9137698d8d3fdbf27efcdc8cd372084b52d484e8db866c5455bbb3f85299b54.db +0 -0
- package/package.json +1 -1
- package/src/config/defaults.ts +13 -20
- package/src/config/manager.ts +3 -10
- package/src/memory/index.ts +76 -197
- package/src/memory/memory.types.ts +1 -2
- package/src/prompts/index.ts +69 -26
- package/src/types/index.ts +8 -46
- package/src/vectorstores/lite.ts +13 -7
- package/tests/init.mem.ts +7 -4
- package/tests/lite.spec.ts +44 -34
- package/tests/memory.discussion.search.test.ts +377 -0
- package/tests/memory.discussion.test.ts +279 -0
- package/tests/memory.update.test.ts +5 -1
- package/tests/memory.facts.test.ts +0 -175
- package/tests/memory.todo.test.ts +0 -126
package/dist/types/index.js
CHANGED
|
@@ -21,19 +21,13 @@ exports.MemoryConfigSchema = zod_1.z.object({
|
|
|
21
21
|
dimension: zod_1.z.number().optional(),
|
|
22
22
|
client: zod_1.z.any().optional(),
|
|
23
23
|
scoring: zod_1.z.object({
|
|
24
|
-
|
|
25
|
-
alpha: zod_1.z.number(),
|
|
26
|
-
beta: zod_1.z.number(),
|
|
27
|
-
gamma: zod_1.z.number(),
|
|
28
|
-
halfLifeDays: zod_1.z.number(),
|
|
29
|
-
}),
|
|
30
|
-
factual: zod_1.z.object({
|
|
24
|
+
assistant_preference: zod_1.z.object({
|
|
31
25
|
alpha: zod_1.z.number(),
|
|
32
26
|
beta: zod_1.z.number(),
|
|
33
27
|
gamma: zod_1.z.number(),
|
|
34
28
|
halfLifeDays: zod_1.z.number(),
|
|
35
29
|
}),
|
|
36
|
-
|
|
30
|
+
discussion: zod_1.z.object({
|
|
37
31
|
alpha: zod_1.z.number(),
|
|
38
32
|
beta: zod_1.z.number(),
|
|
39
33
|
gamma: zod_1.z.number(),
|
|
@@ -47,6 +41,7 @@ exports.MemoryConfigSchema = zod_1.z.object({
|
|
|
47
41
|
}),
|
|
48
42
|
}).optional(),
|
|
49
43
|
recencyCleanupThreshold: zod_1.z.number().min(0).max(1).optional(),
|
|
44
|
+
searchThreshold: zod_1.z.number().min(0).max(1).optional(),
|
|
50
45
|
})
|
|
51
46
|
.passthrough(),
|
|
52
47
|
}),
|
|
@@ -59,25 +54,7 @@ exports.MemoryConfigSchema = zod_1.z.object({
|
|
|
59
54
|
}),
|
|
60
55
|
}),
|
|
61
56
|
historyDbPath: zod_1.z.string().optional(),
|
|
62
|
-
|
|
63
|
-
enableGraph: zod_1.z.boolean().optional(),
|
|
64
|
-
graphStore: zod_1.z
|
|
65
|
-
.object({
|
|
66
|
-
provider: zod_1.z.string(),
|
|
67
|
-
config: zod_1.z.object({
|
|
68
|
-
url: zod_1.z.string(),
|
|
69
|
-
username: zod_1.z.string(),
|
|
70
|
-
password: zod_1.z.string(),
|
|
71
|
-
}),
|
|
72
|
-
llm: zod_1.z
|
|
73
|
-
.object({
|
|
74
|
-
provider: zod_1.z.string(),
|
|
75
|
-
config: zod_1.z.record(zod_1.z.string(), zod_1.z.any()),
|
|
76
|
-
})
|
|
77
|
-
.optional(),
|
|
78
|
-
customPrompt: zod_1.z.string().optional(),
|
|
79
|
-
})
|
|
80
|
-
.optional(),
|
|
57
|
+
capturePrompt: zod_1.z.string().optional(),
|
|
81
58
|
historyStore: zod_1.z
|
|
82
59
|
.object({
|
|
83
60
|
provider: zod_1.z.string(),
|
|
@@ -18,6 +18,7 @@ export declare class LiteVectorStore implements VectorStore {
|
|
|
18
18
|
private currentUserId;
|
|
19
19
|
private scoringConfig;
|
|
20
20
|
private cleanupThreshold?;
|
|
21
|
+
private searchThreshold;
|
|
21
22
|
private static cache;
|
|
22
23
|
constructor(config: VectorStoreConfig, currentUserId: string);
|
|
23
24
|
private init;
|
|
@@ -28,7 +28,8 @@ class LiteVectorStore {
|
|
|
28
28
|
this.currentUserId = currentUserId;
|
|
29
29
|
this.isSecure = config.secure || false;
|
|
30
30
|
this.scoringConfig = config.scoring;
|
|
31
|
-
this.cleanupThreshold = config.recencyCleanupThreshold || 0.25; // (default 0.25 means 2 times the half-life
|
|
31
|
+
this.cleanupThreshold = config.recencyCleanupThreshold || 0.25; // (default 0.25 means 2 times the half-life)
|
|
32
|
+
this.searchThreshold = config.searchThreshold ?? 0; // Seuil de score (default 0 = pas de filtrage)
|
|
32
33
|
config.rootPath = config.rootPath || process.cwd();
|
|
33
34
|
const filename = this.isSecure ? `memories-lite-${currentUserId}.db` : `memories-lite-global.db`;
|
|
34
35
|
this.dbPath = (config.rootPath == ':memory:') ? ':memory:' : path_1.default.join(config.rootPath, filename);
|
|
@@ -195,11 +196,15 @@ class LiteVectorStore {
|
|
|
195
196
|
if (this.filterVector(memoryVector, filters)) {
|
|
196
197
|
const cosineScore = this.cosineSimilarity(query, vector);
|
|
197
198
|
const hybridScore = this.calculateHybridScore(cosineScore, payload);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
//
|
|
200
|
+
// Filtrer par searchThreshold - ne retourner que les résultats au-dessus du seuil
|
|
201
|
+
if (hybridScore >= this.searchThreshold) {
|
|
202
|
+
results.push({
|
|
203
|
+
id: memoryVector.id,
|
|
204
|
+
payload: memoryVector.payload,
|
|
205
|
+
score: hybridScore,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
203
208
|
}
|
|
204
209
|
}
|
|
205
210
|
results.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/config/defaults.ts
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { MemoryConfig, MemoryScoringConfig } from "../types";
|
|
2
2
|
|
|
3
3
|
const DEFAULT_SCORING_CONFIG: MemoryScoringConfig = {
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
factual: { alpha: 0.70, beta: 0.20, gamma: 0.10, halfLifeDays: 150 }, // ~150 days
|
|
4
|
+
//
|
|
5
|
+
// assistant_preference: préférences utilisateur avec l'assistant (style, langue, etc.)
|
|
7
6
|
assistant_preference: { alpha: 0.60, beta: 0.05, gamma: 0.35, halfLifeDays: Infinity },
|
|
8
|
-
|
|
7
|
+
//
|
|
8
|
+
// discussion: mémoires de discussions (synthèses opérationnelles)
|
|
9
|
+
// - alpha=1: score basé uniquement sur la similarité cosinus
|
|
10
|
+
// - beta=0: pas de recency
|
|
11
|
+
// - gamma=0: pas d'importance base
|
|
12
|
+
discussion: { alpha: 1, beta: 0, gamma: 0, halfLifeDays: Infinity },
|
|
13
|
+
//
|
|
14
|
+
// default: fallback si type manquant ou inconnu
|
|
15
|
+
default: { alpha: 0.5, beta: 0.3, gamma: 0.1, halfLifeDays: 30 }
|
|
9
16
|
};
|
|
10
17
|
|
|
11
18
|
export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
|
12
19
|
disableHistory: true,
|
|
13
|
-
|
|
14
|
-
version: "v1.1",
|
|
20
|
+
version: "v2.0",
|
|
15
21
|
embedder: {
|
|
16
22
|
provider: "openai",
|
|
17
23
|
config: {
|
|
@@ -26,6 +32,7 @@ export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
|
|
26
32
|
collectionName: "memories",
|
|
27
33
|
dimension: 768,
|
|
28
34
|
scoring: DEFAULT_SCORING_CONFIG,
|
|
35
|
+
searchThreshold: 0.50, // Seuil minimum de score pour retourner un résultat
|
|
29
36
|
},
|
|
30
37
|
},
|
|
31
38
|
llm: {
|
|
@@ -36,20 +43,6 @@ export const DEFAULT_MEMORY_CONFIG: MemoryConfig = {
|
|
|
36
43
|
modelProperties: undefined,
|
|
37
44
|
},
|
|
38
45
|
},
|
|
39
|
-
graphStore: {
|
|
40
|
-
provider: "neo4j",
|
|
41
|
-
config: {
|
|
42
|
-
url: process.env.NEO4J_URL || "neo4j://localhost:7687",
|
|
43
|
-
username: process.env.NEO4J_USERNAME || "neo4j",
|
|
44
|
-
password: process.env.NEO4J_PASSWORD || "password",
|
|
45
|
-
},
|
|
46
|
-
llm: {
|
|
47
|
-
provider: "openai",
|
|
48
|
-
config: {
|
|
49
|
-
model: "gpt-5-mini",
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
46
|
historyStore: {
|
|
54
47
|
provider: "dummy",
|
|
55
48
|
config: {
|
package/src/config/manager.ts
CHANGED
|
@@ -51,9 +51,8 @@ export class ConfigManager {
|
|
|
51
51
|
dimension: userConf.dimension || defaultConf.dimension,
|
|
52
52
|
// Merge scoring deeply if present in userConf, otherwise use default
|
|
53
53
|
scoring: userConf.scoring ? {
|
|
54
|
-
todo: { ...defaultConf.scoring?.todo, ...userConf.scoring.todo },
|
|
55
|
-
factual: { ...defaultConf.scoring?.factual, ...userConf.scoring.factual },
|
|
56
54
|
assistant_preference: { ...defaultConf.scoring?.assistant_preference, ...userConf.scoring.assistant_preference },
|
|
55
|
+
discussion: { ...defaultConf.scoring?.discussion, ...userConf.scoring.discussion },
|
|
57
56
|
default: { ...defaultConf.scoring?.default, ...userConf.scoring.default },
|
|
58
57
|
} : defaultConf.scoring,
|
|
59
58
|
...userConf, // Include any other passthrough fields from user
|
|
@@ -67,9 +66,8 @@ export class ConfigManager {
|
|
|
67
66
|
client: undefined,
|
|
68
67
|
// Merge scoring deeply if present in userConf, otherwise use default
|
|
69
68
|
scoring: userConf?.scoring ? {
|
|
70
|
-
todo: { ...defaultConf.scoring?.todo, ...userConf.scoring.todo },
|
|
71
|
-
factual: { ...defaultConf.scoring?.factual, ...userConf.scoring.factual },
|
|
72
69
|
assistant_preference: { ...defaultConf.scoring?.assistant_preference, ...userConf.scoring.assistant_preference },
|
|
70
|
+
discussion: { ...defaultConf.scoring?.discussion, ...userConf.scoring.discussion },
|
|
73
71
|
default: { ...defaultConf.scoring?.default, ...userConf.scoring.default },
|
|
74
72
|
} : defaultConf.scoring,
|
|
75
73
|
recencyCleanupThreshold:
|
|
@@ -108,18 +106,13 @@ export class ConfigManager {
|
|
|
108
106
|
},
|
|
109
107
|
historyDbPath:
|
|
110
108
|
userConfig.historyDbPath || DEFAULT_MEMORY_CONFIG.historyDbPath,
|
|
111
|
-
|
|
112
|
-
graphStore: {
|
|
113
|
-
...DEFAULT_MEMORY_CONFIG.graphStore,
|
|
114
|
-
...userConfig.graphStore,
|
|
115
|
-
},
|
|
109
|
+
capturePrompt: userConfig.capturePrompt,
|
|
116
110
|
historyStore: {
|
|
117
111
|
...DEFAULT_MEMORY_CONFIG.historyStore,
|
|
118
112
|
...userConfig.historyStore,
|
|
119
113
|
},
|
|
120
114
|
disableHistory:
|
|
121
115
|
userConfig.disableHistory || DEFAULT_MEMORY_CONFIG.disableHistory,
|
|
122
|
-
enableGraph: userConfig.enableGraph || DEFAULT_MEMORY_CONFIG.enableGraph,
|
|
123
116
|
};
|
|
124
117
|
|
|
125
118
|
// Validate the merged config
|
package/src/memory/index.ts
CHANGED
|
@@ -16,10 +16,8 @@ import {
|
|
|
16
16
|
HistoryManagerFactory,
|
|
17
17
|
} from "../utils/factory";
|
|
18
18
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
getUpdateMemoryMessages,
|
|
22
|
-
MemoryUpdateSchema,
|
|
19
|
+
DiscussionSynthesisSchema,
|
|
20
|
+
getDiscussionSynthesisMessages,
|
|
23
21
|
removeCodeBlocks,
|
|
24
22
|
} from "../prompts";
|
|
25
23
|
import { DummyHistoryManager } from "../storage/DummyHistoryManager";
|
|
@@ -42,22 +40,20 @@ import { zodResponseFormat } from "openai/helpers/zod";
|
|
|
42
40
|
|
|
43
41
|
export class MemoriesLite {
|
|
44
42
|
private config: MemoryConfig;
|
|
45
|
-
private
|
|
43
|
+
private capturePrompt: string | undefined;
|
|
46
44
|
private embedder: Embedder;
|
|
47
45
|
private vectorStoreConfig: VectorStoreConfig;
|
|
48
46
|
private llm: LLM;
|
|
49
47
|
private db: HistoryManager;
|
|
50
48
|
private collectionName: string | undefined;
|
|
51
49
|
private apiVersion: string;
|
|
52
|
-
private graphMemory?: any;
|
|
53
|
-
private enableGraph: boolean;
|
|
54
50
|
telemetryId: string;
|
|
55
51
|
|
|
56
52
|
constructor(config: Partial<MemoryConfig> = {}) {
|
|
57
53
|
// Merge and validate config
|
|
58
54
|
this.config = ConfigManager.mergeConfig(config);
|
|
59
55
|
|
|
60
|
-
this.
|
|
56
|
+
this.capturePrompt = this.config.capturePrompt;
|
|
61
57
|
this.embedder = EmbedderFactory.create(
|
|
62
58
|
this.config.embedder.provider,
|
|
63
59
|
this.config.embedder.config,
|
|
@@ -90,14 +86,8 @@ export class MemoriesLite {
|
|
|
90
86
|
|
|
91
87
|
this.collectionName = this.config.vectorStore.config.collectionName;
|
|
92
88
|
this.apiVersion = this.config.version || "v1.0";
|
|
93
|
-
this.enableGraph = this.config.enableGraph || false;
|
|
94
89
|
this.telemetryId = "anonymous";
|
|
95
90
|
|
|
96
|
-
// Initialize graph memory if configured
|
|
97
|
-
if (this.enableGraph && this.config.graphStore) {
|
|
98
|
-
// this.graphMemory = new MemoryGraph(this.config);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
91
|
// Initialize telemetry if vector store is initialized
|
|
102
92
|
// this._initializeTelemetry();
|
|
103
93
|
}
|
|
@@ -111,7 +101,6 @@ export class MemoriesLite {
|
|
|
111
101
|
api_version: this.apiVersion,
|
|
112
102
|
client_type: "Memory",
|
|
113
103
|
collection_name: this.collectionName,
|
|
114
|
-
enable_graph: this.enableGraph,
|
|
115
104
|
});
|
|
116
105
|
} catch (error) {}
|
|
117
106
|
}
|
|
@@ -152,180 +141,98 @@ export class MemoriesLite {
|
|
|
152
141
|
}
|
|
153
142
|
|
|
154
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Capture une discussion et génère une synthèse (title + summary)
|
|
146
|
+
* Utilise getDiscussionSynthesisMessages pour produire la synthèse
|
|
147
|
+
*/
|
|
155
148
|
private async addToVectorStore(
|
|
156
149
|
messages: Message[],
|
|
157
150
|
metadata: Record<string, any>,
|
|
158
151
|
userId: string,
|
|
159
152
|
filters: SearchFilters,
|
|
160
|
-
|
|
153
|
+
capturePrompt?: string,
|
|
161
154
|
): Promise<MemoryItem[]> {
|
|
162
155
|
|
|
163
156
|
const $t = this.$t;
|
|
164
157
|
const vectorStore = await this.getVectorStore(userId);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
//
|
|
158
|
+
|
|
159
|
+
//
|
|
160
|
+
// Formater les messages pour la synthèse
|
|
161
|
+
const parsedMessages = messages
|
|
162
|
+
.filter((m) => typeof m.content === 'string')
|
|
163
|
+
.map((m) => `**${m.role.toUpperCase()}**: ${$t(m.content as string)}`)
|
|
164
|
+
.join("\n\n");
|
|
168
165
|
|
|
169
|
-
|
|
166
|
+
//
|
|
167
|
+
// Générer la synthèse via LLM
|
|
168
|
+
const [systemPrompt, userPrompt] = getDiscussionSynthesisMessages(
|
|
169
|
+
parsedMessages,
|
|
170
|
+
capturePrompt || this.capturePrompt
|
|
171
|
+
);
|
|
170
172
|
|
|
171
173
|
const response = await this.llm.generateResponse(
|
|
172
174
|
[
|
|
173
175
|
{ role: "system", content: systemPrompt },
|
|
174
176
|
{ role: "user", content: userPrompt },
|
|
175
177
|
],
|
|
176
|
-
{...zodResponseFormat(
|
|
178
|
+
{ ...zodResponseFormat(DiscussionSynthesisSchema, "DiscussionSynthesis") },
|
|
179
|
+
[],
|
|
180
|
+
false
|
|
177
181
|
);
|
|
178
|
-
|
|
182
|
+
|
|
183
|
+
//
|
|
184
|
+
// Parser la réponse
|
|
185
|
+
const parsedResponse = (res: any) => {
|
|
179
186
|
try {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return response;
|
|
187
|
+
if (typeof res === 'object') {
|
|
188
|
+
return res;
|
|
183
189
|
}
|
|
184
|
-
const cleanResponse = removeCodeBlocks(
|
|
190
|
+
const cleanResponse = removeCodeBlocks(res as string);
|
|
185
191
|
return JSON.parse(cleanResponse);
|
|
186
192
|
} catch (e) {
|
|
187
|
-
console.error(
|
|
188
|
-
|
|
189
|
-
response,
|
|
190
|
-
e,
|
|
191
|
-
response
|
|
192
|
-
);
|
|
193
|
-
return [];
|
|
193
|
+
console.error("Failed to parse synthesis from LLM response:", res, e);
|
|
194
|
+
return { title: "Sans titre", summary: "" };
|
|
194
195
|
}
|
|
195
|
-
}
|
|
196
|
-
//
|
|
197
|
-
// can use native structured output
|
|
198
|
-
// Drop factual facts at capture level (do not store factual memories)
|
|
199
|
-
// FIXME Drop factual should be done at prompt level
|
|
200
|
-
const facts = parsedResponse(response).facts?.filter((f:any) => !f.existing )||[];
|
|
196
|
+
};
|
|
201
197
|
|
|
202
|
-
|
|
203
|
-
// console.log("-- DBG facts:", facts);
|
|
198
|
+
const { title, summary } = parsedResponse(response);
|
|
204
199
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
200
|
+
if (!summary) {
|
|
201
|
+
console.warn("-- ⚠️ Empty summary from LLM, skipping memory creation");
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
208
204
|
|
|
209
205
|
//
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
// Create embeddings and search for similar memories
|
|
213
|
-
for (const elem of facts) {
|
|
214
|
-
const fact = elem.fact;
|
|
215
|
-
const embedding = await this.embedder.embed(fact);
|
|
216
|
-
newMessageEmbeddings[fact] = embedding;
|
|
217
|
-
|
|
218
|
-
const existingMemories = await vectorStore.search(
|
|
219
|
-
embedding,
|
|
220
|
-
5,
|
|
221
|
-
filters,
|
|
222
|
-
);
|
|
223
|
-
for (const mem of existingMemories) {
|
|
224
|
-
retrievedOldMemory.push({ id: mem.id, text: mem.payload.data,type: mem.payload.type });
|
|
225
|
-
}
|
|
226
|
-
}
|
|
206
|
+
// Créer l'embedding sur le title seul (TEST COMPARATIF)
|
|
207
|
+
const embedding = await this.embedder.embed(title);
|
|
227
208
|
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
209
|
+
//
|
|
210
|
+
// Préparer les métadonnées
|
|
211
|
+
const memoryType: MemoryType = metadata.type || 'discussion';
|
|
212
|
+
const memoryMetadata = {
|
|
213
|
+
...metadata,
|
|
214
|
+
title,
|
|
215
|
+
type: memoryType,
|
|
216
|
+
userId,
|
|
217
|
+
};
|
|
234
218
|
|
|
235
|
-
//
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// Get memory update decisions
|
|
243
|
-
const lastUserMessage = [...messages].reverse().find(m => m.role === 'user');
|
|
244
|
-
const userInstruction = typeof lastUserMessage?.content === 'string' ? lastUserMessage?.content as string : '';
|
|
245
|
-
const updatePrompt = getUpdateMemoryMessages(uniqueOldMemories, facts, 'French', userInstruction);
|
|
246
|
-
|
|
247
|
-
// console.log("-- DBG updatePrompt:", updatePrompt);
|
|
248
|
-
const updateResponse = await this.llm.generateResponse(
|
|
249
|
-
[{ role: "user", content: updatePrompt }],
|
|
250
|
-
{...zodResponseFormat(MemoryUpdateSchema,"Memory")},[],false,
|
|
219
|
+
//
|
|
220
|
+
// Stocker la mémoire
|
|
221
|
+
const memoryId = await this.createMemory(
|
|
222
|
+
summary,
|
|
223
|
+
{ [summary]: embedding },
|
|
224
|
+
memoryMetadata,
|
|
225
|
+
userId,
|
|
251
226
|
);
|
|
252
|
-
// console.log("-- DBG merge:", updatePrompt);
|
|
253
227
|
|
|
254
|
-
|
|
228
|
+
console.log(`-- 🧠 Memory created: "${title}" (${memoryType})`);
|
|
255
229
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
if(action.reason === "undefined") {
|
|
264
|
-
console.log(`-- ⛔ LLM Error: ${action.event}, ${action.type}, "${action.text}"`);
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
console.log(`-- DBG memory "${userId}": ${action.event}, ${action.type}, "${action.text}", why: "${action.reason}"`);
|
|
268
|
-
try {
|
|
269
|
-
switch (action.event) {
|
|
270
|
-
case "ADD": {
|
|
271
|
-
if(!action.type) {
|
|
272
|
-
// log error
|
|
273
|
-
console.error("Type is mandatory to manage memories:", action);
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
metadata.type = action.type;
|
|
277
|
-
const memoryId = await this.createMemory(
|
|
278
|
-
action.text,
|
|
279
|
-
newMessageEmbeddings,
|
|
280
|
-
metadata,
|
|
281
|
-
userId,
|
|
282
|
-
);
|
|
283
|
-
results.push({
|
|
284
|
-
id: memoryId,
|
|
285
|
-
memory: action.text,
|
|
286
|
-
type: action.type,
|
|
287
|
-
metadata: { event: action.event },
|
|
288
|
-
});
|
|
289
|
-
break;
|
|
290
|
-
}
|
|
291
|
-
case "UPDATE": {
|
|
292
|
-
const realMemoryId = tempUuidMapping[action.id];
|
|
293
|
-
const type = metadata.type = uniqueOldMemories[action.id].type || action.type;
|
|
294
|
-
await this.updateMemory(
|
|
295
|
-
realMemoryId,
|
|
296
|
-
action.text,
|
|
297
|
-
newMessageEmbeddings,
|
|
298
|
-
metadata,
|
|
299
|
-
userId,
|
|
300
|
-
);
|
|
301
|
-
results.push({
|
|
302
|
-
id: realMemoryId,
|
|
303
|
-
memory: action.text,
|
|
304
|
-
type,
|
|
305
|
-
metadata: {
|
|
306
|
-
event: action.event,
|
|
307
|
-
previousMemory: action.old_memory,
|
|
308
|
-
},
|
|
309
|
-
});
|
|
310
|
-
break;
|
|
311
|
-
}
|
|
312
|
-
case "DELETE": {
|
|
313
|
-
const realMemoryId = tempUuidMapping[action.id];
|
|
314
|
-
await this.deleteMemory(realMemoryId, userId);
|
|
315
|
-
results.push({
|
|
316
|
-
id: realMemoryId,
|
|
317
|
-
memory: action.text,
|
|
318
|
-
type: action.type,
|
|
319
|
-
metadata: { event: action.event },
|
|
320
|
-
});
|
|
321
|
-
break;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
} catch (error) {
|
|
325
|
-
console.error(`Error processing memory action: ${error}`);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return results;
|
|
230
|
+
return [{
|
|
231
|
+
id: memoryId,
|
|
232
|
+
memory: summary,
|
|
233
|
+
type: memoryType,
|
|
234
|
+
metadata: { title, event: "ADD" },
|
|
235
|
+
}];
|
|
329
236
|
}
|
|
330
237
|
|
|
331
238
|
static fromConfig(configDict: Record<string, any>): MemoriesLite {
|
|
@@ -342,24 +249,24 @@ export class MemoriesLite {
|
|
|
342
249
|
return LiteVectorStore.from(userId, this.vectorStoreConfig);
|
|
343
250
|
}
|
|
344
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Capture une discussion et génère une mémoire (title + summary)
|
|
254
|
+
*
|
|
255
|
+
* @param messages - Messages de la discussion ou texte brut
|
|
256
|
+
* @param userId - ID utilisateur
|
|
257
|
+
* @param config - Options incluant capturePrompt pour personnaliser la synthèse
|
|
258
|
+
*/
|
|
345
259
|
async capture(
|
|
346
260
|
messages: string | Message[],
|
|
347
261
|
userId: string,
|
|
348
262
|
config: AddMemoryOptions,
|
|
349
263
|
): Promise<SearchResult> {
|
|
350
|
-
// await this._captureEvent("add", {
|
|
351
|
-
// message_count: Array.isArray(messages) ? messages.length : 1,
|
|
352
|
-
// has_metadata: !!config.metadata,
|
|
353
|
-
// has_filters: !!config.filters,
|
|
354
|
-
// infer: config.infer,
|
|
355
|
-
// });
|
|
356
264
|
const {
|
|
357
265
|
agentId,
|
|
358
266
|
runId,
|
|
359
267
|
metadata = {},
|
|
360
268
|
filters = {},
|
|
361
|
-
|
|
362
|
-
customFacts
|
|
269
|
+
capturePrompt
|
|
363
270
|
} = config;
|
|
364
271
|
|
|
365
272
|
if (agentId) filters.agentId = metadata.agentId = agentId;
|
|
@@ -377,31 +284,18 @@ export class MemoriesLite {
|
|
|
377
284
|
|
|
378
285
|
const final_parsedMessages = await parse_vision_messages(parsedMessages);
|
|
379
286
|
|
|
380
|
-
//
|
|
287
|
+
//
|
|
288
|
+
// Générer synthèse et stocker
|
|
381
289
|
const vectorStoreResult = await this.addToVectorStore(
|
|
382
290
|
final_parsedMessages,
|
|
383
291
|
metadata,
|
|
384
292
|
userId,
|
|
385
293
|
filters,
|
|
386
|
-
|
|
294
|
+
capturePrompt,
|
|
387
295
|
);
|
|
388
296
|
|
|
389
|
-
// Add to graph store if available
|
|
390
|
-
let graphResult;
|
|
391
|
-
if (this.graphMemory) {
|
|
392
|
-
try {
|
|
393
|
-
graphResult = await this.graphMemory.add(
|
|
394
|
-
final_parsedMessages.map((m) => m.content).join("\n"),
|
|
395
|
-
filters,
|
|
396
|
-
);
|
|
397
|
-
} catch (error) {
|
|
398
|
-
console.error("Error adding to graph memory:", error);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
297
|
return {
|
|
403
298
|
results: vectorStoreResult,
|
|
404
|
-
relations: graphResult?.relations,
|
|
405
299
|
};
|
|
406
300
|
}
|
|
407
301
|
|
|
@@ -480,16 +374,6 @@ export class MemoriesLite {
|
|
|
480
374
|
);
|
|
481
375
|
|
|
482
376
|
|
|
483
|
-
// Search graph store if available
|
|
484
|
-
let graphResults =[];
|
|
485
|
-
if (this.graphMemory) {
|
|
486
|
-
try {
|
|
487
|
-
graphResults = await this.graphMemory.search(query, filters);
|
|
488
|
-
} catch (error) {
|
|
489
|
-
console.error("Error searching graph memory:", error);
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
377
|
const excludedKeys = new Set([
|
|
494
378
|
"userId",
|
|
495
379
|
"agentId",
|
|
@@ -516,7 +400,6 @@ export class MemoriesLite {
|
|
|
516
400
|
|
|
517
401
|
return {
|
|
518
402
|
results,
|
|
519
|
-
relations: graphResults,
|
|
520
403
|
};
|
|
521
404
|
}
|
|
522
405
|
|
|
@@ -578,10 +461,6 @@ export class MemoriesLite {
|
|
|
578
461
|
// Check provider before attempting deleteCol
|
|
579
462
|
await vectorStore.deleteCol();
|
|
580
463
|
|
|
581
|
-
if (this.graphMemory) {
|
|
582
|
-
await this.graphMemory.deleteAll({ userId: "default" }); // Assuming this is okay, or needs similar check?
|
|
583
|
-
}
|
|
584
|
-
|
|
585
464
|
// Re-initialize factories/clients based on the original config
|
|
586
465
|
this.embedder = EmbedderFactory.create(
|
|
587
466
|
this.config.embedder.provider,
|
|
@@ -10,8 +10,7 @@ export interface Entity {
|
|
|
10
10
|
export interface AddMemoryOptions extends Entity {
|
|
11
11
|
metadata?: Record<string, any>;
|
|
12
12
|
filters?: SearchFilters;
|
|
13
|
-
|
|
14
|
-
infer?: boolean;
|
|
13
|
+
capturePrompt?: string;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
export interface SearchMemoryOptions extends Entity {
|