@smythos/sre 1.5.67 → 1.5.70

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.
@@ -160,6 +160,7 @@ export * from './subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class'
160
160
  export * from './subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class';
161
161
  export * from './subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class';
162
162
  export * from './subsystems/IO/VectorDB.service/embed/BaseEmbedding';
163
+ export * from './subsystems/IO/VectorDB.service/embed/GoogleEmbedding';
163
164
  export * from './subsystems/IO/VectorDB.service/embed/index';
164
165
  export * from './subsystems/IO/VectorDB.service/embed/OpenAIEmbedding';
165
166
  export * from './subsystems/LLMManager/LLM.service/connectors/Anthropic.class';
@@ -0,0 +1,14 @@
1
+ import { GoogleGenAI } from '@google/genai';
2
+ import { BaseEmbedding, TEmbeddings } from './BaseEmbedding';
3
+ import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
4
+ export declare class GoogleEmbeds extends BaseEmbedding {
5
+ private settings?;
6
+ protected client: GoogleGenAI;
7
+ static models: string[];
8
+ canSpecifyDimensions: boolean;
9
+ constructor(settings?: Partial<TEmbeddings>);
10
+ embedTexts(texts: string[], candidate: AccessCandidate): Promise<number[][]>;
11
+ embedText(text: string, candidate: AccessCandidate): Promise<number[]>;
12
+ protected embed(texts: string[], candidate: AccessCandidate): Promise<number[][]>;
13
+ private postProcessEmbedding;
14
+ }
@@ -1,16 +1,21 @@
1
1
  import { OpenAIEmbeds } from './OpenAIEmbedding';
2
+ import { GoogleEmbeds } from './GoogleEmbedding';
2
3
  import { TEmbeddings } from './BaseEmbedding';
3
4
  declare const supportedProviders: {
4
5
  readonly OpenAI: {
5
6
  readonly embedder: typeof OpenAIEmbeds;
6
7
  readonly models: string[];
7
8
  };
9
+ readonly GoogleAI: {
10
+ readonly embedder: typeof GoogleEmbeds;
11
+ readonly models: string[];
12
+ };
8
13
  };
9
14
  export type SupportedProviders = keyof typeof supportedProviders;
10
15
  export type SupportedModels = {
11
16
  [K in SupportedProviders]: (typeof supportedProviders)[K]['models'][number];
12
17
  };
13
18
  export declare class EmbeddingsFactory {
14
- static create(provider: SupportedProviders, config: TEmbeddings): OpenAIEmbeds;
19
+ static create(provider: SupportedProviders, config: TEmbeddings): OpenAIEmbeds | GoogleEmbeds;
15
20
  }
16
21
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smythos/sre",
3
- "version": "1.5.67",
3
+ "version": "1.5.70",
4
4
  "description": "Smyth Runtime Environment",
5
5
  "author": "Alaa-eddine KADDOURI",
6
6
  "license": "MIT",
@@ -281,8 +281,6 @@ export class Conversation extends EventEmitter {
281
281
  let _content = '';
282
282
  const reqMethods = this._reqMethods;
283
283
  const toolsConfig = this._toolsConfig;
284
- //deduplicate tools
285
- toolsConfig.tools = toolsConfig.tools.filter((tool, index, self) => self.findIndex((t) => t.name === tool.name) === index);
286
284
  const endpoints = this._endpoints;
287
285
  const baseUrl = this._baseUrl;
288
286
  const message_id = 'msg_' + randomUUID();
@@ -832,15 +830,22 @@ export class Conversation extends EventEmitter {
832
830
  this._customToolsDeclarations.push(toolDefinition);
833
831
  this._customToolsHandlers[tool.name] = tool.handler;
834
832
 
833
+ //deduplicate tools
834
+
835
835
  const llmInference: LLMInference = await LLMInference.getInstance(this.model, AccessCandidate.team(this._teamId));
836
+ this._customToolsDeclarations = this._customToolsDeclarations.filter(
837
+ (tool, index, self) => self.findIndex((t) => t.name === tool.name) === index
838
+ );
836
839
  const toolsConfig: any = llmInference.connector.formatToolsConfig({
837
840
  type: 'function',
838
- toolDefinitions: [toolDefinition],
841
+ toolDefinitions: this._customToolsDeclarations,
839
842
  toolChoice: this.toolChoice,
840
843
  });
841
844
 
842
- if (this._toolsConfig) this._toolsConfig.tools.push(...toolsConfig?.tools);
843
- else this._toolsConfig = toolsConfig;
845
+ //if (this._toolsConfig) this._toolsConfig.tools.push(...toolsConfig?.tools);
846
+ //else this._toolsConfig = toolsConfig;
847
+
848
+ this._toolsConfig = toolsConfig;
844
849
  }
845
850
  /**
846
851
  * updates LLM model, if spec is available, it will update the tools config
@@ -857,15 +862,19 @@ export class Conversation extends EventEmitter {
857
862
  this._baseUrl = this._spec?.servers?.[0].url;
858
863
 
859
864
  const functionDeclarations = this.getFunctionDeclarations(this._spec);
860
- functionDeclarations.push(...this._customToolsDeclarations);
865
+ //functionDeclarations.push(...this._customToolsDeclarations);
866
+ this._customToolsDeclarations.push(...functionDeclarations);
861
867
  const llmInference: LLMInference = await LLMInference.getInstance(this._model, AccessCandidate.team(this._teamId));
862
868
  if (!llmInference.connector) {
863
869
  this.emit('error', 'No connector found for model: ' + this._model);
864
870
  return;
865
871
  }
872
+ this._customToolsDeclarations = this._customToolsDeclarations.filter(
873
+ (tool, index, self) => self.findIndex((t) => t.name === tool.name) === index
874
+ );
866
875
  this._toolsConfig = llmInference.connector.formatToolsConfig({
867
876
  type: 'function',
868
- toolDefinitions: functionDeclarations,
877
+ toolDefinitions: this._customToolsDeclarations,
869
878
  toolChoice: this.toolChoice,
870
879
  });
871
880
 
package/src/index.ts CHANGED
@@ -166,6 +166,7 @@ export * from './subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class'
166
166
  export * from './subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class';
167
167
  export * from './subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class';
168
168
  export * from './subsystems/IO/VectorDB.service/embed/BaseEmbedding';
169
+ export * from './subsystems/IO/VectorDB.service/embed/GoogleEmbedding';
169
170
  export * from './subsystems/IO/VectorDB.service/embed/index';
170
171
  export * from './subsystems/IO/VectorDB.service/embed/OpenAIEmbedding';
171
172
  export * from './subsystems/LLMManager/LLM.service/connectors/Anthropic.class';
package/src/index.ts.bak CHANGED
@@ -166,6 +166,7 @@ export * from './subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class'
166
166
  export * from './subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class';
167
167
  export * from './subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class';
168
168
  export * from './subsystems/IO/VectorDB.service/embed/BaseEmbedding';
169
+ export * from './subsystems/IO/VectorDB.service/embed/GoogleEmbedding';
169
170
  export * from './subsystems/IO/VectorDB.service/embed/index';
170
171
  export * from './subsystems/IO/VectorDB.service/embed/OpenAIEmbedding';
171
172
  export * from './subsystems/LLMManager/LLM.service/connectors/Anthropic.class';
@@ -0,0 +1,118 @@
1
+ import { GoogleGenAI } from '@google/genai';
2
+ import { BaseEmbedding, TEmbeddings } from './BaseEmbedding';
3
+ import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
4
+ import { getLLMCredentials } from '@sre/LLMManager/LLM.service/LLMCredentials.helper';
5
+ import { TLLMCredentials, TLLMModel, BasicCredentials } from '@sre/types/LLM.types';
6
+
7
+ const DEFAULT_MODEL = 'gemini-embedding-001';
8
+
9
+ export class GoogleEmbeds extends BaseEmbedding {
10
+ protected client: GoogleGenAI;
11
+
12
+ // Keep in sync with Gemini API supported embedding models
13
+ public static models = ['gemini-embedding-001', 'text-embedding-005', 'text-multilingual-embedding-002'];
14
+ public canSpecifyDimensions = true;
15
+
16
+ constructor(private settings?: Partial<TEmbeddings>) {
17
+ super({ model: settings?.model ?? DEFAULT_MODEL, ...settings });
18
+ }
19
+
20
+ async embedTexts(texts: string[], candidate: AccessCandidate): Promise<number[][]> {
21
+ const batches = this.chunkArr(this.processTexts(texts), this.chunkSize);
22
+
23
+ const batchRequests = batches.map((batch) => {
24
+ return this.embed(batch, candidate);
25
+ });
26
+ const batchResponses = await Promise.all(batchRequests);
27
+
28
+ const embeddings: number[][] = [];
29
+ for (let i = 0; i < batchResponses.length; i += 1) {
30
+ const batch = batches[i];
31
+ const batchResponse = batchResponses[i];
32
+ for (let j = 0; j < batch.length; j += 1) {
33
+ embeddings.push(batchResponse[j]);
34
+ }
35
+ }
36
+ return embeddings;
37
+ }
38
+
39
+ async embedText(text: string, candidate: AccessCandidate): Promise<number[]> {
40
+ const processedText = this.processTexts([text])[0];
41
+ const embeddings = await this.embed([processedText], candidate);
42
+ return embeddings[0];
43
+ }
44
+
45
+ protected async embed(texts: string[], candidate: AccessCandidate): Promise<number[][]> {
46
+ let apiKey: string | undefined;
47
+
48
+ // Try to get from credentials first
49
+ try {
50
+ const modelInfo: TLLMModel = {
51
+ provider: 'GoogleAI',
52
+ modelId: this.model,
53
+ credentials: this.settings?.credentials as unknown as TLLMCredentials,
54
+ };
55
+ const credentials = await getLLMCredentials(candidate, modelInfo);
56
+ apiKey = (credentials as BasicCredentials)?.apiKey;
57
+ } catch (e) {
58
+ // If credential system fails, fall back to environment variable
59
+ }
60
+
61
+ // Fall back to environment variable if not found in credentials
62
+ if (!apiKey) {
63
+ apiKey = process.env.GOOGLE_AI_API_KEY;
64
+ }
65
+
66
+ if (!apiKey) {
67
+ throw new Error('Please provide an API key for Google AI embeddings via credentials or GOOGLE_AI_API_KEY environment variable');
68
+ }
69
+
70
+ if (!this.client) {
71
+ this.client = new GoogleGenAI({ apiKey });
72
+ }
73
+
74
+ try {
75
+ const outputDimensionality = this.dimensions && Number.isFinite(this.dimensions) ? this.dimensions : undefined;
76
+
77
+ // Batch request using the new SDK
78
+ const res = await this.client.models.embedContent({
79
+ model: this.model,
80
+ contents: texts,
81
+ ...(outputDimensionality ? { outputDimensionality } : {}),
82
+ });
83
+
84
+ // The SDK can return either { embedding } for single or { embeddings } for batch
85
+ const vectors: number[][] = Array.isArray((res as any).embeddings)
86
+ ? (res as any).embeddings.map((e: any) => e.values as number[])
87
+ : [((res as any).embedding?.values as number[]) || []];
88
+
89
+ // Enforce dimensions and normalization when requested or when non-3072
90
+ const targetDim = outputDimensionality;
91
+ const processed = vectors.map((v) => this.postProcessEmbedding(v, targetDim));
92
+
93
+ return processed;
94
+ } catch (e) {
95
+ throw new Error(`Google Embeddings API error: ${e.message || e}`);
96
+ }
97
+ }
98
+
99
+ private postProcessEmbedding(values: number[], targetDim?: number): number[] {
100
+ let v = Array.isArray(values) ? values.slice() : [];
101
+ if (targetDim && targetDim > 0) {
102
+ if (v.length > targetDim) {
103
+ // SDK ignored smaller dimension: truncate
104
+ v = v.slice(0, targetDim);
105
+ } else if (v.length < targetDim) {
106
+ // SDK returned shorter vector: pad with zeros
107
+ v = v.concat(Array(targetDim - v.length).fill(0));
108
+ }
109
+ }
110
+ // Normalize for non-default 3072 dims (recommended by Google docs)
111
+ const needNormalize = (targetDim && targetDim !== 3072) || (!targetDim && v.length !== 3072);
112
+ if (needNormalize && v.length > 0) {
113
+ const norm = Math.sqrt(v.reduce((acc, x) => acc + x * x, 0));
114
+ if (norm > 0) v = v.map((x) => x / norm);
115
+ }
116
+ return v;
117
+ }
118
+ }
@@ -1,4 +1,5 @@
1
1
  import { OpenAIEmbeds } from './OpenAIEmbedding';
2
+ import { GoogleEmbeds } from './GoogleEmbedding';
2
3
  import { TEmbeddings } from './BaseEmbedding';
3
4
 
4
5
  // a factory to get the correct embedding provider based on the provider name
@@ -7,6 +8,10 @@ const supportedProviders = {
7
8
  embedder: OpenAIEmbeds,
8
9
  models: OpenAIEmbeds.models,
9
10
  },
11
+ GoogleAI: {
12
+ embedder: GoogleEmbeds,
13
+ models: GoogleEmbeds.models,
14
+ },
10
15
  } as const;
11
16
 
12
17
  export type SupportedProviders = keyof typeof supportedProviders;