@ai-sdk/google 4.0.63 → 4.0.65
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/CHANGELOG.md +20 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +205 -129
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +10 -3
- package/dist/internal/index.js +104 -57
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +37 -13
- package/package.json +3 -3
- package/src/convert-json-schema-to-openapi-schema.ts +10 -0
- package/src/google-batch.ts +61 -35
- package/src/google-image-model.ts +3 -0
- package/src/google-language-model.ts +84 -36
- package/src/google-provider.ts +52 -34
package/docs/15-google.mdx
CHANGED
|
@@ -1081,27 +1081,37 @@ import { google } from '@ai-sdk/google';
|
|
|
1081
1081
|
import {
|
|
1082
1082
|
experimental_getBatchResults as getBatchResults,
|
|
1083
1083
|
experimental_getBatchStatus as getBatchStatus,
|
|
1084
|
-
|
|
1084
|
+
experimental_startBatch as startBatch,
|
|
1085
1085
|
} from 'ai';
|
|
1086
1086
|
import { setTimeout } from 'node:timers/promises';
|
|
1087
1087
|
|
|
1088
|
-
const model =
|
|
1088
|
+
const model = 'gemini-3.6-flash';
|
|
1089
1089
|
|
|
1090
|
-
const batch = await
|
|
1091
|
-
|
|
1090
|
+
const batch = await startBatch({
|
|
1091
|
+
provider: google,
|
|
1092
1092
|
requests: [
|
|
1093
|
-
{
|
|
1094
|
-
|
|
1093
|
+
{
|
|
1094
|
+
id: 'capital-france',
|
|
1095
|
+
type: 'text',
|
|
1096
|
+
model,
|
|
1097
|
+
prompt: 'What is the capital of France?',
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
id: 'capital-germany',
|
|
1101
|
+
type: 'text',
|
|
1102
|
+
model,
|
|
1103
|
+
prompt: 'What is the capital of Germany?',
|
|
1104
|
+
},
|
|
1095
1105
|
],
|
|
1096
1106
|
});
|
|
1097
1107
|
|
|
1098
1108
|
let status = batch.status;
|
|
1099
1109
|
while (status === 'pending') {
|
|
1100
1110
|
await setTimeout(60_000);
|
|
1101
|
-
({ status } = await getBatchStatus({
|
|
1111
|
+
({ status } = await getBatchStatus({ provider: google, batch }));
|
|
1102
1112
|
}
|
|
1103
1113
|
|
|
1104
|
-
for await (const item of getBatchResults({
|
|
1114
|
+
for await (const item of getBatchResults({ provider: google, batch })) {
|
|
1105
1115
|
if (item.status === 'succeeded') {
|
|
1106
1116
|
console.log(item.id, item.text);
|
|
1107
1117
|
} else {
|
|
@@ -1110,21 +1120,35 @@ for await (const item of getBatchResults({ model, batch })) {
|
|
|
1110
1120
|
}
|
|
1111
1121
|
```
|
|
1112
1122
|
|
|
1113
|
-
`
|
|
1123
|
+
`startBatch` returns a serializable batch reference. Persist this reference
|
|
1114
1124
|
to check the batch status or retrieve its results from another process. Results
|
|
1115
1125
|
can arrive in a different order from the input requests, so match each result by
|
|
1116
1126
|
its `id`.
|
|
1117
1127
|
|
|
1128
|
+
Each request specifies its `type` and `model`. Google requires every text
|
|
1129
|
+
request in a batch to use the same model and throws before submission when the
|
|
1130
|
+
models differ.
|
|
1131
|
+
|
|
1118
1132
|
#### Webhooks
|
|
1119
1133
|
|
|
1120
1134
|
You can pass a `webhookUrl` to receive a notification when the batch reaches a terminal state:
|
|
1121
1135
|
|
|
1122
1136
|
```ts
|
|
1123
|
-
const batch = await
|
|
1124
|
-
|
|
1137
|
+
const batch = await startBatch({
|
|
1138
|
+
provider: google,
|
|
1125
1139
|
requests: [
|
|
1126
|
-
{
|
|
1127
|
-
|
|
1140
|
+
{
|
|
1141
|
+
id: 'capital-france',
|
|
1142
|
+
type: 'text',
|
|
1143
|
+
model,
|
|
1144
|
+
prompt: 'What is the capital of France?',
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
id: 'capital-germany',
|
|
1148
|
+
type: 'text',
|
|
1149
|
+
model,
|
|
1150
|
+
prompt: 'What is the capital of Germany?',
|
|
1151
|
+
},
|
|
1128
1152
|
],
|
|
1129
1153
|
webhookUrl: 'https://example.com/api/google-batch-webhook',
|
|
1130
1154
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.65",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ai-sdk/provider": "4.0.
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
38
|
+
"@ai-sdk/provider": "4.0.11",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.37"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.1",
|
|
@@ -91,6 +91,8 @@ function convertJSONSchemaDefinition(
|
|
|
91
91
|
format,
|
|
92
92
|
const: constValue,
|
|
93
93
|
minLength,
|
|
94
|
+
minItems,
|
|
95
|
+
maxItems,
|
|
94
96
|
enum: enumValues,
|
|
95
97
|
} = jsonSchema;
|
|
96
98
|
|
|
@@ -196,6 +198,14 @@ function convertJSONSchemaDefinition(
|
|
|
196
198
|
result.minLength = minLength;
|
|
197
199
|
}
|
|
198
200
|
|
|
201
|
+
if (minItems !== undefined) {
|
|
202
|
+
result.minItems = minItems;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (maxItems !== undefined) {
|
|
206
|
+
result.maxItems = maxItems;
|
|
207
|
+
}
|
|
208
|
+
|
|
199
209
|
return result;
|
|
200
210
|
}
|
|
201
211
|
|
package/src/google-batch.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InvalidArgumentError,
|
|
3
3
|
InvalidResponseDataError,
|
|
4
|
-
type
|
|
4
|
+
type Experimental_BatchV4 as BatchV4,
|
|
5
5
|
type Experimental_BatchV4Error as BatchV4Error,
|
|
6
6
|
type Experimental_BatchV4ItemResult as BatchV4ItemResult,
|
|
7
7
|
type Experimental_BatchV4OperationOptions as BatchV4OperationOptions,
|
|
8
|
-
type Experimental_BatchV4StartOptions as BatchV4StartOptions,
|
|
9
8
|
type Experimental_BatchV4StartResult as BatchV4StartResult,
|
|
10
9
|
type Experimental_BatchV4Status as BatchV4Status,
|
|
10
|
+
type Experimental_TextBatchV4Request as TextBatchV4Request,
|
|
11
|
+
type Experimental_BatchV4StartOptions as BatchV4StartOptions,
|
|
11
12
|
type LanguageModelV4GenerateResult,
|
|
12
13
|
} from '@ai-sdk/provider';
|
|
13
14
|
import {
|
|
@@ -23,8 +24,6 @@ import {
|
|
|
23
24
|
postToApi,
|
|
24
25
|
resolve,
|
|
25
26
|
safeValidateTypes,
|
|
26
|
-
WORKFLOW_DESERIALIZE,
|
|
27
|
-
WORKFLOW_SERIALIZE,
|
|
28
27
|
zodSchema,
|
|
29
28
|
type InferSchema,
|
|
30
29
|
type ResponseHandler,
|
|
@@ -45,9 +44,7 @@ const supportedGoogleBatchContentTypes = new Set<
|
|
|
45
44
|
LanguageModelV4GenerateResult['content'][number]['type']
|
|
46
45
|
>(['text', 'reasoning', 'source', 'tool-call', 'tool-result']);
|
|
47
46
|
|
|
48
|
-
type GoogleBatchRequest =
|
|
49
|
-
BatchLanguageModelV4['experimental_doStartBatch']
|
|
50
|
-
>[0]['requests'][number];
|
|
47
|
+
type GoogleBatchRequest = TextBatchV4Request<GoogleModelId>;
|
|
51
48
|
|
|
52
49
|
const googleRpcStatusSchema = z.object({
|
|
53
50
|
code: z.union([z.number(), z.string()]).nullish(),
|
|
@@ -136,33 +133,28 @@ const googleBatchResponsePreviewSchema = lazySchema(() =>
|
|
|
136
133
|
),
|
|
137
134
|
);
|
|
138
135
|
|
|
139
|
-
export class
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
136
|
+
export class GoogleBatch implements BatchV4<{ readonly text: GoogleModelId }> {
|
|
137
|
+
readonly specificationVersion = 'v4' as const;
|
|
138
|
+
readonly provider: string;
|
|
139
|
+
readonly supportedUrls: Record<string, RegExp[]>;
|
|
143
140
|
private readonly batchConfig: GoogleLanguageModelConfig;
|
|
144
141
|
private readonly batchGenerateId: () => string;
|
|
145
142
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
static [WORKFLOW_DESERIALIZE](options: {
|
|
151
|
-
modelId: string;
|
|
143
|
+
constructor(options: {
|
|
144
|
+
provider: string;
|
|
152
145
|
config: GoogleLanguageModelConfig;
|
|
146
|
+
supportedUrls: Record<string, RegExp[]>;
|
|
153
147
|
}) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
super(modelId, config);
|
|
159
|
-
this.batchConfig = config;
|
|
160
|
-
this.batchGenerateId = config.generateId ?? generateId;
|
|
148
|
+
this.provider = options.provider;
|
|
149
|
+
this.batchConfig = options.config;
|
|
150
|
+
this.supportedUrls = options.supportedUrls;
|
|
151
|
+
this.batchGenerateId = options.config.generateId ?? generateId;
|
|
161
152
|
}
|
|
162
153
|
|
|
163
|
-
async
|
|
164
|
-
options: BatchV4StartOptions<
|
|
154
|
+
async doStartBatch(
|
|
155
|
+
options: BatchV4StartOptions<{ text: GoogleModelId }>,
|
|
165
156
|
): Promise<BatchV4StartResult> {
|
|
157
|
+
const modelId = getGoogleBatchModelId(options.requests);
|
|
166
158
|
const warnings: BatchV4StartResult['warnings'] = [];
|
|
167
159
|
const displayName = `ai-sdk-batch-${this.batchGenerateId()}`;
|
|
168
160
|
const inlinedRequests: Array<{
|
|
@@ -187,7 +179,11 @@ export class GoogleBatchLanguageModel
|
|
|
187
179
|
let fileParts: string[] | undefined;
|
|
188
180
|
|
|
189
181
|
for (const request of options.requests) {
|
|
190
|
-
const preparedRequest = await
|
|
182
|
+
const preparedRequest = await GoogleLanguageModel.prepareRequest({
|
|
183
|
+
modelId: request.modelId,
|
|
184
|
+
config: this.batchConfig,
|
|
185
|
+
options: request.options,
|
|
186
|
+
});
|
|
191
187
|
const inlinedRequest = {
|
|
192
188
|
request: preparedRequest.args,
|
|
193
189
|
metadata: { key: request.id },
|
|
@@ -242,7 +238,7 @@ export class GoogleBatchLanguageModel
|
|
|
242
238
|
|
|
243
239
|
const headers = await this.getHeaders(options.headers);
|
|
244
240
|
const createUrl = `${this.batchConfig.baseURL}/${getModelPath(
|
|
245
|
-
|
|
241
|
+
modelId,
|
|
246
242
|
)}:batchGenerateContent`;
|
|
247
243
|
|
|
248
244
|
if (fileParts == null) {
|
|
@@ -353,15 +349,15 @@ export class GoogleBatchLanguageModel
|
|
|
353
349
|
};
|
|
354
350
|
}
|
|
355
351
|
|
|
356
|
-
async
|
|
352
|
+
async doGetBatchStatus(
|
|
357
353
|
options: BatchV4OperationOptions,
|
|
358
354
|
): Promise<BatchV4Status> {
|
|
359
355
|
return convertGoogleBatchStatus(await this.retrieveBatch(options));
|
|
360
356
|
}
|
|
361
357
|
|
|
362
|
-
async
|
|
358
|
+
async doGetBatchResults(
|
|
363
359
|
options: BatchV4OperationOptions,
|
|
364
|
-
): Promise<ReadableStream<BatchV4ItemResult
|
|
360
|
+
): Promise<ReadableStream<BatchV4ItemResult>> {
|
|
365
361
|
const operation = await this.retrieveBatch(options);
|
|
366
362
|
const batchStatus = convertGoogleBatchStatus(operation);
|
|
367
363
|
|
|
@@ -450,7 +446,7 @@ export class GoogleBatchLanguageModel
|
|
|
450
446
|
results:
|
|
451
447
|
| Iterable<GoogleBatchResultLine>
|
|
452
448
|
| AsyncIterable<GoogleBatchResultLine>,
|
|
453
|
-
): AsyncGenerator<BatchV4ItemResult
|
|
449
|
+
): AsyncGenerator<BatchV4ItemResult> {
|
|
454
450
|
for await (const line of results) {
|
|
455
451
|
if (line.error != null) {
|
|
456
452
|
const error = convertGoogleRpcError(
|
|
@@ -462,12 +458,13 @@ export class GoogleBatchLanguageModel
|
|
|
462
458
|
? 'cancelled'
|
|
463
459
|
: 'failed';
|
|
464
460
|
|
|
465
|
-
yield { id: line.key, status, error };
|
|
461
|
+
yield { type: 'text', id: line.key, status, error };
|
|
466
462
|
continue;
|
|
467
463
|
}
|
|
468
464
|
|
|
469
465
|
if (line.response == null) {
|
|
470
466
|
yield {
|
|
467
|
+
type: 'text',
|
|
471
468
|
id: line.key,
|
|
472
469
|
status: 'failed',
|
|
473
470
|
error: {
|
|
@@ -491,6 +488,7 @@ export class GoogleBatchLanguageModel
|
|
|
491
488
|
const promptFeedback = preview.value.promptFeedback ?? undefined;
|
|
492
489
|
const blockReason = promptFeedback?.blockReason ?? undefined;
|
|
493
490
|
yield {
|
|
491
|
+
type: 'text',
|
|
494
492
|
id: line.key,
|
|
495
493
|
status: 'failed',
|
|
496
494
|
error: {
|
|
@@ -522,6 +520,7 @@ export class GoogleBatchLanguageModel
|
|
|
522
520
|
});
|
|
523
521
|
if (!response.success) {
|
|
524
522
|
yield {
|
|
523
|
+
type: 'text',
|
|
525
524
|
id: line.key,
|
|
526
525
|
status: 'failed',
|
|
527
526
|
error: {
|
|
@@ -532,7 +531,8 @@ export class GoogleBatchLanguageModel
|
|
|
532
531
|
continue;
|
|
533
532
|
}
|
|
534
533
|
|
|
535
|
-
const result =
|
|
534
|
+
const result = GoogleLanguageModel.convertGenerateContentResponse({
|
|
535
|
+
config: this.batchConfig,
|
|
536
536
|
response: response.value,
|
|
537
537
|
warnings: [],
|
|
538
538
|
providerOptionsNames: ['google'],
|
|
@@ -543,6 +543,7 @@ export class GoogleBatchLanguageModel
|
|
|
543
543
|
|
|
544
544
|
if (unsupportedPart != null) {
|
|
545
545
|
yield {
|
|
546
|
+
type: 'text',
|
|
546
547
|
id: line.key,
|
|
547
548
|
status: 'failed',
|
|
548
549
|
error: {
|
|
@@ -555,7 +556,7 @@ export class GoogleBatchLanguageModel
|
|
|
555
556
|
continue;
|
|
556
557
|
}
|
|
557
558
|
|
|
558
|
-
yield { id: line.key, status: 'succeeded', result };
|
|
559
|
+
yield { type: 'text', id: line.key, status: 'succeeded', result };
|
|
559
560
|
}
|
|
560
561
|
}
|
|
561
562
|
|
|
@@ -680,3 +681,28 @@ const googleUploadUrlResponseHandler: ResponseHandler<string> = async ({
|
|
|
680
681
|
|
|
681
682
|
return { value: uploadUrl };
|
|
682
683
|
};
|
|
684
|
+
|
|
685
|
+
function getGoogleBatchModelId(
|
|
686
|
+
requests: readonly GoogleBatchRequest[],
|
|
687
|
+
): GoogleModelId {
|
|
688
|
+
const modelId = requests[0]?.modelId;
|
|
689
|
+
|
|
690
|
+
if (modelId == null) {
|
|
691
|
+
throw new InvalidArgumentError({
|
|
692
|
+
argument: 'requests',
|
|
693
|
+
message: 'Google batches require at least one request.',
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
for (const request of requests) {
|
|
698
|
+
if (request.modelId !== modelId) {
|
|
699
|
+
throw new InvalidArgumentError({
|
|
700
|
+
argument: 'requests',
|
|
701
|
+
message:
|
|
702
|
+
'Google batches require every request to use the same model because the model is part of the batch endpoint.',
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return modelId;
|
|
708
|
+
}
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
} from '@ai-sdk/provider';
|
|
14
14
|
import {
|
|
15
15
|
combineHeaders,
|
|
16
|
+
createToolNameMapping,
|
|
16
17
|
createEventSourceResponseHandler,
|
|
17
18
|
createJsonResponseHandler,
|
|
18
19
|
generateId,
|
|
@@ -113,8 +114,10 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
113
114
|
return this.config.supportedUrls?.() ?? {};
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
static async prepareRequest({
|
|
118
|
+
modelId,
|
|
119
|
+
config,
|
|
120
|
+
options: {
|
|
118
121
|
prompt,
|
|
119
122
|
maxOutputTokens,
|
|
120
123
|
temperature,
|
|
@@ -129,19 +132,25 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
129
132
|
toolChoice,
|
|
130
133
|
reasoning,
|
|
131
134
|
providerOptions,
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
},
|
|
136
|
+
isStreaming = false,
|
|
137
|
+
}: {
|
|
138
|
+
modelId: GoogleModelId;
|
|
139
|
+
config: GoogleLanguageModelConfig;
|
|
140
|
+
options: LanguageModelV4CallOptions;
|
|
141
|
+
isStreaming?: boolean;
|
|
142
|
+
}) {
|
|
135
143
|
const warnings: SharedV4Warning[] = [];
|
|
136
144
|
|
|
137
145
|
// Names to look up in providerOptions and to write into providerMetadata.
|
|
138
146
|
// For the Vertex provider we read both the new `googleVertex` key and the
|
|
139
147
|
// legacy `vertex` key (new takes precedence) and write under both for
|
|
140
148
|
// backward compatibility. For other Google providers we use just `google`.
|
|
141
|
-
const providerOptionsNames: readonly string[] =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
const providerOptionsNames: readonly string[] = config.provider.includes(
|
|
150
|
+
'vertex',
|
|
151
|
+
)
|
|
152
|
+
? (['googleVertex', 'vertex'] as const)
|
|
153
|
+
: (['google'] as const);
|
|
145
154
|
|
|
146
155
|
let googleOptions: GoogleLanguageModelOptions | undefined;
|
|
147
156
|
for (const name of providerOptionsNames) {
|
|
@@ -164,7 +173,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
// Add warning if Vertex rag tools are used with a non-Vertex Google provider
|
|
167
|
-
const isVertexProvider =
|
|
176
|
+
const isVertexProvider = config.provider.startsWith('google.vertex.');
|
|
168
177
|
|
|
169
178
|
if (
|
|
170
179
|
tools?.some(
|
|
@@ -178,7 +187,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
178
187
|
message:
|
|
179
188
|
"The 'vertex_rag_store' tool is only supported with the Google Vertex provider " +
|
|
180
189
|
'and might not be supported or could behave unexpectedly with the current Google provider ' +
|
|
181
|
-
`(${
|
|
190
|
+
`(${config.provider}).`,
|
|
182
191
|
});
|
|
183
192
|
}
|
|
184
193
|
|
|
@@ -188,7 +197,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
188
197
|
message:
|
|
189
198
|
"'streamFunctionCallArguments' is only supported on the Vertex AI API " +
|
|
190
199
|
'and will be ignored with the current Google provider ' +
|
|
191
|
-
`(${
|
|
200
|
+
`(${config.provider}). See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#streaming-fc`,
|
|
192
201
|
});
|
|
193
202
|
}
|
|
194
203
|
|
|
@@ -209,7 +218,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
209
218
|
type: 'other',
|
|
210
219
|
message:
|
|
211
220
|
"'sharedRequestType' and 'requestType' are Vertex AI options and " +
|
|
212
|
-
`are ignored with the current Google provider (${
|
|
221
|
+
`are ignored with the current Google provider (${config.provider}).`,
|
|
213
222
|
});
|
|
214
223
|
}
|
|
215
224
|
|
|
@@ -253,15 +262,15 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
253
262
|
message:
|
|
254
263
|
`${droppedImageConfigFields.join(', ')} ` +
|
|
255
264
|
`${droppedImageConfigFields.length === 1 ? 'is a Vertex AI option and is' : 'are Vertex AI options and are'} ` +
|
|
256
|
-
`ignored with the current Google provider (${
|
|
265
|
+
`ignored with the current Google provider (${config.provider}).`,
|
|
257
266
|
});
|
|
258
267
|
imageConfig = geminiApiImageConfig;
|
|
259
268
|
}
|
|
260
269
|
}
|
|
261
270
|
|
|
262
|
-
const isGemmaModel =
|
|
271
|
+
const isGemmaModel = modelId.toLowerCase().startsWith('gemma-');
|
|
263
272
|
const isGemini25DeveloperApiModel =
|
|
264
|
-
!isVertexProvider && gemini25ModelPattern.test(
|
|
273
|
+
!isVertexProvider && gemini25ModelPattern.test(modelId);
|
|
265
274
|
|
|
266
275
|
if (isGemini25DeveloperApiModel && frequencyPenalty != null) {
|
|
267
276
|
warnings.push({
|
|
@@ -276,7 +285,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
276
285
|
});
|
|
277
286
|
}
|
|
278
287
|
|
|
279
|
-
const { usesGemini3Features } = getGoogleModelCapabilities(
|
|
288
|
+
const { usesGemini3Features } = getGoogleModelCapabilities(modelId);
|
|
280
289
|
|
|
281
290
|
const { contents, systemInstruction } = convertToGoogleMessages(prompt, {
|
|
282
291
|
isGemmaModel,
|
|
@@ -294,13 +303,19 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
294
303
|
} = prepareTools({
|
|
295
304
|
tools,
|
|
296
305
|
toolChoice,
|
|
297
|
-
modelId
|
|
306
|
+
modelId,
|
|
298
307
|
isVertexProvider,
|
|
299
308
|
});
|
|
309
|
+
const toolNameMapping = createToolNameMapping({
|
|
310
|
+
tools,
|
|
311
|
+
providerToolNames: {
|
|
312
|
+
'google.code_execution': 'code_execution',
|
|
313
|
+
},
|
|
314
|
+
});
|
|
300
315
|
|
|
301
316
|
const resolvedThinking = resolveThinkingConfig({
|
|
302
317
|
reasoning,
|
|
303
|
-
modelId
|
|
318
|
+
modelId,
|
|
304
319
|
warnings,
|
|
305
320
|
});
|
|
306
321
|
const thinkingConfig =
|
|
@@ -394,17 +409,34 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
394
409
|
warnings: [...warnings, ...toolWarnings],
|
|
395
410
|
providerOptionsNames,
|
|
396
411
|
extraHeaders: vertexPaygoHeaders,
|
|
412
|
+
toolNameMapping,
|
|
397
413
|
};
|
|
398
414
|
}
|
|
399
415
|
|
|
400
|
-
|
|
416
|
+
private getArgs(
|
|
417
|
+
options: LanguageModelV4CallOptions,
|
|
418
|
+
{ isStreaming = false }: { isStreaming?: boolean } = {},
|
|
419
|
+
) {
|
|
420
|
+
return GoogleLanguageModel.prepareRequest({
|
|
421
|
+
modelId: this.modelId,
|
|
422
|
+
config: this.config,
|
|
423
|
+
options,
|
|
424
|
+
isStreaming,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
static convertGenerateContentResponse({
|
|
429
|
+
config,
|
|
401
430
|
response,
|
|
402
431
|
warnings,
|
|
403
432
|
providerOptionsNames,
|
|
433
|
+
toolNameMapping,
|
|
404
434
|
}: {
|
|
435
|
+
config: GoogleLanguageModelConfig;
|
|
405
436
|
response: InferSchema<typeof responseSchema>;
|
|
406
437
|
warnings: SharedV4Warning[];
|
|
407
438
|
providerOptionsNames: readonly string[];
|
|
439
|
+
toolNameMapping?: ReturnType<typeof createToolNameMapping>;
|
|
408
440
|
}): LanguageModelV4GenerateResult {
|
|
409
441
|
const wrapProviderMetadata = (payload: Record<string, unknown>) =>
|
|
410
442
|
Object.fromEntries(
|
|
@@ -431,13 +463,15 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
431
463
|
// Build content array from all parts
|
|
432
464
|
for (const part of parts) {
|
|
433
465
|
if ('executableCode' in part && part.executableCode?.code) {
|
|
434
|
-
const toolCallId =
|
|
466
|
+
const toolCallId = config.generateId();
|
|
435
467
|
lastCodeExecutionToolCallId = toolCallId;
|
|
436
468
|
|
|
437
469
|
content.push({
|
|
438
470
|
type: 'tool-call',
|
|
439
471
|
toolCallId,
|
|
440
|
-
toolName:
|
|
472
|
+
toolName:
|
|
473
|
+
toolNameMapping?.toCustomToolName('code_execution') ??
|
|
474
|
+
'code_execution',
|
|
441
475
|
input: JSON.stringify(part.executableCode),
|
|
442
476
|
providerExecuted: true,
|
|
443
477
|
});
|
|
@@ -446,7 +480,9 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
446
480
|
type: 'tool-result',
|
|
447
481
|
// Results correspond to the most recent executable code part.
|
|
448
482
|
toolCallId: lastCodeExecutionToolCallId!,
|
|
449
|
-
toolName:
|
|
483
|
+
toolName:
|
|
484
|
+
toolNameMapping?.toCustomToolName('code_execution') ??
|
|
485
|
+
'code_execution',
|
|
450
486
|
result: {
|
|
451
487
|
outcome: part.codeExecutionResult.outcome,
|
|
452
488
|
output: part.codeExecutionResult.output ?? '',
|
|
@@ -474,7 +510,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
474
510
|
} else if ('functionCall' in part && part.functionCall.name != null) {
|
|
475
511
|
content.push({
|
|
476
512
|
type: 'tool-call' as const,
|
|
477
|
-
toolCallId: part.functionCall.id ||
|
|
513
|
+
toolCallId: part.functionCall.id || config.generateId(),
|
|
478
514
|
toolName: part.functionCall.name,
|
|
479
515
|
input: JSON.stringify(part.functionCall.args ?? {}),
|
|
480
516
|
providerMetadata: part.thoughtSignature
|
|
@@ -497,7 +533,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
497
533
|
: undefined,
|
|
498
534
|
});
|
|
499
535
|
} else if ('toolCall' in part && part.toolCall) {
|
|
500
|
-
const toolCallId = part.toolCall.id ||
|
|
536
|
+
const toolCallId = part.toolCall.id || config.generateId();
|
|
501
537
|
lastServerToolCallId = toolCallId;
|
|
502
538
|
content.push({
|
|
503
539
|
type: 'tool-call',
|
|
@@ -519,9 +555,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
519
555
|
});
|
|
520
556
|
} else if ('toolResponse' in part && part.toolResponse) {
|
|
521
557
|
const responseToolCallId =
|
|
522
|
-
lastServerToolCallId ||
|
|
523
|
-
part.toolResponse.id ||
|
|
524
|
-
this.config.generateId();
|
|
558
|
+
lastServerToolCallId || part.toolResponse.id || config.generateId();
|
|
525
559
|
content.push({
|
|
526
560
|
type: 'tool-result',
|
|
527
561
|
toolCallId: responseToolCallId,
|
|
@@ -545,7 +579,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
545
579
|
const sources =
|
|
546
580
|
extractSources({
|
|
547
581
|
groundingMetadata: candidate?.groundingMetadata,
|
|
548
|
-
generateId:
|
|
582
|
+
generateId: config.generateId,
|
|
549
583
|
}) ?? [];
|
|
550
584
|
for (const source of sources) {
|
|
551
585
|
content.push(source);
|
|
@@ -586,8 +620,13 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
586
620
|
async doGenerate(
|
|
587
621
|
options: LanguageModelV4CallOptions,
|
|
588
622
|
): Promise<LanguageModelV4GenerateResult> {
|
|
589
|
-
const {
|
|
590
|
-
|
|
623
|
+
const {
|
|
624
|
+
args,
|
|
625
|
+
warnings,
|
|
626
|
+
providerOptionsNames,
|
|
627
|
+
extraHeaders,
|
|
628
|
+
toolNameMapping,
|
|
629
|
+
} = await this.getArgs(options);
|
|
591
630
|
|
|
592
631
|
const mergedHeaders = combineHeaders(
|
|
593
632
|
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
@@ -611,10 +650,12 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
611
650
|
fetch: this.config.fetch,
|
|
612
651
|
});
|
|
613
652
|
|
|
614
|
-
const result =
|
|
653
|
+
const result = GoogleLanguageModel.convertGenerateContentResponse({
|
|
654
|
+
config: this.config,
|
|
615
655
|
response,
|
|
616
656
|
warnings,
|
|
617
657
|
providerOptionsNames,
|
|
658
|
+
toolNameMapping,
|
|
618
659
|
});
|
|
619
660
|
|
|
620
661
|
return {
|
|
@@ -631,8 +672,13 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
631
672
|
async doStream(
|
|
632
673
|
options: LanguageModelV4CallOptions,
|
|
633
674
|
): Promise<LanguageModelV4StreamResult> {
|
|
634
|
-
const {
|
|
635
|
-
|
|
675
|
+
const {
|
|
676
|
+
args,
|
|
677
|
+
warnings,
|
|
678
|
+
providerOptionsNames,
|
|
679
|
+
extraHeaders,
|
|
680
|
+
toolNameMapping,
|
|
681
|
+
} = await this.getArgs(options, { isStreaming: true });
|
|
636
682
|
const wrapProviderMetadata = (payload: Record<string, unknown>) =>
|
|
637
683
|
Object.fromEntries(
|
|
638
684
|
providerOptionsNames.map(name => [name, payload]),
|
|
@@ -820,7 +866,8 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
820
866
|
controller.enqueue({
|
|
821
867
|
type: 'tool-call',
|
|
822
868
|
toolCallId,
|
|
823
|
-
toolName:
|
|
869
|
+
toolName:
|
|
870
|
+
toolNameMapping.toCustomToolName('code_execution'),
|
|
824
871
|
input: JSON.stringify(part.executableCode),
|
|
825
872
|
providerExecuted: true,
|
|
826
873
|
});
|
|
@@ -835,7 +882,8 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
835
882
|
controller.enqueue({
|
|
836
883
|
type: 'tool-result',
|
|
837
884
|
toolCallId,
|
|
838
|
-
toolName:
|
|
885
|
+
toolName:
|
|
886
|
+
toolNameMapping.toCustomToolName('code_execution'),
|
|
839
887
|
result: {
|
|
840
888
|
outcome: part.codeExecutionResult.outcome,
|
|
841
889
|
output: part.codeExecutionResult.output ?? '',
|