mem0ai 2.1.38 → 2.2.1

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.
@@ -12,7 +12,9 @@ var MemoryConfigSchema = z.object({
12
12
  modelProperties: z.record(z.string(), z.any()).optional(),
13
13
  apiKey: z.string().optional(),
14
14
  model: z.union([z.string(), z.any()]).optional(),
15
- baseURL: z.string().optional()
15
+ baseURL: z.string().optional(),
16
+ embeddingDims: z.number().optional(),
17
+ url: z.string().optional()
16
18
  })
17
19
  }),
18
20
  vectorStore: z.object({
@@ -61,6 +63,7 @@ var OpenAIEmbedder = class {
61
63
  constructor(config) {
62
64
  this.openai = new OpenAI({ apiKey: config.apiKey });
63
65
  this.model = config.model || "text-embedding-3-small";
66
+ this.embeddingDims = config.embeddingDims || 1536;
64
67
  }
65
68
  async embed(text) {
66
69
  const response = await this.openai.embeddings.create({
@@ -98,6 +101,7 @@ var OllamaEmbedder = class {
98
101
  host: config.url || "http://localhost:11434"
99
102
  });
100
103
  this.model = config.model || "nomic-embed-text:latest";
104
+ this.embeddingDims = config.embeddingDims || 768;
101
105
  this.ensureModelExists().catch((err) => {
102
106
  logger.error(`Error ensuring model exists: ${err}`);
103
107
  });
@@ -140,7 +144,7 @@ var OpenAILLM = class {
140
144
  apiKey: config.apiKey,
141
145
  baseURL: config.baseURL
142
146
  });
143
- this.model = config.model || "gpt-4o-mini";
147
+ this.model = config.model || "gpt-4.1-nano-2025-04-14";
144
148
  }
145
149
  async generateResponse(messages, responseFormat, tools) {
146
150
  const completion = await this.openai.chat.completions.create({
@@ -269,7 +273,12 @@ var AnthropicLLM = class {
269
273
  system: typeof (systemMessage == null ? void 0 : systemMessage.content) === "string" ? systemMessage.content : void 0,
270
274
  max_tokens: 4096
271
275
  });
272
- return response.content[0].text;
276
+ const firstBlock = response.content[0];
277
+ if (firstBlock.type === "text") {
278
+ return firstBlock.text;
279
+ } else {
280
+ throw new Error("Unexpected response type from Anthropic API");
281
+ }
273
282
  }
274
283
  async generateChat(messages) {
275
284
  const response = await this.generateResponse(messages);
@@ -2171,14 +2180,17 @@ create table ${this.tableName} (
2171
2180
  import { GoogleGenAI } from "@google/genai";
2172
2181
  var GoogleEmbedder = class {
2173
2182
  constructor(config) {
2174
- this.google = new GoogleGenAI({ apiKey: config.apiKey });
2175
- this.model = config.model || "text-embedding-004";
2183
+ this.google = new GoogleGenAI({
2184
+ apiKey: config.apiKey || process.env.GOOGLE_API_KEY
2185
+ });
2186
+ this.model = config.model || "gemini-embedding-001";
2187
+ this.embeddingDims = config.embeddingDims || 1536;
2176
2188
  }
2177
2189
  async embed(text) {
2178
2190
  const response = await this.google.models.embedContent({
2179
2191
  model: this.model,
2180
2192
  contents: text,
2181
- config: { outputDimensionality: 768 }
2193
+ config: { outputDimensionality: this.embeddingDims }
2182
2194
  });
2183
2195
  return response.embeddings[0].values;
2184
2196
  }
@@ -2307,6 +2319,7 @@ var AzureOpenAIEmbedder = class {
2307
2319
  ...rest
2308
2320
  });
2309
2321
  this.model = config.model || "text-embedding-3-small";
2322
+ this.embeddingDims = config.embeddingDims || 1536;
2310
2323
  }
2311
2324
  async embed(text) {
2312
2325
  const response = await this.client.embeddings.create({
@@ -3057,6 +3070,449 @@ var LangchainVectorStore = class {
3057
3070
  }
3058
3071
  };
3059
3072
 
3073
+ // src/oss/src/vector_stores/azure_ai_search.ts
3074
+ import {
3075
+ SearchClient,
3076
+ SearchIndexClient,
3077
+ AzureKeyCredential
3078
+ } from "@azure/search-documents";
3079
+ import { DefaultAzureCredential } from "@azure/identity";
3080
+ var AzureAISearch = class {
3081
+ constructor(config) {
3082
+ this.serviceName = config.serviceName;
3083
+ this.indexName = config.collectionName;
3084
+ this.embeddingModelDims = config.embeddingModelDims;
3085
+ this.compressionType = config.compressionType || "none";
3086
+ this.useFloat16 = config.useFloat16 || false;
3087
+ this.hybridSearch = config.hybridSearch || false;
3088
+ this.vectorFilterMode = config.vectorFilterMode || "preFilter";
3089
+ this.apiKey = config.apiKey;
3090
+ const serviceEndpoint = `https://${this.serviceName}.search.windows.net`;
3091
+ const credential = this.apiKey && this.apiKey !== "" && this.apiKey !== "your-api-key" ? new AzureKeyCredential(this.apiKey) : new DefaultAzureCredential();
3092
+ this.searchClient = new SearchClient(
3093
+ serviceEndpoint,
3094
+ this.indexName,
3095
+ credential
3096
+ );
3097
+ this.indexClient = new SearchIndexClient(serviceEndpoint, credential);
3098
+ this.initialize().catch(console.error);
3099
+ }
3100
+ /**
3101
+ * Initialize the Azure AI Search index if it doesn't exist
3102
+ */
3103
+ async initialize() {
3104
+ try {
3105
+ const collections = await this.listCols();
3106
+ if (!collections.includes(this.indexName)) {
3107
+ await this.createCol();
3108
+ }
3109
+ } catch (error) {
3110
+ console.error("Error initializing Azure AI Search:", error);
3111
+ throw error;
3112
+ }
3113
+ }
3114
+ /**
3115
+ * Create a new index in Azure AI Search
3116
+ */
3117
+ async createCol() {
3118
+ const vectorType = this.useFloat16 ? "Collection(Edm.Half)" : "Collection(Edm.Single)";
3119
+ const compressionConfigurations = [];
3120
+ let compressionName = void 0;
3121
+ if (this.compressionType === "scalar") {
3122
+ compressionName = "myCompression";
3123
+ compressionConfigurations.push({
3124
+ kind: "scalarQuantization",
3125
+ compressionName
3126
+ });
3127
+ } else if (this.compressionType === "binary") {
3128
+ compressionName = "myCompression";
3129
+ compressionConfigurations.push({
3130
+ kind: "binaryQuantization",
3131
+ compressionName
3132
+ });
3133
+ }
3134
+ const fields = [
3135
+ {
3136
+ name: "id",
3137
+ type: "Edm.String",
3138
+ key: true
3139
+ },
3140
+ {
3141
+ name: "user_id",
3142
+ type: "Edm.String",
3143
+ filterable: true
3144
+ },
3145
+ {
3146
+ name: "run_id",
3147
+ type: "Edm.String",
3148
+ filterable: true
3149
+ },
3150
+ {
3151
+ name: "agent_id",
3152
+ type: "Edm.String",
3153
+ filterable: true
3154
+ },
3155
+ {
3156
+ name: "vector",
3157
+ type: vectorType,
3158
+ searchable: true,
3159
+ vectorSearchDimensions: this.embeddingModelDims,
3160
+ vectorSearchProfileName: "my-vector-config"
3161
+ },
3162
+ {
3163
+ name: "payload",
3164
+ type: "Edm.String",
3165
+ searchable: true
3166
+ }
3167
+ ];
3168
+ const vectorSearch = {
3169
+ profiles: [
3170
+ {
3171
+ name: "my-vector-config",
3172
+ algorithmConfigurationName: "my-algorithms-config",
3173
+ compressionName: this.compressionType !== "none" ? compressionName : void 0
3174
+ }
3175
+ ],
3176
+ algorithms: [
3177
+ {
3178
+ kind: "hnsw",
3179
+ name: "my-algorithms-config"
3180
+ }
3181
+ ],
3182
+ compressions: compressionConfigurations
3183
+ };
3184
+ const index = {
3185
+ name: this.indexName,
3186
+ fields,
3187
+ vectorSearch
3188
+ };
3189
+ await this.indexClient.createOrUpdateIndex(index);
3190
+ }
3191
+ /**
3192
+ * Generate a document for insertion
3193
+ */
3194
+ generateDocument(vector, payload, id) {
3195
+ const document = {
3196
+ id,
3197
+ vector,
3198
+ payload: JSON.stringify(payload)
3199
+ };
3200
+ for (const field of ["user_id", "run_id", "agent_id"]) {
3201
+ if (field in payload) {
3202
+ document[field] = payload[field];
3203
+ }
3204
+ }
3205
+ return document;
3206
+ }
3207
+ /**
3208
+ * Insert vectors into the index
3209
+ */
3210
+ async insert(vectors, ids, payloads) {
3211
+ console.log(
3212
+ `Inserting ${vectors.length} vectors into index ${this.indexName}`
3213
+ );
3214
+ const documents = vectors.map(
3215
+ (vector, idx) => this.generateDocument(vector, payloads[idx] || {}, ids[idx])
3216
+ );
3217
+ const response = await this.searchClient.uploadDocuments(documents);
3218
+ for (const result of response.results) {
3219
+ if (!result.succeeded) {
3220
+ throw new Error(
3221
+ `Insert failed for document ${result.key}: ${result.errorMessage}`
3222
+ );
3223
+ }
3224
+ }
3225
+ }
3226
+ /**
3227
+ * Sanitize filter keys to remove non-alphanumeric characters
3228
+ */
3229
+ sanitizeKey(key) {
3230
+ return key.replace(/[^\w]/g, "");
3231
+ }
3232
+ /**
3233
+ * Build OData filter expression from SearchFilters
3234
+ */
3235
+ buildFilterExpression(filters) {
3236
+ const filterConditions = [];
3237
+ for (const [key, value] of Object.entries(filters)) {
3238
+ const safeKey = this.sanitizeKey(key);
3239
+ if (typeof value === "string") {
3240
+ const safeValue = value.replace(/'/g, "''");
3241
+ filterConditions.push(`${safeKey} eq '${safeValue}'`);
3242
+ } else {
3243
+ filterConditions.push(`${safeKey} eq ${value}`);
3244
+ }
3245
+ }
3246
+ return filterConditions.join(" and ");
3247
+ }
3248
+ /**
3249
+ * Extract JSON from payload string
3250
+ * Handles cases where payload might have extra text
3251
+ */
3252
+ extractJson(payload) {
3253
+ try {
3254
+ JSON.parse(payload);
3255
+ return payload;
3256
+ } catch (e) {
3257
+ const match = payload.match(/\{.*\}/s);
3258
+ return match ? match[0] : payload;
3259
+ }
3260
+ }
3261
+ /**
3262
+ * Search for similar vectors
3263
+ */
3264
+ async search(query, limit = 5, filters) {
3265
+ const filterExpression = filters ? this.buildFilterExpression(filters) : void 0;
3266
+ const vectorQuery = {
3267
+ kind: "vector",
3268
+ vector: query,
3269
+ kNearestNeighborsCount: limit,
3270
+ fields: ["vector"]
3271
+ };
3272
+ let searchResults;
3273
+ if (this.hybridSearch) {
3274
+ searchResults = await this.searchClient.search("*", {
3275
+ vectorSearchOptions: {
3276
+ queries: [vectorQuery],
3277
+ filterMode: this.vectorFilterMode
3278
+ },
3279
+ filter: filterExpression,
3280
+ top: limit,
3281
+ searchFields: ["payload"]
3282
+ });
3283
+ } else {
3284
+ searchResults = await this.searchClient.search("*", {
3285
+ vectorSearchOptions: {
3286
+ queries: [vectorQuery],
3287
+ filterMode: this.vectorFilterMode
3288
+ },
3289
+ filter: filterExpression,
3290
+ top: limit
3291
+ });
3292
+ }
3293
+ const results = [];
3294
+ for await (const result of searchResults.results) {
3295
+ const payloadStr = result.document.payload;
3296
+ const payload = JSON.parse(this.extractJson(payloadStr));
3297
+ results.push({
3298
+ id: result.document.id,
3299
+ score: result.score,
3300
+ payload
3301
+ });
3302
+ }
3303
+ return results;
3304
+ }
3305
+ /**
3306
+ * Delete a vector by ID
3307
+ */
3308
+ async delete(vectorId) {
3309
+ const response = await this.searchClient.deleteDocuments([
3310
+ { id: vectorId }
3311
+ ]);
3312
+ for (const result of response.results) {
3313
+ if (!result.succeeded) {
3314
+ throw new Error(
3315
+ `Delete failed for document ${vectorId}: ${result.errorMessage}`
3316
+ );
3317
+ }
3318
+ }
3319
+ console.log(
3320
+ `Deleted document with ID '${vectorId}' from index '${this.indexName}'.`
3321
+ );
3322
+ }
3323
+ /**
3324
+ * Update a vector and its payload
3325
+ */
3326
+ async update(vectorId, vector, payload) {
3327
+ const document = { id: vectorId };
3328
+ if (vector) {
3329
+ document.vector = vector;
3330
+ }
3331
+ if (payload) {
3332
+ document.payload = JSON.stringify(payload);
3333
+ for (const field of ["user_id", "run_id", "agent_id"]) {
3334
+ if (field in payload) {
3335
+ document[field] = payload[field];
3336
+ }
3337
+ }
3338
+ }
3339
+ const response = await this.searchClient.mergeOrUploadDocuments([document]);
3340
+ for (const result of response.results) {
3341
+ if (!result.succeeded) {
3342
+ throw new Error(
3343
+ `Update failed for document ${vectorId}: ${result.errorMessage}`
3344
+ );
3345
+ }
3346
+ }
3347
+ }
3348
+ /**
3349
+ * Retrieve a vector by ID
3350
+ */
3351
+ async get(vectorId) {
3352
+ try {
3353
+ const result = await this.searchClient.getDocument(vectorId);
3354
+ const payloadStr = result.payload;
3355
+ const payload = JSON.parse(this.extractJson(payloadStr));
3356
+ return {
3357
+ id: result.id,
3358
+ payload
3359
+ };
3360
+ } catch (error) {
3361
+ if ((error == null ? void 0 : error.statusCode) === 404) {
3362
+ return null;
3363
+ }
3364
+ throw error;
3365
+ }
3366
+ }
3367
+ /**
3368
+ * List all collections (indexes)
3369
+ */
3370
+ async listCols() {
3371
+ const names = [];
3372
+ for await (const index of this.indexClient.listIndexes()) {
3373
+ names.push(index.name);
3374
+ }
3375
+ return names;
3376
+ }
3377
+ /**
3378
+ * Delete the index
3379
+ */
3380
+ async deleteCol() {
3381
+ await this.indexClient.deleteIndex(this.indexName);
3382
+ }
3383
+ /**
3384
+ * Get information about the index
3385
+ */
3386
+ async colInfo() {
3387
+ const index = await this.indexClient.getIndex(this.indexName);
3388
+ return {
3389
+ name: index.name,
3390
+ fields: index.fields
3391
+ };
3392
+ }
3393
+ /**
3394
+ * List all vectors in the index
3395
+ */
3396
+ async list(filters, limit = 100) {
3397
+ const filterExpression = filters ? this.buildFilterExpression(filters) : void 0;
3398
+ const searchResults = await this.searchClient.search("*", {
3399
+ filter: filterExpression,
3400
+ top: limit
3401
+ });
3402
+ const results = [];
3403
+ for await (const result of searchResults.results) {
3404
+ const payloadStr = result.document.payload;
3405
+ const payload = JSON.parse(this.extractJson(payloadStr));
3406
+ results.push({
3407
+ id: result.document.id,
3408
+ score: result.score,
3409
+ payload
3410
+ });
3411
+ }
3412
+ return [results, results.length];
3413
+ }
3414
+ /**
3415
+ * Generate a random user ID
3416
+ */
3417
+ generateUUID() {
3418
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
3419
+ /[xy]/g,
3420
+ function(c) {
3421
+ const r = Math.random() * 16 | 0;
3422
+ const v = c === "x" ? r : r & 3 | 8;
3423
+ return v.toString(16);
3424
+ }
3425
+ );
3426
+ }
3427
+ /**
3428
+ * Get user ID from memory_migrations collection
3429
+ * Required by VectorStore interface
3430
+ */
3431
+ async getUserId() {
3432
+ try {
3433
+ const collections = await this.listCols();
3434
+ const migrationIndexExists = collections.includes("memory_migrations");
3435
+ if (!migrationIndexExists) {
3436
+ const migrationIndex = {
3437
+ name: "memory_migrations",
3438
+ fields: [
3439
+ {
3440
+ name: "id",
3441
+ type: "Edm.String",
3442
+ key: true
3443
+ },
3444
+ {
3445
+ name: "user_id",
3446
+ type: "Edm.String",
3447
+ searchable: false,
3448
+ filterable: true
3449
+ }
3450
+ ]
3451
+ };
3452
+ await this.indexClient.createOrUpdateIndex(migrationIndex);
3453
+ }
3454
+ const searchResults = await this.searchClient.search("*", {
3455
+ top: 1
3456
+ });
3457
+ for await (const result of searchResults.results) {
3458
+ const userId = result.document.user_id;
3459
+ if (userId) {
3460
+ return userId;
3461
+ }
3462
+ }
3463
+ const randomUserId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
3464
+ await this.searchClient.uploadDocuments([
3465
+ {
3466
+ id: this.generateUUID(),
3467
+ user_id: randomUserId
3468
+ }
3469
+ ]);
3470
+ return randomUserId;
3471
+ } catch (error) {
3472
+ console.error("Error getting user ID:", error);
3473
+ throw error;
3474
+ }
3475
+ }
3476
+ /**
3477
+ * Set user ID in memory_migrations collection
3478
+ * Required by VectorStore interface
3479
+ */
3480
+ async setUserId(userId) {
3481
+ try {
3482
+ const searchResults = await this.searchClient.search("*", {
3483
+ top: 1
3484
+ });
3485
+ let pointId = this.generateUUID();
3486
+ for await (const result of searchResults.results) {
3487
+ pointId = result.document.id;
3488
+ break;
3489
+ }
3490
+ await this.searchClient.mergeOrUploadDocuments([
3491
+ {
3492
+ id: pointId,
3493
+ user_id: userId
3494
+ }
3495
+ ]);
3496
+ } catch (error) {
3497
+ console.error("Error setting user ID:", error);
3498
+ throw error;
3499
+ }
3500
+ }
3501
+ /**
3502
+ * Reset the index by deleting and recreating it
3503
+ */
3504
+ async reset() {
3505
+ console.log(`Resetting index ${this.indexName}...`);
3506
+ try {
3507
+ await this.deleteCol();
3508
+ await this.createCol();
3509
+ } catch (error) {
3510
+ console.error(`Error resetting index ${this.indexName}:`, error);
3511
+ throw error;
3512
+ }
3513
+ }
3514
+ };
3515
+
3060
3516
  // src/oss/src/utils/factory.ts
3061
3517
  var EmbedderFactory = class {
3062
3518
  static create(provider, config) {
@@ -3119,6 +3575,8 @@ var VectorStoreFactory = class {
3119
3575
  return new LangchainVectorStore(config);
3120
3576
  case "vectorize":
3121
3577
  return new VectorizeDB(config);
3578
+ case "azure-ai-search":
3579
+ return new AzureAISearch(config);
3122
3580
  default:
3123
3581
  throw new Error(`Unsupported vector store provider: ${provider}`);
3124
3582
  }
@@ -3233,6 +3691,7 @@ var ConfigManager = class {
3233
3691
  apiKey: (userConf == null ? void 0 : userConf.apiKey) !== void 0 ? userConf.apiKey : defaultConf.apiKey,
3234
3692
  model: finalModel,
3235
3693
  url: userConf == null ? void 0 : userConf.url,
3694
+ embeddingDims: userConf == null ? void 0 : userConf.embeddingDims,
3236
3695
  modelProperties: (userConf == null ? void 0 : userConf.modelProperties) !== void 0 ? userConf.modelProperties : defaultConf.modelProperties
3237
3696
  };
3238
3697
  })()
@@ -3443,7 +3902,7 @@ var MemoryGraph = class {
3443
3902
  }
3444
3903
  this.llm = LLMFactory.create(this.llmProvider, this.config.llm.config);
3445
3904
  this.structuredLlm = LLMFactory.create(
3446
- "openai_structured",
3905
+ this.llmProvider,
3447
3906
  this.config.llm.config
3448
3907
  );
3449
3908
  this.threshold = 0.7;
@@ -4183,8 +4642,13 @@ var Memory = class _Memory {
4183
4642
  return returnedMemories;
4184
4643
  }
4185
4644
  const parsedMessages = messages.map((m) => m.content).join("\n");
4186
- const [systemPrompt, userPrompt] = this.customPrompt ? [this.customPrompt, `Input:
4187
- ${parsedMessages}`] : getFactRetrievalMessages(parsedMessages);
4645
+ const [systemPrompt, userPrompt] = this.customPrompt ? [
4646
+ this.customPrompt.toLowerCase().includes("json") ? this.customPrompt : `${this.customPrompt}
4647
+
4648
+ You MUST return a valid JSON object with a 'facts' key containing an array of strings.`,
4649
+ `Input:
4650
+ ${parsedMessages}`
4651
+ ] : getFactRetrievalMessages(parsedMessages);
4188
4652
  const response = await this.llm.generateResponse(
4189
4653
  [
4190
4654
  { role: "system", content: systemPrompt },
@@ -4562,6 +5026,7 @@ ${parsedMessages}`] : getFactRetrievalMessages(parsedMessages);
4562
5026
  };
4563
5027
  export {
4564
5028
  AnthropicLLM,
5029
+ AzureAISearch,
4565
5030
  AzureOpenAIEmbedder,
4566
5031
  EmbedderFactory,
4567
5032
  GoogleEmbedder,