@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.
- package/dist/index.js +42 -42
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.d.ts +14 -0
- package/dist/types/subsystems/IO/VectorDB.service/embed/index.d.ts +6 -1
- package/package.json +1 -1
- package/src/helpers/Conversation.helper.ts +16 -7
- package/src/index.ts +1 -0
- package/src/index.ts.bak +1 -0
- package/src/subsystems/IO/VectorDB.service/embed/GoogleEmbedding.ts +118 -0
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +5 -0
package/dist/types/index.d.ts
CHANGED
|
@@ -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
|
@@ -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:
|
|
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:
|
|
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;
|