@langchain/google-common 0.2.3 → 0.2.5
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 +7 -1
- package/dist/chat_models.d.ts +1 -0
- package/dist/chat_models.js +8 -2
- package/dist/types-anthropic.d.ts +36 -1
- package/dist/types.d.ts +19 -0
- package/dist/utils/anthropic.cjs +216 -8
- package/dist/utils/anthropic.js +217 -9
- package/dist/utils/common.cjs +27 -1
- package/dist/utils/common.js +28 -2
- package/dist/utils/gemini.cjs +124 -2
- package/dist/utils/gemini.js +126 -4
- package/dist/utils/zod_to_gemini_parameters.cjs +5 -7
- package/dist/utils/zod_to_gemini_parameters.d.ts +2 -1
- package/dist/utils/zod_to_gemini_parameters.js +3 -5
- package/package.json +5 -5
package/dist/chat_models.cjs
CHANGED
|
@@ -144,6 +144,12 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
144
144
|
writable: true,
|
|
145
145
|
value: void 0
|
|
146
146
|
});
|
|
147
|
+
Object.defineProperty(this, "maxReasoningTokens", {
|
|
148
|
+
enumerable: true,
|
|
149
|
+
configurable: true,
|
|
150
|
+
writable: true,
|
|
151
|
+
value: void 0
|
|
152
|
+
});
|
|
147
153
|
Object.defineProperty(this, "topP", {
|
|
148
154
|
enumerable: true,
|
|
149
155
|
configurable: true,
|
|
@@ -369,7 +375,7 @@ class ChatGoogleBase extends chat_models_1.BaseChatModel {
|
|
|
369
375
|
let outputParser;
|
|
370
376
|
let tools;
|
|
371
377
|
if (isZodSchema(schema)) {
|
|
372
|
-
const jsonSchema = (0, zod_to_gemini_parameters_js_1.
|
|
378
|
+
const jsonSchema = (0, zod_to_gemini_parameters_js_1.schemaToGeminiParameters)(schema);
|
|
373
379
|
tools = [
|
|
374
380
|
{
|
|
375
381
|
functionDeclarations: [
|
package/dist/chat_models.d.ts
CHANGED
package/dist/chat_models.js
CHANGED
|
@@ -10,7 +10,7 @@ import { AbstractGoogleLLMConnection } from "./connection.js";
|
|
|
10
10
|
import { DefaultGeminiSafetyHandler, getGeminiAPI } from "./utils/gemini.js";
|
|
11
11
|
import { ApiKeyGoogleAuth } from "./auth.js";
|
|
12
12
|
import { ensureParams } from "./utils/failed_handler.js";
|
|
13
|
-
import {
|
|
13
|
+
import { schemaToGeminiParameters } from "./utils/zod_to_gemini_parameters.js";
|
|
14
14
|
export class ChatConnection extends AbstractGoogleLLMConnection {
|
|
15
15
|
constructor(fields, caller, client, streaming) {
|
|
16
16
|
super(fields, caller, client, streaming);
|
|
@@ -140,6 +140,12 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
140
140
|
writable: true,
|
|
141
141
|
value: void 0
|
|
142
142
|
});
|
|
143
|
+
Object.defineProperty(this, "maxReasoningTokens", {
|
|
144
|
+
enumerable: true,
|
|
145
|
+
configurable: true,
|
|
146
|
+
writable: true,
|
|
147
|
+
value: void 0
|
|
148
|
+
});
|
|
143
149
|
Object.defineProperty(this, "topP", {
|
|
144
150
|
enumerable: true,
|
|
145
151
|
configurable: true,
|
|
@@ -365,7 +371,7 @@ export class ChatGoogleBase extends BaseChatModel {
|
|
|
365
371
|
let outputParser;
|
|
366
372
|
let tools;
|
|
367
373
|
if (isZodSchema(schema)) {
|
|
368
|
-
const jsonSchema =
|
|
374
|
+
const jsonSchema = schemaToGeminiParameters(schema);
|
|
369
375
|
tools = [
|
|
370
376
|
{
|
|
371
377
|
functionDeclarations: [
|
|
@@ -13,8 +13,11 @@ export interface AnthropicMessageContentImage extends AnthropicMessageContentBas
|
|
|
13
13
|
type: "image";
|
|
14
14
|
source: {
|
|
15
15
|
type: "base64" | string;
|
|
16
|
-
media_type
|
|
16
|
+
media_type?: string;
|
|
17
17
|
data: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: "url" | string;
|
|
20
|
+
url: string;
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
23
|
export interface AnthropicMessageContentThinking extends AnthropicMessageContentBase {
|
|
@@ -22,6 +25,38 @@ export interface AnthropicMessageContentThinking extends AnthropicMessageContent
|
|
|
22
25
|
thinking: string;
|
|
23
26
|
signature: string;
|
|
24
27
|
}
|
|
28
|
+
export interface AnthropicMessageContentDocument extends AnthropicMessageContentBase {
|
|
29
|
+
type: "document";
|
|
30
|
+
source: {
|
|
31
|
+
type: "base64" | "text" | string;
|
|
32
|
+
media_type?: "application/pdf" | "text/plain" | string;
|
|
33
|
+
data: string;
|
|
34
|
+
} | {
|
|
35
|
+
type: "url" | string;
|
|
36
|
+
url: string;
|
|
37
|
+
} | {
|
|
38
|
+
type: "content" | string;
|
|
39
|
+
content: {
|
|
40
|
+
type: "image" | string;
|
|
41
|
+
source: {
|
|
42
|
+
type: "base64" | string;
|
|
43
|
+
data: string;
|
|
44
|
+
media_type?: "image/jpeg" | "image/png" | "image/gif" | "image/webp" | string;
|
|
45
|
+
} | {
|
|
46
|
+
type: "url" | string;
|
|
47
|
+
url: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: "text" | string;
|
|
50
|
+
text: string;
|
|
51
|
+
};
|
|
52
|
+
}[];
|
|
53
|
+
};
|
|
54
|
+
citations?: {
|
|
55
|
+
enabled?: boolean;
|
|
56
|
+
};
|
|
57
|
+
context?: string;
|
|
58
|
+
title?: string;
|
|
59
|
+
}
|
|
25
60
|
export interface AnthropicMessageContentRedactedThinking extends AnthropicMessageContentBase {
|
|
26
61
|
type: "redacted_thinking";
|
|
27
62
|
data: string;
|
package/dist/types.d.ts
CHANGED
|
@@ -85,6 +85,10 @@ export interface GoogleAISafetySetting {
|
|
|
85
85
|
}
|
|
86
86
|
export type GoogleAIResponseMimeType = "text/plain" | "application/json";
|
|
87
87
|
export type GoogleAIModelModality = "TEXT" | "IMAGE" | "AUDIO" | string;
|
|
88
|
+
export interface GoogleThinkingConfig {
|
|
89
|
+
thinkingBudget?: number;
|
|
90
|
+
includeThoughts?: boolean;
|
|
91
|
+
}
|
|
88
92
|
export interface GoogleAIModelParams {
|
|
89
93
|
/** Model to use */
|
|
90
94
|
model?: string;
|
|
@@ -97,8 +101,22 @@ export interface GoogleAIModelParams {
|
|
|
97
101
|
temperature?: number;
|
|
98
102
|
/**
|
|
99
103
|
* Maximum number of tokens to generate in the completion.
|
|
104
|
+
* This may include reasoning tokens (for backwards compatibility).
|
|
100
105
|
*/
|
|
101
106
|
maxOutputTokens?: number;
|
|
107
|
+
/**
|
|
108
|
+
* The maximum number of the output tokens that will be used
|
|
109
|
+
* for the "thinking" or "reasoning" stages.
|
|
110
|
+
*/
|
|
111
|
+
maxReasoningTokens?: number;
|
|
112
|
+
/**
|
|
113
|
+
* An alias for "maxReasoningTokens"
|
|
114
|
+
*/
|
|
115
|
+
thinkingBudget?: number;
|
|
116
|
+
/**
|
|
117
|
+
* An OpenAI compatible parameter that will map to "maxReasoningTokens"
|
|
118
|
+
*/
|
|
119
|
+
reasoningEffort?: "low" | "medium" | "high";
|
|
102
120
|
/**
|
|
103
121
|
* Top-p changes how the model selects tokens for output.
|
|
104
122
|
*
|
|
@@ -398,6 +416,7 @@ export interface GeminiGenerationConfig {
|
|
|
398
416
|
responseLogprobs?: boolean;
|
|
399
417
|
logprobs?: number;
|
|
400
418
|
responseModalities?: GoogleAIModelModality[];
|
|
419
|
+
thinkingConfig?: GoogleThinkingConfig;
|
|
401
420
|
}
|
|
402
421
|
export interface GeminiRequest {
|
|
403
422
|
contents?: GeminiContent[];
|
package/dist/utils/anthropic.cjs
CHANGED
|
@@ -373,16 +373,221 @@ function getAnthropicAPI(config) {
|
|
|
373
373
|
return undefined;
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
|
+
const anthropicContentConverter = {
|
|
377
|
+
providerName: "anthropic",
|
|
378
|
+
fromStandardTextBlock(block) {
|
|
379
|
+
return {
|
|
380
|
+
type: "text",
|
|
381
|
+
text: block.text,
|
|
382
|
+
...("cache_control" in (block.metadata ?? {})
|
|
383
|
+
? {
|
|
384
|
+
cache_control: block.metadata
|
|
385
|
+
.cache_control,
|
|
386
|
+
}
|
|
387
|
+
: {}),
|
|
388
|
+
};
|
|
389
|
+
},
|
|
390
|
+
fromStandardImageBlock(block) {
|
|
391
|
+
if (block.source_type === "url") {
|
|
392
|
+
const data = (0, messages_1.parseBase64DataUrl)({
|
|
393
|
+
dataUrl: block.url,
|
|
394
|
+
asTypedArray: false,
|
|
395
|
+
});
|
|
396
|
+
if (data) {
|
|
397
|
+
return {
|
|
398
|
+
type: "image",
|
|
399
|
+
source: {
|
|
400
|
+
type: "base64",
|
|
401
|
+
data: data.data,
|
|
402
|
+
media_type: data.mime_type,
|
|
403
|
+
},
|
|
404
|
+
...("cache_control" in (block.metadata ?? {})
|
|
405
|
+
? { cache_control: block.metadata.cache_control }
|
|
406
|
+
: {}),
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
return {
|
|
411
|
+
type: "image",
|
|
412
|
+
source: {
|
|
413
|
+
type: "url",
|
|
414
|
+
url: block.url,
|
|
415
|
+
media_type: block.mime_type ?? "",
|
|
416
|
+
},
|
|
417
|
+
...("cache_control" in (block.metadata ?? {})
|
|
418
|
+
? { cache_control: block.metadata.cache_control }
|
|
419
|
+
: {}),
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
if (block.source_type === "base64") {
|
|
425
|
+
return {
|
|
426
|
+
type: "image",
|
|
427
|
+
source: {
|
|
428
|
+
type: "base64",
|
|
429
|
+
data: block.data,
|
|
430
|
+
media_type: block.mime_type ?? "",
|
|
431
|
+
},
|
|
432
|
+
...("cache_control" in (block.metadata ?? {})
|
|
433
|
+
? { cache_control: block.metadata.cache_control }
|
|
434
|
+
: {}),
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
throw new Error(`Unsupported image source type: ${block.source_type}`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
fromStandardFileBlock(block) {
|
|
443
|
+
const mime_type = (block.mime_type ?? "").split(";")[0];
|
|
444
|
+
if (block.source_type === "url") {
|
|
445
|
+
if (mime_type === "application/pdf" || mime_type === "") {
|
|
446
|
+
return {
|
|
447
|
+
type: "document",
|
|
448
|
+
source: {
|
|
449
|
+
type: "url",
|
|
450
|
+
url: block.url,
|
|
451
|
+
media_type: block.mime_type ?? "",
|
|
452
|
+
},
|
|
453
|
+
...("cache_control" in (block.metadata ?? {})
|
|
454
|
+
? {
|
|
455
|
+
cache_control: block.metadata
|
|
456
|
+
.cache_control,
|
|
457
|
+
}
|
|
458
|
+
: {}),
|
|
459
|
+
...("citations" in (block.metadata ?? {})
|
|
460
|
+
? {
|
|
461
|
+
citations: block.metadata.citations,
|
|
462
|
+
}
|
|
463
|
+
: {}),
|
|
464
|
+
...("context" in (block.metadata ?? {})
|
|
465
|
+
? { context: block.metadata.context }
|
|
466
|
+
: {}),
|
|
467
|
+
...(block.metadata?.title ||
|
|
468
|
+
block.metadata?.filename ||
|
|
469
|
+
block.metadata?.name
|
|
470
|
+
? {
|
|
471
|
+
title: (block.metadata?.title ||
|
|
472
|
+
block.metadata?.filename ||
|
|
473
|
+
block.metadata?.name),
|
|
474
|
+
}
|
|
475
|
+
: {}),
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
throw new Error(`Unsupported file mime type for file url source: ${block.mime_type}`);
|
|
479
|
+
}
|
|
480
|
+
else if (block.source_type === "text") {
|
|
481
|
+
if (mime_type === "text/plain" || mime_type === "") {
|
|
482
|
+
return {
|
|
483
|
+
type: "document",
|
|
484
|
+
source: {
|
|
485
|
+
type: "text",
|
|
486
|
+
data: block.text,
|
|
487
|
+
media_type: block.mime_type ?? "",
|
|
488
|
+
},
|
|
489
|
+
...("cache_control" in (block.metadata ?? {})
|
|
490
|
+
? {
|
|
491
|
+
cache_control: block.metadata
|
|
492
|
+
.cache_control,
|
|
493
|
+
}
|
|
494
|
+
: {}),
|
|
495
|
+
...("citations" in (block.metadata ?? {})
|
|
496
|
+
? {
|
|
497
|
+
citations: block.metadata.citations,
|
|
498
|
+
}
|
|
499
|
+
: {}),
|
|
500
|
+
...("context" in (block.metadata ?? {})
|
|
501
|
+
? { context: block.metadata.context }
|
|
502
|
+
: {}),
|
|
503
|
+
...("title" in (block.metadata ?? {})
|
|
504
|
+
? { title: block.metadata.title }
|
|
505
|
+
: {}),
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
throw new Error(`Unsupported file mime type for file text source: ${block.mime_type}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else if (block.source_type === "base64") {
|
|
513
|
+
if (mime_type === "application/pdf" || mime_type === "") {
|
|
514
|
+
return {
|
|
515
|
+
type: "document",
|
|
516
|
+
source: {
|
|
517
|
+
type: "base64",
|
|
518
|
+
data: block.data,
|
|
519
|
+
media_type: "application/pdf",
|
|
520
|
+
},
|
|
521
|
+
...("cache_control" in (block.metadata ?? {})
|
|
522
|
+
? {
|
|
523
|
+
cache_control: block.metadata
|
|
524
|
+
.cache_control,
|
|
525
|
+
}
|
|
526
|
+
: {}),
|
|
527
|
+
...("citations" in (block.metadata ?? {})
|
|
528
|
+
? {
|
|
529
|
+
citations: block.metadata.citations,
|
|
530
|
+
}
|
|
531
|
+
: {}),
|
|
532
|
+
...("context" in (block.metadata ?? {})
|
|
533
|
+
? { context: block.metadata.context }
|
|
534
|
+
: {}),
|
|
535
|
+
...("title" in (block.metadata ?? {})
|
|
536
|
+
? { title: block.metadata.title }
|
|
537
|
+
: {}),
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
else if (["image/jpeg", "image/png", "image/gif", "image/webp"].includes(mime_type)) {
|
|
541
|
+
return {
|
|
542
|
+
type: "document",
|
|
543
|
+
source: {
|
|
544
|
+
type: "content",
|
|
545
|
+
content: [
|
|
546
|
+
{
|
|
547
|
+
type: "image",
|
|
548
|
+
source: {
|
|
549
|
+
type: "base64",
|
|
550
|
+
data: block.data,
|
|
551
|
+
media_type: mime_type,
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
],
|
|
555
|
+
},
|
|
556
|
+
...("cache_control" in (block.metadata ?? {})
|
|
557
|
+
? {
|
|
558
|
+
cache_control: block.metadata
|
|
559
|
+
.cache_control,
|
|
560
|
+
}
|
|
561
|
+
: {}),
|
|
562
|
+
...("citations" in (block.metadata ?? {})
|
|
563
|
+
? {
|
|
564
|
+
citations: block.metadata.citations,
|
|
565
|
+
}
|
|
566
|
+
: {}),
|
|
567
|
+
...("context" in (block.metadata ?? {})
|
|
568
|
+
? { context: block.metadata.context }
|
|
569
|
+
: {}),
|
|
570
|
+
...("title" in (block.metadata ?? {})
|
|
571
|
+
? { title: block.metadata.title }
|
|
572
|
+
: {}),
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
throw new Error(`Unsupported file mime type for file base64 source: ${block.mime_type}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
throw new Error(`Unsupported file source type: ${block.source_type}`);
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
};
|
|
376
584
|
function contentToAnthropicContent(content) {
|
|
377
|
-
const ret = [];
|
|
378
585
|
const ca = typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
379
|
-
ca
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
});
|
|
385
|
-
return ret;
|
|
586
|
+
return ca
|
|
587
|
+
.map((complex) => (0, messages_1.isDataContentBlock)(complex)
|
|
588
|
+
? (0, messages_1.convertToProviderContentBlock)(complex, anthropicContentConverter)
|
|
589
|
+
: contentComplexToAnthropicContent(complex))
|
|
590
|
+
.filter(Boolean);
|
|
386
591
|
}
|
|
387
592
|
function toolCallToAnthropicContent(toolCall) {
|
|
388
593
|
return {
|
|
@@ -439,6 +644,9 @@ function getAnthropicAPI(config) {
|
|
|
439
644
|
return aiMessageToAnthropicMessage(base);
|
|
440
645
|
case "tool":
|
|
441
646
|
return toolMessageToAnthropicMessage(base);
|
|
647
|
+
case "system":
|
|
648
|
+
// System messages are handled in formatSystem()
|
|
649
|
+
return undefined;
|
|
442
650
|
default:
|
|
443
651
|
console.warn(`Unknown BaseMessage type: ${type}`, base);
|
|
444
652
|
return undefined;
|
package/dist/utils/anthropic.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChatGenerationChunk, } from "@langchain/core/outputs";
|
|
2
|
-
import { AIMessageChunk, } from "@langchain/core/messages";
|
|
2
|
+
import { AIMessageChunk, isDataContentBlock, convertToProviderContentBlock, parseBase64DataUrl, } from "@langchain/core/messages";
|
|
3
3
|
export function getAnthropicAPI(config) {
|
|
4
4
|
function partToString(part) {
|
|
5
5
|
return "text" in part ? part.text : "";
|
|
@@ -370,16 +370,221 @@ export function getAnthropicAPI(config) {
|
|
|
370
370
|
return undefined;
|
|
371
371
|
}
|
|
372
372
|
}
|
|
373
|
+
const anthropicContentConverter = {
|
|
374
|
+
providerName: "anthropic",
|
|
375
|
+
fromStandardTextBlock(block) {
|
|
376
|
+
return {
|
|
377
|
+
type: "text",
|
|
378
|
+
text: block.text,
|
|
379
|
+
...("cache_control" in (block.metadata ?? {})
|
|
380
|
+
? {
|
|
381
|
+
cache_control: block.metadata
|
|
382
|
+
.cache_control,
|
|
383
|
+
}
|
|
384
|
+
: {}),
|
|
385
|
+
};
|
|
386
|
+
},
|
|
387
|
+
fromStandardImageBlock(block) {
|
|
388
|
+
if (block.source_type === "url") {
|
|
389
|
+
const data = parseBase64DataUrl({
|
|
390
|
+
dataUrl: block.url,
|
|
391
|
+
asTypedArray: false,
|
|
392
|
+
});
|
|
393
|
+
if (data) {
|
|
394
|
+
return {
|
|
395
|
+
type: "image",
|
|
396
|
+
source: {
|
|
397
|
+
type: "base64",
|
|
398
|
+
data: data.data,
|
|
399
|
+
media_type: data.mime_type,
|
|
400
|
+
},
|
|
401
|
+
...("cache_control" in (block.metadata ?? {})
|
|
402
|
+
? { cache_control: block.metadata.cache_control }
|
|
403
|
+
: {}),
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
return {
|
|
408
|
+
type: "image",
|
|
409
|
+
source: {
|
|
410
|
+
type: "url",
|
|
411
|
+
url: block.url,
|
|
412
|
+
media_type: block.mime_type ?? "",
|
|
413
|
+
},
|
|
414
|
+
...("cache_control" in (block.metadata ?? {})
|
|
415
|
+
? { cache_control: block.metadata.cache_control }
|
|
416
|
+
: {}),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
if (block.source_type === "base64") {
|
|
422
|
+
return {
|
|
423
|
+
type: "image",
|
|
424
|
+
source: {
|
|
425
|
+
type: "base64",
|
|
426
|
+
data: block.data,
|
|
427
|
+
media_type: block.mime_type ?? "",
|
|
428
|
+
},
|
|
429
|
+
...("cache_control" in (block.metadata ?? {})
|
|
430
|
+
? { cache_control: block.metadata.cache_control }
|
|
431
|
+
: {}),
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
throw new Error(`Unsupported image source type: ${block.source_type}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
},
|
|
439
|
+
fromStandardFileBlock(block) {
|
|
440
|
+
const mime_type = (block.mime_type ?? "").split(";")[0];
|
|
441
|
+
if (block.source_type === "url") {
|
|
442
|
+
if (mime_type === "application/pdf" || mime_type === "") {
|
|
443
|
+
return {
|
|
444
|
+
type: "document",
|
|
445
|
+
source: {
|
|
446
|
+
type: "url",
|
|
447
|
+
url: block.url,
|
|
448
|
+
media_type: block.mime_type ?? "",
|
|
449
|
+
},
|
|
450
|
+
...("cache_control" in (block.metadata ?? {})
|
|
451
|
+
? {
|
|
452
|
+
cache_control: block.metadata
|
|
453
|
+
.cache_control,
|
|
454
|
+
}
|
|
455
|
+
: {}),
|
|
456
|
+
...("citations" in (block.metadata ?? {})
|
|
457
|
+
? {
|
|
458
|
+
citations: block.metadata.citations,
|
|
459
|
+
}
|
|
460
|
+
: {}),
|
|
461
|
+
...("context" in (block.metadata ?? {})
|
|
462
|
+
? { context: block.metadata.context }
|
|
463
|
+
: {}),
|
|
464
|
+
...(block.metadata?.title ||
|
|
465
|
+
block.metadata?.filename ||
|
|
466
|
+
block.metadata?.name
|
|
467
|
+
? {
|
|
468
|
+
title: (block.metadata?.title ||
|
|
469
|
+
block.metadata?.filename ||
|
|
470
|
+
block.metadata?.name),
|
|
471
|
+
}
|
|
472
|
+
: {}),
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
throw new Error(`Unsupported file mime type for file url source: ${block.mime_type}`);
|
|
476
|
+
}
|
|
477
|
+
else if (block.source_type === "text") {
|
|
478
|
+
if (mime_type === "text/plain" || mime_type === "") {
|
|
479
|
+
return {
|
|
480
|
+
type: "document",
|
|
481
|
+
source: {
|
|
482
|
+
type: "text",
|
|
483
|
+
data: block.text,
|
|
484
|
+
media_type: block.mime_type ?? "",
|
|
485
|
+
},
|
|
486
|
+
...("cache_control" in (block.metadata ?? {})
|
|
487
|
+
? {
|
|
488
|
+
cache_control: block.metadata
|
|
489
|
+
.cache_control,
|
|
490
|
+
}
|
|
491
|
+
: {}),
|
|
492
|
+
...("citations" in (block.metadata ?? {})
|
|
493
|
+
? {
|
|
494
|
+
citations: block.metadata.citations,
|
|
495
|
+
}
|
|
496
|
+
: {}),
|
|
497
|
+
...("context" in (block.metadata ?? {})
|
|
498
|
+
? { context: block.metadata.context }
|
|
499
|
+
: {}),
|
|
500
|
+
...("title" in (block.metadata ?? {})
|
|
501
|
+
? { title: block.metadata.title }
|
|
502
|
+
: {}),
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
throw new Error(`Unsupported file mime type for file text source: ${block.mime_type}`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
else if (block.source_type === "base64") {
|
|
510
|
+
if (mime_type === "application/pdf" || mime_type === "") {
|
|
511
|
+
return {
|
|
512
|
+
type: "document",
|
|
513
|
+
source: {
|
|
514
|
+
type: "base64",
|
|
515
|
+
data: block.data,
|
|
516
|
+
media_type: "application/pdf",
|
|
517
|
+
},
|
|
518
|
+
...("cache_control" in (block.metadata ?? {})
|
|
519
|
+
? {
|
|
520
|
+
cache_control: block.metadata
|
|
521
|
+
.cache_control,
|
|
522
|
+
}
|
|
523
|
+
: {}),
|
|
524
|
+
...("citations" in (block.metadata ?? {})
|
|
525
|
+
? {
|
|
526
|
+
citations: block.metadata.citations,
|
|
527
|
+
}
|
|
528
|
+
: {}),
|
|
529
|
+
...("context" in (block.metadata ?? {})
|
|
530
|
+
? { context: block.metadata.context }
|
|
531
|
+
: {}),
|
|
532
|
+
...("title" in (block.metadata ?? {})
|
|
533
|
+
? { title: block.metadata.title }
|
|
534
|
+
: {}),
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
else if (["image/jpeg", "image/png", "image/gif", "image/webp"].includes(mime_type)) {
|
|
538
|
+
return {
|
|
539
|
+
type: "document",
|
|
540
|
+
source: {
|
|
541
|
+
type: "content",
|
|
542
|
+
content: [
|
|
543
|
+
{
|
|
544
|
+
type: "image",
|
|
545
|
+
source: {
|
|
546
|
+
type: "base64",
|
|
547
|
+
data: block.data,
|
|
548
|
+
media_type: mime_type,
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
},
|
|
553
|
+
...("cache_control" in (block.metadata ?? {})
|
|
554
|
+
? {
|
|
555
|
+
cache_control: block.metadata
|
|
556
|
+
.cache_control,
|
|
557
|
+
}
|
|
558
|
+
: {}),
|
|
559
|
+
...("citations" in (block.metadata ?? {})
|
|
560
|
+
? {
|
|
561
|
+
citations: block.metadata.citations,
|
|
562
|
+
}
|
|
563
|
+
: {}),
|
|
564
|
+
...("context" in (block.metadata ?? {})
|
|
565
|
+
? { context: block.metadata.context }
|
|
566
|
+
: {}),
|
|
567
|
+
...("title" in (block.metadata ?? {})
|
|
568
|
+
? { title: block.metadata.title }
|
|
569
|
+
: {}),
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
throw new Error(`Unsupported file mime type for file base64 source: ${block.mime_type}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
throw new Error(`Unsupported file source type: ${block.source_type}`);
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
};
|
|
373
581
|
function contentToAnthropicContent(content) {
|
|
374
|
-
const ret = [];
|
|
375
582
|
const ca = typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
376
|
-
ca
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
});
|
|
382
|
-
return ret;
|
|
583
|
+
return ca
|
|
584
|
+
.map((complex) => isDataContentBlock(complex)
|
|
585
|
+
? convertToProviderContentBlock(complex, anthropicContentConverter)
|
|
586
|
+
: contentComplexToAnthropicContent(complex))
|
|
587
|
+
.filter(Boolean);
|
|
383
588
|
}
|
|
384
589
|
function toolCallToAnthropicContent(toolCall) {
|
|
385
590
|
return {
|
|
@@ -436,6 +641,9 @@ export function getAnthropicAPI(config) {
|
|
|
436
641
|
return aiMessageToAnthropicMessage(base);
|
|
437
642
|
case "tool":
|
|
438
643
|
return toolMessageToAnthropicMessage(base);
|
|
644
|
+
case "system":
|
|
645
|
+
// System messages are handled in formatSystem()
|
|
646
|
+
return undefined;
|
|
439
647
|
default:
|
|
440
648
|
console.warn(`Unknown BaseMessage type: ${type}`, base);
|
|
441
649
|
return undefined;
|
package/dist/utils/common.cjs
CHANGED
|
@@ -69,7 +69,7 @@ function convertToGeminiTools(tools) {
|
|
|
69
69
|
geminiTools[functionDeclarationsIndex].functionDeclarations.push(...funcs);
|
|
70
70
|
}
|
|
71
71
|
else if ((0, function_calling_1.isLangChainTool)(tool)) {
|
|
72
|
-
const jsonSchema = (0, zod_to_gemini_parameters_js_1.
|
|
72
|
+
const jsonSchema = (0, zod_to_gemini_parameters_js_1.schemaToGeminiParameters)(tool.schema);
|
|
73
73
|
geminiTools[functionDeclarationsIndex].functionDeclarations.push({
|
|
74
74
|
name: tool.name,
|
|
75
75
|
description: tool.description ?? `A function available to call.`,
|
|
@@ -91,6 +91,22 @@ function convertToGeminiTools(tools) {
|
|
|
91
91
|
return geminiTools;
|
|
92
92
|
}
|
|
93
93
|
exports.convertToGeminiTools = convertToGeminiTools;
|
|
94
|
+
function reasoningEffortToReasoningTokens(_modelName, effort) {
|
|
95
|
+
if (effort === undefined) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const maxEffort = 24 * 1024; // Max for Gemini 2.5 Flash
|
|
99
|
+
switch (effort) {
|
|
100
|
+
case "low":
|
|
101
|
+
return maxEffort / 3;
|
|
102
|
+
case "medium":
|
|
103
|
+
return (2 * maxEffort) / 3;
|
|
104
|
+
case "high":
|
|
105
|
+
return maxEffort;
|
|
106
|
+
default:
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
94
110
|
function copyAIModelParamsInto(params, options, target) {
|
|
95
111
|
const ret = target || {};
|
|
96
112
|
const model = options?.model ?? params?.model ?? target.model;
|
|
@@ -103,6 +119,16 @@ function copyAIModelParamsInto(params, options, target) {
|
|
|
103
119
|
options?.maxOutputTokens ??
|
|
104
120
|
params?.maxOutputTokens ??
|
|
105
121
|
target.maxOutputTokens;
|
|
122
|
+
ret.maxReasoningTokens =
|
|
123
|
+
options?.maxReasoningTokens ??
|
|
124
|
+
params?.maxReasoningTokens ??
|
|
125
|
+
target?.maxReasoningTokens ??
|
|
126
|
+
options?.thinkingBudget ??
|
|
127
|
+
params?.thinkingBudget ??
|
|
128
|
+
target?.thinkingBudget ??
|
|
129
|
+
reasoningEffortToReasoningTokens(ret.modelName, params?.reasoningEffort) ??
|
|
130
|
+
reasoningEffortToReasoningTokens(ret.modelName, target?.reasoningEffort) ??
|
|
131
|
+
reasoningEffortToReasoningTokens(ret.modelName, options?.reasoningEffort);
|
|
106
132
|
ret.topP = options?.topP ?? params?.topP ?? target.topP;
|
|
107
133
|
ret.topK = options?.topK ?? params?.topK ?? target.topK;
|
|
108
134
|
ret.presencePenalty =
|
package/dist/utils/common.js
CHANGED
|
@@ -2,7 +2,7 @@ import { isOpenAITool } from "@langchain/core/language_models/base";
|
|
|
2
2
|
import { isLangChainTool } from "@langchain/core/utils/function_calling";
|
|
3
3
|
import { isModelGemini, isModelGemma, validateGeminiParams } from "./gemini.js";
|
|
4
4
|
import { GeminiToolAttributes, } from "../types.js";
|
|
5
|
-
import { jsonSchemaToGeminiParameters,
|
|
5
|
+
import { jsonSchemaToGeminiParameters, schemaToGeminiParameters, } from "./zod_to_gemini_parameters.js";
|
|
6
6
|
import { isModelClaude, validateClaudeParams } from "./anthropic.js";
|
|
7
7
|
export function copyAIModelParams(params, options) {
|
|
8
8
|
return copyAIModelParamsInto(params, options, {});
|
|
@@ -65,7 +65,7 @@ export function convertToGeminiTools(tools) {
|
|
|
65
65
|
geminiTools[functionDeclarationsIndex].functionDeclarations.push(...funcs);
|
|
66
66
|
}
|
|
67
67
|
else if (isLangChainTool(tool)) {
|
|
68
|
-
const jsonSchema =
|
|
68
|
+
const jsonSchema = schemaToGeminiParameters(tool.schema);
|
|
69
69
|
geminiTools[functionDeclarationsIndex].functionDeclarations.push({
|
|
70
70
|
name: tool.name,
|
|
71
71
|
description: tool.description ?? `A function available to call.`,
|
|
@@ -86,6 +86,22 @@ export function convertToGeminiTools(tools) {
|
|
|
86
86
|
});
|
|
87
87
|
return geminiTools;
|
|
88
88
|
}
|
|
89
|
+
function reasoningEffortToReasoningTokens(_modelName, effort) {
|
|
90
|
+
if (effort === undefined) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
const maxEffort = 24 * 1024; // Max for Gemini 2.5 Flash
|
|
94
|
+
switch (effort) {
|
|
95
|
+
case "low":
|
|
96
|
+
return maxEffort / 3;
|
|
97
|
+
case "medium":
|
|
98
|
+
return (2 * maxEffort) / 3;
|
|
99
|
+
case "high":
|
|
100
|
+
return maxEffort;
|
|
101
|
+
default:
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
89
105
|
export function copyAIModelParamsInto(params, options, target) {
|
|
90
106
|
const ret = target || {};
|
|
91
107
|
const model = options?.model ?? params?.model ?? target.model;
|
|
@@ -98,6 +114,16 @@ export function copyAIModelParamsInto(params, options, target) {
|
|
|
98
114
|
options?.maxOutputTokens ??
|
|
99
115
|
params?.maxOutputTokens ??
|
|
100
116
|
target.maxOutputTokens;
|
|
117
|
+
ret.maxReasoningTokens =
|
|
118
|
+
options?.maxReasoningTokens ??
|
|
119
|
+
params?.maxReasoningTokens ??
|
|
120
|
+
target?.maxReasoningTokens ??
|
|
121
|
+
options?.thinkingBudget ??
|
|
122
|
+
params?.thinkingBudget ??
|
|
123
|
+
target?.thinkingBudget ??
|
|
124
|
+
reasoningEffortToReasoningTokens(ret.modelName, params?.reasoningEffort) ??
|
|
125
|
+
reasoningEffortToReasoningTokens(ret.modelName, target?.reasoningEffort) ??
|
|
126
|
+
reasoningEffortToReasoningTokens(ret.modelName, options?.reasoningEffort);
|
|
101
127
|
ret.topP = options?.topP ?? params?.topP ?? target.topP;
|
|
102
128
|
ret.topK = options?.topK ?? params?.topK ?? target.topK;
|
|
103
129
|
ret.presencePenalty =
|
package/dist/utils/gemini.cjs
CHANGED
|
@@ -198,6 +198,109 @@ function getGeminiAPI(config) {
|
|
|
198
198
|
}
|
|
199
199
|
throw new Error(`Invalid media content: ${JSON.stringify(content, null, 1)}`);
|
|
200
200
|
}
|
|
201
|
+
const standardContentBlockConverter = {
|
|
202
|
+
providerName: "Google Gemini",
|
|
203
|
+
fromStandardTextBlock(block) {
|
|
204
|
+
return {
|
|
205
|
+
text: block.text,
|
|
206
|
+
};
|
|
207
|
+
},
|
|
208
|
+
fromStandardImageBlock(block) {
|
|
209
|
+
if (block.source_type === "url") {
|
|
210
|
+
const data = (0, messages_1.parseBase64DataUrl)({ dataUrl: block.url });
|
|
211
|
+
if (data) {
|
|
212
|
+
return {
|
|
213
|
+
inlineData: {
|
|
214
|
+
mimeType: data.mime_type,
|
|
215
|
+
data: data.data,
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
return {
|
|
221
|
+
fileData: {
|
|
222
|
+
mimeType: block.mime_type ?? "",
|
|
223
|
+
fileUri: block.url,
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (block.source_type === "base64") {
|
|
229
|
+
return {
|
|
230
|
+
inlineData: {
|
|
231
|
+
mimeType: block.mime_type ?? "",
|
|
232
|
+
data: block.data,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
throw new Error(`Unsupported source type: ${block.source_type}`);
|
|
237
|
+
},
|
|
238
|
+
fromStandardAudioBlock(block) {
|
|
239
|
+
if (block.source_type === "url") {
|
|
240
|
+
const data = (0, messages_1.parseBase64DataUrl)({ dataUrl: block.url });
|
|
241
|
+
if (data) {
|
|
242
|
+
return {
|
|
243
|
+
inlineData: {
|
|
244
|
+
mimeType: data.mime_type,
|
|
245
|
+
data: data.data,
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
return {
|
|
251
|
+
fileData: {
|
|
252
|
+
mimeType: block.mime_type ?? "",
|
|
253
|
+
fileUri: block.url,
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (block.source_type === "base64") {
|
|
259
|
+
return {
|
|
260
|
+
inlineData: {
|
|
261
|
+
mimeType: block.mime_type ?? "",
|
|
262
|
+
data: block.data,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
throw new Error(`Unsupported source type: ${block.source_type}`);
|
|
267
|
+
},
|
|
268
|
+
fromStandardFileBlock(block) {
|
|
269
|
+
if (block.source_type === "text") {
|
|
270
|
+
return {
|
|
271
|
+
text: block.text,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
if (block.source_type === "url") {
|
|
275
|
+
const data = (0, messages_1.parseBase64DataUrl)({ dataUrl: block.url });
|
|
276
|
+
if (data) {
|
|
277
|
+
return {
|
|
278
|
+
inlineData: {
|
|
279
|
+
mimeType: data.mime_type,
|
|
280
|
+
data: data.data,
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
return {
|
|
286
|
+
fileData: {
|
|
287
|
+
mimeType: block.mime_type ?? "",
|
|
288
|
+
fileUri: block.url,
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (block.source_type === "base64") {
|
|
294
|
+
return {
|
|
295
|
+
inlineData: {
|
|
296
|
+
mimeType: block.mime_type ?? "",
|
|
297
|
+
data: block.data,
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
throw new Error(`Unsupported source type: ${block.source_type}`);
|
|
302
|
+
},
|
|
303
|
+
};
|
|
201
304
|
async function messageContentComplexToPart(content) {
|
|
202
305
|
switch (content.type) {
|
|
203
306
|
case "text":
|
|
@@ -219,7 +322,9 @@ function getGeminiAPI(config) {
|
|
|
219
322
|
throw new Error(`Cannot coerce "${content.type}" message part into a string.`);
|
|
220
323
|
}
|
|
221
324
|
async function messageContentComplexToParts(content) {
|
|
222
|
-
const contents = content.map(
|
|
325
|
+
const contents = content.map((m) => (0, messages_1.isDataContentBlock)(m)
|
|
326
|
+
? (0, messages_1.convertToProviderContentBlock)(m, standardContentBlockConverter)
|
|
327
|
+
: messageContentComplexToPart(m));
|
|
223
328
|
return Promise.all(contents);
|
|
224
329
|
}
|
|
225
330
|
async function messageContentToParts(content) {
|
|
@@ -951,6 +1056,13 @@ function getGeminiAPI(config) {
|
|
|
951
1056
|
ret.logprobs = parameters.topLogprobs;
|
|
952
1057
|
}
|
|
953
1058
|
}
|
|
1059
|
+
// Add thinking configuration if explicitly set
|
|
1060
|
+
if (typeof parameters.maxReasoningTokens !== "undefined") {
|
|
1061
|
+
ret.thinkingConfig = {
|
|
1062
|
+
thinkingBudget: parameters.maxReasoningTokens,
|
|
1063
|
+
includeThoughts: true,
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
954
1066
|
// Remove any undefined properties, so we don't send them
|
|
955
1067
|
let attribute;
|
|
956
1068
|
for (attribute in ret) {
|
|
@@ -994,7 +1106,7 @@ function getGeminiAPI(config) {
|
|
|
994
1106
|
}
|
|
995
1107
|
}
|
|
996
1108
|
function structuredToolToFunctionDeclaration(tool) {
|
|
997
|
-
const jsonSchema = (0, zod_to_gemini_parameters_js_1.
|
|
1109
|
+
const jsonSchema = (0, zod_to_gemini_parameters_js_1.schemaToGeminiParameters)(tool.schema);
|
|
998
1110
|
return {
|
|
999
1111
|
name: tool.name,
|
|
1000
1112
|
description: tool.description ?? `A function available to call.`,
|
|
@@ -1113,6 +1225,16 @@ function validateGeminiParams(params) {
|
|
|
1113
1225
|
if (params.maxOutputTokens && params.maxOutputTokens < 0) {
|
|
1114
1226
|
throw new Error("`maxOutputTokens` must be a positive integer");
|
|
1115
1227
|
}
|
|
1228
|
+
if (typeof params.maxReasoningTokens !== "undefined") {
|
|
1229
|
+
if (params.maxReasoningTokens < 0) {
|
|
1230
|
+
throw new Error("`maxReasoningTokens` must be non-negative integer");
|
|
1231
|
+
}
|
|
1232
|
+
if (typeof params.maxOutputTokens !== "undefined") {
|
|
1233
|
+
if (params.maxReasoningTokens >= params.maxOutputTokens) {
|
|
1234
|
+
throw new Error("`maxOutputTokens` must be greater than `maxReasoningTokens`");
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1116
1238
|
if (params.temperature &&
|
|
1117
1239
|
(params.temperature < 0 || params.temperature > 2)) {
|
|
1118
1240
|
throw new Error("`temperature` must be in the range of [0.0,2.0]");
|
package/dist/utils/gemini.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
|
-
import { AIMessage, AIMessageChunk, isAIMessage, } from "@langchain/core/messages";
|
|
2
|
+
import { AIMessage, AIMessageChunk, isAIMessage, parseBase64DataUrl, isDataContentBlock, convertToProviderContentBlock, } from "@langchain/core/messages";
|
|
3
3
|
import { ChatGenerationChunk, } from "@langchain/core/outputs";
|
|
4
4
|
import { isLangChainTool } from "@langchain/core/utils/function_calling";
|
|
5
5
|
import { concat } from "@langchain/core/utils/stream";
|
|
6
6
|
import { GoogleAISafetyError } from "./safety.js";
|
|
7
7
|
import { GeminiSearchToolAttributes, } from "../types.js";
|
|
8
|
-
import {
|
|
8
|
+
import { schemaToGeminiParameters } from "./zod_to_gemini_parameters.js";
|
|
9
9
|
export class DefaultGeminiSafetyHandler {
|
|
10
10
|
constructor(settings) {
|
|
11
11
|
Object.defineProperty(this, "errorFinish", {
|
|
@@ -193,6 +193,109 @@ export function getGeminiAPI(config) {
|
|
|
193
193
|
}
|
|
194
194
|
throw new Error(`Invalid media content: ${JSON.stringify(content, null, 1)}`);
|
|
195
195
|
}
|
|
196
|
+
const standardContentBlockConverter = {
|
|
197
|
+
providerName: "Google Gemini",
|
|
198
|
+
fromStandardTextBlock(block) {
|
|
199
|
+
return {
|
|
200
|
+
text: block.text,
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
fromStandardImageBlock(block) {
|
|
204
|
+
if (block.source_type === "url") {
|
|
205
|
+
const data = parseBase64DataUrl({ dataUrl: block.url });
|
|
206
|
+
if (data) {
|
|
207
|
+
return {
|
|
208
|
+
inlineData: {
|
|
209
|
+
mimeType: data.mime_type,
|
|
210
|
+
data: data.data,
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
return {
|
|
216
|
+
fileData: {
|
|
217
|
+
mimeType: block.mime_type ?? "",
|
|
218
|
+
fileUri: block.url,
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (block.source_type === "base64") {
|
|
224
|
+
return {
|
|
225
|
+
inlineData: {
|
|
226
|
+
mimeType: block.mime_type ?? "",
|
|
227
|
+
data: block.data,
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
throw new Error(`Unsupported source type: ${block.source_type}`);
|
|
232
|
+
},
|
|
233
|
+
fromStandardAudioBlock(block) {
|
|
234
|
+
if (block.source_type === "url") {
|
|
235
|
+
const data = parseBase64DataUrl({ dataUrl: block.url });
|
|
236
|
+
if (data) {
|
|
237
|
+
return {
|
|
238
|
+
inlineData: {
|
|
239
|
+
mimeType: data.mime_type,
|
|
240
|
+
data: data.data,
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
return {
|
|
246
|
+
fileData: {
|
|
247
|
+
mimeType: block.mime_type ?? "",
|
|
248
|
+
fileUri: block.url,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (block.source_type === "base64") {
|
|
254
|
+
return {
|
|
255
|
+
inlineData: {
|
|
256
|
+
mimeType: block.mime_type ?? "",
|
|
257
|
+
data: block.data,
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
throw new Error(`Unsupported source type: ${block.source_type}`);
|
|
262
|
+
},
|
|
263
|
+
fromStandardFileBlock(block) {
|
|
264
|
+
if (block.source_type === "text") {
|
|
265
|
+
return {
|
|
266
|
+
text: block.text,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if (block.source_type === "url") {
|
|
270
|
+
const data = parseBase64DataUrl({ dataUrl: block.url });
|
|
271
|
+
if (data) {
|
|
272
|
+
return {
|
|
273
|
+
inlineData: {
|
|
274
|
+
mimeType: data.mime_type,
|
|
275
|
+
data: data.data,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
return {
|
|
281
|
+
fileData: {
|
|
282
|
+
mimeType: block.mime_type ?? "",
|
|
283
|
+
fileUri: block.url,
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (block.source_type === "base64") {
|
|
289
|
+
return {
|
|
290
|
+
inlineData: {
|
|
291
|
+
mimeType: block.mime_type ?? "",
|
|
292
|
+
data: block.data,
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
throw new Error(`Unsupported source type: ${block.source_type}`);
|
|
297
|
+
},
|
|
298
|
+
};
|
|
196
299
|
async function messageContentComplexToPart(content) {
|
|
197
300
|
switch (content.type) {
|
|
198
301
|
case "text":
|
|
@@ -214,7 +317,9 @@ export function getGeminiAPI(config) {
|
|
|
214
317
|
throw new Error(`Cannot coerce "${content.type}" message part into a string.`);
|
|
215
318
|
}
|
|
216
319
|
async function messageContentComplexToParts(content) {
|
|
217
|
-
const contents = content.map(
|
|
320
|
+
const contents = content.map((m) => isDataContentBlock(m)
|
|
321
|
+
? convertToProviderContentBlock(m, standardContentBlockConverter)
|
|
322
|
+
: messageContentComplexToPart(m));
|
|
218
323
|
return Promise.all(contents);
|
|
219
324
|
}
|
|
220
325
|
async function messageContentToParts(content) {
|
|
@@ -946,6 +1051,13 @@ export function getGeminiAPI(config) {
|
|
|
946
1051
|
ret.logprobs = parameters.topLogprobs;
|
|
947
1052
|
}
|
|
948
1053
|
}
|
|
1054
|
+
// Add thinking configuration if explicitly set
|
|
1055
|
+
if (typeof parameters.maxReasoningTokens !== "undefined") {
|
|
1056
|
+
ret.thinkingConfig = {
|
|
1057
|
+
thinkingBudget: parameters.maxReasoningTokens,
|
|
1058
|
+
includeThoughts: true,
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
949
1061
|
// Remove any undefined properties, so we don't send them
|
|
950
1062
|
let attribute;
|
|
951
1063
|
for (attribute in ret) {
|
|
@@ -989,7 +1101,7 @@ export function getGeminiAPI(config) {
|
|
|
989
1101
|
}
|
|
990
1102
|
}
|
|
991
1103
|
function structuredToolToFunctionDeclaration(tool) {
|
|
992
|
-
const jsonSchema =
|
|
1104
|
+
const jsonSchema = schemaToGeminiParameters(tool.schema);
|
|
993
1105
|
return {
|
|
994
1106
|
name: tool.name,
|
|
995
1107
|
description: tool.description ?? `A function available to call.`,
|
|
@@ -1107,6 +1219,16 @@ export function validateGeminiParams(params) {
|
|
|
1107
1219
|
if (params.maxOutputTokens && params.maxOutputTokens < 0) {
|
|
1108
1220
|
throw new Error("`maxOutputTokens` must be a positive integer");
|
|
1109
1221
|
}
|
|
1222
|
+
if (typeof params.maxReasoningTokens !== "undefined") {
|
|
1223
|
+
if (params.maxReasoningTokens < 0) {
|
|
1224
|
+
throw new Error("`maxReasoningTokens` must be non-negative integer");
|
|
1225
|
+
}
|
|
1226
|
+
if (typeof params.maxOutputTokens !== "undefined") {
|
|
1227
|
+
if (params.maxReasoningTokens >= params.maxOutputTokens) {
|
|
1228
|
+
throw new Error("`maxOutputTokens` must be greater than `maxReasoningTokens`");
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1110
1232
|
if (params.temperature &&
|
|
1111
1233
|
(params.temperature < 0 || params.temperature > 2)) {
|
|
1112
1234
|
throw new Error("`temperature` must be in the range of [0.0,2.0]");
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.jsonSchemaToGeminiParameters = exports.
|
|
4
|
+
exports.jsonSchemaToGeminiParameters = exports.schemaToGeminiParameters = exports.removeAdditionalProperties = void 0;
|
|
5
|
+
const types_1 = require("@langchain/core/utils/types");
|
|
5
6
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
6
7
|
function removeAdditionalProperties(
|
|
7
8
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -26,17 +27,14 @@ obj) {
|
|
|
26
27
|
return obj;
|
|
27
28
|
}
|
|
28
29
|
exports.removeAdditionalProperties = removeAdditionalProperties;
|
|
29
|
-
function
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
-
zodObj) {
|
|
30
|
+
function schemaToGeminiParameters(schema) {
|
|
32
31
|
// Gemini doesn't accept either the $schema or additionalProperties
|
|
33
32
|
// attributes, so we need to explicitly remove them.
|
|
34
|
-
|
|
35
|
-
const jsonSchema = removeAdditionalProperties((0, zod_to_json_schema_1.zodToJsonSchema)(zodObj));
|
|
33
|
+
const jsonSchema = removeAdditionalProperties((0, types_1.isZodSchema)(schema) ? (0, zod_to_json_schema_1.zodToJsonSchema)(schema) : schema);
|
|
36
34
|
const { $schema, ...rest } = jsonSchema;
|
|
37
35
|
return rest;
|
|
38
36
|
}
|
|
39
|
-
exports.
|
|
37
|
+
exports.schemaToGeminiParameters = schemaToGeminiParameters;
|
|
40
38
|
function jsonSchemaToGeminiParameters(
|
|
41
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
40
|
schema) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
|
+
import { type JsonSchema7Type } from "zod-to-json-schema";
|
|
2
3
|
import { GeminiFunctionSchema, GeminiJsonSchema } from "../types.js";
|
|
3
4
|
export declare function removeAdditionalProperties(obj: Record<string, any>): GeminiJsonSchema;
|
|
4
|
-
export declare function
|
|
5
|
+
export declare function schemaToGeminiParameters<RunOutput extends Record<string, any> = Record<string, any>>(schema: z.ZodType<RunOutput> | z.ZodEffects<z.ZodType<RunOutput>> | JsonSchema7Type): GeminiFunctionSchema;
|
|
5
6
|
export declare function jsonSchemaToGeminiParameters(schema: Record<string, any>): GeminiFunctionSchema;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import { isZodSchema } from "@langchain/core/utils/types";
|
|
2
3
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
4
|
export function removeAdditionalProperties(
|
|
4
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -22,13 +23,10 @@ obj) {
|
|
|
22
23
|
}
|
|
23
24
|
return obj;
|
|
24
25
|
}
|
|
25
|
-
export function
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
-
zodObj) {
|
|
26
|
+
export function schemaToGeminiParameters(schema) {
|
|
28
27
|
// Gemini doesn't accept either the $schema or additionalProperties
|
|
29
28
|
// attributes, so we need to explicitly remove them.
|
|
30
|
-
|
|
31
|
-
const jsonSchema = removeAdditionalProperties(zodToJsonSchema(zodObj));
|
|
29
|
+
const jsonSchema = removeAdditionalProperties(isZodSchema(schema) ? zodToJsonSchema(schema) : schema);
|
|
32
30
|
const { $schema, ...rest } = jsonSchema;
|
|
33
31
|
return rest;
|
|
34
32
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/google-common",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Core types and classes for Google services.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"zod-to-json-schema": "^3.22.4"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@langchain/core": ">=0.
|
|
39
|
+
"@langchain/core": ">=0.3.48 <0.4.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@jest/globals": "^29.5.0",
|
|
43
|
-
"@langchain/core": "
|
|
43
|
+
"@langchain/core": "0.3.48",
|
|
44
44
|
"@langchain/scripts": ">=0.1.0 <0.2.0",
|
|
45
45
|
"@swc/core": "^1.3.90",
|
|
46
46
|
"@swc/jest": "^0.2.29",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"jest": "^29.5.0",
|
|
59
59
|
"jest-environment-node": "^29.6.4",
|
|
60
60
|
"prettier": "^2.8.3",
|
|
61
|
-
"release-it": "^
|
|
61
|
+
"release-it": "^18.1.2",
|
|
62
62
|
"rollup": "^4.5.2",
|
|
63
63
|
"ts-jest": "^29.1.0",
|
|
64
64
|
"typescript": "<5.2.0",
|
|
@@ -138,4 +138,4 @@
|
|
|
138
138
|
"experimental/utils/media_core.d.ts",
|
|
139
139
|
"experimental/utils/media_core.d.cts"
|
|
140
140
|
]
|
|
141
|
-
}
|
|
141
|
+
}
|