@ai-sdk/google 4.0.94 → 4.0.96
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 +20 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +173 -15
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +6 -3
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +172 -14
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +228 -42
- package/package.json +2 -2
- package/src/continue-google-stream.ts +75 -0
- package/src/convert-google-usage.ts +76 -0
- package/src/google-language-model-options.ts +12 -0
- package/src/google-language-model.ts +146 -24
- package/src/google-prompt.ts +18 -0
- package/src/interactions/google-interactions-language-model-options.ts +1 -0
- package/src/interactions/google-interactions-language-model.ts +6 -6
- package/src/map-google-finish-reason.ts +3 -0
package/docs/15-google.mdx
CHANGED
|
@@ -1,18 +1,67 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Google
|
|
3
|
-
description: Learn how to use Google
|
|
3
|
+
description: Learn how to use Google models through AI Gateway or the direct Google provider.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Google Provider
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
the [Google](https://ai.google.dev/api/rest)
|
|
8
|
+
You can use [Google](https://ai.google.dev) models through [AI Gateway](/providers/ai-sdk-providers/ai-gateway) (recommended)
|
|
9
|
+
or connect directly to the [Google APIs](https://ai.google.dev/api/rest) with `@ai-sdk/google`.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
```ts provider="google" model="google/gemini-4-argon" highlight="5"
|
|
12
|
+
import { generateText } from 'ai';
|
|
13
|
+
__PROVIDER_IMPORT__;
|
|
14
|
+
|
|
15
|
+
const { text } = await generateText({
|
|
16
|
+
model: __MODEL__,
|
|
17
|
+
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
console.log(text);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Using AI Gateway
|
|
24
|
+
|
|
25
|
+
The AI SDK uses AI Gateway by default for model strings.
|
|
26
|
+
AI Gateway provides access to Google and other providers through a single API key, with usage and cost tracking.
|
|
27
|
+
Install the `ai` package:
|
|
28
|
+
|
|
29
|
+
<InstallPackages packages="ai" />
|
|
30
|
+
|
|
31
|
+
Set an [AI Gateway API key](https://vercel.com/docs/ai-gateway/getting-started) in your environment:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
export AI_GATEWAY_API_KEY=your_api_key_here
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Vercel deployments can also use [OIDC authentication](/providers/ai-sdk-providers/ai-gateway#oidc-authentication-vercel-deployments).
|
|
38
|
+
See the [AI Gateway provider documentation](/providers/ai-sdk-providers/ai-gateway) for configuration
|
|
39
|
+
and the [model catalog](https://vercel.com/ai-gateway/models?search=google) for available Google models.
|
|
40
|
+
|
|
41
|
+
Google model options can be passed through `providerOptions.google` when using AI Gateway.
|
|
42
|
+
Support depends on the model and the provider serving the request; see [Gateway provider options](https://vercel.com/docs/ai-gateway/models-and-providers/provider-options).
|
|
43
|
+
|
|
44
|
+
## Using `@ai-sdk/google`
|
|
12
45
|
|
|
13
|
-
|
|
46
|
+
For direct access to the Google APIs, install `ai` and `@ai-sdk/google`:
|
|
14
47
|
|
|
15
|
-
<InstallPackages packages="@ai-sdk/google" />
|
|
48
|
+
<InstallPackages packages="ai @ai-sdk/google" />
|
|
49
|
+
|
|
50
|
+
Set your [Google API key](https://aistudio.google.com/apikey) in the `GOOGLE_GENERATIVE_AI_API_KEY` environment variable:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
export GOOGLE_GENERATIVE_AI_API_KEY=your_api_key_here
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
AI Gateway does not expose every API in `@ai-sdk/google`.
|
|
57
|
+
Use the direct provider for Google-specific APIs such as [`google.interactions(...)`](#interactions-api),
|
|
58
|
+
or when you need to customize the Google connection with [`createGoogle`](#provider-instance).
|
|
59
|
+
|
|
60
|
+
<Note>
|
|
61
|
+
The following sections document the direct `@ai-sdk/google` provider,
|
|
62
|
+
including its model factories, tools, and settings. Gateway model and feature
|
|
63
|
+
availability can differ from the direct provider.
|
|
64
|
+
</Note>
|
|
16
65
|
|
|
17
66
|
## Provider Instance
|
|
18
67
|
|
|
@@ -77,11 +126,11 @@ You can use the following optional settings to customize the Google provider ins
|
|
|
77
126
|
## Language Models
|
|
78
127
|
|
|
79
128
|
You can create models that call the [Google Generative AI API](https://ai.google.dev/api/rest) using the provider instance.
|
|
80
|
-
The first argument is the model id, e.g. `gemini-
|
|
129
|
+
The first argument is the model id, e.g. `gemini-4-argon`.
|
|
81
130
|
The models support tool calls and some have multi-modal capabilities.
|
|
82
131
|
|
|
83
132
|
```ts
|
|
84
|
-
const model = google('gemini-
|
|
133
|
+
const model = google('gemini-4-argon');
|
|
85
134
|
```
|
|
86
135
|
|
|
87
136
|
You can use Google language models to generate text with the `generateText` function:
|
|
@@ -91,7 +140,7 @@ import { google } from '@ai-sdk/google';
|
|
|
91
140
|
import { generateText } from 'ai';
|
|
92
141
|
|
|
93
142
|
const { text } = await generateText({
|
|
94
|
-
model: google('gemini-
|
|
143
|
+
model: google('gemini-4-argon'),
|
|
95
144
|
prompt: 'Write a vegetarian lasagna recipe for 4 people.',
|
|
96
145
|
});
|
|
97
146
|
```
|
|
@@ -116,7 +165,7 @@ You can pass them as an options argument:
|
|
|
116
165
|
```ts
|
|
117
166
|
import { google, type GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
118
167
|
|
|
119
|
-
const model = google('gemini-
|
|
168
|
+
const model = google('gemini-4-argon');
|
|
120
169
|
|
|
121
170
|
await generateText({
|
|
122
171
|
model,
|
|
@@ -253,6 +302,12 @@ The following optional provider options are available for Google models:
|
|
|
253
302
|
[Priority inference](https://ai.google.dev/gemini-api/docs/priority-inference)
|
|
254
303
|
and [Flex inference](https://ai.google.dev/gemini-api/docs/flex-inference).
|
|
255
304
|
|
|
305
|
+
- **continuationToken** _string_
|
|
306
|
+
|
|
307
|
+
Optional. Resumes a response that stopped because it used up its
|
|
308
|
+
`maxOutputTokens` budget (Gemini 4 long decode). Send it with the original
|
|
309
|
+
request and a higher `maxOutputTokens`. See [Long decode](#long-decode).
|
|
310
|
+
|
|
256
311
|
- **threshold** _string_
|
|
257
312
|
|
|
258
313
|
Optional. Standalone threshold setting that can be used independently of `safetySettings`.
|
|
@@ -270,7 +325,7 @@ For Gemini 3 and later models, use the `thinkingLevel` parameter to control the
|
|
|
270
325
|
import { google, GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
271
326
|
import { generateText } from 'ai';
|
|
272
327
|
|
|
273
|
-
const model = google('gemini-
|
|
328
|
+
const model = google('gemini-4-argon');
|
|
274
329
|
|
|
275
330
|
const { text, reasoning } = await generateText({
|
|
276
331
|
model: model,
|
|
@@ -318,6 +373,136 @@ console.log(text);
|
|
|
318
373
|
console.log(reasoning); // Reasoning summary
|
|
319
374
|
```
|
|
320
375
|
|
|
376
|
+
### Long decode
|
|
377
|
+
|
|
378
|
+
Gemini 4 models such as `gemini-4-argon` can keep thinking and writing past a
|
|
379
|
+
single request's limits, up to the shared 1M token context window (input,
|
|
380
|
+
thinking, and output tokens together). Use it for hard math, science, proofs,
|
|
381
|
+
and long coding or agentic tasks.
|
|
382
|
+
|
|
383
|
+
- A single request generates at most 32,768 tokens without streaming and 65,536
|
|
384
|
+
tokens with streaming (`streamText`). Thinking tokens count towards this cap.
|
|
385
|
+
- `maxOutputTokens` is a **cumulative budget across requests**, not a target
|
|
386
|
+
length. When a request reaches the per-request cap while budget remains, the
|
|
387
|
+
provider automatically sends the same request again with a continuation token
|
|
388
|
+
and combines the results into one response. Set `maxOutputTokens` above the
|
|
389
|
+
per-request cap (up to 1M minus the input tokens) to enable this. If you do
|
|
390
|
+
not set it, the call ends after one request.
|
|
391
|
+
- A lower `maxOutputTokens` does not make the model think less, it ends the
|
|
392
|
+
response early (possibly before any answer) and you are still charged for the
|
|
393
|
+
tokens. Use `thinkingConfig.thinkingLevel` to control how much the model
|
|
394
|
+
thinks. `thinkingBudget` is not supported by these models.
|
|
395
|
+
- Complex requests can run for several minutes. Make sure your HTTP client
|
|
396
|
+
allows read timeouts of at least 15 to 20 minutes.
|
|
397
|
+
|
|
398
|
+
**Usage across requests.** Each continued request re-sends the prompt plus all
|
|
399
|
+
output so far as input, so its prompt token count includes everything
|
|
400
|
+
generated before it. `usage` is the sum of all requests, which matches what
|
|
401
|
+
Google bills (re-sent tokens are billed at a discount through implicit
|
|
402
|
+
caching). Do not use the summed input tokens for context window checks or
|
|
403
|
+
compaction: they can be several times larger than the real context. When a
|
|
404
|
+
response spanned more than one request,
|
|
405
|
+
`providerMetadata.google.initialPromptTokenCount` holds the prompt token count
|
|
406
|
+
of the first request (the google-genai SDKs expose the same value as
|
|
407
|
+
`initial_prompt_token_count`):
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
const result = await generateText({
|
|
411
|
+
model: google('gemini-4-argon'),
|
|
412
|
+
prompt,
|
|
413
|
+
maxOutputTokens: 500_000,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// Billing: summed across all requests
|
|
417
|
+
console.log(result.usage.inputTokens.total);
|
|
418
|
+
|
|
419
|
+
// Context window: the first request's prompt plus the generated output
|
|
420
|
+
const promptTokens =
|
|
421
|
+
result.finalStep.providerMetadata?.google?.initialPromptTokenCount ??
|
|
422
|
+
result.usage.inputTokens.total;
|
|
423
|
+
const contextTokens = promptTokens + (result.usage.outputTokens.total ?? 0);
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Resuming after the budget is used up.** When the cumulative generated tokens
|
|
427
|
+
reach `maxOutputTokens`, the finish reason is `length` and the provider returns
|
|
428
|
+
a continuation token on `result.providerMetadata.google.continuationToken`. To
|
|
429
|
+
continue, send the **original request unchanged** (same prompt, tools, and
|
|
430
|
+
settings; do not append the partial output as a message) together with the
|
|
431
|
+
token as `providerOptions.google.continuationToken` and a **higher**
|
|
432
|
+
`maxOutputTokens`. Resending with the same `maxOutputTokens` fails because the
|
|
433
|
+
budget is used up. Each response contains only the newly generated content.
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
import { google } from '@ai-sdk/google';
|
|
437
|
+
import { generateText } from 'ai';
|
|
438
|
+
|
|
439
|
+
const prompt = 'Prove that sqrt(2) is irrational, in detail.';
|
|
440
|
+
|
|
441
|
+
const result = await generateText({
|
|
442
|
+
model: google('gemini-4-argon'),
|
|
443
|
+
prompt,
|
|
444
|
+
maxOutputTokens: 128_000,
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
const continuationToken =
|
|
448
|
+
result.finalStep.providerMetadata?.google?.continuationToken;
|
|
449
|
+
|
|
450
|
+
if (result.finishReason === 'length' && typeof continuationToken === 'string') {
|
|
451
|
+
// The budget was used up. Raise it to keep going.
|
|
452
|
+
const continued = await generateText({
|
|
453
|
+
model: google('gemini-4-argon'),
|
|
454
|
+
prompt,
|
|
455
|
+
maxOutputTokens: 256_000,
|
|
456
|
+
providerOptions: { google: { continuationToken } },
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
console.log(result.text + continued.text);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Things to keep in mind:
|
|
464
|
+
|
|
465
|
+
- **Dropped streams.** Streamed parts are forwarded as they arrive and are not
|
|
466
|
+
buffered between the server's checkpoints, so a stream that drops mid-request
|
|
467
|
+
is not resumed automatically. Retry the request from the start.
|
|
468
|
+
- **Provider metadata is per call.** If you store the conversation history,
|
|
469
|
+
combine the content of all calls into one model message only after the final
|
|
470
|
+
call finishes. Keep thought signatures unchanged, including the ones on empty
|
|
471
|
+
trailing text parts.
|
|
472
|
+
- **Zero Data Retention.** Continuation works with `store: false` because the
|
|
473
|
+
state travels encrypted inside the token.
|
|
474
|
+
|
|
475
|
+
#### Long decode with the Interactions API
|
|
476
|
+
|
|
477
|
+
With the [Interactions API](#interactions-api), long decode requires
|
|
478
|
+
`background: true`. The server runs every request itself, so no client-side
|
|
479
|
+
continuation is needed, and `usage` covers all requests. Set an explicit
|
|
480
|
+
`maxOutputTokens` above 65,536 (without it, you get a single 64K request) and
|
|
481
|
+
keep `store` enabled (the default). The provider polls the interaction (or
|
|
482
|
+
streams it, reconnecting when the connection drops) until it finishes.
|
|
483
|
+
|
|
484
|
+
```ts
|
|
485
|
+
import { google } from '@ai-sdk/google';
|
|
486
|
+
import { generateText } from 'ai';
|
|
487
|
+
|
|
488
|
+
const result = await generateText({
|
|
489
|
+
model: google.interactions('gemini-4-argon'),
|
|
490
|
+
prompt: 'Prove that sqrt(2) is irrational, in detail.',
|
|
491
|
+
maxOutputTokens: 500_000,
|
|
492
|
+
providerOptions: {
|
|
493
|
+
google: {
|
|
494
|
+
background: true,
|
|
495
|
+
pollingTimeoutMs: 60 * 60 * 1000, // default: 30 minutes
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
});
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Without `background: true`, an interaction generates at most 65,536 tokens.
|
|
502
|
+
Requests with a higher `maxOutputTokens` are rejected by the API, and an
|
|
503
|
+
interaction that reaches the cap finishes with `length`. Long decode is not
|
|
504
|
+
available with the Vertex AI Interactions API.
|
|
505
|
+
|
|
321
506
|
### File Inputs
|
|
322
507
|
|
|
323
508
|
The Google provider supports file inputs, e.g. PDF files.
|
|
@@ -327,7 +512,7 @@ import { google } from '@ai-sdk/google';
|
|
|
327
512
|
import { generateText } from 'ai';
|
|
328
513
|
|
|
329
514
|
const result = await generateText({
|
|
330
|
-
model: google('gemini-
|
|
515
|
+
model: google('gemini-4-argon'),
|
|
331
516
|
messages: [
|
|
332
517
|
{
|
|
333
518
|
role: 'user',
|
|
@@ -354,7 +539,7 @@ import { google } from '@ai-sdk/google';
|
|
|
354
539
|
import { generateText } from 'ai';
|
|
355
540
|
|
|
356
541
|
const result = await generateText({
|
|
357
|
-
model: google('gemini-
|
|
542
|
+
model: google('gemini-4-argon'),
|
|
358
543
|
messages: [
|
|
359
544
|
{
|
|
360
545
|
role: 'user',
|
|
@@ -390,7 +575,7 @@ Google supports both explicit and implicit caching to help reduce costs on repet
|
|
|
390
575
|
|
|
391
576
|
#### Implicit Caching
|
|
392
577
|
|
|
393
|
-
Gemini models automatically provide cache cost savings without needing to create an explicit cache. When you send requests that share common prefixes with previous requests, you
|
|
578
|
+
Gemini models automatically provide cache cost savings without needing to create an explicit cache. When you send requests that share common prefixes with previous requests, you can receive discounted pricing on cached input tokens.
|
|
394
579
|
|
|
395
580
|
To maximize cache hits with implicit caching:
|
|
396
581
|
|
|
@@ -409,13 +594,13 @@ const baseContext =
|
|
|
409
594
|
'You are a cooking assistant with expertise in Italian cuisine. Here are 1000 lasagna recipes for reference...';
|
|
410
595
|
|
|
411
596
|
const { text: veggieLasagna } = await generateText({
|
|
412
|
-
model: google('gemini-
|
|
597
|
+
model: google('gemini-4-argon'),
|
|
413
598
|
prompt: `${baseContext}\n\nWrite a vegetarian lasagna recipe for 4 people.`,
|
|
414
599
|
});
|
|
415
600
|
|
|
416
601
|
// Second request with same prefix - eligible for cache hit
|
|
417
602
|
const { text: meatLasagna, providerMetadata } = await generateText({
|
|
418
|
-
model: google('gemini-
|
|
603
|
+
model: google('gemini-4-argon'),
|
|
419
604
|
prompt: `${baseContext}\n\nWrite a meat lasagna recipe for 12 people.`,
|
|
420
605
|
});
|
|
421
606
|
|
|
@@ -443,7 +628,7 @@ console.log('Cached tokens:', providerMetadata.google);
|
|
|
443
628
|
|
|
444
629
|
#### Explicit Caching
|
|
445
630
|
|
|
446
|
-
For guaranteed cost savings, you can still use explicit caching with Gemini 2.5 and 3 series models. See the [models page](https://ai.google.dev/gemini-api/docs/models) to check if caching is supported for the used model:
|
|
631
|
+
For guaranteed cost savings, you can still use explicit caching with Gemini 2.5 and 3 series models. Gemini 4 Argon supports implicit caching only, so this example uses `gemini-3.8-flash`. See the [models page](https://ai.google.dev/gemini-api/docs/models) to check if caching is supported for the used model:
|
|
447
632
|
|
|
448
633
|
```ts
|
|
449
634
|
import { google, type GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
@@ -503,7 +688,7 @@ import { googleTools } from '@ai-sdk/google/internal';
|
|
|
503
688
|
import { generateText } from 'ai';
|
|
504
689
|
|
|
505
690
|
const { text, toolCalls, toolResults } = await generateText({
|
|
506
|
-
model: google('gemini-
|
|
691
|
+
model: google('gemini-4-argon'),
|
|
507
692
|
tools: { code_execution: google.tools.codeExecution({}) },
|
|
508
693
|
prompt: 'Use python to calculate the 20th fibonacci number.',
|
|
509
694
|
});
|
|
@@ -522,7 +707,7 @@ import { GoogleProviderMetadata } from '@ai-sdk/google';
|
|
|
522
707
|
import { generateText } from 'ai';
|
|
523
708
|
|
|
524
709
|
const { text, sources, providerMetadata } = await generateText({
|
|
525
|
-
model: google('gemini-
|
|
710
|
+
model: google('gemini-4-argon'),
|
|
526
711
|
tools: {
|
|
527
712
|
google_search: google.tools.googleSearch({}),
|
|
528
713
|
},
|
|
@@ -630,7 +815,7 @@ const vertex = createGoogleVertex({
|
|
|
630
815
|
});
|
|
631
816
|
|
|
632
817
|
const { text, sources, providerMetadata } = await generateText({
|
|
633
|
-
model: vertex('gemini-
|
|
818
|
+
model: vertex('gemini-4-argon'),
|
|
634
819
|
tools: {
|
|
635
820
|
enterprise_web_search: vertex.tools.enterpriseWebSearch({}),
|
|
636
821
|
},
|
|
@@ -653,7 +838,7 @@ import { google } from '@ai-sdk/google';
|
|
|
653
838
|
import { generateText } from 'ai';
|
|
654
839
|
|
|
655
840
|
const { text, sources, providerMetadata } = await generateText({
|
|
656
|
-
model: google('gemini-
|
|
841
|
+
model: google('gemini-4-argon'),
|
|
657
842
|
tools: {
|
|
658
843
|
file_search: google.tools.fileSearch({
|
|
659
844
|
fileSearchStoreNames: [
|
|
@@ -683,7 +868,7 @@ import { google } from '@ai-sdk/google';
|
|
|
683
868
|
import { generateText } from 'ai';
|
|
684
869
|
|
|
685
870
|
const { text, sources, providerMetadata } = await generateText({
|
|
686
|
-
model: google('gemini-
|
|
871
|
+
model: google('gemini-4-argon'),
|
|
687
872
|
prompt: `Based on the document: https://ai.google.dev/gemini-api/docs/url-context.
|
|
688
873
|
Answer this question: How many links we can consume in one request?`,
|
|
689
874
|
tools: {
|
|
@@ -761,7 +946,7 @@ import { google } from '@ai-sdk/google';
|
|
|
761
946
|
import { generateText } from 'ai';
|
|
762
947
|
|
|
763
948
|
const { text, sources, providerMetadata } = await generateText({
|
|
764
|
-
model: google('gemini-
|
|
949
|
+
model: google('gemini-4-argon'),
|
|
765
950
|
prompt: `Based on this context: https://ai-sdk.dev/providers/ai-sdk-providers/google, tell me how to use Gemini with AI SDK.
|
|
766
951
|
Also, provide the latest news about AI SDK V5.`,
|
|
767
952
|
tools: {
|
|
@@ -786,7 +971,7 @@ import { GoogleProviderMetadata } from '@ai-sdk/google';
|
|
|
786
971
|
import { generateText } from 'ai';
|
|
787
972
|
|
|
788
973
|
const { text, sources, providerMetadata } = await generateText({
|
|
789
|
-
model: google('gemini-
|
|
974
|
+
model: google('gemini-4-argon'),
|
|
790
975
|
tools: {
|
|
791
976
|
google_maps: google.tools.googleMaps({}),
|
|
792
977
|
},
|
|
@@ -850,7 +1035,7 @@ const vertex = createGoogleVertex({
|
|
|
850
1035
|
});
|
|
851
1036
|
|
|
852
1037
|
const { text, sources, providerMetadata } = await generateText({
|
|
853
|
-
model: vertex('gemini-
|
|
1038
|
+
model: vertex('gemini-4-argon'),
|
|
854
1039
|
tools: {
|
|
855
1040
|
vertex_rag_store: vertex.tools.vertexRagStore({
|
|
856
1041
|
ragCorpus:
|
|
@@ -1024,7 +1209,7 @@ You can also disable provider-enforced structured outputs for object generation:
|
|
|
1024
1209
|
|
|
1025
1210
|
```ts highlight="3,8"
|
|
1026
1211
|
const { output } = await generateText({
|
|
1027
|
-
model: google('gemini-
|
|
1212
|
+
model: google('gemini-4-argon'),
|
|
1028
1213
|
providerOptions: {
|
|
1029
1214
|
google: {
|
|
1030
1215
|
structuredOutputs: false,
|
|
@@ -1059,6 +1244,7 @@ will still validate the response against the schema in `Output.object`.
|
|
|
1059
1244
|
| Model | Image Input | Object Generation | Tool Usage | Tool Streaming | Google Search | URL Context |
|
|
1060
1245
|
| ------------------------------------- | ----------- | ----------------- | ---------- | -------------- | ------------- | ----------- |
|
|
1061
1246
|
| `gemini-nano-banana-2.1` | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Check /> | <Cross /> |
|
|
1247
|
+
| `gemini-4-argon` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1062
1248
|
| `gemini-3.8-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1063
1249
|
| `gemini-3.7-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
1064
1250
|
| `gemini-3.6-flash` | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
@@ -1106,7 +1292,7 @@ You can pass a `webhookUrl` to receive a notification when the batch reaches a t
|
|
|
1106
1292
|
import { google } from '@ai-sdk/google';
|
|
1107
1293
|
import { experimental_startBatch as startBatch } from 'ai';
|
|
1108
1294
|
|
|
1109
|
-
const model = 'gemini-
|
|
1295
|
+
const model = 'gemini-4-argon';
|
|
1110
1296
|
|
|
1111
1297
|
const batch = await startBatch({
|
|
1112
1298
|
provider: google,
|
|
@@ -1325,13 +1511,13 @@ import { google } from '@ai-sdk/google';
|
|
|
1325
1511
|
import { generateText } from 'ai';
|
|
1326
1512
|
|
|
1327
1513
|
const { text } = await generateText({
|
|
1328
|
-
model: google.interactions('gemini-
|
|
1514
|
+
model: google.interactions('gemini-4-argon'),
|
|
1329
1515
|
prompt: 'Hello, how are you?',
|
|
1330
1516
|
});
|
|
1331
1517
|
```
|
|
1332
1518
|
|
|
1333
1519
|
`google.interactions(...)` accepts a model ID string (e.g.
|
|
1334
|
-
`'gemini-
|
|
1520
|
+
`'gemini-4-argon'`, `'gemini-3.1-pro-preview'`), `{ agent: <name> }` to use
|
|
1335
1521
|
a Gemini [agent preset](#agent-presets), or `{ managedAgent: <name> }` to
|
|
1336
1522
|
invoke a [managed agent](#managed-agents) you created on Google's side.
|
|
1337
1523
|
The returned model can be passed to `generateText` and `streamText` like
|
|
@@ -1358,7 +1544,7 @@ import {
|
|
|
1358
1544
|
import { generateText } from 'ai';
|
|
1359
1545
|
|
|
1360
1546
|
await generateText({
|
|
1361
|
-
model: google.interactions('gemini-
|
|
1547
|
+
model: google.interactions('gemini-4-argon'),
|
|
1362
1548
|
prompt: 'What color is the sky in one word?',
|
|
1363
1549
|
providerOptions: {
|
|
1364
1550
|
google: {
|
|
@@ -1536,7 +1722,7 @@ import {
|
|
|
1536
1722
|
import { generateText } from 'ai';
|
|
1537
1723
|
|
|
1538
1724
|
const turn1 = await generateText({
|
|
1539
|
-
model: google.interactions('gemini-
|
|
1725
|
+
model: google.interactions('gemini-4-argon'),
|
|
1540
1726
|
prompt: 'What are the three largest cities in Spain?',
|
|
1541
1727
|
});
|
|
1542
1728
|
|
|
@@ -1545,7 +1731,7 @@ const interactionId = turn1.providerMetadata?.google?.interactionId as
|
|
|
1545
1731
|
| undefined;
|
|
1546
1732
|
|
|
1547
1733
|
const turn2 = await generateText({
|
|
1548
|
-
model: google.interactions('gemini-
|
|
1734
|
+
model: google.interactions('gemini-4-argon'),
|
|
1549
1735
|
prompt: 'What is the most famous landmark in the second one?',
|
|
1550
1736
|
providerOptions: {
|
|
1551
1737
|
google: {
|
|
@@ -1570,7 +1756,7 @@ const messages: Array<ModelMessage> = [
|
|
|
1570
1756
|
];
|
|
1571
1757
|
|
|
1572
1758
|
const turn1 = await generateText({
|
|
1573
|
-
model: google.interactions('gemini-
|
|
1759
|
+
model: google.interactions('gemini-4-argon'),
|
|
1574
1760
|
messages,
|
|
1575
1761
|
providerOptions: {
|
|
1576
1762
|
google: { store: false } satisfies GoogleLanguageModelInteractionsOptions,
|
|
@@ -1584,7 +1770,7 @@ messages.push({
|
|
|
1584
1770
|
});
|
|
1585
1771
|
|
|
1586
1772
|
const turn2 = await generateText({
|
|
1587
|
-
model: google.interactions('gemini-
|
|
1773
|
+
model: google.interactions('gemini-4-argon'),
|
|
1588
1774
|
messages,
|
|
1589
1775
|
providerOptions: {
|
|
1590
1776
|
google: { store: false } satisfies GoogleLanguageModelInteractionsOptions,
|
|
@@ -1594,7 +1780,7 @@ const turn2 = await generateText({
|
|
|
1594
1780
|
|
|
1595
1781
|
### Agentic video understanding
|
|
1596
1782
|
|
|
1597
|
-
Gemini 3.7 Flash, 3.6 Flash, and 3.5 Flash Lite support agentic video
|
|
1783
|
+
Gemini 4 Argon, 3.7 Flash, 3.6 Flash, and 3.5 Flash Lite support agentic video
|
|
1598
1784
|
understanding through the Interactions API. Instead of sampling the entire
|
|
1599
1785
|
video at a fixed frame rate, the model dynamically navigates the timeline and
|
|
1600
1786
|
loads the transcripts, frames, or audio needed for the prompt.
|
|
@@ -1608,7 +1794,7 @@ import { google, type GoogleInteractionsVideoOptions } from '@ai-sdk/google';
|
|
|
1608
1794
|
import { generateText } from 'ai';
|
|
1609
1795
|
|
|
1610
1796
|
const result = await generateText({
|
|
1611
|
-
model: google.interactions('gemini-
|
|
1797
|
+
model: google.interactions('gemini-4-argon'),
|
|
1612
1798
|
messages: [
|
|
1613
1799
|
{
|
|
1614
1800
|
role: 'user',
|
|
@@ -1708,7 +1894,7 @@ import { google } from '@ai-sdk/google';
|
|
|
1708
1894
|
import { generateText } from 'ai';
|
|
1709
1895
|
|
|
1710
1896
|
const { text, sources } = await generateText({
|
|
1711
|
-
model: google.interactions('gemini-
|
|
1897
|
+
model: google.interactions('gemini-4-argon'),
|
|
1712
1898
|
tools: {
|
|
1713
1899
|
google_search: google.tools.googleSearch({}),
|
|
1714
1900
|
},
|
|
@@ -1732,7 +1918,7 @@ const weatherTool = tool({
|
|
|
1732
1918
|
});
|
|
1733
1919
|
|
|
1734
1920
|
const { text, toolCalls } = await generateText({
|
|
1735
|
-
model: google.interactions('gemini-
|
|
1921
|
+
model: google.interactions('gemini-4-argon'),
|
|
1736
1922
|
tools: { getWeather: weatherTool },
|
|
1737
1923
|
stopWhen: isStepCount(5),
|
|
1738
1924
|
prompt: 'What is the weather in San Francisco right now?',
|
|
@@ -2031,7 +2217,7 @@ import { google } from '@ai-sdk/google';
|
|
|
2031
2217
|
import { streamText } from 'ai';
|
|
2032
2218
|
|
|
2033
2219
|
const result = streamText({
|
|
2034
|
-
model: google.interactions('gemini-
|
|
2220
|
+
model: google.interactions('gemini-4-argon'),
|
|
2035
2221
|
prompt: 'Hello, how are you?',
|
|
2036
2222
|
});
|
|
2037
2223
|
|
|
@@ -2411,14 +2597,14 @@ Older models continue to use labelled transcripts, such as
|
|
|
2411
2597
|
|
|
2412
2598
|
Create an experimental decision model with `google.decisionModel(modelId)`.
|
|
2413
2599
|
It uses Gemini structured output for Choice, Score, and Boolean questions. Choose a model
|
|
2414
|
-
that supports structured output, such as `gemini-
|
|
2600
|
+
that supports structured output, such as `gemini-4-argon`.
|
|
2415
2601
|
|
|
2416
2602
|
```ts
|
|
2417
2603
|
import { google } from '@ai-sdk/google';
|
|
2418
2604
|
import { experimental_decide } from 'ai';
|
|
2419
2605
|
|
|
2420
2606
|
const { answers } = await experimental_decide({
|
|
2421
|
-
model: google.decisionModel('gemini-
|
|
2607
|
+
model: google.decisionModel('gemini-4-argon'),
|
|
2422
2608
|
state: 'I was charged twice.',
|
|
2423
2609
|
questions: {
|
|
2424
2610
|
requestsRefund: {
|
|
@@ -2432,7 +2618,7 @@ const { answers } = await experimental_decide({
|
|
|
2432
2618
|
},
|
|
2433
2619
|
},
|
|
2434
2620
|
providerOptions: {
|
|
2435
|
-
google: { thinkingConfig: { thinkingLevel: '
|
|
2621
|
+
google: { thinkingConfig: { thinkingLevel: 'low' } },
|
|
2436
2622
|
},
|
|
2437
2623
|
});
|
|
2438
2624
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/google",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.96",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@ai-sdk/provider": "4.0.27",
|
|
39
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.60"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@ai-sdk/test-server": "2.0.4",
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ParseResult } from '@ai-sdk/provider-utils';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Concatenates the event streams of a long decode response that spans several
|
|
5
|
+
* requests (Gemini 4 long decode).
|
|
6
|
+
*
|
|
7
|
+
* Events of the current stream are passed through unchanged. When an event
|
|
8
|
+
* signals that the per-request cap was reached while budget remains
|
|
9
|
+
* (`getContinuationToken` returns a token), the next request is sent with that
|
|
10
|
+
* token once the current stream ends, and its events are appended. If the
|
|
11
|
+
* continuation request fails, the error is emitted as a failed parse result
|
|
12
|
+
* and the stream ends.
|
|
13
|
+
*/
|
|
14
|
+
export function continueGoogleStream<T>({
|
|
15
|
+
stream,
|
|
16
|
+
getContinuationToken,
|
|
17
|
+
continueStream,
|
|
18
|
+
}: {
|
|
19
|
+
stream: ReadableStream<ParseResult<T>>;
|
|
20
|
+
getContinuationToken: (value: T) => string | undefined;
|
|
21
|
+
continueStream: (
|
|
22
|
+
continuationToken: string,
|
|
23
|
+
) => Promise<ReadableStream<ParseResult<T>>>;
|
|
24
|
+
}): ReadableStream<ParseResult<T>> {
|
|
25
|
+
let reader = stream.getReader();
|
|
26
|
+
let pendingContinuationToken: string | undefined;
|
|
27
|
+
|
|
28
|
+
return new ReadableStream<ParseResult<T>>({
|
|
29
|
+
async pull(controller) {
|
|
30
|
+
while (true) {
|
|
31
|
+
const { done, value } = await reader.read();
|
|
32
|
+
|
|
33
|
+
if (!done) {
|
|
34
|
+
if (value.success) {
|
|
35
|
+
const token = getContinuationToken(value.value);
|
|
36
|
+
if (token != null) {
|
|
37
|
+
pendingContinuationToken = token;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
controller.enqueue(value);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (pendingContinuationToken == null) {
|
|
45
|
+
controller.close();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const continuationToken = pendingContinuationToken;
|
|
50
|
+
pendingContinuationToken = undefined;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
reader = (await continueStream(continuationToken)).getReader();
|
|
54
|
+
} catch (error) {
|
|
55
|
+
// Surfaced as an `error` stream part, followed by the `finish` part
|
|
56
|
+
// with the last continuation token so the caller can resume.
|
|
57
|
+
controller.enqueue({
|
|
58
|
+
success: false,
|
|
59
|
+
error: error as Extract<
|
|
60
|
+
ParseResult<T>,
|
|
61
|
+
{ success: false }
|
|
62
|
+
>['error'],
|
|
63
|
+
rawValue: undefined,
|
|
64
|
+
});
|
|
65
|
+
controller.close();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
async cancel(reason) {
|
|
72
|
+
await reader.cancel(reason);
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|