@memberjunction/ai-vertex 2.128.0 → 2.130.0
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/__tests__/vertexLLM.test.d.ts +2 -0
- package/dist/__tests__/vertexLLM.test.d.ts.map +1 -0
- package/dist/__tests__/vertexLLM.test.js +439 -0
- package/dist/__tests__/vertexLLM.test.js.map +1 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/models/vertexLLM.d.ts +109 -54
- package/dist/models/vertexLLM.d.ts.map +1 -1
- package/dist/models/vertexLLM.js +151 -271
- package/dist/models/vertexLLM.js.map +1 -1
- package/package.json +12 -5
- package/readme.md +94 -20
- package/dist/models/vertexEmbedding.d.ts +0 -23
- package/dist/models/vertexEmbedding.d.ts.map +0 -1
- package/dist/models/vertexEmbedding.js +0 -179
- package/dist/models/vertexEmbedding.js.map +0 -1
|
@@ -1,63 +1,118 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
1
|
+
import { GeminiLLM } from '@memberjunction/ai-gemini';
|
|
2
|
+
import { GoogleGenAI } from '@google/genai';
|
|
3
|
+
/**
|
|
4
|
+
* Credentials format for Vertex AI authentication
|
|
5
|
+
*
|
|
6
|
+
* This interface supports four authentication methods:
|
|
7
|
+
* 1. Application Default Credentials (ADC) - Just provide project and location
|
|
8
|
+
* 2. Service Account JSON String - Provide serviceAccountJson with full JSON as string
|
|
9
|
+
* 3. Service Account JSON Inline - Provide full service account fields directly
|
|
10
|
+
* 4. Key File Path - Provide path to service account JSON file
|
|
11
|
+
*/
|
|
12
|
+
export interface VertexAICredentials {
|
|
13
|
+
/** GCP Project ID (required) */
|
|
14
|
+
project: string;
|
|
15
|
+
/** GCP Location/Region (default: 'us-central1') */
|
|
16
|
+
location?: string;
|
|
17
|
+
serviceAccountJson?: string;
|
|
18
|
+
type?: 'service_account';
|
|
19
|
+
project_id?: string;
|
|
20
|
+
private_key_id?: string;
|
|
21
|
+
private_key?: string;
|
|
22
|
+
client_email?: string;
|
|
23
|
+
client_id?: string;
|
|
24
|
+
auth_uri?: string;
|
|
25
|
+
token_uri?: string;
|
|
26
|
+
auth_provider_x509_cert_url?: string;
|
|
27
|
+
client_x509_cert_url?: string;
|
|
28
|
+
keyFilePath?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* VertexLLM - Google Vertex AI implementation
|
|
32
|
+
*
|
|
33
|
+
* Extends GeminiLLM and reuses all its logic (chat, streaming, thinking, parameters,
|
|
34
|
+
* multimodal content, message alternation, error handling, etc.).
|
|
35
|
+
*
|
|
36
|
+
* The only difference is authentication - this class overrides the constructor to
|
|
37
|
+
* handle GCP authentication instead of API keys.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Option 1: ADC (Application Default Credentials)
|
|
41
|
+
* // Set GOOGLE_APPLICATION_CREDENTIALS env var or use gcloud auth
|
|
42
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
43
|
+
* project: 'my-project',
|
|
44
|
+
* location: 'us-central1'
|
|
45
|
+
* }));
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Option 2: Service account JSON as string (from credential system)
|
|
49
|
+
* const serviceAccountJson = JSON.stringify({
|
|
50
|
+
* type: 'service_account',
|
|
51
|
+
* project_id: 'my-project',
|
|
52
|
+
* private_key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
|
|
53
|
+
* client_email: 'sa@my-project.iam.gserviceaccount.com',
|
|
54
|
+
* client_id: '123456789'
|
|
55
|
+
* // ... other service account fields
|
|
56
|
+
* });
|
|
57
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
58
|
+
* project: 'my-project',
|
|
59
|
+
* location: 'us-central1',
|
|
60
|
+
* serviceAccountJson: serviceAccountJson
|
|
61
|
+
* }));
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Option 3: Service account JSON inline
|
|
65
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
66
|
+
* type: 'service_account',
|
|
67
|
+
* project_id: 'my-project',
|
|
68
|
+
* private_key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
|
|
69
|
+
* client_email: 'sa@my-project.iam.gserviceaccount.com',
|
|
70
|
+
* client_id: '123456789',
|
|
71
|
+
* // ... other service account fields
|
|
72
|
+
* location: 'us-central1'
|
|
73
|
+
* }));
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Option 4: Key file path reference
|
|
77
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
78
|
+
* keyFilePath: '/path/to/service-account.json',
|
|
79
|
+
* project: 'my-project',
|
|
80
|
+
* location: 'us-central1'
|
|
81
|
+
* }));
|
|
82
|
+
*/
|
|
83
|
+
export declare class VertexLLM extends GeminiLLM {
|
|
84
|
+
private _credentials;
|
|
49
85
|
/**
|
|
50
|
-
*
|
|
86
|
+
* Create a new VertexLLM instance
|
|
87
|
+
*
|
|
88
|
+
* @param credentialsJson - JSON string containing Vertex AI credentials.
|
|
89
|
+
* Must include at minimum: { project: 'id', location?: 'region' }
|
|
90
|
+
* Can include full service account JSON or keyFilePath for authentication.
|
|
91
|
+
*
|
|
92
|
+
* If neither service account fields nor keyFilePath are provided,
|
|
93
|
+
* will use Application Default Credentials (ADC).
|
|
51
94
|
*/
|
|
52
|
-
|
|
95
|
+
constructor(credentialsJson: string);
|
|
53
96
|
/**
|
|
54
|
-
*
|
|
97
|
+
* Override parent's createClient() factory method to create Vertex AI client
|
|
98
|
+
*
|
|
99
|
+
* This factory method is called lazily on first use, so _credentials will always be set.
|
|
100
|
+
* The rest of the functionality (chat, streaming, etc.) remains identical.
|
|
55
101
|
*/
|
|
56
|
-
|
|
102
|
+
protected createClient(): Promise<GoogleGenAI>;
|
|
57
103
|
/**
|
|
58
|
-
*
|
|
104
|
+
* Get Vertex AI credentials (for debugging/logging)
|
|
105
|
+
*
|
|
106
|
+
* Note: Returns a copy to prevent external modification.
|
|
107
|
+
* Sensitive fields like private_key are included, so be careful when logging.
|
|
59
108
|
*/
|
|
60
|
-
|
|
109
|
+
get Credentials(): VertexAICredentials;
|
|
61
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Load function to prevent tree-shaking
|
|
113
|
+
*
|
|
114
|
+
* Call this function from your module's public-api.ts to ensure
|
|
115
|
+
* the class is not removed during tree-shaking optimization.
|
|
116
|
+
*/
|
|
62
117
|
export declare function LoadVertexLLM(): void;
|
|
63
118
|
//# sourceMappingURL=vertexLLM.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertexLLM.d.ts","sourceRoot":"","sources":["../../src/models/vertexLLM.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"vertexLLM.d.ts","sourceRoot":"","sources":["../../src/models/vertexLLM.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI5C;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAEhB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAG5B,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,qBACa,SAAU,SAAQ,SAAS;IACtC,OAAO,CAAC,YAAY,CAAsB;IAE1C;;;;;;;;;OASG;gBACS,eAAe,EAAE,MAAM;IAiDnC;;;;;OAKG;cACa,YAAY,IAAI,OAAO,CAAC,WAAW,CAAC;IAiDpD;;;;;OAKG;IACH,IAAW,WAAW,IAAI,mBAAmB,CAE5C;CACF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAEpC"}
|
package/dist/models/vertexLLM.js
CHANGED
|
@@ -7,304 +7,184 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
};
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.LoadVertexLLM = exports.VertexLLM = void 0;
|
|
10
|
-
const
|
|
10
|
+
const ai_gemini_1 = require("@memberjunction/ai-gemini");
|
|
11
|
+
const genai_1 = require("@google/genai");
|
|
11
12
|
const global_1 = require("@memberjunction/global");
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
13
|
+
const ai_1 = require("@memberjunction/ai");
|
|
14
|
+
/**
|
|
15
|
+
* VertexLLM - Google Vertex AI implementation
|
|
16
|
+
*
|
|
17
|
+
* Extends GeminiLLM and reuses all its logic (chat, streaming, thinking, parameters,
|
|
18
|
+
* multimodal content, message alternation, error handling, etc.).
|
|
19
|
+
*
|
|
20
|
+
* The only difference is authentication - this class overrides the constructor to
|
|
21
|
+
* handle GCP authentication instead of API keys.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Option 1: ADC (Application Default Credentials)
|
|
25
|
+
* // Set GOOGLE_APPLICATION_CREDENTIALS env var or use gcloud auth
|
|
26
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
27
|
+
* project: 'my-project',
|
|
28
|
+
* location: 'us-central1'
|
|
29
|
+
* }));
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Option 2: Service account JSON as string (from credential system)
|
|
33
|
+
* const serviceAccountJson = JSON.stringify({
|
|
34
|
+
* type: 'service_account',
|
|
35
|
+
* project_id: 'my-project',
|
|
36
|
+
* private_key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
|
|
37
|
+
* client_email: 'sa@my-project.iam.gserviceaccount.com',
|
|
38
|
+
* client_id: '123456789'
|
|
39
|
+
* // ... other service account fields
|
|
40
|
+
* });
|
|
41
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
42
|
+
* project: 'my-project',
|
|
43
|
+
* location: 'us-central1',
|
|
44
|
+
* serviceAccountJson: serviceAccountJson
|
|
45
|
+
* }));
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* // Option 3: Service account JSON inline
|
|
49
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
50
|
+
* type: 'service_account',
|
|
51
|
+
* project_id: 'my-project',
|
|
52
|
+
* private_key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
|
|
53
|
+
* client_email: 'sa@my-project.iam.gserviceaccount.com',
|
|
54
|
+
* client_id: '123456789',
|
|
55
|
+
* // ... other service account fields
|
|
56
|
+
* location: 'us-central1'
|
|
57
|
+
* }));
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* // Option 4: Key file path reference
|
|
61
|
+
* const llm = new VertexLLM(JSON.stringify({
|
|
62
|
+
* keyFilePath: '/path/to/service-account.json',
|
|
63
|
+
* project: 'my-project',
|
|
64
|
+
* location: 'us-central1'
|
|
65
|
+
* }));
|
|
66
|
+
*/
|
|
67
|
+
let VertexLLM = class VertexLLM extends ai_gemini_1.GeminiLLM {
|
|
37
68
|
/**
|
|
38
|
-
*
|
|
69
|
+
* Create a new VertexLLM instance
|
|
70
|
+
*
|
|
71
|
+
* @param credentialsJson - JSON string containing Vertex AI credentials.
|
|
72
|
+
* Must include at minimum: { project: 'id', location?: 'region' }
|
|
73
|
+
* Can include full service account JSON or keyFilePath for authentication.
|
|
74
|
+
*
|
|
75
|
+
* If neither service account fields nor keyFilePath are provided,
|
|
76
|
+
* will use Application Default Credentials (ADC).
|
|
39
77
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
78
|
+
constructor(credentialsJson) {
|
|
79
|
+
// Parse credentials
|
|
80
|
+
let credentials;
|
|
42
81
|
try {
|
|
43
|
-
|
|
44
|
-
const vertexParams = this.mapToVertexParams(params);
|
|
45
|
-
// The model ID should be in the format like "gemini-pro", "text-bison", etc.
|
|
46
|
-
const modelName = params.model;
|
|
47
|
-
// Get the appropriate service for the model
|
|
48
|
-
const generativeModel = this.getGenerativeModelForModel(modelName);
|
|
49
|
-
// Prepare request parameters
|
|
50
|
-
const requestParams = {
|
|
51
|
-
model: modelName,
|
|
52
|
-
temperature: vertexParams.temperature,
|
|
53
|
-
maxOutputTokens: vertexParams.maxOutputTokens,
|
|
54
|
-
topP: vertexParams.topP,
|
|
55
|
-
topK: vertexParams.topK,
|
|
56
|
-
safetySettings: vertexParams.safetySettings
|
|
57
|
-
};
|
|
58
|
-
// Send the request
|
|
59
|
-
const response = await generativeModel.generateContent({
|
|
60
|
-
contents: this.mapToVertexContents(vertexParams.messages),
|
|
61
|
-
generationConfig: requestParams
|
|
62
|
-
});
|
|
63
|
-
const result = response.response;
|
|
64
|
-
// Extract the response content
|
|
65
|
-
let content = '';
|
|
66
|
-
if (result.candidates && result.candidates.length > 0) {
|
|
67
|
-
const candidate = result.candidates[0];
|
|
68
|
-
if (candidate.content && candidate.content.parts && candidate.content.parts.length > 0) {
|
|
69
|
-
content = candidate.content.parts.map(part => {
|
|
70
|
-
if (typeof part === 'string') {
|
|
71
|
-
return part;
|
|
72
|
-
}
|
|
73
|
-
else if (part.text) {
|
|
74
|
-
return part.text;
|
|
75
|
-
}
|
|
76
|
-
return '';
|
|
77
|
-
}).join('');
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// Extract usage information
|
|
81
|
-
const tokenUsage = {
|
|
82
|
-
promptTokens: result.usageMetadata?.promptTokenCount || 0,
|
|
83
|
-
completionTokens: result.usageMetadata?.candidatesTokenCount || 0,
|
|
84
|
-
totalTokens: (result.usageMetadata?.promptTokenCount || 0) + (result.usageMetadata?.candidatesTokenCount || 0)
|
|
85
|
-
};
|
|
86
|
-
const endTime = new Date();
|
|
87
|
-
// Create ModelUsage
|
|
88
|
-
const usage = new ai_1.ModelUsage(tokenUsage.promptTokens, tokenUsage.completionTokens);
|
|
89
|
-
// Create the ChatResult
|
|
90
|
-
const choices = [{
|
|
91
|
-
message: {
|
|
92
|
-
role: ai_1.ChatMessageRole.assistant,
|
|
93
|
-
content: content
|
|
94
|
-
},
|
|
95
|
-
finish_reason: result.candidates?.[0]?.finishReason || 'stop',
|
|
96
|
-
index: 0
|
|
97
|
-
}];
|
|
98
|
-
const chatResult = {
|
|
99
|
-
success: true,
|
|
100
|
-
statusText: "OK",
|
|
101
|
-
startTime: startTime,
|
|
102
|
-
endTime: endTime,
|
|
103
|
-
timeElapsed: endTime.getTime() - startTime.getTime(),
|
|
104
|
-
data: {
|
|
105
|
-
choices: choices,
|
|
106
|
-
usage: usage
|
|
107
|
-
},
|
|
108
|
-
errorMessage: "",
|
|
109
|
-
exception: null,
|
|
110
|
-
};
|
|
111
|
-
// Add model-specific response details
|
|
112
|
-
chatResult.modelSpecificResponseDetails = {
|
|
113
|
-
provider: 'vertex',
|
|
114
|
-
model: params.model,
|
|
115
|
-
promptFeedback: result.promptFeedback,
|
|
116
|
-
safetyRatings: result.candidates?.[0]?.safetyRatings,
|
|
117
|
-
citationMetadata: result.candidates?.[0]?.citationMetadata,
|
|
118
|
-
finishReason: result.candidates?.[0]?.finishReason
|
|
119
|
-
};
|
|
120
|
-
return chatResult;
|
|
82
|
+
credentials = JSON.parse(credentialsJson);
|
|
121
83
|
}
|
|
122
84
|
catch (error) {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
success: false,
|
|
126
|
-
statusText: "Error",
|
|
127
|
-
startTime: startTime,
|
|
128
|
-
endTime: endTime,
|
|
129
|
-
timeElapsed: endTime.getTime() - startTime.getTime(),
|
|
130
|
-
data: {
|
|
131
|
-
choices: [],
|
|
132
|
-
usage: new ai_1.ModelUsage(0, 0)
|
|
133
|
-
},
|
|
134
|
-
errorMessage: error.message || "Error calling Google Vertex AI",
|
|
135
|
-
exception: error,
|
|
136
|
-
errorInfo: ai_1.ErrorAnalyzer.analyzeError(error, 'Vertex')
|
|
137
|
-
};
|
|
85
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
86
|
+
throw new Error(`Invalid Vertex AI credentials JSON: ${message}`);
|
|
138
87
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
topP: vertexParams.topP,
|
|
156
|
-
topK: vertexParams.topK,
|
|
157
|
-
safetySettings: vertexParams.safetySettings
|
|
158
|
-
};
|
|
159
|
-
// Send the streaming request
|
|
160
|
-
return generativeModel.generateContentStream({
|
|
161
|
-
contents: this.mapToVertexContents(vertexParams.messages),
|
|
162
|
-
generationConfig: requestParams
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Process a streaming chunk from Vertex AI
|
|
167
|
-
*/
|
|
168
|
-
processStreamingChunk(chunk) {
|
|
169
|
-
let content = '';
|
|
170
|
-
let finishReason = null;
|
|
171
|
-
let usage = null;
|
|
172
|
-
if (chunk && chunk.candidates && chunk.candidates.length > 0) {
|
|
173
|
-
const candidate = chunk.candidates[0];
|
|
174
|
-
if (candidate.content && candidate.content.parts && candidate.content.parts.length > 0) {
|
|
175
|
-
content = candidate.content.parts.map(part => {
|
|
176
|
-
if (typeof part === 'string') {
|
|
177
|
-
return part;
|
|
178
|
-
}
|
|
179
|
-
else if (part.text) {
|
|
180
|
-
return part.text;
|
|
181
|
-
}
|
|
182
|
-
return '';
|
|
183
|
-
}).join('');
|
|
88
|
+
// If serviceAccountJson is provided as a string, parse it and merge with credentials
|
|
89
|
+
if (credentials.serviceAccountJson) {
|
|
90
|
+
try {
|
|
91
|
+
const serviceAccount = JSON.parse(credentials.serviceAccountJson);
|
|
92
|
+
// Merge service account fields into credentials (serviceAccountJson fields take precedence)
|
|
93
|
+
credentials = {
|
|
94
|
+
...credentials,
|
|
95
|
+
...serviceAccount,
|
|
96
|
+
// Keep top-level project and location if they exist
|
|
97
|
+
project: credentials.project || serviceAccount.project_id,
|
|
98
|
+
location: credentials.location
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
103
|
+
throw new Error(`Invalid serviceAccountJson: ${message}`);
|
|
184
104
|
}
|
|
185
|
-
finishReason = candidate.finishReason || null;
|
|
186
105
|
}
|
|
187
|
-
//
|
|
188
|
-
if (
|
|
189
|
-
|
|
106
|
+
// Validate required fields
|
|
107
|
+
if (!credentials.project && !credentials.project_id) {
|
|
108
|
+
throw new Error('Vertex AI credentials must include "project" or "project_id"');
|
|
190
109
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
110
|
+
// Use project_id if provided, otherwise use project
|
|
111
|
+
const projectId = credentials.project_id || credentials.project;
|
|
112
|
+
const location = credentials.location || 'us-central1';
|
|
113
|
+
// Normalize credentials
|
|
114
|
+
credentials.project = projectId;
|
|
115
|
+
credentials.location = location;
|
|
116
|
+
// Call parent constructor with project ID (BaseLLM stores this as apiKey)
|
|
117
|
+
super(projectId);
|
|
118
|
+
// Set credentials after super() call
|
|
119
|
+
// Parent constructor doesn't initialize the client, so this is safe
|
|
120
|
+
this._credentials = credentials;
|
|
196
121
|
}
|
|
197
122
|
/**
|
|
198
|
-
*
|
|
123
|
+
* Override parent's createClient() factory method to create Vertex AI client
|
|
124
|
+
*
|
|
125
|
+
* This factory method is called lazily on first use, so _credentials will always be set.
|
|
126
|
+
* The rest of the functionality (chat, streaming, etc.) remains identical.
|
|
199
127
|
*/
|
|
200
|
-
|
|
201
|
-
//
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
result.data = {
|
|
207
|
-
choices: [{
|
|
208
|
-
message: {
|
|
209
|
-
role: ai_1.ChatMessageRole.assistant,
|
|
210
|
-
content: accumulatedContent ? accumulatedContent : ''
|
|
211
|
-
},
|
|
212
|
-
finish_reason: lastChunk?.finishReason || 'stop',
|
|
213
|
-
index: 0
|
|
214
|
-
}],
|
|
215
|
-
usage: usage || new ai_1.ModelUsage(0, 0)
|
|
128
|
+
async createClient() {
|
|
129
|
+
// Build Vertex AI config
|
|
130
|
+
const config = {
|
|
131
|
+
vertexai: true,
|
|
132
|
+
project: this._credentials.project,
|
|
133
|
+
location: this._credentials.location
|
|
216
134
|
};
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Not implemented yet
|
|
224
|
-
*/
|
|
225
|
-
async SummarizeText(params) {
|
|
226
|
-
throw new Error("Method not implemented.");
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Not implemented yet
|
|
230
|
-
*/
|
|
231
|
-
async ClassifyText(params) {
|
|
232
|
-
throw new Error("Method not implemented.");
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Map MemberJunction ChatParams to Vertex-specific params
|
|
236
|
-
*/
|
|
237
|
-
mapToVertexParams(params) {
|
|
238
|
-
return {
|
|
239
|
-
model: params.model,
|
|
240
|
-
messages: this.convertToVertexMessages(params.messages),
|
|
241
|
-
temperature: params.temperature,
|
|
242
|
-
maxOutputTokens: params.maxOutputTokens
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Convert MemberJunction chat messages to Vertex-compatible messages
|
|
247
|
-
*/
|
|
248
|
-
convertToVertexMessages(messages) {
|
|
249
|
-
return messages.map(msg => {
|
|
250
|
-
return {
|
|
251
|
-
role: this.mapRole(msg.role),
|
|
252
|
-
content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)
|
|
135
|
+
// If keyFilePath is provided, configure file-based auth
|
|
136
|
+
if (this._credentials.keyFilePath) {
|
|
137
|
+
config.googleAuthOptions = {
|
|
138
|
+
keyFile: this._credentials.keyFilePath
|
|
253
139
|
};
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Map message roles to Vertex format
|
|
258
|
-
*/
|
|
259
|
-
mapRole(role) {
|
|
260
|
-
switch (role) {
|
|
261
|
-
case ai_1.ChatMessageRole.system:
|
|
262
|
-
return 'system';
|
|
263
|
-
case ai_1.ChatMessageRole.assistant:
|
|
264
|
-
return 'model';
|
|
265
|
-
case ai_1.ChatMessageRole.user:
|
|
266
|
-
default:
|
|
267
|
-
return 'user';
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Get the appropriate generative model based on model name
|
|
272
|
-
*/
|
|
273
|
-
getGenerativeModelForModel(modelName) {
|
|
274
|
-
// For different model types, we might need different parameters
|
|
275
|
-
if (modelName.startsWith('gemini-')) {
|
|
276
|
-
return this._client.getGenerativeModel({ model: modelName });
|
|
277
|
-
}
|
|
278
|
-
else if (modelName.startsWith('text-')) {
|
|
279
|
-
return this._client.getGenerativeModel({ model: modelName });
|
|
280
|
-
}
|
|
281
|
-
else if (modelName.startsWith('code-')) {
|
|
282
|
-
return this._client.getGenerativeModel({ model: modelName });
|
|
283
140
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
141
|
+
// If full service account JSON is provided, use inline credentials
|
|
142
|
+
else if (this._credentials.type === 'service_account' && this._credentials.private_key) {
|
|
143
|
+
config.googleAuthOptions = {
|
|
144
|
+
credentials: {
|
|
145
|
+
type: this._credentials.type,
|
|
146
|
+
project_id: this._credentials.project_id || this._credentials.project,
|
|
147
|
+
private_key_id: this._credentials.private_key_id || '',
|
|
148
|
+
private_key: this._credentials.private_key,
|
|
149
|
+
client_email: this._credentials.client_email || '',
|
|
150
|
+
client_id: this._credentials.client_id || '',
|
|
151
|
+
auth_uri: this._credentials.auth_uri || 'https://accounts.google.com/o/oauth2/auth',
|
|
152
|
+
token_uri: this._credentials.token_uri || 'https://oauth2.googleapis.com/token',
|
|
153
|
+
auth_provider_x509_cert_url: this._credentials.auth_provider_x509_cert_url || 'https://www.googleapis.com/oauth2/v1/certs',
|
|
154
|
+
client_x509_cert_url: this._credentials.client_x509_cert_url || ''
|
|
155
|
+
}
|
|
156
|
+
};
|
|
287
157
|
}
|
|
158
|
+
// Otherwise, use Application Default Credentials (ADC)
|
|
159
|
+
// This will look for:
|
|
160
|
+
// 1. GOOGLE_APPLICATION_CREDENTIALS environment variable pointing to key file
|
|
161
|
+
// 2. gcloud auth application-default login credentials
|
|
162
|
+
// 3. GCE/GKE/Cloud Run service account (when running in Google Cloud)
|
|
163
|
+
// Create Vertex AI client with the configured options
|
|
164
|
+
return new genai_1.GoogleGenAI(config);
|
|
288
165
|
}
|
|
289
166
|
/**
|
|
290
|
-
*
|
|
167
|
+
* Get Vertex AI credentials (for debugging/logging)
|
|
168
|
+
*
|
|
169
|
+
* Note: Returns a copy to prevent external modification.
|
|
170
|
+
* Sensitive fields like private_key are included, so be careful when logging.
|
|
291
171
|
*/
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
return messages.map(msg => {
|
|
295
|
-
return {
|
|
296
|
-
role: msg.role,
|
|
297
|
-
parts: [{ text: msg.content }]
|
|
298
|
-
};
|
|
299
|
-
});
|
|
172
|
+
get Credentials() {
|
|
173
|
+
return { ...this._credentials };
|
|
300
174
|
}
|
|
301
175
|
};
|
|
302
176
|
exports.VertexLLM = VertexLLM;
|
|
303
177
|
exports.VertexLLM = VertexLLM = __decorate([
|
|
304
178
|
(0, global_1.RegisterClass)(ai_1.BaseLLM, "VertexLLM")
|
|
305
179
|
], VertexLLM);
|
|
180
|
+
/**
|
|
181
|
+
* Load function to prevent tree-shaking
|
|
182
|
+
*
|
|
183
|
+
* Call this function from your module's public-api.ts to ensure
|
|
184
|
+
* the class is not removed during tree-shaking optimization.
|
|
185
|
+
*/
|
|
306
186
|
function LoadVertexLLM() {
|
|
307
|
-
//
|
|
187
|
+
// Intentionally empty - just prevents tree-shaking
|
|
308
188
|
}
|
|
309
189
|
exports.LoadVertexLLM = LoadVertexLLM;
|
|
310
190
|
//# sourceMappingURL=vertexLLM.js.map
|