@ai-sdk/google 4.0.62 → 4.0.64
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 +15 -0
- package/dist/index.d.ts +32 -3
- package/dist/index.js +277 -106
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +6 -4
- package/dist/internal/index.js +195 -32
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +135 -30
- package/package.json +1 -1
- package/src/convert-json-schema-to-openapi-schema.ts +10 -0
- package/src/google-batch.ts +82 -70
- package/src/google-language-model-options.ts +1 -0
- package/src/google-language-model.ts +35 -8
- package/src/index.ts +1 -0
- package/src/interactions/build-google-interactions-stream-transform.ts +52 -1
- package/src/interactions/convert-to-google-interactions-input.ts +99 -0
- package/src/interactions/google-interactions-api.ts +18 -0
- package/src/interactions/google-interactions-language-model-options.ts +24 -0
- package/src/interactions/google-interactions-prompt.ts +31 -0
- package/src/interactions/google-interactions-provider-metadata.ts +12 -0
- package/src/interactions/parse-google-interactions-outputs.ts +44 -0
package/docs/15-google.mdx
CHANGED
|
@@ -68,11 +68,11 @@ You can use the following optional settings to customize the Google provider ins
|
|
|
68
68
|
## Language Models
|
|
69
69
|
|
|
70
70
|
You can create models that call the [Google Generative AI API](https://ai.google.dev/api/rest) using the provider instance.
|
|
71
|
-
The first argument is the model id, e.g. `gemini-3.
|
|
71
|
+
The first argument is the model id, e.g. `gemini-3.8-flash`.
|
|
72
72
|
The models support tool calls and some have multi-modal capabilities.
|
|
73
73
|
|
|
74
74
|
```ts
|
|
75
|
-
const model = google('gemini-3.
|
|
75
|
+
const model = google('gemini-3.8-flash');
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
You can use Google language models to generate text with the `generateText` function:
|
|
@@ -82,7 +82,7 @@ import { google } from '@ai-sdk/google';
|
|
|
82
82
|
import { generateText } from 'ai';
|
|
83
83
|
|
|
84
84
|
const { text } = await generateText({
|
|
85
|
-
model: google('gemini-3.
|
|
85
|
+
model: google('gemini-3.8-flash'),
|
|
86
86
|
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
|
|
87
87
|
});
|
|
88
88
|
```
|
|
@@ -107,7 +107,7 @@ You can pass them as an options argument:
|
|
|
107
107
|
```ts
|
|
108
108
|
import { google, type GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
109
109
|
|
|
110
|
-
const model = google('gemini-3.
|
|
110
|
+
const model = google('gemini-3.8-flash');
|
|
111
111
|
|
|
112
112
|
await generateText({
|
|
113
113
|
model,
|
|
@@ -262,7 +262,7 @@ For Gemini 3 and later models, use the `thinkingLevel` parameter to control the
|
|
|
262
262
|
import { google, GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
263
263
|
import { generateText } from 'ai';
|
|
264
264
|
|
|
265
|
-
const model = google('gemini-3.
|
|
265
|
+
const model = google('gemini-3.8-flash');
|
|
266
266
|
|
|
267
267
|
const { text, reasoning } = await generateText({
|
|
268
268
|
model: model,
|
|
@@ -319,7 +319,7 @@ import { google } from '@ai-sdk/google';
|
|
|
319
319
|
import { generateText } from 'ai';
|
|
320
320
|
|
|
321
321
|
const result = await generateText({
|
|
322
|
-
model: google('gemini-3.
|
|
322
|
+
model: google('gemini-3.8-flash'),
|
|
323
323
|
messages: [
|
|
324
324
|
{
|
|
325
325
|
role: 'user',
|
|
@@ -346,7 +346,7 @@ import { google } from '@ai-sdk/google';
|
|
|
346
346
|
import { generateText } from 'ai';
|
|
347
347
|
|
|
348
348
|
const result = await generateText({
|
|
349
|
-
model: google('gemini-3.
|
|
349
|
+
model: google('gemini-3.8-flash'),
|
|
350
350
|
messages: [
|
|
351
351
|
{
|
|
352
352
|
role: 'user',
|
|
@@ -401,13 +401,13 @@ const baseContext =
|
|
|
401
401
|
'You are a cooking assistant with expertise in Italian cuisine. Here are 1000 lasagna recipes for reference...';
|
|
402
402
|
|
|
403
403
|
const { text: veggieLasagna } = await generateText({
|
|
404
|
-
model: google('gemini-3.
|
|
404
|
+
model: google('gemini-3.8-flash'),
|
|
405
405
|
prompt: `${baseContext}\n\nWrite a vegetarian lasagna recipe for 4 people.`,
|
|
406
406
|
});
|
|
407
407
|
|
|
408
408
|
// Second request with same prefix - eligible for cache hit
|
|
409
409
|
const { text: meatLasagna, providerMetadata } = await generateText({
|
|
410
|
-
model: google('gemini-3.
|
|
410
|
+
model: google('gemini-3.8-flash'),
|
|
411
411
|
prompt: `${baseContext}\n\nWrite a meat lasagna recipe for 12 people.`,
|
|
412
412
|
});
|
|
413
413
|
|
|
@@ -446,7 +446,7 @@ const ai = new GoogleGenAI({
|
|
|
446
446
|
apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
|
|
447
447
|
});
|
|
448
448
|
|
|
449
|
-
const model = 'gemini-3.
|
|
449
|
+
const model = 'gemini-3.8-flash';
|
|
450
450
|
|
|
451
451
|
// Create a cache with the content you want to reuse
|
|
452
452
|
const cache = await ai.caches.create({
|
|
@@ -495,7 +495,7 @@ import { googleTools } from '@ai-sdk/google/internal';
|
|
|
495
495
|
import { generateText } from 'ai';
|
|
496
496
|
|
|
497
497
|
const { text, toolCalls, toolResults } = await generateText({
|
|
498
|
-
model: google('gemini-3.
|
|
498
|
+
model: google('gemini-3.8-flash'),
|
|
499
499
|
tools: { code_execution: google.tools.codeExecution({}) },
|
|
500
500
|
prompt: 'Use python to calculate the 20th fibonacci number.',
|
|
501
501
|
});
|
|
@@ -514,7 +514,7 @@ import { GoogleProviderMetadata } from '@ai-sdk/google';
|
|
|
514
514
|
import { generateText } from 'ai';
|
|
515
515
|
|
|
516
516
|
const { text, sources, providerMetadata } = await generateText({
|
|
517
|
-
model: google('gemini-3.
|
|
517
|
+
model: google('gemini-3.8-flash'),
|
|
518
518
|
tools: {
|
|
519
519
|
google_search: google.tools.googleSearch({}),
|
|
520
520
|
},
|
|
@@ -622,7 +622,7 @@ const vertex = createGoogleVertex({
|
|
|
622
622
|
});
|
|
623
623
|
|
|
624
624
|
const { text, sources, providerMetadata } = await generateText({
|
|
625
|
-
model: vertex('gemini-3.
|
|
625
|
+
model: vertex('gemini-3.8-flash'),
|
|
626
626
|
tools: {
|
|
627
627
|
enterprise_web_search: vertex.tools.enterpriseWebSearch({}),
|
|
628
628
|
},
|
|
@@ -645,7 +645,7 @@ import { google } from '@ai-sdk/google';
|
|
|
645
645
|
import { generateText } from 'ai';
|
|
646
646
|
|
|
647
647
|
const { text, sources } = await generateText({
|
|
648
|
-
model: google('gemini-3.
|
|
648
|
+
model: google('gemini-3.8-flash'),
|
|
649
649
|
tools: {
|
|
650
650
|
file_search: google.tools.fileSearch({
|
|
651
651
|
fileSearchStoreNames: [
|
|
@@ -672,7 +672,7 @@ import { google } from '@ai-sdk/google';
|
|
|
672
672
|
import { generateText } from 'ai';
|
|
673
673
|
|
|
674
674
|
const { text, sources, providerMetadata } = await generateText({
|
|
675
|
-
model: google('gemini-3.
|
|
675
|
+
model: google('gemini-3.8-flash'),
|
|
676
676
|
prompt: `Based on the document: https://ai.google.dev/gemini-api/docs/url-context.
|
|
677
677
|
Answer this question: How many links we can consume in one request?`,
|
|
678
678
|
tools: {
|
|
@@ -750,7 +750,7 @@ import { google } from '@ai-sdk/google';
|
|
|
750
750
|
import { generateText } from 'ai';
|
|
751
751
|
|
|
752
752
|
const { text, sources, providerMetadata } = await generateText({
|
|
753
|
-
model: google('gemini-3.
|
|
753
|
+
model: google('gemini-3.8-flash'),
|
|
754
754
|
prompt: `Based on this context: https://ai-sdk.dev/providers/ai-sdk-providers/google, tell me how to use Gemini with AI SDK.
|
|
755
755
|
Also, provide the latest news about AI SDK V5.`,
|
|
756
756
|
tools: {
|
|
@@ -775,7 +775,7 @@ import { GoogleProviderMetadata } from '@ai-sdk/google';
|
|
|
775
775
|
import { generateText } from 'ai';
|
|
776
776
|
|
|
777
777
|
const { text, sources, providerMetadata } = await generateText({
|
|
778
|
-
model: google('gemini-3.
|
|
778
|
+
model: google('gemini-3.8-flash'),
|
|
779
779
|
tools: {
|
|
780
780
|
google_maps: google.tools.googleMaps({}),
|
|
781
781
|
},
|
|
@@ -839,7 +839,7 @@ const vertex = createGoogleVertex({
|
|
|
839
839
|
});
|
|
840
840
|
|
|
841
841
|
const { text, sources, providerMetadata } = await generateText({
|
|
842
|
-
model: vertex('gemini-3.
|
|
842
|
+
model: vertex('gemini-3.8-flash'),
|
|
843
843
|
tools: {
|
|
844
844
|
vertex_rag_store: vertex.tools.vertexRagStore({
|
|
845
845
|
ragCorpus:
|
|
@@ -1006,7 +1006,7 @@ You can disable structured outputs for object generation as a workaround:
|
|
|
1006
1006
|
|
|
1007
1007
|
```ts highlight="3,8"
|
|
1008
1008
|
const { output } = await generateText({
|
|
1009
|
-
model: google('gemini-3.
|
|
1009
|
+
model: google('gemini-3.8-flash'),
|
|
1010
1010
|
providerOptions: {
|
|
1011
1011
|
google: {
|
|
1012
1012
|
structuredOutputs: false,
|
|
@@ -1041,6 +1041,7 @@ The following Zod features are known to not work with Google:
|
|
|
1041
1041
|
|
|
1042
1042
|
| Model | Image Input | Object Generation | Tool Usage | Tool Streaming | Google Search | URL Context |
|
|
1043
1043
|
| ------------------------------------- | ----------- | ----------------- | ---------- | -------------- | ------------- | ----------- |
|
|
1044
|
+
| `gemini-3.8-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1044
1045
|
| `gemini-3.7-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1045
1046
|
| `gemini-3.6-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1046
1047
|
| `gemini-3.5-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
@@ -1270,13 +1271,13 @@ import { google } from '@ai-sdk/google';
|
|
|
1270
1271
|
import { generateText } from 'ai';
|
|
1271
1272
|
|
|
1272
1273
|
const { text } = await generateText({
|
|
1273
|
-
model: google.interactions('gemini-3.
|
|
1274
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1274
1275
|
prompt: 'Hello, how are you?',
|
|
1275
1276
|
});
|
|
1276
1277
|
```
|
|
1277
1278
|
|
|
1278
1279
|
`google.interactions(...)` accepts a model ID string (e.g.
|
|
1279
|
-
`'gemini-3.
|
|
1280
|
+
`'gemini-3.8-flash'`, `'gemini-3.1-pro-preview'`), `{ agent: <name> }` to use
|
|
1280
1281
|
a Gemini [agent preset](#agent-presets), or `{ managedAgent: <name> }` to
|
|
1281
1282
|
invoke a [managed agent](#managed-agents) you created on Google's side.
|
|
1282
1283
|
The returned model can be passed to `generateText` and `streamText` like
|
|
@@ -1303,7 +1304,7 @@ import {
|
|
|
1303
1304
|
import { generateText } from 'ai';
|
|
1304
1305
|
|
|
1305
1306
|
await generateText({
|
|
1306
|
-
model: google.interactions('gemini-3.
|
|
1307
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1307
1308
|
prompt: 'What color is the sky in one word?',
|
|
1308
1309
|
providerOptions: {
|
|
1309
1310
|
google: {
|
|
@@ -1452,7 +1453,20 @@ exposes:
|
|
|
1452
1453
|
- **signature** _string_
|
|
1453
1454
|
|
|
1454
1455
|
Per-block signature hash, set by the SDK on output reasoning and
|
|
1455
|
-
tool-call parts. Round-tripped automatically on
|
|
1456
|
+
tool-call or agentic video processing parts. Round-tripped automatically on
|
|
1457
|
+
the next turn.
|
|
1458
|
+
|
|
1459
|
+
Agentic video custom parts additionally expose:
|
|
1460
|
+
|
|
1461
|
+
- **processingId** _string_
|
|
1462
|
+
|
|
1463
|
+
ID of an agentic video `processing_call`. Present on
|
|
1464
|
+
`google.processing_call` custom parts.
|
|
1465
|
+
|
|
1466
|
+
- **processingCallId** _string_
|
|
1467
|
+
|
|
1468
|
+
ID of the matching agentic video processing call. Present on
|
|
1469
|
+
`google.processing_result` custom parts.
|
|
1456
1470
|
|
|
1457
1471
|
### Stateful chaining
|
|
1458
1472
|
|
|
@@ -1468,7 +1482,7 @@ import {
|
|
|
1468
1482
|
import { generateText } from 'ai';
|
|
1469
1483
|
|
|
1470
1484
|
const turn1 = await generateText({
|
|
1471
|
-
model: google.interactions('gemini-3.
|
|
1485
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1472
1486
|
prompt: 'What are the three largest cities in Spain?',
|
|
1473
1487
|
});
|
|
1474
1488
|
|
|
@@ -1477,7 +1491,7 @@ const interactionId = turn1.providerMetadata?.google?.interactionId as
|
|
|
1477
1491
|
| undefined;
|
|
1478
1492
|
|
|
1479
1493
|
const turn2 = await generateText({
|
|
1480
|
-
model: google.interactions('gemini-3.
|
|
1494
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1481
1495
|
prompt: 'What is the most famous landmark in the second one?',
|
|
1482
1496
|
providerOptions: {
|
|
1483
1497
|
google: {
|
|
@@ -1502,7 +1516,7 @@ const messages: Array<ModelMessage> = [
|
|
|
1502
1516
|
];
|
|
1503
1517
|
|
|
1504
1518
|
const turn1 = await generateText({
|
|
1505
|
-
model: google.interactions('gemini-3.
|
|
1519
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1506
1520
|
messages,
|
|
1507
1521
|
providerOptions: {
|
|
1508
1522
|
google: { store: false } satisfies GoogleLanguageModelInteractionsOptions,
|
|
@@ -1516,7 +1530,7 @@ messages.push({
|
|
|
1516
1530
|
});
|
|
1517
1531
|
|
|
1518
1532
|
const turn2 = await generateText({
|
|
1519
|
-
model: google.interactions('gemini-3.
|
|
1533
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1520
1534
|
messages,
|
|
1521
1535
|
providerOptions: {
|
|
1522
1536
|
google: { store: false } satisfies GoogleLanguageModelInteractionsOptions,
|
|
@@ -1524,6 +1538,97 @@ const turn2 = await generateText({
|
|
|
1524
1538
|
});
|
|
1525
1539
|
```
|
|
1526
1540
|
|
|
1541
|
+
### Agentic video understanding
|
|
1542
|
+
|
|
1543
|
+
Gemini 3.7 Flash, 3.6 Flash, and 3.5 Flash Lite support agentic video
|
|
1544
|
+
understanding through the Interactions API. Instead of sampling the entire
|
|
1545
|
+
video at a fixed frame rate, the model dynamically navigates the timeline and
|
|
1546
|
+
loads the transcripts, frames, or audio needed for the prompt.
|
|
1547
|
+
|
|
1548
|
+
Set `processing: 'agentic'` in the Google provider options of an individual
|
|
1549
|
+
video file part. You can validate the per-file options with
|
|
1550
|
+
`GoogleInteractionsVideoOptions`:
|
|
1551
|
+
|
|
1552
|
+
```ts
|
|
1553
|
+
import { google, type GoogleInteractionsVideoOptions } from '@ai-sdk/google';
|
|
1554
|
+
import { generateText } from 'ai';
|
|
1555
|
+
|
|
1556
|
+
const result = await generateText({
|
|
1557
|
+
model: google.interactions('gemini-3.7-flash'),
|
|
1558
|
+
messages: [
|
|
1559
|
+
{
|
|
1560
|
+
role: 'user',
|
|
1561
|
+
content: [
|
|
1562
|
+
{
|
|
1563
|
+
type: 'file',
|
|
1564
|
+
data: 'https://www.youtube.com/watch?v=9hE5-98ZeCg',
|
|
1565
|
+
mediaType: 'video',
|
|
1566
|
+
providerOptions: {
|
|
1567
|
+
google: {
|
|
1568
|
+
processing: 'agentic',
|
|
1569
|
+
} satisfies GoogleInteractionsVideoOptions,
|
|
1570
|
+
},
|
|
1571
|
+
},
|
|
1572
|
+
{
|
|
1573
|
+
type: 'text',
|
|
1574
|
+
text: 'Identify the three most important moments and include timestamps.',
|
|
1575
|
+
},
|
|
1576
|
+
],
|
|
1577
|
+
},
|
|
1578
|
+
],
|
|
1579
|
+
providerOptions: {
|
|
1580
|
+
google: {
|
|
1581
|
+
thinkingSummaries: 'auto',
|
|
1582
|
+
},
|
|
1583
|
+
},
|
|
1584
|
+
});
|
|
1585
|
+
|
|
1586
|
+
const processingSteps = result.content.filter(
|
|
1587
|
+
part =>
|
|
1588
|
+
part.type === 'custom' &&
|
|
1589
|
+
(part.kind === 'google.processing_call' ||
|
|
1590
|
+
part.kind === 'google.processing_result'),
|
|
1591
|
+
);
|
|
1592
|
+
```
|
|
1593
|
+
|
|
1594
|
+
Agentic navigation is exposed as `custom` content parts:
|
|
1595
|
+
|
|
1596
|
+
- `google.processing_call` marks a request by the model to inspect part of the
|
|
1597
|
+
video. Its `providerMetadata.google.processingId` contains the processing ID.
|
|
1598
|
+
- `google.processing_result` marks completion of that request. Its
|
|
1599
|
+
`providerMetadata.google.processingCallId` links it to the processing call.
|
|
1600
|
+
|
|
1601
|
+
These parts are informational and do not require a tool response. They are
|
|
1602
|
+
available from both `generateText` and `streamText`.
|
|
1603
|
+
|
|
1604
|
+
For static processing, use `'static'` or provide clipping and frame-rate
|
|
1605
|
+
options:
|
|
1606
|
+
|
|
1607
|
+
```ts
|
|
1608
|
+
const video = {
|
|
1609
|
+
type: 'file' as const,
|
|
1610
|
+
data: videoBytes,
|
|
1611
|
+
mediaType: 'video/mp4',
|
|
1612
|
+
providerOptions: {
|
|
1613
|
+
google: {
|
|
1614
|
+
processing: {
|
|
1615
|
+
type: 'static',
|
|
1616
|
+
startOffset: 1200,
|
|
1617
|
+
endOffset: 1500,
|
|
1618
|
+
fps: 0.5,
|
|
1619
|
+
},
|
|
1620
|
+
} satisfies GoogleInteractionsVideoOptions,
|
|
1621
|
+
},
|
|
1622
|
+
};
|
|
1623
|
+
```
|
|
1624
|
+
|
|
1625
|
+
With stateful conversations, pass the returned `interactionId` as
|
|
1626
|
+
`previousInteractionId`; Gemini retains the video context server-side. With
|
|
1627
|
+
`store: false`, append `result.responseMessages` and re-send the full history.
|
|
1628
|
+
The processing custom parts and their signatures are then round-tripped as
|
|
1629
|
+
native `processing_call` and `processing_result` steps so the video context is
|
|
1630
|
+
preserved.
|
|
1631
|
+
|
|
1527
1632
|
### Built-in Tools
|
|
1528
1633
|
|
|
1529
1634
|
The Interactions API ships a built-in tool catalog. The provider-defined
|
|
@@ -1549,7 +1654,7 @@ import { google } from '@ai-sdk/google';
|
|
|
1549
1654
|
import { generateText } from 'ai';
|
|
1550
1655
|
|
|
1551
1656
|
const { text, sources } = await generateText({
|
|
1552
|
-
model: google.interactions('gemini-3.
|
|
1657
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1553
1658
|
tools: {
|
|
1554
1659
|
google_search: google.tools.googleSearch({}),
|
|
1555
1660
|
},
|
|
@@ -1573,7 +1678,7 @@ const weatherTool = tool({
|
|
|
1573
1678
|
});
|
|
1574
1679
|
|
|
1575
1680
|
const { text, toolCalls } = await generateText({
|
|
1576
|
-
model: google.interactions('gemini-3.
|
|
1681
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1577
1682
|
tools: { getWeather: weatherTool },
|
|
1578
1683
|
stopWhen: isStepCount(5),
|
|
1579
1684
|
prompt: 'What is the weather in San Francisco right now?',
|
|
@@ -1872,7 +1977,7 @@ import { google } from '@ai-sdk/google';
|
|
|
1872
1977
|
import { streamText } from 'ai';
|
|
1873
1978
|
|
|
1874
1979
|
const result = streamText({
|
|
1875
|
-
model: google.interactions('gemini-3.
|
|
1980
|
+
model: google.interactions('gemini-3.8-flash'),
|
|
1876
1981
|
prompt: 'Hello, how are you?',
|
|
1877
1982
|
});
|
|
1878
1983
|
|
package/package.json
CHANGED
|
@@ -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
|
@@ -105,6 +105,7 @@ const googleFileUploadResponseSchema = lazySchema(() =>
|
|
|
105
105
|
z.object({
|
|
106
106
|
file: z.object({
|
|
107
107
|
name: z.string(),
|
|
108
|
+
expirationTime: z.string().nullish(),
|
|
108
109
|
}),
|
|
109
110
|
}),
|
|
110
111
|
),
|
|
@@ -243,10 +244,9 @@ export class GoogleBatchLanguageModel
|
|
|
243
244
|
const createUrl = `${this.batchConfig.baseURL}/${getModelPath(
|
|
244
245
|
this.modelId,
|
|
245
246
|
)}:batchGenerateContent`;
|
|
246
|
-
let operation: GoogleBatchOperation;
|
|
247
247
|
|
|
248
248
|
if (fileParts == null) {
|
|
249
|
-
const { value } = await postJsonToApi({
|
|
249
|
+
const { value: operation } = await postJsonToApi({
|
|
250
250
|
url: createUrl,
|
|
251
251
|
headers,
|
|
252
252
|
body: inlineBatchBody,
|
|
@@ -257,86 +257,98 @@ export class GoogleBatchLanguageModel
|
|
|
257
257
|
abortSignal: options.abortSignal,
|
|
258
258
|
fetch: this.batchConfig.fetch,
|
|
259
259
|
});
|
|
260
|
-
operation = value;
|
|
261
|
-
} else {
|
|
262
|
-
const inputFile = new Blob(fileParts, { type: 'application/jsonl' });
|
|
263
|
-
// Blob snapshots the strings, so release the potentially large input array.
|
|
264
|
-
fileParts.length = 0;
|
|
265
|
-
if (inputFile.size > googleBatchInputFileMaxBytes) {
|
|
266
|
-
throw new InvalidArgumentError({
|
|
267
|
-
argument: 'requests',
|
|
268
|
-
message: 'Google batch input files must not exceed 2 GB.',
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
260
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
successfulResponseHandler: googleUploadUrlResponseHandler,
|
|
287
|
-
abortSignal: options.abortSignal,
|
|
288
|
-
fetch: this.batchConfig.fetch,
|
|
261
|
+
return {
|
|
262
|
+
batchId: operation.name,
|
|
263
|
+
...convertGoogleBatchStatus(operation),
|
|
264
|
+
warnings,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const inputFile = new Blob(fileParts, { type: 'application/jsonl' });
|
|
269
|
+
// Blob snapshots the strings, so release the potentially large input array.
|
|
270
|
+
fileParts.length = 0;
|
|
271
|
+
if (inputFile.size > googleBatchInputFileMaxBytes) {
|
|
272
|
+
throw new InvalidArgumentError({
|
|
273
|
+
argument: 'requests',
|
|
274
|
+
message: 'Google batch input files must not exceed 2 GB.',
|
|
289
275
|
});
|
|
276
|
+
}
|
|
290
277
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
278
|
+
const { value: uploadUrl } = await postJsonToApi({
|
|
279
|
+
url: `${this.getBaseOrigin()}/upload/v1beta/files`,
|
|
280
|
+
headers: combineHeaders(headers, {
|
|
281
|
+
'X-Goog-Upload-Protocol': 'resumable',
|
|
282
|
+
'X-Goog-Upload-Command': 'start',
|
|
283
|
+
'X-Goog-Upload-Header-Content-Length': String(inputFile.size),
|
|
284
|
+
'X-Goog-Upload-Header-Content-Type': 'application/jsonl',
|
|
285
|
+
}),
|
|
286
|
+
body: {
|
|
287
|
+
file: {
|
|
288
|
+
display_name: `${displayName}-input`,
|
|
297
289
|
},
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
290
|
+
},
|
|
291
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
292
|
+
successfulResponseHandler: googleUploadUrlResponseHandler,
|
|
293
|
+
abortSignal: options.abortSignal,
|
|
294
|
+
fetch: this.batchConfig.fetch,
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const { value: uploadedFile } = await postToApi({
|
|
298
|
+
url: uploadUrl,
|
|
299
|
+
headers: {
|
|
300
|
+
'X-Goog-Upload-Offset': '0',
|
|
301
|
+
'X-Goog-Upload-Command': 'upload, finalize',
|
|
302
|
+
'Content-Type': 'application/jsonl',
|
|
303
|
+
},
|
|
304
|
+
body: {
|
|
305
|
+
content: inputFile,
|
|
306
|
+
values: {
|
|
307
|
+
byteLength: inputFile.size,
|
|
308
|
+
mediaType: 'application/jsonl',
|
|
304
309
|
},
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
310
|
+
},
|
|
311
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
312
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
313
|
+
googleFileUploadResponseSchema,
|
|
314
|
+
),
|
|
315
|
+
abortSignal: options.abortSignal,
|
|
316
|
+
fetch: this.batchConfig.fetch,
|
|
317
|
+
});
|
|
312
318
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
},
|
|
319
|
+
const { value: operation } = await postJsonToApi({
|
|
320
|
+
url: createUrl,
|
|
321
|
+
headers,
|
|
322
|
+
body: {
|
|
323
|
+
batch: {
|
|
324
|
+
displayName,
|
|
325
|
+
...(options.webhookUrl != null && {
|
|
326
|
+
webhookConfig: { uris: [options.webhookUrl] },
|
|
327
|
+
}),
|
|
328
|
+
inputConfig: {
|
|
329
|
+
fileName: uploadedFile.file.name,
|
|
325
330
|
},
|
|
326
331
|
},
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
332
|
+
},
|
|
333
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
334
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
335
|
+
googleBatchOperationSchema,
|
|
336
|
+
),
|
|
337
|
+
abortSignal: options.abortSignal,
|
|
338
|
+
fetch: this.batchConfig.fetch,
|
|
339
|
+
});
|
|
336
340
|
|
|
337
341
|
return {
|
|
338
342
|
batchId: operation.name,
|
|
339
343
|
...convertGoogleBatchStatus(operation),
|
|
344
|
+
providerMetadata: {
|
|
345
|
+
google: {
|
|
346
|
+
inputFileId: uploadedFile.file.name,
|
|
347
|
+
...(uploadedFile.file.expirationTime != null
|
|
348
|
+
? { inputFileExpiresAt: uploadedFile.file.expirationTime }
|
|
349
|
+
: {}),
|
|
350
|
+
},
|
|
351
|
+
},
|
|
340
352
|
warnings,
|
|
341
353
|
};
|
|
342
354
|
}
|