@smythos/sre 1.7.18 → 1.7.40

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.
Files changed (69) hide show
  1. package/dist/index.js +120 -82
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/Components/DataSourceIndexer.class.d.ts +4 -12
  4. package/dist/types/Components/GenAILLM.class.d.ts +5 -5
  5. package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +37 -0
  6. package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +30 -0
  7. package/dist/types/Components/RAG/DataSourceIndexer.class.d.ts +14 -0
  8. package/dist/types/Components/RAG/DataSourceLookup.class.d.ts +36 -0
  9. package/dist/types/Components/index.d.ts +3 -3
  10. package/dist/types/helpers/Conversation.helper.d.ts +3 -0
  11. package/dist/types/index.d.ts +3 -3
  12. package/dist/types/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.d.ts +1 -0
  13. package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +11 -4
  14. package/dist/types/subsystems/IO/VectorDB.service/embed/index.d.ts +5 -0
  15. package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +10 -3
  16. package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +4 -2
  17. package/dist/types/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.d.ts +35 -0
  18. package/dist/types/subsystems/Security/Account.service/AccountConnector.d.ts +2 -2
  19. package/dist/types/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.d.ts +10 -0
  20. package/dist/types/subsystems/Security/Vault.service/connectors/SecretsManager.class.d.ts +6 -2
  21. package/dist/types/types/LLM.types.d.ts +2 -0
  22. package/dist/types/types/VectorDB.types.d.ts +4 -0
  23. package/dist/types/utils/array.utils.d.ts +4 -0
  24. package/dist/types/utils/string.utils.d.ts +1 -0
  25. package/package.json +3 -3
  26. package/src/Components/APIEndpoint.class.ts +1 -6
  27. package/src/Components/Component.class.ts +14 -1
  28. package/src/Components/DataSourceIndexer.class.ts +148 -34
  29. package/src/Components/GenAILLM.class.ts +21 -11
  30. package/src/Components/RAG/DataSourceCleaner.class.ts +178 -0
  31. package/src/Components/RAG/DataSourceComponent.class.ts +111 -0
  32. package/src/Components/RAG/DataSourceIndexer.class.ts +254 -0
  33. package/src/Components/{DataSourceLookup.class.ts → RAG/DataSourceLookup.class.ts} +92 -3
  34. package/src/Components/ServerlessCode.class.ts +1 -4
  35. package/src/Components/index.ts +3 -3
  36. package/src/helpers/AWSLambdaCode.helper.ts +40 -45
  37. package/src/helpers/Conversation.helper.ts +14 -10
  38. package/src/helpers/S3Cache.helper.ts +2 -1
  39. package/src/index.ts +212 -212
  40. package/src/index.ts.bak +212 -212
  41. package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +3 -1
  42. package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +145 -19
  43. package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +56 -22
  44. package/src/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.ts +1 -0
  45. package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +2 -1
  46. package/src/subsystems/IO/VectorDB.service/embed/index.ts +18 -0
  47. package/src/subsystems/LLMManager/LLM.inference.ts +63 -47
  48. package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +35 -10
  49. package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +12 -4
  50. package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +4 -4
  51. package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +105 -23
  52. package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +17 -5
  53. package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +18 -3
  54. package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +14 -5
  55. package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +6 -4
  56. package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +5 -5
  57. package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +8 -3
  58. package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +9 -8
  59. package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +126 -28
  60. package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +38 -6
  61. package/src/subsystems/Security/Account.service/AccountConnector.ts +3 -3
  62. package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +111 -48
  63. package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +41 -66
  64. package/src/types/LLM.types.ts +5 -0
  65. package/src/types/VectorDB.types.ts +4 -0
  66. package/src/utils/array.utils.ts +11 -0
  67. package/src/utils/base64.utils.ts +1 -1
  68. package/src/utils/string.utils.ts +3 -192
  69. package/src/Components/DataSourceCleaner.class.ts +0 -92
@@ -1,4 +1,3 @@
1
- //==[ SRE: S3Storage ]======================
2
1
  import { ConnectorService } from '@sre/Core/ConnectorsService';
3
2
  import { JSONContentHelper } from '@sre/helpers/JsonContent.helper';
4
3
  import { Logger } from '@sre/helpers/Log.helper';
@@ -17,12 +16,21 @@ import {
17
16
  VectorDBResult,
18
17
  VectorsResultData,
19
18
  } from '@sre/types/VectorDB.types';
19
+ import { calcSizeMb } from '@sre/utils/string.utils';
20
20
  import { CreateIndexSimpleReq, DataType, ErrorCode, FieldType, MilvusClient } from '@zilliz/milvus2-sdk-node';
21
21
  import crypto from 'crypto';
22
22
  import { jsonrepair } from 'jsonrepair';
23
23
  import { EmbeddingsFactory } from '../embed';
24
24
  import { BaseEmbedding, TEmbeddings } from '../embed/BaseEmbedding';
25
25
  import { DeleteTarget, VectorDBConnector } from '../VectorDBConnector';
26
+ import { NKVConnector } from '@sre/IO/NKV.service/NKVConnector';
27
+
28
+ //! Due to current bug (still investigating), any consumer of this connector
29
+ //! needs to install @zilliz/milvus2-sdk-node in the package.json of the project so it can work
30
+
31
+ //* Note, we are storing Datasources info inside both NKV and Milvus (using some quirks).
32
+ //* The connector favors NKV as storage number 1, and Milvus acting as fallback storage.
33
+ //* This is because Milvus operations are heavy and can be slow the more u add big datasources
26
34
 
27
35
  const console = Logger('Milvus');
28
36
 
@@ -42,7 +50,7 @@ export type MilvusConfig = {
42
50
  };
43
51
 
44
52
  // Define schema field names as a type for strong typing
45
- type SchemaFieldNames = 'id' | 'text' | 'namespaceId' | 'datasourceId' | 'datasourceLabel' | 'vector' | 'acl' | 'user_metadata';
53
+ type SchemaFieldNames = 'id' | 'text' | 'namespaceId' | 'datasourceId' | 'datasourceLabel' | 'vector' | 'acl' | 'user_metadata' | 'smyth_metadata';
46
54
 
47
55
  type SchemaField = FieldType & { name: SchemaFieldNames };
48
56
 
@@ -55,6 +63,7 @@ export class MilvusVectorDB extends VectorDBConnector {
55
63
  public embedder: BaseEmbedding;
56
64
  private SCHEMA_DEFINITION: SchemaField[];
57
65
  private INDEX_PARAMS: IndexParams;
66
+ private nkvConnector: NKVConnector;
58
67
 
59
68
  constructor(protected _settings: MilvusConfig) {
60
69
  super(_settings);
@@ -72,16 +81,22 @@ export class MilvusVectorDB extends VectorDBConnector {
72
81
 
73
82
  console.log('clientConfig', clientConfig);
74
83
 
75
- this.client = new MilvusClient(clientConfig);
84
+ this.client = new MilvusClient(clientConfig, undefined, undefined, undefined, {
85
+ 'grpc.max_receive_message_length': 50 * 1024 * 1024,
86
+ 'grpc.max_send_message_length': 50 * 1024 * 1024,
87
+ max_receive_message_length: 50 * 1024 * 1024,
88
+ max_send_message_length: 50 * 1024 * 1024,
89
+ });
76
90
  console.info('Milvus client initialized');
77
91
  this.accountConnector = ConnectorService.getAccountConnector();
78
92
  this.cache = ConnectorService.getCacheConnector();
93
+ this.nkvConnector = ConnectorService.getNKVConnector();
79
94
 
80
95
  if (!_settings.embeddings) {
81
96
  _settings.embeddings = { provider: 'OpenAI', model: 'text-embedding-3-large', dimensions: 3072 };
82
97
  }
83
98
 
84
- if (!_settings.embeddings.dimensions) _settings.embeddings.dimensions = 3072;
99
+ if (!_settings.embeddings?.dimensions) _settings.embeddings.dimensions = 3072;
85
100
 
86
101
  this.embedder = EmbeddingsFactory.create(_settings.embeddings.provider, _settings.embeddings);
87
102
 
@@ -128,6 +143,11 @@ export class MilvusVectorDB extends VectorDBConnector {
128
143
  data_type: DataType.VarChar,
129
144
  max_length: 2048,
130
145
  },
146
+ {
147
+ name: 'smyth_metadata',
148
+ data_type: DataType.VarChar,
149
+ max_length: 65535,
150
+ },
131
151
  ];
132
152
  this.INDEX_PARAMS = {
133
153
  index_type: 'AUTOINDEX',
@@ -192,6 +212,11 @@ export class MilvusVectorDB extends VectorDBConnector {
192
212
  throw new Error(`Error dropping collection: ${res}`);
193
213
  }
194
214
 
215
+ // delete the linked datasources from nkv
216
+ await this.nkvConnector
217
+ .requester(acRequest.candidate as AccessCandidate)
218
+ .deleteAll(`vectorDB:${this.id}:namespaces:${preparedNs}:datasources`);
219
+
195
220
  await this.deleteACL(AccessCandidate.clone(acRequest.candidate), namespace);
196
221
  }
197
222
 
@@ -213,10 +238,13 @@ export class MilvusVectorDB extends VectorDBConnector {
213
238
  const result = await this.client.search({
214
239
  data: _vector as number[],
215
240
  collection_name: preparedNs,
216
- output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],
217
241
  limit: options.topK || 10,
218
242
  });
219
243
 
244
+ if (result.status.error_code !== ErrorCode.SUCCESS) {
245
+ throw new Error(`Error searching data: ${result.status.detail}`);
246
+ }
247
+
220
248
  return result.results.map((match) => {
221
249
  let _record = match;
222
250
  if (match?.[this.USER_METADATA_KEY]) {
@@ -249,17 +277,45 @@ export class MilvusVectorDB extends VectorDBConnector {
249
277
 
250
278
  const sourceType = this.embedder.detectSourceType(sourceWrapper[0].source);
251
279
  if (sourceType === 'unknown' || sourceType === 'url') throw new Error('Unsupported source type');
280
+
252
281
  const transformedSource = await this.embedder.transformSource(sourceWrapper, sourceType, acRequest.candidate as AccessCandidate);
253
- const preparedSource: Record<SchemaFieldNames, any>[] = transformedSource.map((s) => ({
254
- id: s.id,
255
- text: s.metadata?.text,
256
- user_metadata: s.metadata?.[this.USER_METADATA_KEY],
257
- namespaceId: preparedNs,
258
- datasourceId: s.metadata?.datasourceId,
259
- datasourceLabel: s.metadata?.datasourceLabel,
260
- vector: s.source,
261
- acl: s.metadata?.acl,
262
- }));
282
+
283
+ const liveSchema = await this.client.describeCollection({
284
+ collection_name: preparedNs,
285
+ });
286
+
287
+ // only incl the fields that are in the live schema
288
+
289
+ const preparedSource: Partial<Record<SchemaFieldNames, any>>[] = transformedSource.map((s) => {
290
+ function schemaFieldExists(field: SchemaFieldNames) {
291
+ return liveSchema.schema.fields.some((f) => f.name === field);
292
+ }
293
+ return {
294
+ id: s.id,
295
+ text: s.metadata?.text,
296
+ user_metadata: s.metadata?.[this.USER_METADATA_KEY],
297
+ namespaceId: preparedNs,
298
+ datasourceId: s.metadata?.datasourceId, // legacy field
299
+ datasourceLabel: s.metadata?.datasourceLabel, // legacy field
300
+ vector: s.source,
301
+ acl: s.metadata?.acl,
302
+ ...(schemaFieldExists('smyth_metadata')
303
+ ? {
304
+ smyth_metadata: JSON.stringify({
305
+ datasource: {
306
+ id: s.metadata?.datasourceId,
307
+ label: s.metadata?.datasourceLabel,
308
+ chunkSize: s.metadata?.chunkSize,
309
+ chunkOverlap: s.metadata?.chunkOverlap,
310
+ createdAt: s.metadata?.createdAt,
311
+ datasourceSizeMb: s.metadata?.datasourceSizeMb,
312
+ chunkIndex: s.metadata?.chunkIndex,
313
+ },
314
+ }),
315
+ }
316
+ : {}),
317
+ };
318
+ });
263
319
 
264
320
  const res = await this.client.insert({
265
321
  collection_name: preparedNs,
@@ -322,6 +378,9 @@ export class MilvusVectorDB extends VectorDBConnector {
322
378
  const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner);
323
379
  const dsId = datasource.id || crypto.randomUUID();
324
380
 
381
+ if (!datasource.chunkSize) datasource.chunkSize = 1000;
382
+ if (!datasource.chunkOverlap) datasource.chunkOverlap = 200;
383
+
325
384
  const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);
326
385
  const chunkedText = this.embedder.chunkText(datasource.text, {
327
386
  chunkSize: datasource.chunkSize,
@@ -329,6 +388,7 @@ export class MilvusVectorDB extends VectorDBConnector {
329
388
  });
330
389
  const ids = Array.from({ length: chunkedText.length }, (_, i) => crypto.randomUUID());
331
390
  const label = datasource.label || 'Untitled';
391
+ const totalSizeMb = calcSizeMb(datasource.text);
332
392
  const source: IVectorDataSourceDto[] = chunkedText.map<IVectorDataSourceDto>((doc, i) => {
333
393
  return {
334
394
  id: ids[i],
@@ -338,6 +398,11 @@ export class MilvusVectorDB extends VectorDBConnector {
338
398
  namespaceId: formattedNs,
339
399
  datasourceId: dsId,
340
400
  datasourceLabel: label,
401
+ chunkSize: datasource?.chunkSize?.toString(),
402
+ chunkOverlap: datasource?.chunkOverlap?.toString(),
403
+ createdAt: new Date().getTime().toString(),
404
+ datasourceSizeMb: totalSizeMb.toString(),
405
+ chunkIndex: i,
341
406
  user_metadata: datasource.metadata ? jsonrepair(JSON.stringify(datasource.metadata)) : JSON.stringify({}),
342
407
  },
343
408
  };
@@ -354,7 +419,16 @@ export class MilvusVectorDB extends VectorDBConnector {
354
419
  text: datasource.text,
355
420
  vectorIds: _vIds.map((v) => v.id),
356
421
  id: dsId,
422
+ chunkSize: datasource.chunkSize,
423
+ chunkOverlap: datasource.chunkOverlap,
424
+ createdAt: new Date(),
425
+ datasourceSizeMb: totalSizeMb,
357
426
  };
427
+
428
+ await this.nkvConnector
429
+ .requester(acRequest.candidate as AccessCandidate)
430
+ .set(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, dsId, JSON.stringify(dsData));
431
+
358
432
  if (datasource.returnFullVectorInfo) {
359
433
  dsData.vectorInfo = _vIds;
360
434
  }
@@ -367,6 +441,10 @@ export class MilvusVectorDB extends VectorDBConnector {
367
441
  const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);
368
442
 
369
443
  await this.delete(acRequest, namespace, { datasourceId });
444
+
445
+ await this.nkvConnector
446
+ .requester(acRequest.candidate as AccessCandidate)
447
+ .delete(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, datasourceId);
370
448
  }
371
449
 
372
450
  @SecureConnector.AccessControl
@@ -374,12 +452,26 @@ export class MilvusVectorDB extends VectorDBConnector {
374
452
  //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);
375
453
  const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);
376
454
 
455
+ //* [1] Get datasources from NKV
456
+ try {
457
+ const nkvDatasources = await this.nkvConnector
458
+ .requester(acRequest.candidate as AccessCandidate)
459
+ .list(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`)
460
+ .then((ds) => ds.map((d) => JSONContentHelper.create(d.data?.toString()).tryParse() as IStorageVectorDataSource));
461
+
462
+ return nkvDatasources;
463
+ } catch (error) {
464
+ console.error('[NKV] Error listing datasources: ', error);
465
+ }
466
+
467
+ console.info('Trying to get datasources from Milvus');
468
+ //* [2] Get datasources from Milvus [EXPENSIVE OPERATION] that may exhaust rpc channel
377
469
  // Use queryIterator for memory-efficient pagination
378
470
  const batchSize = 1000; // Process 1000 records at a time
379
471
  const iterator = await this.client.queryIterator({
380
472
  collection_name: formattedNs,
381
473
  batchSize: batchSize,
382
- output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],
474
+ // output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],
383
475
  });
384
476
 
385
477
  // Group records by datasourceId using Map for efficient lookups
@@ -395,16 +487,19 @@ export class MilvusVectorDB extends VectorDBConnector {
395
487
  namespaceId: formattedNs,
396
488
  candidateId: acRequest.candidate.id,
397
489
  candidateRole: acRequest.candidate.role,
398
- text: record.text,
490
+ // text: record.text,
399
491
  name: record.datasourceLabel,
400
492
  metadata: record[this.USER_METADATA_KEY]
401
493
  ? JSONContentHelper.create(record[this.USER_METADATA_KEY].toString()).tryParse()
402
494
  : undefined,
403
- vectorIds: [],
404
495
  id: datasourceId,
496
+ vectorIds: [], // to be filled iteratively
497
+ text: '', // to be filled iteratively
405
498
  });
406
499
  }
407
500
  datasourceMap.get(datasourceId)!.vectorIds.push(record.id);
501
+ // the text here represents the total text of the datasource (not a vector-stored text)
502
+ datasourceMap.get(datasourceId)!.text += record.text;
408
503
  }
409
504
  }
410
505
  } finally {
@@ -418,10 +513,41 @@ export class MilvusVectorDB extends VectorDBConnector {
418
513
  protected async getDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<IStorageVectorDataSource | undefined> {
419
514
  //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);
420
515
  const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);
516
+
517
+ //* [1] Get datasource from NKV
518
+ try {
519
+ const nkvDatasource = await this.nkvConnector
520
+ .requester(acRequest.candidate as AccessCandidate)
521
+ .get(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, datasourceId)
522
+ .then((ds) => JSONContentHelper.create(ds?.toString()).tryParse() as IStorageVectorDataSource);
523
+
524
+ if (nkvDatasource) {
525
+ return nkvDatasource;
526
+ } else {
527
+ console.info('Datasource not found in NKV');
528
+ }
529
+ } catch (error) {
530
+ console.error('[NKV] Error getting datasource: ', error);
531
+ }
532
+
533
+ console.info('Trying to get datasource from Milvus');
534
+
535
+ //* [2] Get datasource from Milvus
421
536
  const res = await this.client.query({
422
537
  collection_name: formattedNs,
423
538
  expr: `datasourceId == "${datasourceId}"`,
424
- output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],
539
+ // output_fields: [
540
+ // 'id',
541
+ // 'text',
542
+ // this.USER_METADATA_KEY,
543
+ // 'namespaceId',
544
+ // 'datasourceId',
545
+ // 'datasourceLabel',
546
+ // 'vector',
547
+ // 'chunkSize',
548
+ // 'chunkOverlap',
549
+ // 'createdAt',
550
+ // ],
425
551
  });
426
552
  // if 0 results, throw error
427
553
  if (res.data.length === 0) {
@@ -24,20 +24,29 @@ import { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector'
24
24
  import crypto from 'crypto';
25
25
  import { BaseEmbedding, TEmbeddings } from '../embed/BaseEmbedding';
26
26
  import { EmbeddingsFactory, SupportedProviders, SupportedModels } from '../embed';
27
-
27
+ import { calcSizeMb } from '@sre/utils/string.utils';
28
28
  import { jsonrepair } from 'jsonrepair';
29
+ import { chunkArr } from '@sre/utils/array.utils';
29
30
 
30
31
  const console = Logger('Pinecone VectorDB');
31
32
 
32
33
  export type PineconeConfig = {
33
34
  /**
34
- * The Pinecone API key
35
+ * The Pinecone API key [LEGACY]
35
36
  */
36
- apiKey: string;
37
+ apiKey?: string;
37
38
  /**
38
- * The Pinecone index name
39
+ * The Pinecone index name [LEGACY]
39
40
  */
40
- indexName: string;
41
+ indexName?: string;
42
+
43
+ /**
44
+ * The Pinecone credentials [New unified format]
45
+ */
46
+ credentials?: {
47
+ apiKey: string;
48
+ indexName: string;
49
+ };
41
50
  /**
42
51
  * The embeddings model to use
43
52
  */
@@ -55,28 +64,28 @@ export class PineconeVectorDB extends VectorDBConnector {
55
64
 
56
65
  constructor(protected _settings: PineconeConfig) {
57
66
  super(_settings);
58
- if (!_settings.apiKey) {
67
+ if (!_settings.apiKey && !_settings?.credentials?.apiKey) {
59
68
  console.warn('Missing Pinecone API key : returning empty Pinecone connector');
60
69
  return;
61
70
  }
62
- if (!_settings.indexName) {
71
+ if (!_settings.indexName && !_settings?.credentials?.indexName) {
63
72
  console.warn('Missing Pinecone index name : returning empty Pinecone connector');
64
73
  return;
65
74
  }
66
75
 
67
76
  this.client = new Pinecone({
68
- apiKey: _settings.apiKey,
77
+ apiKey: _settings.apiKey || _settings.credentials?.apiKey,
69
78
  });
70
79
  console.info('Pinecone client initialized');
71
- console.info('Pinecone index name:', _settings.indexName);
72
- this.indexName = _settings.indexName;
80
+ console.info('Pinecone index name:', _settings.indexName || _settings.credentials?.indexName);
81
+ this.indexName = _settings.indexName || _settings.credentials?.indexName;
73
82
  this.accountConnector = ConnectorService.getAccountConnector();
74
83
  this.cache = ConnectorService.getCacheConnector();
75
84
  this.nkvConnector = ConnectorService.getNKVConnector();
76
85
  if (!_settings.embeddings) {
77
86
  _settings.embeddings = { provider: 'OpenAI', model: 'text-embedding-3-large', dimensions: 3072 };
78
87
  }
79
- if (!_settings.embeddings.dimensions) _settings.embeddings.dimensions = 3072;
88
+ if (!_settings.embeddings?.dimensions) _settings.embeddings.dimensions = 3072;
80
89
 
81
90
  this.embedder = EmbeddingsFactory.create(_settings.embeddings.provider, _settings.embeddings);
82
91
  }
@@ -229,17 +238,28 @@ export class PineconeVectorDB extends VectorDBConnector {
229
238
  const sourceType = this.embedder.detectSourceType(sourceWrapper[0].source);
230
239
  if (sourceType === 'unknown' || sourceType === 'url') throw new Error('Invalid source type');
231
240
  const transformedSource = await this.embedder.transformSource(sourceWrapper, sourceType, acRequest.candidate as AccessCandidate);
232
- const preparedSource = transformedSource.map((s) => ({
241
+ const preparedSources = transformedSource.map((s) => ({
233
242
  id: s.id,
234
243
  values: s.source as number[],
235
244
  metadata: s.metadata,
236
245
  }));
237
246
 
238
- // await pineconeStore.addDocuments(chunks, ids);
239
- await this.client
240
- .Index(this.indexName)
241
- .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))
242
- .upsert(preparedSource);
247
+ // pinecone advices to use batches of 100 at a time
248
+ const batchSize = 100;
249
+ const chunkedVectors = chunkArr(preparedSources, batchSize);
250
+
251
+ // await this.client
252
+ // .Index(this.indexName)
253
+ // .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))
254
+ // .upsert(preparedSources);
255
+
256
+ const promises = chunkedVectors.map(async (chunk) => {
257
+ await this.client
258
+ .Index(this.indexName)
259
+ .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))
260
+ .upsert(chunk);
261
+ });
262
+ await Promise.all(promises);
243
263
 
244
264
  const accessCandidate = acRequest.candidate;
245
265
 
@@ -249,7 +269,7 @@ export class PineconeVectorDB extends VectorDBConnector {
249
269
  await this.setACL(acRequest, namespace, acl);
250
270
  }
251
271
 
252
- return preparedSource.map((s) => {
272
+ return preparedSources.map((s) => {
253
273
  const { text, acl, user_metadata, ...restMetadata } = s.metadata || {};
254
274
  return {
255
275
  id: s.id,
@@ -272,10 +292,16 @@ export class PineconeVectorDB extends VectorDBConnector {
272
292
  } else {
273
293
  const _ids = Array.isArray(deleteTarget) ? deleteTarget : [deleteTarget];
274
294
 
275
- const res = await this.client
276
- .Index(this.indexName)
277
- .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))
278
- .deleteMany(_ids);
295
+ const batchSize = 800;
296
+ const chunkedIds = chunkArr(_ids, batchSize);
297
+
298
+ const promises = chunkedIds.map(async (chunk) => {
299
+ await this.client
300
+ .Index(this.indexName)
301
+ .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))
302
+ .deleteMany(chunk);
303
+ });
304
+ await Promise.all(promises);
279
305
  }
280
306
  }
281
307
 
@@ -285,6 +311,9 @@ export class PineconeVectorDB extends VectorDBConnector {
285
311
  const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner);
286
312
  const dsId = datasource.id || crypto.randomUUID();
287
313
 
314
+ if (!datasource.chunkSize) datasource.chunkSize = 2000;
315
+ if (!datasource.chunkOverlap) datasource.chunkOverlap = 200;
316
+
288
317
  const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);
289
318
  const chunkedText = this.embedder.chunkText(datasource.text, {
290
319
  chunkSize: datasource.chunkSize,
@@ -301,6 +330,7 @@ export class PineconeVectorDB extends VectorDBConnector {
301
330
  namespaceId: formattedNs,
302
331
  datasourceId: dsId,
303
332
  datasourceLabel: label,
333
+ chunkIndex: i,
304
334
  user_metadata: datasource.metadata ? jsonrepair(JSON.stringify(datasource.metadata)) : undefined,
305
335
  },
306
336
  };
@@ -317,6 +347,10 @@ export class PineconeVectorDB extends VectorDBConnector {
317
347
  text: datasource.text,
318
348
  vectorIds: _vIds.map((v) => v.id),
319
349
  id: dsId,
350
+ datasourceSizeMb: calcSizeMb(datasource.text),
351
+ chunkSize: datasource.chunkSize,
352
+ chunkOverlap: datasource.chunkOverlap,
353
+ createdAt: new Date(),
320
354
  };
321
355
  if (datasource.returnFullVectorInfo) {
322
356
  dsData.vectorInfo = _vIds;
@@ -18,6 +18,7 @@ export class GoogleEmbeds extends BaseEmbedding {
18
18
  }
19
19
 
20
20
  async embedTexts(texts: string[], candidate: AccessCandidate): Promise<number[][]> {
21
+ // we split into batches to avoid provider limits
21
22
  const batches = this.chunkArr(this.processTexts(texts), this.batchSize);
22
23
 
23
24
  const batchRequests = batches.map((batch) => {
@@ -24,7 +24,7 @@ export class OpenAIEmbeds extends BaseEmbedding {
24
24
  protected client: OpenAIClient;
25
25
  protected clientConfig: ClientOptions;
26
26
 
27
- public static models = ['text-embedding-ada-002', 'text-embedding-3-large'];
27
+ public static models = ['text-embedding-3-large', 'text-embedding-ada-002'];
28
28
  public canSpecifyDimensions = true;
29
29
 
30
30
  constructor(private settings?: Partial<TEmbeddings>) {
@@ -41,6 +41,7 @@ export class OpenAIEmbeds extends BaseEmbedding {
41
41
  }
42
42
 
43
43
  async embedTexts(texts: string[], candidate: AccessCandidate): Promise<number[][]> {
44
+ // we split into batches to avoid provider limits
44
45
  const batches = this.chunkArr(this.processTexts(texts), this.batchSize);
45
46
 
46
47
  const batchRequests = batches.map((batch) => {
@@ -34,4 +34,22 @@ export class EmbeddingsFactory {
34
34
 
35
35
  return new supportedProviders[provider as SupportedProviders].embedder(config);
36
36
  }
37
+
38
+ public static getProviderByModel(model: SupportedModels): SupportedProviders {
39
+ return Object.keys(supportedProviders).find((provider) => supportedProviders[provider].models.includes(model)) as SupportedProviders;
40
+ }
41
+
42
+ public static getModels() {
43
+ return Object.keys(supportedProviders)
44
+ .reduce((acc, provider) => {
45
+ acc.push(
46
+ ...supportedProviders[provider].models.map((model) => ({
47
+ provider,
48
+ model,
49
+ }))
50
+ );
51
+ return acc;
52
+ }, [] as { provider: SupportedProviders; model: SupportedModels[SupportedProviders] }[])
53
+ .filter((item) => item.model !== 'text-embedding-ada-002'); //! SPECIAL case for ada-002, it doesn't support dimensions passing
54
+ }
37
55
  }