@langchain/google-common 0.1.8 → 0.2.1
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 +5 -11
- package/dist/chat_models.js +5 -11
- package/dist/connection.cjs +22 -2
- package/dist/connection.d.ts +3 -0
- package/dist/connection.js +22 -2
- package/dist/types-anthropic.d.ts +30 -2
- package/dist/utils/anthropic.cjs +69 -2
- package/dist/utils/anthropic.js +69 -2
- package/dist/utils/gemini.cjs +136 -34
- package/dist/utils/gemini.js +136 -34
- package/package.json +1 -1
package/dist/chat_models.cjs
CHANGED
|
@@ -131,25 +131,25 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
131
131
|
enumerable: true,
|
|
132
132
|
configurable: true,
|
|
133
133
|
writable: true,
|
|
134
|
-
value: 0
|
|
134
|
+
value: void 0
|
|
135
135
|
});
|
|
136
136
|
Object.defineProperty(this, "maxOutputTokens", {
|
|
137
137
|
enumerable: true,
|
|
138
138
|
configurable: true,
|
|
139
139
|
writable: true,
|
|
140
|
-
value:
|
|
140
|
+
value: void 0
|
|
141
141
|
});
|
|
142
142
|
Object.defineProperty(this, "topP", {
|
|
143
143
|
enumerable: true,
|
|
144
144
|
configurable: true,
|
|
145
145
|
writable: true,
|
|
146
|
-
value: 0
|
|
146
|
+
value: void 0
|
|
147
147
|
});
|
|
148
148
|
Object.defineProperty(this, "topK", {
|
|
149
149
|
enumerable: true,
|
|
150
150
|
configurable: true,
|
|
151
151
|
writable: true,
|
|
152
|
-
value:
|
|
152
|
+
value: void 0
|
|
153
153
|
});
|
|
154
154
|
Object.defineProperty(this, "presencePenalty", {
|
|
155
155
|
enumerable: true,
|
|
@@ -246,13 +246,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
246
246
|
return new auth_js_1.ApiKeyGoogleAuth(apiKey);
|
|
247
247
|
}
|
|
248
248
|
buildApiKey(fields) {
|
|
249
|
-
|
|
250
|
-
return fields?.apiKey ?? (0, env_1.getEnvironmentVariable)("GOOGLE_API_KEY");
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
// GCP doesn't support API Keys
|
|
254
|
-
return undefined;
|
|
255
|
-
}
|
|
249
|
+
return fields?.apiKey ?? (0, env_1.getEnvironmentVariable)("GOOGLE_API_KEY");
|
|
256
250
|
}
|
|
257
251
|
buildClient(fields) {
|
|
258
252
|
const apiKey = this.buildApiKey(fields);
|
package/dist/chat_models.js
CHANGED
|
@@ -127,25 +127,25 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
127
127
|
enumerable: true,
|
|
128
128
|
configurable: true,
|
|
129
129
|
writable: true,
|
|
130
|
-
value: 0
|
|
130
|
+
value: void 0
|
|
131
131
|
});
|
|
132
132
|
Object.defineProperty(this, "maxOutputTokens", {
|
|
133
133
|
enumerable: true,
|
|
134
134
|
configurable: true,
|
|
135
135
|
writable: true,
|
|
136
|
-
value:
|
|
136
|
+
value: void 0
|
|
137
137
|
});
|
|
138
138
|
Object.defineProperty(this, "topP", {
|
|
139
139
|
enumerable: true,
|
|
140
140
|
configurable: true,
|
|
141
141
|
writable: true,
|
|
142
|
-
value: 0
|
|
142
|
+
value: void 0
|
|
143
143
|
});
|
|
144
144
|
Object.defineProperty(this, "topK", {
|
|
145
145
|
enumerable: true,
|
|
146
146
|
configurable: true,
|
|
147
147
|
writable: true,
|
|
148
|
-
value:
|
|
148
|
+
value: void 0
|
|
149
149
|
});
|
|
150
150
|
Object.defineProperty(this, "presencePenalty", {
|
|
151
151
|
enumerable: true,
|
|
@@ -242,13 +242,7 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
242
242
|
return new ApiKeyGoogleAuth(apiKey);
|
|
243
243
|
}
|
|
244
244
|
buildApiKey(fields) {
|
|
245
|
-
|
|
246
|
-
return fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
// GCP doesn't support API Keys
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
245
|
+
return fields?.apiKey ?? getEnvironmentVariable("GOOGLE_API_KEY");
|
|
252
246
|
}
|
|
253
247
|
buildClient(fields) {
|
|
254
248
|
const apiKey = this.buildApiKey(fields);
|
package/dist/connection.cjs
CHANGED
|
@@ -223,8 +223,14 @@ class GoogleAIConnection extends GoogleHostConnection {
|
|
|
223
223
|
throw new Error(`Unknown API: ${this.apiName}`);
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
|
+
get isApiKey() {
|
|
227
|
+
return this.client.clientType === "apiKey";
|
|
228
|
+
}
|
|
226
229
|
get computedPlatformType() {
|
|
227
|
-
|
|
230
|
+
// This is not a completely correct assumption, since GCP can
|
|
231
|
+
// have an API Key. But if so, then people need to set the platform
|
|
232
|
+
// type explicitly.
|
|
233
|
+
if (this.isApiKey) {
|
|
228
234
|
return "gai";
|
|
229
235
|
}
|
|
230
236
|
else {
|
|
@@ -246,13 +252,27 @@ class GoogleAIConnection extends GoogleHostConnection {
|
|
|
246
252
|
const url = `https://generativelanguage.googleapis.com/${this.apiVersion}/models/${this.model}:${method}`;
|
|
247
253
|
return url;
|
|
248
254
|
}
|
|
249
|
-
async
|
|
255
|
+
async buildUrlVertexExpress() {
|
|
256
|
+
const method = await this.buildUrlMethod();
|
|
257
|
+
const publisher = this.modelPublisher;
|
|
258
|
+
const url = `https://aiplatform.googleapis.com/${this.apiVersion}/publishers/${publisher}/models/${this.model}:${method}`;
|
|
259
|
+
return url;
|
|
260
|
+
}
|
|
261
|
+
async buildUrlVertexLocation() {
|
|
250
262
|
const projectId = await this.client.getProjectId();
|
|
251
263
|
const method = await this.buildUrlMethod();
|
|
252
264
|
const publisher = this.modelPublisher;
|
|
253
265
|
const url = `https://${this.endpoint}/${this.apiVersion}/projects/${projectId}/locations/${this.location}/publishers/${publisher}/models/${this.model}:${method}`;
|
|
254
266
|
return url;
|
|
255
267
|
}
|
|
268
|
+
async buildUrlVertex() {
|
|
269
|
+
if (this.isApiKey) {
|
|
270
|
+
return this.buildUrlVertexExpress();
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
return this.buildUrlVertexLocation();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
256
276
|
async buildUrl() {
|
|
257
277
|
switch (this.platform) {
|
|
258
278
|
case "gai":
|
package/dist/connection.d.ts
CHANGED
|
@@ -50,10 +50,13 @@ export declare abstract class GoogleAIConnection<CallOptions extends AsyncCaller
|
|
|
50
50
|
get computedAPIName(): string;
|
|
51
51
|
get apiName(): string;
|
|
52
52
|
get api(): GoogleAIAPI;
|
|
53
|
+
get isApiKey(): boolean;
|
|
53
54
|
get computedPlatformType(): GooglePlatformType;
|
|
54
55
|
get computedLocation(): string;
|
|
55
56
|
abstract buildUrlMethod(): Promise<string>;
|
|
56
57
|
buildUrlGenerativeLanguage(): Promise<string>;
|
|
58
|
+
buildUrlVertexExpress(): Promise<string>;
|
|
59
|
+
buildUrlVertexLocation(): Promise<string>;
|
|
57
60
|
buildUrlVertex(): Promise<string>;
|
|
58
61
|
buildUrl(): Promise<string>;
|
|
59
62
|
abstract formatData(input: InputType, parameters: GoogleAIModelRequestParams): Promise<unknown>;
|
package/dist/connection.js
CHANGED
|
@@ -217,8 +217,14 @@ export class GoogleAIConnection extends GoogleHostConnection {
|
|
|
217
217
|
throw new Error(`Unknown API: ${this.apiName}`);
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
|
+
get isApiKey() {
|
|
221
|
+
return this.client.clientType === "apiKey";
|
|
222
|
+
}
|
|
220
223
|
get computedPlatformType() {
|
|
221
|
-
|
|
224
|
+
// This is not a completely correct assumption, since GCP can
|
|
225
|
+
// have an API Key. But if so, then people need to set the platform
|
|
226
|
+
// type explicitly.
|
|
227
|
+
if (this.isApiKey) {
|
|
222
228
|
return "gai";
|
|
223
229
|
}
|
|
224
230
|
else {
|
|
@@ -240,13 +246,27 @@ export class GoogleAIConnection extends GoogleHostConnection {
|
|
|
240
246
|
const url = `https://generativelanguage.googleapis.com/${this.apiVersion}/models/${this.model}:${method}`;
|
|
241
247
|
return url;
|
|
242
248
|
}
|
|
243
|
-
async
|
|
249
|
+
async buildUrlVertexExpress() {
|
|
250
|
+
const method = await this.buildUrlMethod();
|
|
251
|
+
const publisher = this.modelPublisher;
|
|
252
|
+
const url = `https://aiplatform.googleapis.com/${this.apiVersion}/publishers/${publisher}/models/${this.model}:${method}`;
|
|
253
|
+
return url;
|
|
254
|
+
}
|
|
255
|
+
async buildUrlVertexLocation() {
|
|
244
256
|
const projectId = await this.client.getProjectId();
|
|
245
257
|
const method = await this.buildUrlMethod();
|
|
246
258
|
const publisher = this.modelPublisher;
|
|
247
259
|
const url = `https://${this.endpoint}/${this.apiVersion}/projects/${projectId}/locations/${this.location}/publishers/${publisher}/models/${this.model}:${method}`;
|
|
248
260
|
return url;
|
|
249
261
|
}
|
|
262
|
+
async buildUrlVertex() {
|
|
263
|
+
if (this.isApiKey) {
|
|
264
|
+
return this.buildUrlVertexExpress();
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
return this.buildUrlVertexLocation();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
250
270
|
async buildUrl() {
|
|
251
271
|
switch (this.platform) {
|
|
252
272
|
case "gai":
|
|
@@ -17,6 +17,15 @@ export interface AnthropicMessageContentImage extends AnthropicMessageContentBas
|
|
|
17
17
|
data: string;
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
export interface AnthropicMessageContentThinking extends AnthropicMessageContentBase {
|
|
21
|
+
type: "thinking";
|
|
22
|
+
thinking: string;
|
|
23
|
+
signature: string;
|
|
24
|
+
}
|
|
25
|
+
export interface AnthropicMessageContentRedactedThinking extends AnthropicMessageContentBase {
|
|
26
|
+
type: "redacted_thinking";
|
|
27
|
+
data: string;
|
|
28
|
+
}
|
|
20
29
|
export type AnthropicMessageContentToolUseInput = object;
|
|
21
30
|
export interface AnthropicMessageContentToolUse extends AnthropicMessageContentBase {
|
|
22
31
|
type: "tool_use";
|
|
@@ -31,7 +40,7 @@ export interface AnthropicMessageContentToolResult extends AnthropicMessageConte
|
|
|
31
40
|
is_error?: boolean;
|
|
32
41
|
content: string | AnthropicMessageContentToolResultContent[];
|
|
33
42
|
}
|
|
34
|
-
export type AnthropicMessageContent = AnthropicMessageContentText | AnthropicMessageContentImage | AnthropicMessageContentToolUse | AnthropicMessageContentToolResult;
|
|
43
|
+
export type AnthropicMessageContent = AnthropicMessageContentText | AnthropicMessageContentImage | AnthropicMessageContentToolUse | AnthropicMessageContentToolResult | AnthropicMessageContentThinking | AnthropicMessageContentRedactedThinking;
|
|
35
44
|
export interface AnthropicMessage {
|
|
36
45
|
role: string;
|
|
37
46
|
content: string | AnthropicMessageContent[];
|
|
@@ -61,6 +70,14 @@ export interface AnthropicTool {
|
|
|
61
70
|
cache_control?: AnthropicCacheControl;
|
|
62
71
|
input_schema: AnthropicToolInputSchema;
|
|
63
72
|
}
|
|
73
|
+
export interface AnthropicThinkingEnabled {
|
|
74
|
+
type: "enabled";
|
|
75
|
+
budget_tokens: number;
|
|
76
|
+
}
|
|
77
|
+
export interface AnthropicThinkingDisabled {
|
|
78
|
+
type: "disabled";
|
|
79
|
+
}
|
|
80
|
+
export type AnthropicThinking = AnthropicThinkingEnabled | AnthropicThinkingDisabled;
|
|
64
81
|
export interface AnthropicRequest {
|
|
65
82
|
anthropic_version: string;
|
|
66
83
|
messages: AnthropicMessage[];
|
|
@@ -74,6 +91,7 @@ export interface AnthropicRequest {
|
|
|
74
91
|
metadata?: AnthropicMetadata;
|
|
75
92
|
tool_choice?: AnthropicToolChoice;
|
|
76
93
|
tools?: AnthropicTool[];
|
|
94
|
+
thinking?: AnthropicThinking;
|
|
77
95
|
}
|
|
78
96
|
export type AnthropicRequestSettings = Pick<AnthropicRequest, "max_tokens" | "temperature" | "top_k" | "top_p" | "stop_sequences" | "stream">;
|
|
79
97
|
export interface AnthropicContentText {
|
|
@@ -86,7 +104,16 @@ export interface AnthropicContentToolUse {
|
|
|
86
104
|
name: string;
|
|
87
105
|
input: object;
|
|
88
106
|
}
|
|
89
|
-
export
|
|
107
|
+
export interface AnthropicContentThinking {
|
|
108
|
+
type: "thinking";
|
|
109
|
+
thinking: string;
|
|
110
|
+
signature: string;
|
|
111
|
+
}
|
|
112
|
+
export interface AnthropicContentRedactedThinking {
|
|
113
|
+
type: "redacted_thinking";
|
|
114
|
+
data: string;
|
|
115
|
+
}
|
|
116
|
+
export type AnthropicContent = AnthropicContentText | AnthropicContentToolUse | AnthropicContentThinking | AnthropicContentRedactedThinking;
|
|
90
117
|
export interface AnthropicUsage {
|
|
91
118
|
input_tokens: number;
|
|
92
119
|
output_tokens: number;
|
|
@@ -106,6 +133,7 @@ export interface AnthropicResponseMessage {
|
|
|
106
133
|
}
|
|
107
134
|
export interface AnthropicAPIConfig {
|
|
108
135
|
version?: string;
|
|
136
|
+
thinking?: AnthropicThinking;
|
|
109
137
|
}
|
|
110
138
|
export type AnthropicStreamEventType = "message_start" | "content_block_start" | "content_block_delta" | "content_block_stop" | "message_delta" | "message_stop" | "ping" | "error";
|
|
111
139
|
export type AnthropicStreamDeltaType = "text_delta" | "input_json_delta";
|
package/dist/utils/anthropic.cjs
CHANGED
|
@@ -70,6 +70,18 @@ function getAnthropicAPI(config) {
|
|
|
70
70
|
tool_calls: [tool],
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
+
function thinkingContentToMessageFields(thinkingContent) {
|
|
74
|
+
// TODO: Once a reasoning/thinking type is defined in LangChain, use it
|
|
75
|
+
return {
|
|
76
|
+
content: [thinkingContent],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function redactedThinkingContentToMessageFields(thinkingContent) {
|
|
80
|
+
// TODO: Once a reasoning/thinking type is defined in LangChain, use it
|
|
81
|
+
return {
|
|
82
|
+
content: [thinkingContent],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
73
85
|
function anthropicContentToMessageFields(anthropicContent) {
|
|
74
86
|
const type = anthropicContent?.type;
|
|
75
87
|
switch (type) {
|
|
@@ -77,7 +89,12 @@ function getAnthropicAPI(config) {
|
|
|
77
89
|
return textContentToMessageFields(anthropicContent);
|
|
78
90
|
case "tool_use":
|
|
79
91
|
return toolUseContentToMessageFields(anthropicContent);
|
|
92
|
+
case "thinking":
|
|
93
|
+
return thinkingContentToMessageFields(anthropicContent);
|
|
94
|
+
case "redacted_thinking":
|
|
95
|
+
return redactedThinkingContentToMessageFields(anthropicContent);
|
|
80
96
|
default:
|
|
97
|
+
console.error(`Unknown message type: ${type}`, anthropicContent);
|
|
81
98
|
return undefined;
|
|
82
99
|
}
|
|
83
100
|
}
|
|
@@ -321,6 +338,25 @@ function getAnthropicAPI(config) {
|
|
|
321
338
|
},
|
|
322
339
|
};
|
|
323
340
|
}
|
|
341
|
+
function thinkingContentToAnthropicContent(
|
|
342
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
343
|
+
content) {
|
|
344
|
+
// TODO: Once a Langchain Thinking type is defined, use it
|
|
345
|
+
return {
|
|
346
|
+
type: "thinking",
|
|
347
|
+
thinking: content.thinking,
|
|
348
|
+
signature: content.signature,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
function redactedThinkingContentToAnthropicContent(
|
|
352
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
353
|
+
content) {
|
|
354
|
+
// TODO: Once a Langchain Thinking type is defined, use it
|
|
355
|
+
return {
|
|
356
|
+
type: "redacted_thinking",
|
|
357
|
+
data: content.data,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
324
360
|
function contentComplexToAnthropicContent(content) {
|
|
325
361
|
const type = content?.type;
|
|
326
362
|
switch (type) {
|
|
@@ -328,8 +364,12 @@ function getAnthropicAPI(config) {
|
|
|
328
364
|
return textContentToAnthropicContent(content);
|
|
329
365
|
case "image_url":
|
|
330
366
|
return imageContentToAnthropicContent(content);
|
|
367
|
+
case "thinking":
|
|
368
|
+
return thinkingContentToAnthropicContent(content);
|
|
369
|
+
case "redacted_thinking":
|
|
370
|
+
return redactedThinkingContentToAnthropicContent(content);
|
|
331
371
|
default:
|
|
332
|
-
console.warn(`Unexpected content type: ${type}
|
|
372
|
+
console.warn(`Unexpected content type: ${type}`, content);
|
|
333
373
|
return undefined;
|
|
334
374
|
}
|
|
335
375
|
}
|
|
@@ -344,6 +384,20 @@ function getAnthropicAPI(config) {
|
|
|
344
384
|
});
|
|
345
385
|
return ret;
|
|
346
386
|
}
|
|
387
|
+
function toolCallToAnthropicContent(toolCall) {
|
|
388
|
+
return {
|
|
389
|
+
type: "tool_use",
|
|
390
|
+
id: toolCall.id,
|
|
391
|
+
name: toolCall.name,
|
|
392
|
+
input: toolCall.args,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function toolCallsToAnthropicContent(toolCalls) {
|
|
396
|
+
if (toolCalls === undefined) {
|
|
397
|
+
return [];
|
|
398
|
+
}
|
|
399
|
+
return toolCalls.map(toolCallToAnthropicContent);
|
|
400
|
+
}
|
|
347
401
|
function baseRoleToAnthropicMessage(base, role) {
|
|
348
402
|
const content = contentToAnthropicContent(base.content);
|
|
349
403
|
return {
|
|
@@ -351,6 +405,15 @@ function getAnthropicAPI(config) {
|
|
|
351
405
|
content,
|
|
352
406
|
};
|
|
353
407
|
}
|
|
408
|
+
function aiMessageToAnthropicMessage(base) {
|
|
409
|
+
const ret = baseRoleToAnthropicMessage(base, "assistant");
|
|
410
|
+
const toolContent = toolCallsToAnthropicContent(base.tool_calls);
|
|
411
|
+
if (toolContent.length > 0) {
|
|
412
|
+
const content = ret.content;
|
|
413
|
+
ret.content = [...content, ...toolContent];
|
|
414
|
+
}
|
|
415
|
+
return ret;
|
|
416
|
+
}
|
|
354
417
|
function toolMessageToAnthropicMessage(base) {
|
|
355
418
|
const role = "user";
|
|
356
419
|
const toolUseId = base.tool_call_id;
|
|
@@ -373,10 +436,11 @@ function getAnthropicAPI(config) {
|
|
|
373
436
|
case "human":
|
|
374
437
|
return baseRoleToAnthropicMessage(base, "user");
|
|
375
438
|
case "ai":
|
|
376
|
-
return
|
|
439
|
+
return aiMessageToAnthropicMessage(base);
|
|
377
440
|
case "tool":
|
|
378
441
|
return toolMessageToAnthropicMessage(base);
|
|
379
442
|
default:
|
|
443
|
+
console.warn(`Unknown BaseMessage type: ${type}`, base);
|
|
380
444
|
return undefined;
|
|
381
445
|
}
|
|
382
446
|
}
|
|
@@ -519,6 +583,9 @@ function getAnthropicAPI(config) {
|
|
|
519
583
|
if (system?.length) {
|
|
520
584
|
ret.system = system;
|
|
521
585
|
}
|
|
586
|
+
if (config?.thinking) {
|
|
587
|
+
ret.thinking = config?.thinking;
|
|
588
|
+
}
|
|
522
589
|
return ret;
|
|
523
590
|
}
|
|
524
591
|
return {
|
package/dist/utils/anthropic.js
CHANGED
|
@@ -67,6 +67,18 @@ export function getAnthropicAPI(config) {
|
|
|
67
67
|
tool_calls: [tool],
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
|
+
function thinkingContentToMessageFields(thinkingContent) {
|
|
71
|
+
// TODO: Once a reasoning/thinking type is defined in LangChain, use it
|
|
72
|
+
return {
|
|
73
|
+
content: [thinkingContent],
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function redactedThinkingContentToMessageFields(thinkingContent) {
|
|
77
|
+
// TODO: Once a reasoning/thinking type is defined in LangChain, use it
|
|
78
|
+
return {
|
|
79
|
+
content: [thinkingContent],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
70
82
|
function anthropicContentToMessageFields(anthropicContent) {
|
|
71
83
|
const type = anthropicContent?.type;
|
|
72
84
|
switch (type) {
|
|
@@ -74,7 +86,12 @@ export function getAnthropicAPI(config) {
|
|
|
74
86
|
return textContentToMessageFields(anthropicContent);
|
|
75
87
|
case "tool_use":
|
|
76
88
|
return toolUseContentToMessageFields(anthropicContent);
|
|
89
|
+
case "thinking":
|
|
90
|
+
return thinkingContentToMessageFields(anthropicContent);
|
|
91
|
+
case "redacted_thinking":
|
|
92
|
+
return redactedThinkingContentToMessageFields(anthropicContent);
|
|
77
93
|
default:
|
|
94
|
+
console.error(`Unknown message type: ${type}`, anthropicContent);
|
|
78
95
|
return undefined;
|
|
79
96
|
}
|
|
80
97
|
}
|
|
@@ -318,6 +335,25 @@ export function getAnthropicAPI(config) {
|
|
|
318
335
|
},
|
|
319
336
|
};
|
|
320
337
|
}
|
|
338
|
+
function thinkingContentToAnthropicContent(
|
|
339
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
340
|
+
content) {
|
|
341
|
+
// TODO: Once a Langchain Thinking type is defined, use it
|
|
342
|
+
return {
|
|
343
|
+
type: "thinking",
|
|
344
|
+
thinking: content.thinking,
|
|
345
|
+
signature: content.signature,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function redactedThinkingContentToAnthropicContent(
|
|
349
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
350
|
+
content) {
|
|
351
|
+
// TODO: Once a Langchain Thinking type is defined, use it
|
|
352
|
+
return {
|
|
353
|
+
type: "redacted_thinking",
|
|
354
|
+
data: content.data,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
321
357
|
function contentComplexToAnthropicContent(content) {
|
|
322
358
|
const type = content?.type;
|
|
323
359
|
switch (type) {
|
|
@@ -325,8 +361,12 @@ export function getAnthropicAPI(config) {
|
|
|
325
361
|
return textContentToAnthropicContent(content);
|
|
326
362
|
case "image_url":
|
|
327
363
|
return imageContentToAnthropicContent(content);
|
|
364
|
+
case "thinking":
|
|
365
|
+
return thinkingContentToAnthropicContent(content);
|
|
366
|
+
case "redacted_thinking":
|
|
367
|
+
return redactedThinkingContentToAnthropicContent(content);
|
|
328
368
|
default:
|
|
329
|
-
console.warn(`Unexpected content type: ${type}
|
|
369
|
+
console.warn(`Unexpected content type: ${type}`, content);
|
|
330
370
|
return undefined;
|
|
331
371
|
}
|
|
332
372
|
}
|
|
@@ -341,6 +381,20 @@ export function getAnthropicAPI(config) {
|
|
|
341
381
|
});
|
|
342
382
|
return ret;
|
|
343
383
|
}
|
|
384
|
+
function toolCallToAnthropicContent(toolCall) {
|
|
385
|
+
return {
|
|
386
|
+
type: "tool_use",
|
|
387
|
+
id: toolCall.id,
|
|
388
|
+
name: toolCall.name,
|
|
389
|
+
input: toolCall.args,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function toolCallsToAnthropicContent(toolCalls) {
|
|
393
|
+
if (toolCalls === undefined) {
|
|
394
|
+
return [];
|
|
395
|
+
}
|
|
396
|
+
return toolCalls.map(toolCallToAnthropicContent);
|
|
397
|
+
}
|
|
344
398
|
function baseRoleToAnthropicMessage(base, role) {
|
|
345
399
|
const content = contentToAnthropicContent(base.content);
|
|
346
400
|
return {
|
|
@@ -348,6 +402,15 @@ export function getAnthropicAPI(config) {
|
|
|
348
402
|
content,
|
|
349
403
|
};
|
|
350
404
|
}
|
|
405
|
+
function aiMessageToAnthropicMessage(base) {
|
|
406
|
+
const ret = baseRoleToAnthropicMessage(base, "assistant");
|
|
407
|
+
const toolContent = toolCallsToAnthropicContent(base.tool_calls);
|
|
408
|
+
if (toolContent.length > 0) {
|
|
409
|
+
const content = ret.content;
|
|
410
|
+
ret.content = [...content, ...toolContent];
|
|
411
|
+
}
|
|
412
|
+
return ret;
|
|
413
|
+
}
|
|
351
414
|
function toolMessageToAnthropicMessage(base) {
|
|
352
415
|
const role = "user";
|
|
353
416
|
const toolUseId = base.tool_call_id;
|
|
@@ -370,10 +433,11 @@ export function getAnthropicAPI(config) {
|
|
|
370
433
|
case "human":
|
|
371
434
|
return baseRoleToAnthropicMessage(base, "user");
|
|
372
435
|
case "ai":
|
|
373
|
-
return
|
|
436
|
+
return aiMessageToAnthropicMessage(base);
|
|
374
437
|
case "tool":
|
|
375
438
|
return toolMessageToAnthropicMessage(base);
|
|
376
439
|
default:
|
|
440
|
+
console.warn(`Unknown BaseMessage type: ${type}`, base);
|
|
377
441
|
return undefined;
|
|
378
442
|
}
|
|
379
443
|
}
|
|
@@ -516,6 +580,9 @@ export function getAnthropicAPI(config) {
|
|
|
516
580
|
if (system?.length) {
|
|
517
581
|
ret.system = system;
|
|
518
582
|
}
|
|
583
|
+
if (config?.thinking) {
|
|
584
|
+
ret.thinking = config?.thinking;
|
|
585
|
+
}
|
|
519
586
|
return ret;
|
|
520
587
|
}
|
|
521
588
|
return {
|
package/dist/utils/gemini.cjs
CHANGED
|
@@ -5,6 +5,7 @@ const uuid_1 = require("uuid");
|
|
|
5
5
|
const messages_1 = require("@langchain/core/messages");
|
|
6
6
|
const outputs_1 = require("@langchain/core/outputs");
|
|
7
7
|
const function_calling_1 = require("@langchain/core/utils/function_calling");
|
|
8
|
+
const stream_1 = require("@langchain/core/utils/stream");
|
|
8
9
|
const safety_js_1 = require("./safety.cjs");
|
|
9
10
|
const types_js_1 = require("../types.cjs");
|
|
10
11
|
const zod_to_gemini_parameters_js_1 = require("./zod_to_gemini_parameters.cjs");
|
|
@@ -604,9 +605,12 @@ function getGeminiAPI(config) {
|
|
|
604
605
|
function partToChatGeneration(part) {
|
|
605
606
|
const message = partToMessageChunk(part);
|
|
606
607
|
const text = partToText(part);
|
|
608
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
609
|
+
const generationInfo = {};
|
|
607
610
|
return new outputs_1.ChatGenerationChunk({
|
|
608
611
|
text,
|
|
609
612
|
message,
|
|
613
|
+
generationInfo,
|
|
610
614
|
});
|
|
611
615
|
}
|
|
612
616
|
function groundingSupportByPart(groundingSupports) {
|
|
@@ -657,43 +661,134 @@ function getGeminiAPI(config) {
|
|
|
657
661
|
});
|
|
658
662
|
return ret;
|
|
659
663
|
}
|
|
664
|
+
function combineContent(gen, forceComplex = false) {
|
|
665
|
+
const allString = gen.every((item) => typeof item.message.content === "string");
|
|
666
|
+
if (allString && !forceComplex) {
|
|
667
|
+
// Everything is a string, and we don't want to force it to return
|
|
668
|
+
// MessageContentComplex[], so concatenate the content into one string
|
|
669
|
+
return gen.map((item) => item.message.content).join("");
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
// We either have complex types, or we want to force them, so turn
|
|
673
|
+
// it into an array of complex types.
|
|
674
|
+
const ret = [];
|
|
675
|
+
gen.forEach((item) => {
|
|
676
|
+
if (typeof item.message.content === "string") {
|
|
677
|
+
// If this is a string, turn it into a text type
|
|
678
|
+
ret.push({
|
|
679
|
+
text: item.message.content,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
// Otherwise, add all the complex types to what we're returning
|
|
684
|
+
item.message.content.forEach((c) => {
|
|
685
|
+
ret.push(c);
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
return ret;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function combineText(gen) {
|
|
693
|
+
return gen.map((item) => item.text ?? "").join("");
|
|
694
|
+
}
|
|
695
|
+
/*
|
|
696
|
+
* We don't really need the entire AIMessageChunk here, but it is
|
|
697
|
+
* a conventient way to combine all the Tool Calling information.
|
|
698
|
+
*/
|
|
699
|
+
function combineToolCalls(gen) {
|
|
700
|
+
let ret = new messages_1.AIMessageChunk("");
|
|
701
|
+
gen.forEach((item) => {
|
|
702
|
+
const message = item?.message;
|
|
703
|
+
ret = (0, stream_1.concat)(ret, message);
|
|
704
|
+
});
|
|
705
|
+
return ret;
|
|
706
|
+
}
|
|
707
|
+
function combineAdditionalKwargs(gen) {
|
|
708
|
+
const ret = {};
|
|
709
|
+
gen.forEach((item) => {
|
|
710
|
+
const message = item?.message;
|
|
711
|
+
const kwargs = message?.additional_kwargs ?? {};
|
|
712
|
+
const keys = Object.keys(kwargs);
|
|
713
|
+
keys.forEach((key) => {
|
|
714
|
+
const value = kwargs[key];
|
|
715
|
+
if (Object.hasOwn(ret, key) &&
|
|
716
|
+
Array.isArray(ret[key]) &&
|
|
717
|
+
Array.isArray(value)) {
|
|
718
|
+
ret[key].push(...value);
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
ret[key] = value;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
return ret;
|
|
726
|
+
}
|
|
727
|
+
function combineGenerations(generations, response) {
|
|
728
|
+
const gen = splitGenerationTypes(generations, response);
|
|
729
|
+
const combinedContent = combineContent(gen.content);
|
|
730
|
+
const combinedText = combineText(gen.content);
|
|
731
|
+
const combinedToolCalls = combineToolCalls(gen.content);
|
|
732
|
+
const kwargs = combineAdditionalKwargs(gen.content);
|
|
733
|
+
const lastContent = gen.content[gen.content.length - 1];
|
|
734
|
+
// Add usage metadata
|
|
735
|
+
let usageMetadata;
|
|
736
|
+
if ("usageMetadata" in response.data) {
|
|
737
|
+
usageMetadata = {
|
|
738
|
+
input_tokens: response.data.usageMetadata.promptTokenCount,
|
|
739
|
+
output_tokens: response.data.usageMetadata
|
|
740
|
+
.candidatesTokenCount,
|
|
741
|
+
total_tokens: response.data.usageMetadata.totalTokenCount,
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
// Add thinking / reasoning
|
|
745
|
+
// if (gen.reasoning && gen.reasoning.length > 0) {
|
|
746
|
+
// kwargs.reasoning_content = combineContent(gen.reasoning, true);
|
|
747
|
+
// }
|
|
748
|
+
// Build the message and the generation chunk to return
|
|
749
|
+
const message = new messages_1.AIMessageChunk({
|
|
750
|
+
content: combinedContent,
|
|
751
|
+
additional_kwargs: kwargs,
|
|
752
|
+
usage_metadata: usageMetadata,
|
|
753
|
+
tool_calls: combinedToolCalls.tool_calls,
|
|
754
|
+
invalid_tool_calls: combinedToolCalls.invalid_tool_calls,
|
|
755
|
+
});
|
|
756
|
+
return [
|
|
757
|
+
new outputs_1.ChatGenerationChunk({
|
|
758
|
+
message,
|
|
759
|
+
text: combinedText,
|
|
760
|
+
generationInfo: lastContent.generationInfo,
|
|
761
|
+
}),
|
|
762
|
+
];
|
|
763
|
+
}
|
|
764
|
+
function splitGenerationTypes(generations, _response) {
|
|
765
|
+
const content = [];
|
|
766
|
+
const reasoning = [];
|
|
767
|
+
generations.forEach((gen) => {
|
|
768
|
+
if (gen?.generationInfo?.thought) {
|
|
769
|
+
reasoning.push(gen);
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
content.push(gen);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
return {
|
|
776
|
+
content,
|
|
777
|
+
reasoning,
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Although this returns an array, only the first (or maybe last)
|
|
782
|
+
* element in the array is used. So we need to combine them into
|
|
783
|
+
* just one element that contains everything we need.
|
|
784
|
+
* @param response
|
|
785
|
+
*/
|
|
660
786
|
function responseToChatGenerations(response) {
|
|
661
|
-
|
|
662
|
-
if (
|
|
787
|
+
const generations = responseToGroundedChatGenerations(response);
|
|
788
|
+
if (generations.length === 0) {
|
|
663
789
|
return [];
|
|
664
790
|
}
|
|
665
|
-
|
|
666
|
-
const combinedContent = ret.map((item) => item.message.content).join("");
|
|
667
|
-
const combinedText = ret.map((item) => item.text).join("");
|
|
668
|
-
const toolCallChunks = ret[ret.length - 1]?.message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
|
|
669
|
-
name: toolCall.function.name,
|
|
670
|
-
args: toolCall.function.arguments,
|
|
671
|
-
id: toolCall.id,
|
|
672
|
-
index: i,
|
|
673
|
-
type: "tool_call_chunk",
|
|
674
|
-
}));
|
|
675
|
-
let usageMetadata;
|
|
676
|
-
if ("usageMetadata" in response.data) {
|
|
677
|
-
usageMetadata = {
|
|
678
|
-
input_tokens: response.data.usageMetadata.promptTokenCount,
|
|
679
|
-
output_tokens: response.data.usageMetadata
|
|
680
|
-
.candidatesTokenCount,
|
|
681
|
-
total_tokens: response.data.usageMetadata.totalTokenCount,
|
|
682
|
-
};
|
|
683
|
-
}
|
|
684
|
-
ret = [
|
|
685
|
-
new outputs_1.ChatGenerationChunk({
|
|
686
|
-
message: new messages_1.AIMessageChunk({
|
|
687
|
-
content: combinedContent,
|
|
688
|
-
additional_kwargs: ret[ret.length - 1]?.message.additional_kwargs,
|
|
689
|
-
tool_call_chunks: toolCallChunks,
|
|
690
|
-
usage_metadata: usageMetadata,
|
|
691
|
-
}),
|
|
692
|
-
text: combinedText,
|
|
693
|
-
generationInfo: ret[ret.length - 1].generationInfo,
|
|
694
|
-
}),
|
|
695
|
-
];
|
|
696
|
-
}
|
|
791
|
+
const ret = combineGenerations(generations, response);
|
|
697
792
|
// Add logprobs information to the message
|
|
698
793
|
const candidate = response?.data
|
|
699
794
|
?.candidates?.[0];
|
|
@@ -847,6 +942,13 @@ function getGeminiAPI(config) {
|
|
|
847
942
|
ret.logprobs = parameters.topLogprobs;
|
|
848
943
|
}
|
|
849
944
|
}
|
|
945
|
+
// Remove any undefined properties, so we don't send them
|
|
946
|
+
let attribute;
|
|
947
|
+
for (attribute in ret) {
|
|
948
|
+
if (ret[attribute] === undefined) {
|
|
949
|
+
delete ret[attribute];
|
|
950
|
+
}
|
|
951
|
+
}
|
|
850
952
|
return ret;
|
|
851
953
|
}
|
|
852
954
|
function formatSafetySettings(parameters) {
|
package/dist/utils/gemini.js
CHANGED
|
@@ -2,6 +2,7 @@ import { v4 as uuidv4 } from "uuid";
|
|
|
2
2
|
import { AIMessage, AIMessageChunk, isAIMessage, } from "@langchain/core/messages";
|
|
3
3
|
import { ChatGenerationChunk, } from "@langchain/core/outputs";
|
|
4
4
|
import { isLangChainTool } from "@langchain/core/utils/function_calling";
|
|
5
|
+
import { concat } from "@langchain/core/utils/stream";
|
|
5
6
|
import { GoogleAISafetyError } from "./safety.js";
|
|
6
7
|
import { GeminiSearchToolAttributes, } from "../types.js";
|
|
7
8
|
import { zodToGeminiParameters } from "./zod_to_gemini_parameters.js";
|
|
@@ -599,9 +600,12 @@ export function getGeminiAPI(config) {
|
|
|
599
600
|
function partToChatGeneration(part) {
|
|
600
601
|
const message = partToMessageChunk(part);
|
|
601
602
|
const text = partToText(part);
|
|
603
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
604
|
+
const generationInfo = {};
|
|
602
605
|
return new ChatGenerationChunk({
|
|
603
606
|
text,
|
|
604
607
|
message,
|
|
608
|
+
generationInfo,
|
|
605
609
|
});
|
|
606
610
|
}
|
|
607
611
|
function groundingSupportByPart(groundingSupports) {
|
|
@@ -652,43 +656,134 @@ export function getGeminiAPI(config) {
|
|
|
652
656
|
});
|
|
653
657
|
return ret;
|
|
654
658
|
}
|
|
659
|
+
function combineContent(gen, forceComplex = false) {
|
|
660
|
+
const allString = gen.every((item) => typeof item.message.content === "string");
|
|
661
|
+
if (allString && !forceComplex) {
|
|
662
|
+
// Everything is a string, and we don't want to force it to return
|
|
663
|
+
// MessageContentComplex[], so concatenate the content into one string
|
|
664
|
+
return gen.map((item) => item.message.content).join("");
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
// We either have complex types, or we want to force them, so turn
|
|
668
|
+
// it into an array of complex types.
|
|
669
|
+
const ret = [];
|
|
670
|
+
gen.forEach((item) => {
|
|
671
|
+
if (typeof item.message.content === "string") {
|
|
672
|
+
// If this is a string, turn it into a text type
|
|
673
|
+
ret.push({
|
|
674
|
+
text: item.message.content,
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
// Otherwise, add all the complex types to what we're returning
|
|
679
|
+
item.message.content.forEach((c) => {
|
|
680
|
+
ret.push(c);
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
return ret;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
function combineText(gen) {
|
|
688
|
+
return gen.map((item) => item.text ?? "").join("");
|
|
689
|
+
}
|
|
690
|
+
/*
|
|
691
|
+
* We don't really need the entire AIMessageChunk here, but it is
|
|
692
|
+
* a conventient way to combine all the Tool Calling information.
|
|
693
|
+
*/
|
|
694
|
+
function combineToolCalls(gen) {
|
|
695
|
+
let ret = new AIMessageChunk("");
|
|
696
|
+
gen.forEach((item) => {
|
|
697
|
+
const message = item?.message;
|
|
698
|
+
ret = concat(ret, message);
|
|
699
|
+
});
|
|
700
|
+
return ret;
|
|
701
|
+
}
|
|
702
|
+
function combineAdditionalKwargs(gen) {
|
|
703
|
+
const ret = {};
|
|
704
|
+
gen.forEach((item) => {
|
|
705
|
+
const message = item?.message;
|
|
706
|
+
const kwargs = message?.additional_kwargs ?? {};
|
|
707
|
+
const keys = Object.keys(kwargs);
|
|
708
|
+
keys.forEach((key) => {
|
|
709
|
+
const value = kwargs[key];
|
|
710
|
+
if (Object.hasOwn(ret, key) &&
|
|
711
|
+
Array.isArray(ret[key]) &&
|
|
712
|
+
Array.isArray(value)) {
|
|
713
|
+
ret[key].push(...value);
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
ret[key] = value;
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
});
|
|
720
|
+
return ret;
|
|
721
|
+
}
|
|
722
|
+
function combineGenerations(generations, response) {
|
|
723
|
+
const gen = splitGenerationTypes(generations, response);
|
|
724
|
+
const combinedContent = combineContent(gen.content);
|
|
725
|
+
const combinedText = combineText(gen.content);
|
|
726
|
+
const combinedToolCalls = combineToolCalls(gen.content);
|
|
727
|
+
const kwargs = combineAdditionalKwargs(gen.content);
|
|
728
|
+
const lastContent = gen.content[gen.content.length - 1];
|
|
729
|
+
// Add usage metadata
|
|
730
|
+
let usageMetadata;
|
|
731
|
+
if ("usageMetadata" in response.data) {
|
|
732
|
+
usageMetadata = {
|
|
733
|
+
input_tokens: response.data.usageMetadata.promptTokenCount,
|
|
734
|
+
output_tokens: response.data.usageMetadata
|
|
735
|
+
.candidatesTokenCount,
|
|
736
|
+
total_tokens: response.data.usageMetadata.totalTokenCount,
|
|
737
|
+
};
|
|
738
|
+
}
|
|
739
|
+
// Add thinking / reasoning
|
|
740
|
+
// if (gen.reasoning && gen.reasoning.length > 0) {
|
|
741
|
+
// kwargs.reasoning_content = combineContent(gen.reasoning, true);
|
|
742
|
+
// }
|
|
743
|
+
// Build the message and the generation chunk to return
|
|
744
|
+
const message = new AIMessageChunk({
|
|
745
|
+
content: combinedContent,
|
|
746
|
+
additional_kwargs: kwargs,
|
|
747
|
+
usage_metadata: usageMetadata,
|
|
748
|
+
tool_calls: combinedToolCalls.tool_calls,
|
|
749
|
+
invalid_tool_calls: combinedToolCalls.invalid_tool_calls,
|
|
750
|
+
});
|
|
751
|
+
return [
|
|
752
|
+
new ChatGenerationChunk({
|
|
753
|
+
message,
|
|
754
|
+
text: combinedText,
|
|
755
|
+
generationInfo: lastContent.generationInfo,
|
|
756
|
+
}),
|
|
757
|
+
];
|
|
758
|
+
}
|
|
759
|
+
function splitGenerationTypes(generations, _response) {
|
|
760
|
+
const content = [];
|
|
761
|
+
const reasoning = [];
|
|
762
|
+
generations.forEach((gen) => {
|
|
763
|
+
if (gen?.generationInfo?.thought) {
|
|
764
|
+
reasoning.push(gen);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
content.push(gen);
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
return {
|
|
771
|
+
content,
|
|
772
|
+
reasoning,
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Although this returns an array, only the first (or maybe last)
|
|
777
|
+
* element in the array is used. So we need to combine them into
|
|
778
|
+
* just one element that contains everything we need.
|
|
779
|
+
* @param response
|
|
780
|
+
*/
|
|
655
781
|
function responseToChatGenerations(response) {
|
|
656
|
-
|
|
657
|
-
if (
|
|
782
|
+
const generations = responseToGroundedChatGenerations(response);
|
|
783
|
+
if (generations.length === 0) {
|
|
658
784
|
return [];
|
|
659
785
|
}
|
|
660
|
-
|
|
661
|
-
const combinedContent = ret.map((item) => item.message.content).join("");
|
|
662
|
-
const combinedText = ret.map((item) => item.text).join("");
|
|
663
|
-
const toolCallChunks = ret[ret.length - 1]?.message.additional_kwargs?.tool_calls?.map((toolCall, i) => ({
|
|
664
|
-
name: toolCall.function.name,
|
|
665
|
-
args: toolCall.function.arguments,
|
|
666
|
-
id: toolCall.id,
|
|
667
|
-
index: i,
|
|
668
|
-
type: "tool_call_chunk",
|
|
669
|
-
}));
|
|
670
|
-
let usageMetadata;
|
|
671
|
-
if ("usageMetadata" in response.data) {
|
|
672
|
-
usageMetadata = {
|
|
673
|
-
input_tokens: response.data.usageMetadata.promptTokenCount,
|
|
674
|
-
output_tokens: response.data.usageMetadata
|
|
675
|
-
.candidatesTokenCount,
|
|
676
|
-
total_tokens: response.data.usageMetadata.totalTokenCount,
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
ret = [
|
|
680
|
-
new ChatGenerationChunk({
|
|
681
|
-
message: new AIMessageChunk({
|
|
682
|
-
content: combinedContent,
|
|
683
|
-
additional_kwargs: ret[ret.length - 1]?.message.additional_kwargs,
|
|
684
|
-
tool_call_chunks: toolCallChunks,
|
|
685
|
-
usage_metadata: usageMetadata,
|
|
686
|
-
}),
|
|
687
|
-
text: combinedText,
|
|
688
|
-
generationInfo: ret[ret.length - 1].generationInfo,
|
|
689
|
-
}),
|
|
690
|
-
];
|
|
691
|
-
}
|
|
786
|
+
const ret = combineGenerations(generations, response);
|
|
692
787
|
// Add logprobs information to the message
|
|
693
788
|
const candidate = response?.data
|
|
694
789
|
?.candidates?.[0];
|
|
@@ -842,6 +937,13 @@ export function getGeminiAPI(config) {
|
|
|
842
937
|
ret.logprobs = parameters.topLogprobs;
|
|
843
938
|
}
|
|
844
939
|
}
|
|
940
|
+
// Remove any undefined properties, so we don't send them
|
|
941
|
+
let attribute;
|
|
942
|
+
for (attribute in ret) {
|
|
943
|
+
if (ret[attribute] === undefined) {
|
|
944
|
+
delete ret[attribute];
|
|
945
|
+
}
|
|
946
|
+
}
|
|
845
947
|
return ret;
|
|
846
948
|
}
|
|
847
949
|
function formatSafetySettings(parameters) {
|