@ai-sdk/google 4.0.64 → 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 +13 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +152 -106
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +7 -2
- package/dist/internal/index.js +51 -34
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +37 -13
- package/package.json +3 -3
- package/src/google-batch.ts +61 -35
- package/src/google-image-model.ts +3 -0
- package/src/google-language-model.ts +49 -28
- 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",
|
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
|
+
}
|
|
@@ -114,8 +114,10 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
114
114
|
return this.config.supportedUrls?.() ?? {};
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
static async prepareRequest({
|
|
118
|
+
modelId,
|
|
119
|
+
config,
|
|
120
|
+
options: {
|
|
119
121
|
prompt,
|
|
120
122
|
maxOutputTokens,
|
|
121
123
|
temperature,
|
|
@@ -130,19 +132,25 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
130
132
|
toolChoice,
|
|
131
133
|
reasoning,
|
|
132
134
|
providerOptions,
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
},
|
|
136
|
+
isStreaming = false,
|
|
137
|
+
}: {
|
|
138
|
+
modelId: GoogleModelId;
|
|
139
|
+
config: GoogleLanguageModelConfig;
|
|
140
|
+
options: LanguageModelV4CallOptions;
|
|
141
|
+
isStreaming?: boolean;
|
|
142
|
+
}) {
|
|
136
143
|
const warnings: SharedV4Warning[] = [];
|
|
137
144
|
|
|
138
145
|
// Names to look up in providerOptions and to write into providerMetadata.
|
|
139
146
|
// For the Vertex provider we read both the new `googleVertex` key and the
|
|
140
147
|
// legacy `vertex` key (new takes precedence) and write under both for
|
|
141
148
|
// backward compatibility. For other Google providers we use just `google`.
|
|
142
|
-
const providerOptionsNames: readonly string[] =
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
const providerOptionsNames: readonly string[] = config.provider.includes(
|
|
150
|
+
'vertex',
|
|
151
|
+
)
|
|
152
|
+
? (['googleVertex', 'vertex'] as const)
|
|
153
|
+
: (['google'] as const);
|
|
146
154
|
|
|
147
155
|
let googleOptions: GoogleLanguageModelOptions | undefined;
|
|
148
156
|
for (const name of providerOptionsNames) {
|
|
@@ -165,7 +173,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
// Add warning if Vertex rag tools are used with a non-Vertex Google provider
|
|
168
|
-
const isVertexProvider =
|
|
176
|
+
const isVertexProvider = config.provider.startsWith('google.vertex.');
|
|
169
177
|
|
|
170
178
|
if (
|
|
171
179
|
tools?.some(
|
|
@@ -179,7 +187,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
179
187
|
message:
|
|
180
188
|
"The 'vertex_rag_store' tool is only supported with the Google Vertex provider " +
|
|
181
189
|
'and might not be supported or could behave unexpectedly with the current Google provider ' +
|
|
182
|
-
`(${
|
|
190
|
+
`(${config.provider}).`,
|
|
183
191
|
});
|
|
184
192
|
}
|
|
185
193
|
|
|
@@ -189,7 +197,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
189
197
|
message:
|
|
190
198
|
"'streamFunctionCallArguments' is only supported on the Vertex AI API " +
|
|
191
199
|
'and will be ignored with the current Google provider ' +
|
|
192
|
-
`(${
|
|
200
|
+
`(${config.provider}). See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#streaming-fc`,
|
|
193
201
|
});
|
|
194
202
|
}
|
|
195
203
|
|
|
@@ -210,7 +218,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
210
218
|
type: 'other',
|
|
211
219
|
message:
|
|
212
220
|
"'sharedRequestType' and 'requestType' are Vertex AI options and " +
|
|
213
|
-
`are ignored with the current Google provider (${
|
|
221
|
+
`are ignored with the current Google provider (${config.provider}).`,
|
|
214
222
|
});
|
|
215
223
|
}
|
|
216
224
|
|
|
@@ -254,15 +262,15 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
254
262
|
message:
|
|
255
263
|
`${droppedImageConfigFields.join(', ')} ` +
|
|
256
264
|
`${droppedImageConfigFields.length === 1 ? 'is a Vertex AI option and is' : 'are Vertex AI options and are'} ` +
|
|
257
|
-
`ignored with the current Google provider (${
|
|
265
|
+
`ignored with the current Google provider (${config.provider}).`,
|
|
258
266
|
});
|
|
259
267
|
imageConfig = geminiApiImageConfig;
|
|
260
268
|
}
|
|
261
269
|
}
|
|
262
270
|
|
|
263
|
-
const isGemmaModel =
|
|
271
|
+
const isGemmaModel = modelId.toLowerCase().startsWith('gemma-');
|
|
264
272
|
const isGemini25DeveloperApiModel =
|
|
265
|
-
!isVertexProvider && gemini25ModelPattern.test(
|
|
273
|
+
!isVertexProvider && gemini25ModelPattern.test(modelId);
|
|
266
274
|
|
|
267
275
|
if (isGemini25DeveloperApiModel && frequencyPenalty != null) {
|
|
268
276
|
warnings.push({
|
|
@@ -277,7 +285,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
277
285
|
});
|
|
278
286
|
}
|
|
279
287
|
|
|
280
|
-
const { usesGemini3Features } = getGoogleModelCapabilities(
|
|
288
|
+
const { usesGemini3Features } = getGoogleModelCapabilities(modelId);
|
|
281
289
|
|
|
282
290
|
const { contents, systemInstruction } = convertToGoogleMessages(prompt, {
|
|
283
291
|
isGemmaModel,
|
|
@@ -295,7 +303,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
295
303
|
} = prepareTools({
|
|
296
304
|
tools,
|
|
297
305
|
toolChoice,
|
|
298
|
-
modelId
|
|
306
|
+
modelId,
|
|
299
307
|
isVertexProvider,
|
|
300
308
|
});
|
|
301
309
|
const toolNameMapping = createToolNameMapping({
|
|
@@ -307,7 +315,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
307
315
|
|
|
308
316
|
const resolvedThinking = resolveThinkingConfig({
|
|
309
317
|
reasoning,
|
|
310
|
-
modelId
|
|
318
|
+
modelId,
|
|
311
319
|
warnings,
|
|
312
320
|
});
|
|
313
321
|
const thinkingConfig =
|
|
@@ -405,12 +413,26 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
405
413
|
};
|
|
406
414
|
}
|
|
407
415
|
|
|
408
|
-
|
|
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,
|
|
409
430
|
response,
|
|
410
431
|
warnings,
|
|
411
432
|
providerOptionsNames,
|
|
412
433
|
toolNameMapping,
|
|
413
434
|
}: {
|
|
435
|
+
config: GoogleLanguageModelConfig;
|
|
414
436
|
response: InferSchema<typeof responseSchema>;
|
|
415
437
|
warnings: SharedV4Warning[];
|
|
416
438
|
providerOptionsNames: readonly string[];
|
|
@@ -441,7 +463,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
441
463
|
// Build content array from all parts
|
|
442
464
|
for (const part of parts) {
|
|
443
465
|
if ('executableCode' in part && part.executableCode?.code) {
|
|
444
|
-
const toolCallId =
|
|
466
|
+
const toolCallId = config.generateId();
|
|
445
467
|
lastCodeExecutionToolCallId = toolCallId;
|
|
446
468
|
|
|
447
469
|
content.push({
|
|
@@ -488,7 +510,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
488
510
|
} else if ('functionCall' in part && part.functionCall.name != null) {
|
|
489
511
|
content.push({
|
|
490
512
|
type: 'tool-call' as const,
|
|
491
|
-
toolCallId: part.functionCall.id ||
|
|
513
|
+
toolCallId: part.functionCall.id || config.generateId(),
|
|
492
514
|
toolName: part.functionCall.name,
|
|
493
515
|
input: JSON.stringify(part.functionCall.args ?? {}),
|
|
494
516
|
providerMetadata: part.thoughtSignature
|
|
@@ -511,7 +533,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
511
533
|
: undefined,
|
|
512
534
|
});
|
|
513
535
|
} else if ('toolCall' in part && part.toolCall) {
|
|
514
|
-
const toolCallId = part.toolCall.id ||
|
|
536
|
+
const toolCallId = part.toolCall.id || config.generateId();
|
|
515
537
|
lastServerToolCallId = toolCallId;
|
|
516
538
|
content.push({
|
|
517
539
|
type: 'tool-call',
|
|
@@ -533,9 +555,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
533
555
|
});
|
|
534
556
|
} else if ('toolResponse' in part && part.toolResponse) {
|
|
535
557
|
const responseToolCallId =
|
|
536
|
-
lastServerToolCallId ||
|
|
537
|
-
part.toolResponse.id ||
|
|
538
|
-
this.config.generateId();
|
|
558
|
+
lastServerToolCallId || part.toolResponse.id || config.generateId();
|
|
539
559
|
content.push({
|
|
540
560
|
type: 'tool-result',
|
|
541
561
|
toolCallId: responseToolCallId,
|
|
@@ -559,7 +579,7 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
559
579
|
const sources =
|
|
560
580
|
extractSources({
|
|
561
581
|
groundingMetadata: candidate?.groundingMetadata,
|
|
562
|
-
generateId:
|
|
582
|
+
generateId: config.generateId,
|
|
563
583
|
}) ?? [];
|
|
564
584
|
for (const source of sources) {
|
|
565
585
|
content.push(source);
|
|
@@ -630,7 +650,8 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
630
650
|
fetch: this.config.fetch,
|
|
631
651
|
});
|
|
632
652
|
|
|
633
|
-
const result =
|
|
653
|
+
const result = GoogleLanguageModel.convertGenerateContentResponse({
|
|
654
|
+
config: this.config,
|
|
634
655
|
response,
|
|
635
656
|
warnings,
|
|
636
657
|
providerOptionsNames,
|
package/src/google-provider.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
EmbeddingModelV4,
|
|
3
|
-
|
|
3
|
+
Experimental_BatchV4 as BatchV4,
|
|
4
4
|
Experimental_VideoModelV4,
|
|
5
5
|
FilesV4,
|
|
6
6
|
ImageModelV4,
|
|
@@ -23,7 +23,8 @@ import {
|
|
|
23
23
|
import { VERSION } from './version';
|
|
24
24
|
import { GoogleEmbeddingModel } from './google-embedding-model';
|
|
25
25
|
import type { GoogleEmbeddingModelId } from './google-embedding-model-options';
|
|
26
|
-
import {
|
|
26
|
+
import { GoogleBatch } from './google-batch';
|
|
27
|
+
import { GoogleLanguageModel } from './google-language-model';
|
|
27
28
|
import type { GoogleModelId } from './google-language-model-options';
|
|
28
29
|
import { googleTools } from './google-tools';
|
|
29
30
|
|
|
@@ -54,11 +55,13 @@ const googleFilesUrlPattern =
|
|
|
54
55
|
/^https:\/\/generativelanguage\.googleapis\.com\/v1beta\/files\/.*$/;
|
|
55
56
|
|
|
56
57
|
export interface GoogleProvider extends ProviderV4 {
|
|
57
|
-
(modelId: GoogleModelId):
|
|
58
|
+
(modelId: GoogleModelId): LanguageModelV4;
|
|
58
59
|
|
|
59
|
-
languageModel(modelId: GoogleModelId):
|
|
60
|
+
languageModel(modelId: GoogleModelId): LanguageModelV4;
|
|
60
61
|
|
|
61
|
-
chat(modelId: GoogleModelId):
|
|
62
|
+
chat(modelId: GoogleModelId): LanguageModelV4;
|
|
63
|
+
|
|
64
|
+
experimental_batch(): BatchV4<{ text: GoogleModelId }>;
|
|
62
65
|
|
|
63
66
|
/**
|
|
64
67
|
* Creates a model for image generation.
|
|
@@ -71,7 +74,7 @@ export interface GoogleProvider extends ProviderV4 {
|
|
|
71
74
|
/**
|
|
72
75
|
* @deprecated Use `chat()` instead.
|
|
73
76
|
*/
|
|
74
|
-
generativeAI(modelId: GoogleModelId):
|
|
77
|
+
generativeAI(modelId: GoogleModelId): LanguageModelV4;
|
|
75
78
|
|
|
76
79
|
/**
|
|
77
80
|
* Creates a model for text embeddings.
|
|
@@ -258,35 +261,49 @@ export function createGoogle(
|
|
|
258
261
|
`ai-sdk/google/${VERSION}`,
|
|
259
262
|
);
|
|
260
263
|
|
|
264
|
+
const getSupportedUrls = (
|
|
265
|
+
modelId?: GoogleModelId,
|
|
266
|
+
includeExternalUrls = modelId == null || supportsExternalFileUrls(modelId),
|
|
267
|
+
) => ({
|
|
268
|
+
'*': [
|
|
269
|
+
googleFilesUrlPattern,
|
|
270
|
+
new RegExp(`^${baseURL}/files/.*$`),
|
|
271
|
+
new RegExp(
|
|
272
|
+
`^https://(?:www\\.)?youtube\\.com/watch\\?v=[\\w-]+(?:&[\\w=&.-]*)?$`,
|
|
273
|
+
),
|
|
274
|
+
new RegExp(`^https://youtu\\.be/[\\w-]+(?:\\?[\\w=&.-]*)?$`),
|
|
275
|
+
],
|
|
276
|
+
...(includeExternalUrls
|
|
277
|
+
? Object.fromEntries(
|
|
278
|
+
supportedExternalUrlMediaTypes.map(mediaType => [
|
|
279
|
+
mediaType,
|
|
280
|
+
[externalHttpsUrlPattern],
|
|
281
|
+
]),
|
|
282
|
+
)
|
|
283
|
+
: {}),
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const languageModelConfig = {
|
|
287
|
+
provider: providerName,
|
|
288
|
+
baseURL,
|
|
289
|
+
headers: getHeaders,
|
|
290
|
+
generateId: options.generateId ?? generateId,
|
|
291
|
+
fetch: options.fetch,
|
|
292
|
+
};
|
|
293
|
+
|
|
261
294
|
const createChatModel = (modelId: GoogleModelId) =>
|
|
262
|
-
new
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// YouTube URLs (public or unlisted videos)
|
|
275
|
-
new RegExp(
|
|
276
|
-
`^https://(?:www\\.)?youtube\\.com/watch\\?v=[\\w-]+(?:&[\\w=&.-]*)?$`,
|
|
277
|
-
),
|
|
278
|
-
new RegExp(`^https://youtu\\.be/[\\w-]+(?:\\?[\\w=&.-]*)?$`),
|
|
279
|
-
],
|
|
280
|
-
...(supportsExternalFileUrls(modelId)
|
|
281
|
-
? Object.fromEntries(
|
|
282
|
-
supportedExternalUrlMediaTypes.map(mediaType => [
|
|
283
|
-
mediaType,
|
|
284
|
-
[externalHttpsUrlPattern],
|
|
285
|
-
]),
|
|
286
|
-
)
|
|
287
|
-
: {}),
|
|
288
|
-
}),
|
|
289
|
-
fetch: options.fetch,
|
|
295
|
+
new GoogleLanguageModel(modelId, {
|
|
296
|
+
...languageModelConfig,
|
|
297
|
+
supportedUrls: () => getSupportedUrls(modelId),
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const createBatch = () =>
|
|
301
|
+
new GoogleBatch({
|
|
302
|
+
provider: `${providerName.replace(/\.generative-ai$/, '')}.batch`,
|
|
303
|
+
config: languageModelConfig,
|
|
304
|
+
// Batch prompt conversion happens before the model is available to the
|
|
305
|
+
// provider. Only advertise URL support shared by every batch model.
|
|
306
|
+
supportedUrls: getSupportedUrls(undefined, false),
|
|
290
307
|
});
|
|
291
308
|
|
|
292
309
|
const createEmbeddingModel = (modelId: GoogleEmbeddingModelId) =>
|
|
@@ -410,6 +427,7 @@ export function createGoogle(
|
|
|
410
427
|
provider.languageModel = createChatModel;
|
|
411
428
|
provider.chat = createChatModel;
|
|
412
429
|
provider.generativeAI = createChatModel;
|
|
430
|
+
provider.experimental_batch = createBatch;
|
|
413
431
|
provider.embedding = createEmbeddingModel;
|
|
414
432
|
provider.embeddingModel = createEmbeddingModel;
|
|
415
433
|
provider.textEmbedding = createEmbeddingModel;
|