@langchain/google-common 0.2.8 → 0.2.10
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/chat_models.cjs +8 -5
- package/dist/chat_models.d.ts +1 -0
- package/dist/chat_models.js +8 -5
- package/dist/connection.cjs +29 -2
- package/dist/connection.d.ts +2 -0
- package/dist/connection.js +29 -2
- package/dist/types.cjs +1 -0
- package/dist/types.d.ts +44 -5
- package/dist/types.js +1 -0
- package/dist/utils/common.cjs +1 -0
- package/dist/utils/common.js +1 -0
- package/dist/utils/gemini.cjs +68 -5
- package/dist/utils/gemini.js +68 -5
- package/dist/utils/zod_to_gemini_parameters.cjs +27 -0
- package/dist/utils/zod_to_gemini_parameters.js +27 -0
- package/package.json +2 -2
package/dist/chat_models.cjs
CHANGED
|
@@ -162,6 +162,12 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
162
162
|
writable: true,
|
|
163
163
|
value: void 0
|
|
164
164
|
});
|
|
165
|
+
Object.defineProperty(this, "seed", {
|
|
166
|
+
enumerable: true,
|
|
167
|
+
configurable: true,
|
|
168
|
+
writable: true,
|
|
169
|
+
value: void 0
|
|
170
|
+
});
|
|
165
171
|
Object.defineProperty(this, "presencePenalty", {
|
|
166
172
|
enumerable: true,
|
|
167
173
|
configurable: true,
|
|
@@ -282,7 +288,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
282
288
|
return this.connection.platform;
|
|
283
289
|
}
|
|
284
290
|
bindTools(tools, kwargs) {
|
|
285
|
-
return this.
|
|
291
|
+
return this.withConfig({ tools: (0, common_js_1.convertToGeminiTools)(tools), ...kwargs });
|
|
286
292
|
}
|
|
287
293
|
// Replace
|
|
288
294
|
_llmType() {
|
|
@@ -418,10 +424,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
418
424
|
keyName: functionName,
|
|
419
425
|
});
|
|
420
426
|
}
|
|
421
|
-
const llm = this.
|
|
422
|
-
tools,
|
|
423
|
-
tool_choice: functionName,
|
|
424
|
-
});
|
|
427
|
+
const llm = this.bindTools(tools).withConfig({ tool_choice: functionName });
|
|
425
428
|
if (!includeRaw) {
|
|
426
429
|
return llm.pipe(outputParser).withConfig({
|
|
427
430
|
runName: "ChatGoogleStructuredOutput",
|
package/dist/chat_models.d.ts
CHANGED
package/dist/chat_models.js
CHANGED
|
@@ -158,6 +158,12 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
158
158
|
writable: true,
|
|
159
159
|
value: void 0
|
|
160
160
|
});
|
|
161
|
+
Object.defineProperty(this, "seed", {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
configurable: true,
|
|
164
|
+
writable: true,
|
|
165
|
+
value: void 0
|
|
166
|
+
});
|
|
161
167
|
Object.defineProperty(this, "presencePenalty", {
|
|
162
168
|
enumerable: true,
|
|
163
169
|
configurable: true,
|
|
@@ -278,7 +284,7 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
278
284
|
return this.connection.platform;
|
|
279
285
|
}
|
|
280
286
|
bindTools(tools, kwargs) {
|
|
281
|
-
return this.
|
|
287
|
+
return this.withConfig({ tools: convertToGeminiTools(tools), ...kwargs });
|
|
282
288
|
}
|
|
283
289
|
// Replace
|
|
284
290
|
_llmType() {
|
|
@@ -414,10 +420,7 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
414
420
|
keyName: functionName,
|
|
415
421
|
});
|
|
416
422
|
}
|
|
417
|
-
const llm = this.
|
|
418
|
-
tools,
|
|
419
|
-
tool_choice: functionName,
|
|
420
|
-
});
|
|
423
|
+
const llm = this.bindTools(tools).withConfig({ tool_choice: functionName });
|
|
421
424
|
if (!includeRaw) {
|
|
422
425
|
return llm.pipe(outputParser).withConfig({
|
|
423
426
|
runName: "ChatGoogleStructuredOutput",
|
package/dist/connection.cjs
CHANGED
|
@@ -121,12 +121,24 @@ class GoogleHostConnection extends GoogleConnection {
|
|
|
121
121
|
value: void 0
|
|
122
122
|
});
|
|
123
123
|
this.caller = caller;
|
|
124
|
-
this.platformType = fields
|
|
124
|
+
this.platformType = this.fieldPlatformType(fields);
|
|
125
125
|
this._endpoint = fields?.endpoint;
|
|
126
126
|
this._location = fields?.location;
|
|
127
127
|
this._apiVersion = fields?.apiVersion;
|
|
128
128
|
this.client = client;
|
|
129
129
|
}
|
|
130
|
+
fieldPlatformType(fields) {
|
|
131
|
+
if (typeof fields === "undefined") {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
if (typeof fields.platformType !== "undefined") {
|
|
135
|
+
return fields.platformType;
|
|
136
|
+
}
|
|
137
|
+
if (fields.vertexai === true) {
|
|
138
|
+
return "gcp";
|
|
139
|
+
}
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
130
142
|
get platform() {
|
|
131
143
|
return this.platformType ?? this.computedPlatformType;
|
|
132
144
|
}
|
|
@@ -149,7 +161,12 @@ class GoogleHostConnection extends GoogleConnection {
|
|
|
149
161
|
return this._endpoint ?? this.computedEndpoint;
|
|
150
162
|
}
|
|
151
163
|
get computedEndpoint() {
|
|
152
|
-
|
|
164
|
+
if (this.location === "global") {
|
|
165
|
+
return "aiplatform.googleapis.com";
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
return `${this.location}-aiplatform.googleapis.com`;
|
|
169
|
+
}
|
|
153
170
|
}
|
|
154
171
|
buildMethod() {
|
|
155
172
|
return "POST";
|
|
@@ -233,6 +250,16 @@ class GoogleAIConnection extends GoogleHostConnection {
|
|
|
233
250
|
get isApiKey() {
|
|
234
251
|
return this.client.clientType === "apiKey";
|
|
235
252
|
}
|
|
253
|
+
fieldPlatformType(fields) {
|
|
254
|
+
const ret = super.fieldPlatformType(fields);
|
|
255
|
+
if (typeof ret !== "undefined") {
|
|
256
|
+
return ret;
|
|
257
|
+
}
|
|
258
|
+
if (fields?.vertexai === false) {
|
|
259
|
+
return "gai";
|
|
260
|
+
}
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
236
263
|
get computedPlatformType() {
|
|
237
264
|
// This is not a completely correct assumption, since GCP can
|
|
238
265
|
// have an API Key. But if so, then people need to set the platform
|
package/dist/connection.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare abstract class GoogleHostConnection<CallOptions extends AsyncCall
|
|
|
27
27
|
_location: string | undefined;
|
|
28
28
|
_apiVersion: string | undefined;
|
|
29
29
|
constructor(fields: GoogleConnectionParams<AuthOptions> | undefined, caller: AsyncCaller, client: GoogleAbstractedClient, streaming?: boolean);
|
|
30
|
+
fieldPlatformType(fields: GoogleConnectionParams<any> | undefined): GooglePlatformType | undefined;
|
|
30
31
|
get platform(): GooglePlatformType;
|
|
31
32
|
get computedPlatformType(): GooglePlatformType;
|
|
32
33
|
get computedApiVersion(): string;
|
|
@@ -53,6 +54,7 @@ export declare abstract class GoogleAIConnection<CallOptions extends AsyncCaller
|
|
|
53
54
|
get apiName(): string;
|
|
54
55
|
get api(): GoogleAIAPI;
|
|
55
56
|
get isApiKey(): boolean;
|
|
57
|
+
fieldPlatformType(fields: GoogleConnectionParams<any> | undefined): GooglePlatformType | undefined;
|
|
56
58
|
get computedPlatformType(): GooglePlatformType;
|
|
57
59
|
get computedApiVersion(): string;
|
|
58
60
|
get computedLocation(): string;
|
package/dist/connection.js
CHANGED
|
@@ -117,12 +117,24 @@ export class GoogleHostConnection extends GoogleConnection {
|
|
|
117
117
|
value: void 0
|
|
118
118
|
});
|
|
119
119
|
this.caller = caller;
|
|
120
|
-
this.platformType = fields
|
|
120
|
+
this.platformType = this.fieldPlatformType(fields);
|
|
121
121
|
this._endpoint = fields?.endpoint;
|
|
122
122
|
this._location = fields?.location;
|
|
123
123
|
this._apiVersion = fields?.apiVersion;
|
|
124
124
|
this.client = client;
|
|
125
125
|
}
|
|
126
|
+
fieldPlatformType(fields) {
|
|
127
|
+
if (typeof fields === "undefined") {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
if (typeof fields.platformType !== "undefined") {
|
|
131
|
+
return fields.platformType;
|
|
132
|
+
}
|
|
133
|
+
if (fields.vertexai === true) {
|
|
134
|
+
return "gcp";
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
126
138
|
get platform() {
|
|
127
139
|
return this.platformType ?? this.computedPlatformType;
|
|
128
140
|
}
|
|
@@ -145,7 +157,12 @@ export class GoogleHostConnection extends GoogleConnection {
|
|
|
145
157
|
return this._endpoint ?? this.computedEndpoint;
|
|
146
158
|
}
|
|
147
159
|
get computedEndpoint() {
|
|
148
|
-
|
|
160
|
+
if (this.location === "global") {
|
|
161
|
+
return "aiplatform.googleapis.com";
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
return `${this.location}-aiplatform.googleapis.com`;
|
|
165
|
+
}
|
|
149
166
|
}
|
|
150
167
|
buildMethod() {
|
|
151
168
|
return "POST";
|
|
@@ -227,6 +244,16 @@ export class GoogleAIConnection extends GoogleHostConnection {
|
|
|
227
244
|
get isApiKey() {
|
|
228
245
|
return this.client.clientType === "apiKey";
|
|
229
246
|
}
|
|
247
|
+
fieldPlatformType(fields) {
|
|
248
|
+
const ret = super.fieldPlatformType(fields);
|
|
249
|
+
if (typeof ret !== "undefined") {
|
|
250
|
+
return ret;
|
|
251
|
+
}
|
|
252
|
+
if (fields?.vertexai === false) {
|
|
253
|
+
return "gai";
|
|
254
|
+
}
|
|
255
|
+
return undefined;
|
|
256
|
+
}
|
|
230
257
|
get computedPlatformType() {
|
|
231
258
|
// This is not a completely correct assumption, since GCP can
|
|
232
259
|
// have an API Key. But if so, then people need to set the platform
|
package/dist/types.cjs
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -36,6 +36,11 @@ export interface GoogleConnectionParams<AuthOptions> extends GoogleClientParams<
|
|
|
36
36
|
* the "platform" getter.
|
|
37
37
|
*/
|
|
38
38
|
platformType?: GooglePlatformType;
|
|
39
|
+
/**
|
|
40
|
+
* For compatibility with Google's libraries, should this use Vertex?
|
|
41
|
+
* The "platformType" parmeter takes precedence.
|
|
42
|
+
*/
|
|
43
|
+
vertexai?: boolean;
|
|
39
44
|
}
|
|
40
45
|
export declare const GoogleAISafetyCategory: {
|
|
41
46
|
readonly Harassment: "HARM_CATEGORY_HARASSMENT";
|
|
@@ -137,6 +142,10 @@ export interface GoogleAIModelParams {
|
|
|
137
142
|
* among the 3 most probable tokens (using temperature).
|
|
138
143
|
*/
|
|
139
144
|
topK?: number;
|
|
145
|
+
/**
|
|
146
|
+
* Seed used in decoding. If not set, the request uses a randomly generated seed.
|
|
147
|
+
*/
|
|
148
|
+
seed?: number;
|
|
140
149
|
/**
|
|
141
150
|
* Presence penalty applied to the next token's logprobs
|
|
142
151
|
* if the token has already been seen in the response.
|
|
@@ -257,28 +266,39 @@ export interface GoogleResponse {
|
|
|
257
266
|
export interface GoogleRawResponse extends GoogleResponse {
|
|
258
267
|
data: Blob;
|
|
259
268
|
}
|
|
260
|
-
export interface
|
|
269
|
+
export interface GeminiPartBase {
|
|
270
|
+
thought?: boolean;
|
|
271
|
+
}
|
|
272
|
+
export interface GeminiVideoMetadata {
|
|
273
|
+
fps?: number;
|
|
274
|
+
startOffset?: string;
|
|
275
|
+
endOffset?: string;
|
|
276
|
+
}
|
|
277
|
+
export interface GeminiPartBaseFile extends GeminiPartBase {
|
|
278
|
+
videoMetadata?: GeminiVideoMetadata;
|
|
279
|
+
}
|
|
280
|
+
export interface GeminiPartText extends GeminiPartBase {
|
|
261
281
|
text: string;
|
|
262
282
|
}
|
|
263
|
-
export interface GeminiPartInlineData {
|
|
283
|
+
export interface GeminiPartInlineData extends GeminiPartBaseFile {
|
|
264
284
|
inlineData: {
|
|
265
285
|
mimeType: string;
|
|
266
286
|
data: string;
|
|
267
287
|
};
|
|
268
288
|
}
|
|
269
|
-
export interface GeminiPartFileData {
|
|
289
|
+
export interface GeminiPartFileData extends GeminiPartBaseFile {
|
|
270
290
|
fileData: {
|
|
271
291
|
mimeType: string;
|
|
272
292
|
fileUri: string;
|
|
273
293
|
};
|
|
274
294
|
}
|
|
275
|
-
export interface GeminiPartFunctionCall {
|
|
295
|
+
export interface GeminiPartFunctionCall extends GeminiPartBase {
|
|
276
296
|
functionCall: {
|
|
277
297
|
name: string;
|
|
278
298
|
args?: object;
|
|
279
299
|
};
|
|
280
300
|
}
|
|
281
|
-
export interface GeminiPartFunctionResponse {
|
|
301
|
+
export interface GeminiPartFunctionResponse extends GeminiPartBase {
|
|
282
302
|
functionResponse: {
|
|
283
303
|
name: string;
|
|
284
304
|
response: object;
|
|
@@ -347,6 +367,18 @@ export interface GeminiSegment {
|
|
|
347
367
|
export interface GeminiRetrievalMetadata {
|
|
348
368
|
googleSearchDynamicRetrievalScore: number;
|
|
349
369
|
}
|
|
370
|
+
export type GeminiUrlRetrievalStatus = "URL_RETRIEVAL_STATUS_SUCCESS" | "URL_RETRIEVAL_STATUS_ERROR";
|
|
371
|
+
export interface GeminiUrlRetrievalContext {
|
|
372
|
+
retrievedUrl: string;
|
|
373
|
+
urlRetrievalStatus: GeminiUrlRetrievalStatus;
|
|
374
|
+
}
|
|
375
|
+
export interface GeminiUrlRetrievalMetadata {
|
|
376
|
+
urlRetrievalContexts: GeminiUrlRetrievalContext[];
|
|
377
|
+
}
|
|
378
|
+
export type GeminiUrlMetadata = GeminiUrlRetrievalContext;
|
|
379
|
+
export interface GeminiUrlContextMetadata {
|
|
380
|
+
urlMetadata: GeminiUrlMetadata[];
|
|
381
|
+
}
|
|
350
382
|
export interface GeminiLogprobsResult {
|
|
351
383
|
topCandidates: GeminiLogprobsTopCandidate[];
|
|
352
384
|
chosenCandidates: GeminiLogprobsResultCandidate[];
|
|
@@ -368,6 +400,7 @@ export interface GeminiTool {
|
|
|
368
400
|
functionDeclarations?: GeminiFunctionDeclaration[];
|
|
369
401
|
googleSearchRetrieval?: GoogleSearchRetrieval;
|
|
370
402
|
googleSearch?: GoogleSearch;
|
|
403
|
+
urlContext?: UrlContext;
|
|
371
404
|
retrieval?: VertexAIRetrieval;
|
|
372
405
|
}
|
|
373
406
|
export type GoogleSearchToolSetting = boolean | "googleSearchRetrieval" | "googleSearch" | string;
|
|
@@ -381,6 +414,8 @@ export interface GoogleSearchRetrieval {
|
|
|
381
414
|
}
|
|
382
415
|
export interface GoogleSearch {
|
|
383
416
|
}
|
|
417
|
+
export interface UrlContext {
|
|
418
|
+
}
|
|
384
419
|
export interface VertexAIRetrieval {
|
|
385
420
|
vertexAiSearch: {
|
|
386
421
|
datastore: string;
|
|
@@ -410,6 +445,7 @@ export interface GeminiGenerationConfig {
|
|
|
410
445
|
temperature?: number;
|
|
411
446
|
topP?: number;
|
|
412
447
|
topK?: number;
|
|
448
|
+
seed?: number;
|
|
413
449
|
presencePenalty?: number;
|
|
414
450
|
frequencyPenalty?: number;
|
|
415
451
|
responseMimeType?: GoogleAIResponseMimeType;
|
|
@@ -443,6 +479,8 @@ export interface GeminiResponseCandidate {
|
|
|
443
479
|
safetyRatings: GeminiSafetyRating[];
|
|
444
480
|
citationMetadata?: GeminiCitationMetadata;
|
|
445
481
|
groundingMetadata?: GeminiGroundingMetadata;
|
|
482
|
+
urlRetrievalMetadata?: GeminiUrlRetrievalMetadata;
|
|
483
|
+
urlContextMetadata?: GeminiUrlContextMetadata;
|
|
446
484
|
avgLogprobs?: number;
|
|
447
485
|
logprobsResult: GeminiLogprobsResult;
|
|
448
486
|
finishMessage?: string;
|
|
@@ -495,6 +533,7 @@ export interface GoogleAISafetyParams {
|
|
|
495
533
|
export type GeminiJsonSchema = Record<string, unknown> & {
|
|
496
534
|
properties?: Record<string, GeminiJsonSchema>;
|
|
497
535
|
type: GeminiFunctionSchemaType;
|
|
536
|
+
nullable?: boolean;
|
|
498
537
|
};
|
|
499
538
|
export interface GeminiJsonSchemaDirty extends GeminiJsonSchema {
|
|
500
539
|
items?: GeminiJsonSchemaDirty;
|
package/dist/types.js
CHANGED
package/dist/utils/common.cjs
CHANGED
|
@@ -131,6 +131,7 @@ function copyAIModelParamsInto(params, options, target) {
|
|
|
131
131
|
reasoningEffortToReasoningTokens(ret.modelName, options?.reasoningEffort);
|
|
132
132
|
ret.topP = options?.topP ?? params?.topP ?? target.topP;
|
|
133
133
|
ret.topK = options?.topK ?? params?.topK ?? target.topK;
|
|
134
|
+
ret.seed = options?.seed ?? params?.seed ?? target.seed;
|
|
134
135
|
ret.presencePenalty =
|
|
135
136
|
options?.presencePenalty ??
|
|
136
137
|
params?.presencePenalty ??
|
package/dist/utils/common.js
CHANGED
|
@@ -126,6 +126,7 @@ export function copyAIModelParamsInto(params, options, target) {
|
|
|
126
126
|
reasoningEffortToReasoningTokens(ret.modelName, options?.reasoningEffort);
|
|
127
127
|
ret.topP = options?.topP ?? params?.topP ?? target.topP;
|
|
128
128
|
ret.topK = options?.topK ?? params?.topK ?? target.topK;
|
|
129
|
+
ret.seed = options?.seed ?? params?.seed ?? target.seed;
|
|
129
130
|
ret.presencePenalty =
|
|
130
131
|
options?.presencePenalty ??
|
|
131
132
|
params?.presencePenalty ??
|
package/dist/utils/gemini.cjs
CHANGED
|
@@ -136,7 +136,7 @@ function getGeminiAPI(config) {
|
|
|
136
136
|
return null;
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
function
|
|
139
|
+
function messageContentImageUrlData(content) {
|
|
140
140
|
const url = typeof content.image_url === "string"
|
|
141
141
|
? content.image_url
|
|
142
142
|
: content.image_url.url;
|
|
@@ -159,6 +159,11 @@ function getGeminiAPI(config) {
|
|
|
159
159
|
};
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
+
function messageContentImageUrl(content) {
|
|
163
|
+
const ret = messageContentImageUrlData(content);
|
|
164
|
+
supplementVideoMetadata(content, ret);
|
|
165
|
+
return ret;
|
|
166
|
+
}
|
|
162
167
|
async function blobToFileData(blob) {
|
|
163
168
|
return {
|
|
164
169
|
fileData: {
|
|
@@ -170,7 +175,7 @@ function getGeminiAPI(config) {
|
|
|
170
175
|
async function fileUriContentToBlob(uri) {
|
|
171
176
|
return config?.mediaManager?.getMediaBlob(uri);
|
|
172
177
|
}
|
|
173
|
-
async function
|
|
178
|
+
async function messageContentMediaData(
|
|
174
179
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
175
180
|
content) {
|
|
176
181
|
if ("mimeType" in content && "data" in content) {
|
|
@@ -198,6 +203,34 @@ function getGeminiAPI(config) {
|
|
|
198
203
|
}
|
|
199
204
|
throw new Error(`Invalid media content: ${JSON.stringify(content, null, 1)}`);
|
|
200
205
|
}
|
|
206
|
+
function supplementVideoMetadata(
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
208
|
+
content, ret) {
|
|
209
|
+
// Add videoMetadata if defined
|
|
210
|
+
if ("videoMetadata" in content && typeof ret === "object") {
|
|
211
|
+
// eslint-disable-next-line no-param-reassign
|
|
212
|
+
ret.videoMetadata = content.videoMetadata;
|
|
213
|
+
}
|
|
214
|
+
return ret;
|
|
215
|
+
}
|
|
216
|
+
async function messageContentMedia(
|
|
217
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
218
|
+
content) {
|
|
219
|
+
const ret = await messageContentMediaData(content);
|
|
220
|
+
supplementVideoMetadata(content, ret);
|
|
221
|
+
return ret;
|
|
222
|
+
}
|
|
223
|
+
function messageContentReasoning(content) {
|
|
224
|
+
if (content?.reasoning && content?.reasoning.length > 0) {
|
|
225
|
+
return {
|
|
226
|
+
text: content.reasoning,
|
|
227
|
+
thought: true,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
201
234
|
const standardContentBlockConverter = {
|
|
202
235
|
providerName: "Google Gemini",
|
|
203
236
|
fromStandardTextBlock(block) {
|
|
@@ -316,8 +349,10 @@ function getGeminiAPI(config) {
|
|
|
316
349
|
break;
|
|
317
350
|
case "media":
|
|
318
351
|
return await messageContentMedia(content);
|
|
352
|
+
case "reasoning":
|
|
353
|
+
return messageContentReasoning(content);
|
|
319
354
|
default:
|
|
320
|
-
throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${content}`);
|
|
355
|
+
throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${JSON.stringify(content)}`);
|
|
321
356
|
}
|
|
322
357
|
throw new Error(`Cannot coerce "${content.type}" message part into a string.`);
|
|
323
358
|
}
|
|
@@ -471,6 +506,12 @@ function getGeminiAPI(config) {
|
|
|
471
506
|
return [];
|
|
472
507
|
}
|
|
473
508
|
}
|
|
509
|
+
function thoughtPartToMessageContent(part) {
|
|
510
|
+
return {
|
|
511
|
+
type: "reasoning",
|
|
512
|
+
reasoning: part.text,
|
|
513
|
+
};
|
|
514
|
+
}
|
|
474
515
|
function textPartToMessageContent(part) {
|
|
475
516
|
return {
|
|
476
517
|
type: "text",
|
|
@@ -495,6 +536,9 @@ function getGeminiAPI(config) {
|
|
|
495
536
|
if (part === undefined || part === null) {
|
|
496
537
|
return null;
|
|
497
538
|
}
|
|
539
|
+
else if (part.thought) {
|
|
540
|
+
return thoughtPartToMessageContent(part);
|
|
541
|
+
}
|
|
498
542
|
else if ("text" in part) {
|
|
499
543
|
return textPartToMessageContent(part);
|
|
500
544
|
}
|
|
@@ -639,6 +683,19 @@ function getGeminiAPI(config) {
|
|
|
639
683
|
content,
|
|
640
684
|
};
|
|
641
685
|
}
|
|
686
|
+
function candidateToUrlContextMetadata(candidate) {
|
|
687
|
+
const retrieval = candidate?.urlRetrievalMetadata?.urlRetrievalContexts ?? [];
|
|
688
|
+
const context = candidate?.urlContextMetadata?.urlMetadata ?? [];
|
|
689
|
+
const all = [...retrieval, ...context];
|
|
690
|
+
if (all.length === 0) {
|
|
691
|
+
return undefined;
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
return {
|
|
695
|
+
urlMetadata: all,
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
}
|
|
642
699
|
function addModalityCounts(modalityTokenCounts, details) {
|
|
643
700
|
modalityTokenCounts?.forEach((modalityTokenCount) => {
|
|
644
701
|
const { modality, tokenCount } = modalityTokenCount;
|
|
@@ -659,6 +716,9 @@ function getGeminiAPI(config) {
|
|
|
659
716
|
const total_tokens = usageMetadata.totalTokenCount ?? input_tokens + output_tokens;
|
|
660
717
|
const input_token_details = {};
|
|
661
718
|
addModalityCounts(usageMetadata.promptTokensDetails, input_token_details);
|
|
719
|
+
if (typeof usageMetadata?.cachedContentTokenCount === "number") {
|
|
720
|
+
input_token_details.cache_read = usageMetadata.cachedContentTokenCount;
|
|
721
|
+
}
|
|
662
722
|
const output_token_details = {};
|
|
663
723
|
addModalityCounts(usageMetadata?.candidatesTokensDetails, output_token_details);
|
|
664
724
|
if (typeof usageMetadata?.thoughtsTokenCount === "number") {
|
|
@@ -701,6 +761,7 @@ function getGeminiAPI(config) {
|
|
|
701
761
|
grounding_metadata: data.candidates[0]?.groundingMetadata,
|
|
702
762
|
finish_reason,
|
|
703
763
|
finish_message: data.candidates[0]?.finishMessage,
|
|
764
|
+
url_context_metadata: candidateToUrlContextMetadata(data.candidates[0]),
|
|
704
765
|
avgLogprobs: data.candidates[0]?.avgLogprobs,
|
|
705
766
|
logprobs: candidateToLogprobs(data.candidates[0]),
|
|
706
767
|
};
|
|
@@ -828,6 +889,7 @@ function getGeminiAPI(config) {
|
|
|
828
889
|
if (typeof item.message.content === "string") {
|
|
829
890
|
// If this is a string, turn it into a text type
|
|
830
891
|
ret.push({
|
|
892
|
+
type: "text",
|
|
831
893
|
text: item.message.content,
|
|
832
894
|
});
|
|
833
895
|
}
|
|
@@ -1072,6 +1134,7 @@ function getGeminiAPI(config) {
|
|
|
1072
1134
|
temperature: parameters.temperature,
|
|
1073
1135
|
topK: parameters.topK,
|
|
1074
1136
|
topP: parameters.topP,
|
|
1137
|
+
seed: parameters.seed,
|
|
1075
1138
|
presencePenalty: parameters.presencePenalty,
|
|
1076
1139
|
frequencyPenalty: parameters.frequencyPenalty,
|
|
1077
1140
|
maxOutputTokens: parameters.maxOutputTokens,
|
|
@@ -1090,10 +1153,10 @@ function getGeminiAPI(config) {
|
|
|
1090
1153
|
// Add thinking configuration if explicitly set
|
|
1091
1154
|
// Note that you cannot have thinkingBudget set to 0 and includeThoughts true
|
|
1092
1155
|
if (typeof parameters.maxReasoningTokens !== "undefined") {
|
|
1156
|
+
const includeThoughts = parameters.maxReasoningTokens > 0;
|
|
1093
1157
|
ret.thinkingConfig = {
|
|
1094
1158
|
thinkingBudget: parameters.maxReasoningTokens,
|
|
1095
|
-
|
|
1096
|
-
includeThoughts: false,
|
|
1159
|
+
includeThoughts,
|
|
1097
1160
|
};
|
|
1098
1161
|
}
|
|
1099
1162
|
// Remove any undefined properties, so we don't send them
|
package/dist/utils/gemini.js
CHANGED
|
@@ -131,7 +131,7 @@ export function getGeminiAPI(config) {
|
|
|
131
131
|
return null;
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
-
function
|
|
134
|
+
function messageContentImageUrlData(content) {
|
|
135
135
|
const url = typeof content.image_url === "string"
|
|
136
136
|
? content.image_url
|
|
137
137
|
: content.image_url.url;
|
|
@@ -154,6 +154,11 @@ export function getGeminiAPI(config) {
|
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
+
function messageContentImageUrl(content) {
|
|
158
|
+
const ret = messageContentImageUrlData(content);
|
|
159
|
+
supplementVideoMetadata(content, ret);
|
|
160
|
+
return ret;
|
|
161
|
+
}
|
|
157
162
|
async function blobToFileData(blob) {
|
|
158
163
|
return {
|
|
159
164
|
fileData: {
|
|
@@ -165,7 +170,7 @@ export function getGeminiAPI(config) {
|
|
|
165
170
|
async function fileUriContentToBlob(uri) {
|
|
166
171
|
return config?.mediaManager?.getMediaBlob(uri);
|
|
167
172
|
}
|
|
168
|
-
async function
|
|
173
|
+
async function messageContentMediaData(
|
|
169
174
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
175
|
content) {
|
|
171
176
|
if ("mimeType" in content && "data" in content) {
|
|
@@ -193,6 +198,34 @@ export function getGeminiAPI(config) {
|
|
|
193
198
|
}
|
|
194
199
|
throw new Error(`Invalid media content: ${JSON.stringify(content, null, 1)}`);
|
|
195
200
|
}
|
|
201
|
+
function supplementVideoMetadata(
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
203
|
+
content, ret) {
|
|
204
|
+
// Add videoMetadata if defined
|
|
205
|
+
if ("videoMetadata" in content && typeof ret === "object") {
|
|
206
|
+
// eslint-disable-next-line no-param-reassign
|
|
207
|
+
ret.videoMetadata = content.videoMetadata;
|
|
208
|
+
}
|
|
209
|
+
return ret;
|
|
210
|
+
}
|
|
211
|
+
async function messageContentMedia(
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
213
|
+
content) {
|
|
214
|
+
const ret = await messageContentMediaData(content);
|
|
215
|
+
supplementVideoMetadata(content, ret);
|
|
216
|
+
return ret;
|
|
217
|
+
}
|
|
218
|
+
function messageContentReasoning(content) {
|
|
219
|
+
if (content?.reasoning && content?.reasoning.length > 0) {
|
|
220
|
+
return {
|
|
221
|
+
text: content.reasoning,
|
|
222
|
+
thought: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
196
229
|
const standardContentBlockConverter = {
|
|
197
230
|
providerName: "Google Gemini",
|
|
198
231
|
fromStandardTextBlock(block) {
|
|
@@ -311,8 +344,10 @@ export function getGeminiAPI(config) {
|
|
|
311
344
|
break;
|
|
312
345
|
case "media":
|
|
313
346
|
return await messageContentMedia(content);
|
|
347
|
+
case "reasoning":
|
|
348
|
+
return messageContentReasoning(content);
|
|
314
349
|
default:
|
|
315
|
-
throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${content}`);
|
|
350
|
+
throw new Error(`Unsupported type "${content.type}" received while converting message to message parts: ${JSON.stringify(content)}`);
|
|
316
351
|
}
|
|
317
352
|
throw new Error(`Cannot coerce "${content.type}" message part into a string.`);
|
|
318
353
|
}
|
|
@@ -466,6 +501,12 @@ export function getGeminiAPI(config) {
|
|
|
466
501
|
return [];
|
|
467
502
|
}
|
|
468
503
|
}
|
|
504
|
+
function thoughtPartToMessageContent(part) {
|
|
505
|
+
return {
|
|
506
|
+
type: "reasoning",
|
|
507
|
+
reasoning: part.text,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
469
510
|
function textPartToMessageContent(part) {
|
|
470
511
|
return {
|
|
471
512
|
type: "text",
|
|
@@ -490,6 +531,9 @@ export function getGeminiAPI(config) {
|
|
|
490
531
|
if (part === undefined || part === null) {
|
|
491
532
|
return null;
|
|
492
533
|
}
|
|
534
|
+
else if (part.thought) {
|
|
535
|
+
return thoughtPartToMessageContent(part);
|
|
536
|
+
}
|
|
493
537
|
else if ("text" in part) {
|
|
494
538
|
return textPartToMessageContent(part);
|
|
495
539
|
}
|
|
@@ -634,6 +678,19 @@ export function getGeminiAPI(config) {
|
|
|
634
678
|
content,
|
|
635
679
|
};
|
|
636
680
|
}
|
|
681
|
+
function candidateToUrlContextMetadata(candidate) {
|
|
682
|
+
const retrieval = candidate?.urlRetrievalMetadata?.urlRetrievalContexts ?? [];
|
|
683
|
+
const context = candidate?.urlContextMetadata?.urlMetadata ?? [];
|
|
684
|
+
const all = [...retrieval, ...context];
|
|
685
|
+
if (all.length === 0) {
|
|
686
|
+
return undefined;
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
return {
|
|
690
|
+
urlMetadata: all,
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
}
|
|
637
694
|
function addModalityCounts(modalityTokenCounts, details) {
|
|
638
695
|
modalityTokenCounts?.forEach((modalityTokenCount) => {
|
|
639
696
|
const { modality, tokenCount } = modalityTokenCount;
|
|
@@ -654,6 +711,9 @@ export function getGeminiAPI(config) {
|
|
|
654
711
|
const total_tokens = usageMetadata.totalTokenCount ?? input_tokens + output_tokens;
|
|
655
712
|
const input_token_details = {};
|
|
656
713
|
addModalityCounts(usageMetadata.promptTokensDetails, input_token_details);
|
|
714
|
+
if (typeof usageMetadata?.cachedContentTokenCount === "number") {
|
|
715
|
+
input_token_details.cache_read = usageMetadata.cachedContentTokenCount;
|
|
716
|
+
}
|
|
657
717
|
const output_token_details = {};
|
|
658
718
|
addModalityCounts(usageMetadata?.candidatesTokensDetails, output_token_details);
|
|
659
719
|
if (typeof usageMetadata?.thoughtsTokenCount === "number") {
|
|
@@ -696,6 +756,7 @@ export function getGeminiAPI(config) {
|
|
|
696
756
|
grounding_metadata: data.candidates[0]?.groundingMetadata,
|
|
697
757
|
finish_reason,
|
|
698
758
|
finish_message: data.candidates[0]?.finishMessage,
|
|
759
|
+
url_context_metadata: candidateToUrlContextMetadata(data.candidates[0]),
|
|
699
760
|
avgLogprobs: data.candidates[0]?.avgLogprobs,
|
|
700
761
|
logprobs: candidateToLogprobs(data.candidates[0]),
|
|
701
762
|
};
|
|
@@ -823,6 +884,7 @@ export function getGeminiAPI(config) {
|
|
|
823
884
|
if (typeof item.message.content === "string") {
|
|
824
885
|
// If this is a string, turn it into a text type
|
|
825
886
|
ret.push({
|
|
887
|
+
type: "text",
|
|
826
888
|
text: item.message.content,
|
|
827
889
|
});
|
|
828
890
|
}
|
|
@@ -1067,6 +1129,7 @@ export function getGeminiAPI(config) {
|
|
|
1067
1129
|
temperature: parameters.temperature,
|
|
1068
1130
|
topK: parameters.topK,
|
|
1069
1131
|
topP: parameters.topP,
|
|
1132
|
+
seed: parameters.seed,
|
|
1070
1133
|
presencePenalty: parameters.presencePenalty,
|
|
1071
1134
|
frequencyPenalty: parameters.frequencyPenalty,
|
|
1072
1135
|
maxOutputTokens: parameters.maxOutputTokens,
|
|
@@ -1085,10 +1148,10 @@ export function getGeminiAPI(config) {
|
|
|
1085
1148
|
// Add thinking configuration if explicitly set
|
|
1086
1149
|
// Note that you cannot have thinkingBudget set to 0 and includeThoughts true
|
|
1087
1150
|
if (typeof parameters.maxReasoningTokens !== "undefined") {
|
|
1151
|
+
const includeThoughts = parameters.maxReasoningTokens > 0;
|
|
1088
1152
|
ret.thinkingConfig = {
|
|
1089
1153
|
thinkingBudget: parameters.maxReasoningTokens,
|
|
1090
|
-
|
|
1091
|
-
includeThoughts: false,
|
|
1154
|
+
includeThoughts,
|
|
1092
1155
|
};
|
|
1093
1156
|
}
|
|
1094
1157
|
// Remove any undefined properties, so we don't send them
|
|
@@ -12,6 +12,31 @@ obj) {
|
|
|
12
12
|
if ("additionalProperties" in newObj) {
|
|
13
13
|
delete newObj.additionalProperties;
|
|
14
14
|
}
|
|
15
|
+
if (Array.isArray(obj.type)) {
|
|
16
|
+
const len = obj.type.length;
|
|
17
|
+
const nullIndex = obj.type.indexOf("null");
|
|
18
|
+
if (len === 2 && nullIndex >= 0) {
|
|
19
|
+
// There are only two values set for the type, and one of them is "null".
|
|
20
|
+
// Set the type to the other one and set nullable to true.
|
|
21
|
+
const typeIndex = nullIndex === 0 ? 1 : 0;
|
|
22
|
+
newObj.type = obj.type[typeIndex];
|
|
23
|
+
newObj.nullable = true;
|
|
24
|
+
}
|
|
25
|
+
else if (len === 1 && nullIndex === 0) {
|
|
26
|
+
// This is nullable only without a type, which doesn't
|
|
27
|
+
// make sense for Gemini
|
|
28
|
+
throw new Error("zod_to_gemini_parameters: Gemini cannot handle null type");
|
|
29
|
+
}
|
|
30
|
+
else if (len === 1) {
|
|
31
|
+
// Although an array, it has only one value.
|
|
32
|
+
// So set it to the string to match what Gemini expects.
|
|
33
|
+
newObj.type = obj?.type[0];
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Anything else could be a union type, so reject it.
|
|
37
|
+
throw new Error("zod_to_gemini_parameters: Gemini cannot handle union types");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
15
40
|
for (const key in newObj) {
|
|
16
41
|
if (key in newObj) {
|
|
17
42
|
if (Array.isArray(newObj[key])) {
|
|
@@ -30,6 +55,8 @@ exports.removeAdditionalProperties = removeAdditionalProperties;
|
|
|
30
55
|
function schemaToGeminiParameters(schema) {
|
|
31
56
|
// Gemini doesn't accept either the $schema or additionalProperties
|
|
32
57
|
// attributes, so we need to explicitly remove them.
|
|
58
|
+
// Zod sometimes also makes an array of type (because of .nullish()),
|
|
59
|
+
// which needs cleaning up.
|
|
33
60
|
const jsonSchema = removeAdditionalProperties((0, types_1.isZodSchema)(schema) ? (0, zod_to_json_schema_1.zodToJsonSchema)(schema) : schema);
|
|
34
61
|
const { $schema, ...rest } = jsonSchema;
|
|
35
62
|
return rest;
|
|
@@ -9,6 +9,31 @@ obj) {
|
|
|
9
9
|
if ("additionalProperties" in newObj) {
|
|
10
10
|
delete newObj.additionalProperties;
|
|
11
11
|
}
|
|
12
|
+
if (Array.isArray(obj.type)) {
|
|
13
|
+
const len = obj.type.length;
|
|
14
|
+
const nullIndex = obj.type.indexOf("null");
|
|
15
|
+
if (len === 2 && nullIndex >= 0) {
|
|
16
|
+
// There are only two values set for the type, and one of them is "null".
|
|
17
|
+
// Set the type to the other one and set nullable to true.
|
|
18
|
+
const typeIndex = nullIndex === 0 ? 1 : 0;
|
|
19
|
+
newObj.type = obj.type[typeIndex];
|
|
20
|
+
newObj.nullable = true;
|
|
21
|
+
}
|
|
22
|
+
else if (len === 1 && nullIndex === 0) {
|
|
23
|
+
// This is nullable only without a type, which doesn't
|
|
24
|
+
// make sense for Gemini
|
|
25
|
+
throw new Error("zod_to_gemini_parameters: Gemini cannot handle null type");
|
|
26
|
+
}
|
|
27
|
+
else if (len === 1) {
|
|
28
|
+
// Although an array, it has only one value.
|
|
29
|
+
// So set it to the string to match what Gemini expects.
|
|
30
|
+
newObj.type = obj?.type[0];
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// Anything else could be a union type, so reject it.
|
|
34
|
+
throw new Error("zod_to_gemini_parameters: Gemini cannot handle union types");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
12
37
|
for (const key in newObj) {
|
|
13
38
|
if (key in newObj) {
|
|
14
39
|
if (Array.isArray(newObj[key])) {
|
|
@@ -26,6 +51,8 @@ obj) {
|
|
|
26
51
|
export function schemaToGeminiParameters(schema) {
|
|
27
52
|
// Gemini doesn't accept either the $schema or additionalProperties
|
|
28
53
|
// attributes, so we need to explicitly remove them.
|
|
54
|
+
// Zod sometimes also makes an array of type (because of .nullish()),
|
|
55
|
+
// which needs cleaning up.
|
|
29
56
|
const jsonSchema = removeAdditionalProperties(isZodSchema(schema) ? zodToJsonSchema(schema) : schema);
|
|
30
57
|
const { $schema, ...rest } = jsonSchema;
|
|
31
58
|
return rest;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/google-common",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "Core types and classes for Google services.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@jest/globals": "^29.5.0",
|
|
43
|
-
"@langchain/core": "0.3.
|
|
43
|
+
"@langchain/core": "0.3.57",
|
|
44
44
|
"@langchain/scripts": ">=0.1.0 <0.2.0",
|
|
45
45
|
"@swc/core": "^1.3.90",
|
|
46
46
|
"@swc/jest": "^0.2.29",
|