@ai-sdk/openai 4.0.9 → 4.0.11
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 +22 -3
- package/dist/index.js +330 -76
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +16 -3
- package/dist/internal/index.js +329 -75
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +123 -87
- package/package.json +3 -3
- package/src/chat/convert-openai-chat-usage.ts +5 -2
- package/src/chat/convert-to-openai-chat-messages.ts +114 -7
- package/src/chat/openai-chat-api.ts +2 -0
- package/src/chat/openai-chat-language-model-options.ts +20 -2
- package/src/chat/openai-chat-language-model.ts +1 -0
- package/src/chat/openai-chat-prompt.ts +8 -4
- package/src/openai-language-model-capabilities.ts +2 -1
- package/src/responses/convert-openai-responses-usage.ts +5 -2
- package/src/responses/convert-to-openai-responses-input.ts +123 -6
- package/src/responses/openai-responses-api.ts +77 -11
- package/src/responses/openai-responses-language-model-options.ts +40 -7
- package/src/responses/openai-responses-language-model.ts +37 -1
- package/src/responses/openai-responses-provider-metadata.ts +1 -0
package/docs/03-openai.mdx
CHANGED
|
@@ -11,21 +11,7 @@ The [OpenAI](https://openai.com/) provider contains language model support for t
|
|
|
11
11
|
|
|
12
12
|
The OpenAI provider is available in the `@ai-sdk/openai` module. You can install it with
|
|
13
13
|
|
|
14
|
-
<
|
|
15
|
-
<Tab>
|
|
16
|
-
<Snippet text="pnpm add @ai-sdk/openai" dark />
|
|
17
|
-
</Tab>
|
|
18
|
-
<Tab>
|
|
19
|
-
<Snippet text="npm install @ai-sdk/openai" dark />
|
|
20
|
-
</Tab>
|
|
21
|
-
<Tab>
|
|
22
|
-
<Snippet text="yarn add @ai-sdk/openai" dark />
|
|
23
|
-
</Tab>
|
|
24
|
-
|
|
25
|
-
<Tab>
|
|
26
|
-
<Snippet text="bun add @ai-sdk/openai" dark />
|
|
27
|
-
</Tab>
|
|
28
|
-
</Tabs>
|
|
14
|
+
<InstallPackages packages="@ai-sdk/openai" />
|
|
29
15
|
|
|
30
16
|
## Provider Instance
|
|
31
17
|
|
|
@@ -201,16 +187,20 @@ The following provider options are available:
|
|
|
201
187
|
- **user** _string_
|
|
202
188
|
A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. Defaults to `undefined`.
|
|
203
189
|
|
|
204
|
-
- **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'_
|
|
190
|
+
- **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'_
|
|
205
191
|
Reasoning effort for reasoning models. Defaults to `medium`. If you use `providerOptions` to set the `reasoningEffort` option, this model setting will be ignored.
|
|
206
192
|
|
|
207
193
|
<Note>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
OpenAI's GPT-5.1-Codex-Max model. Setting `reasoningEffort` to 'none' or
|
|
211
|
-
'xhigh' with unsupported models will result in an error.
|
|
194
|
+
Supported reasoning efforts vary by model. GPT-5.6 supports `'none'`, `'low'`,
|
|
195
|
+
`'medium'`, `'high'`, `'xhigh'`, and `'max'`.
|
|
212
196
|
</Note>
|
|
213
197
|
|
|
198
|
+
- **reasoningMode** _'standard' | 'pro'_
|
|
199
|
+
Controls how much model work GPT-5.6 performs before returning a final answer. `'standard'` is the default. Use `'pro'` for difficult tasks where quality matters more than latency and token usage.
|
|
200
|
+
|
|
201
|
+
- **reasoningContext** _'auto' | 'current_turn' | 'all_turns'_
|
|
202
|
+
Controls which available reasoning items GPT-5.6 can reuse. `'auto'` uses the model default, `'current_turn'` excludes reasoning from earlier turns, and `'all_turns'` makes compatible earlier reasoning available. The effective context is returned as `providerMetadata.openai.reasoningContext`.
|
|
203
|
+
|
|
214
204
|
- **reasoningSummary** _'auto' | 'detailed'_
|
|
215
205
|
Controls whether the model returns its reasoning process. Set to `'auto'` for a condensed summary, `'detailed'` for more comprehensive reasoning. Defaults to `undefined` (no reasoning summaries). When enabled, reasoning summaries appear in the stream as events with type `'reasoning'` and in non-streaming responses within the `reasoning` field.
|
|
216
206
|
|
|
@@ -252,8 +242,11 @@ The following provider options are available:
|
|
|
252
242
|
- **promptCacheKey** _string_
|
|
253
243
|
A cache key for manual prompt caching control. Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
|
|
254
244
|
|
|
245
|
+
- **promptCacheOptions** _object_
|
|
246
|
+
Configures prompt caching for GPT-5.6 and later models. `mode` can be `'implicit'` or `'explicit'`, and `ttl` currently only supports `'30m'`. In explicit mode, only content blocks marked with a prompt cache breakpoint are cached.
|
|
247
|
+
|
|
255
248
|
- **promptCacheRetention** _'in_memory' | '24h'_
|
|
256
|
-
The retention policy for
|
|
249
|
+
The legacy retention policy for models before GPT-5.6. Set to `'24h'` to enable extended prompt caching on supported models. For GPT-5.6 and later models, use `promptCacheOptions.ttl` instead.
|
|
257
250
|
|
|
258
251
|
- **safetyIdentifier** _string_
|
|
259
252
|
A stable identifier used to help detect users of your application that may be violating OpenAI's usage policies. The IDs should be a string that uniquely identifies each user.
|
|
@@ -285,7 +278,8 @@ const providerMetadata = result.providerMetadata as
|
|
|
285
278
|
| OpenaiResponsesProviderMetadata
|
|
286
279
|
| undefined;
|
|
287
280
|
|
|
288
|
-
const { responseId, logprobs, serviceTier } =
|
|
281
|
+
const { responseId, logprobs, serviceTier, reasoningContext } =
|
|
282
|
+
providerMetadata?.openai ?? {};
|
|
289
283
|
|
|
290
284
|
// responseId can be used to continue a conversation (previousResponseId).
|
|
291
285
|
console.log(responseId);
|
|
@@ -299,6 +293,8 @@ The following OpenAI-specific metadata may be returned:
|
|
|
299
293
|
Log probabilities of output tokens (when enabled).
|
|
300
294
|
- **serviceTier** _(optional)_
|
|
301
295
|
Service tier information returned by the API.
|
|
296
|
+
- **reasoningContext** _(optional)_
|
|
297
|
+
Effective persisted-reasoning context returned by GPT-5.6 (`'current_turn'` or `'all_turns'`).
|
|
302
298
|
|
|
303
299
|
#### Reasoning Output
|
|
304
300
|
|
|
@@ -363,20 +359,7 @@ The [`ai-sdk-openai-websocket-fetch`](https://www.npmjs.com/package/ai-sdk-opena
|
|
|
363
359
|
package provides a drop-in `fetch` replacement that routes streaming requests
|
|
364
360
|
through a persistent WebSocket connection.
|
|
365
361
|
|
|
366
|
-
<
|
|
367
|
-
<Tab>
|
|
368
|
-
<Snippet text="pnpm add ai-sdk-openai-websocket-fetch" dark />
|
|
369
|
-
</Tab>
|
|
370
|
-
<Tab>
|
|
371
|
-
<Snippet text="npm install ai-sdk-openai-websocket-fetch" dark />
|
|
372
|
-
</Tab>
|
|
373
|
-
<Tab>
|
|
374
|
-
<Snippet text="yarn add ai-sdk-openai-websocket-fetch" dark />
|
|
375
|
-
</Tab>
|
|
376
|
-
<Tab>
|
|
377
|
-
<Snippet text="bun add ai-sdk-openai-websocket-fetch" dark />
|
|
378
|
-
</Tab>
|
|
379
|
-
</Tabs>
|
|
362
|
+
<InstallPackages packages="ai-sdk-openai-websocket-fetch" />
|
|
380
363
|
|
|
381
364
|
Pass the WebSocket fetch to `createOpenAI` via the `fetch` option:
|
|
382
365
|
|
|
@@ -1791,12 +1774,14 @@ The following optional provider options are available for OpenAI chat models:
|
|
|
1791
1774
|
A unique identifier representing your end-user, which can help OpenAI to
|
|
1792
1775
|
monitor and detect abuse. [Learn more](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids).
|
|
1793
1776
|
|
|
1794
|
-
- **reasoningEffort** _'minimal' | 'low' | 'medium' | 'high' | 'xhigh'_
|
|
1777
|
+
- **reasoningEffort** _'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'_
|
|
1795
1778
|
|
|
1796
1779
|
Reasoning effort for reasoning models. Defaults to `medium`. If you use
|
|
1797
1780
|
`providerOptions` to set the `reasoningEffort` option, this
|
|
1798
1781
|
model setting will be ignored.
|
|
1799
1782
|
|
|
1783
|
+
Supported reasoning efforts vary by model. GPT-5.6 supports `'none'`, `'low'`, `'medium'`, `'high'`, `'xhigh'`, and `'max'`.
|
|
1784
|
+
|
|
1800
1785
|
- **maxCompletionTokens** _number_
|
|
1801
1786
|
|
|
1802
1787
|
Maximum number of completion tokens to generate. Useful for reasoning models.
|
|
@@ -1834,9 +1819,13 @@ The following optional provider options are available for OpenAI chat models:
|
|
|
1834
1819
|
|
|
1835
1820
|
A cache key for manual prompt caching control. Used by OpenAI to cache responses for similar requests to optimize your cache hit rates.
|
|
1836
1821
|
|
|
1822
|
+
- **promptCacheOptions** _object_
|
|
1823
|
+
|
|
1824
|
+
Configures prompt caching for GPT-5.6 and later models. `mode` can be `'implicit'` or `'explicit'`, and `ttl` currently only supports `'30m'`. In explicit mode, only content blocks marked with a prompt cache breakpoint are cached.
|
|
1825
|
+
|
|
1837
1826
|
- **promptCacheRetention** _'in_memory' | '24h'_
|
|
1838
1827
|
|
|
1839
|
-
The retention policy for
|
|
1828
|
+
The legacy retention policy for models before GPT-5.6. Set to `'24h'` to enable extended prompt caching on supported models. For GPT-5.6 and later models, use `promptCacheOptions.ttl` instead.
|
|
1840
1829
|
|
|
1841
1830
|
- **safetyIdentifier** _string_
|
|
1842
1831
|
|
|
@@ -2138,7 +2127,7 @@ const rejectedPredictionTokens = openaiMetadata?.rejectedPredictionTokens;
|
|
|
2138
2127
|
|
|
2139
2128
|
#### Image Detail
|
|
2140
2129
|
|
|
2141
|
-
You can use the `openai` provider option to set the [image input detail](https://platform.openai.com/docs/guides/images-vision?api-mode=responses#specify-image-input-detail-level) to `high`, `low`, or `auto`:
|
|
2130
|
+
You can use the `openai` provider option to set the [image input detail](https://platform.openai.com/docs/guides/images-vision?api-mode=responses#specify-image-input-detail-level) to `high`, `low`, `original`, or `auto`:
|
|
2142
2131
|
|
|
2143
2132
|
```ts highlight="13-16"
|
|
2144
2133
|
const result = await generateText({
|
|
@@ -2164,6 +2153,8 @@ const result = await generateText({
|
|
|
2164
2153
|
});
|
|
2165
2154
|
```
|
|
2166
2155
|
|
|
2156
|
+
For GPT-5.6, `original` preserves the input dimensions without resizing to a patch budget or pixel-dimension limit. `auto` and an omitted detail setting use the same sizing behavior as `original`, which can increase input token usage for large images.
|
|
2157
|
+
|
|
2167
2158
|
<Note type="warning">
|
|
2168
2159
|
Because the `UIMessage` type (used by AI SDK UI hooks like `useChat`) does not
|
|
2169
2160
|
support the `providerOptions` property, you can use `convertToModelMessages`
|
|
@@ -2213,9 +2204,8 @@ including `gpt-4o` and `gpt-4o-mini`.
|
|
|
2213
2204
|
- Prompt caching is automatically enabled for these models, when the prompt is 1024 tokens or longer. It does
|
|
2214
2205
|
not need to be explicitly enabled.
|
|
2215
2206
|
- You can use the response `usage` to access the number of prompt tokens that were a cache hit via `usage.inputTokenDetails.cacheReadTokens`.
|
|
2216
|
-
-
|
|
2217
|
-
|
|
2218
|
-
to an hour.
|
|
2207
|
+
- For GPT-5.6 and later models, `usage.inputTokenDetails.cacheWriteTokens` reports tokens written to the cache.
|
|
2208
|
+
- For GPT-5.6 and later models, `promptCacheOptions.ttl` sets a minimum cache lifetime of 30 minutes. Earlier models generally retain in-memory prefixes for 5-10 minutes of inactivity, up to one hour.
|
|
2219
2209
|
|
|
2220
2210
|
```ts highlight="11"
|
|
2221
2211
|
import { openai } from '@ai-sdk/openai';
|
|
@@ -2248,19 +2238,61 @@ const { text, usage } = await generateText({
|
|
|
2248
2238
|
console.log('Cached tokens:', usage.inputTokenDetails.cacheReadTokens);
|
|
2249
2239
|
```
|
|
2250
2240
|
|
|
2251
|
-
|
|
2241
|
+
GPT-5.6 and later models support explicit cache breakpoints on text, image, and file content blocks. Set a request-level cache key and mark the end of each reusable prefix with `promptCacheBreakpoint`:
|
|
2242
|
+
|
|
2243
|
+
```ts highlight="9-12,20-28"
|
|
2244
|
+
import {
|
|
2245
|
+
openai,
|
|
2246
|
+
type OpenAILanguageModelResponsesOptions,
|
|
2247
|
+
} from '@ai-sdk/openai';
|
|
2248
|
+
import { generateText } from 'ai';
|
|
2249
|
+
|
|
2250
|
+
const { usage } = await generateText({
|
|
2251
|
+
model: openai('gpt-5.6'),
|
|
2252
|
+
providerOptions: {
|
|
2253
|
+
openai: {
|
|
2254
|
+
promptCacheKey: 'tenant:acme:support-v1',
|
|
2255
|
+
promptCacheOptions: { mode: 'explicit', ttl: '30m' },
|
|
2256
|
+
} satisfies OpenAILanguageModelResponsesOptions,
|
|
2257
|
+
},
|
|
2258
|
+
messages: [
|
|
2259
|
+
{
|
|
2260
|
+
role: 'user',
|
|
2261
|
+
content: [
|
|
2262
|
+
{
|
|
2263
|
+
type: 'text',
|
|
2264
|
+
text: `A stable prefix of at least 1024 tokens...`,
|
|
2265
|
+
providerOptions: {
|
|
2266
|
+
openai: {
|
|
2267
|
+
promptCacheBreakpoint: { mode: 'explicit' },
|
|
2268
|
+
},
|
|
2269
|
+
},
|
|
2270
|
+
},
|
|
2271
|
+
{ type: 'text', text: 'What should I do next?' },
|
|
2272
|
+
],
|
|
2273
|
+
},
|
|
2274
|
+
],
|
|
2275
|
+
});
|
|
2276
|
+
|
|
2277
|
+
console.log('Cache reads:', usage.inputTokenDetails.cacheReadTokens);
|
|
2278
|
+
console.log('Cache writes:', usage.inputTokenDetails.cacheWriteTokens);
|
|
2279
|
+
```
|
|
2280
|
+
|
|
2281
|
+
In `'implicit'` mode, OpenAI places an automatic breakpoint on the latest message and also honors explicit breakpoints. In `'explicit'` mode, only marked content blocks are eligible for caching; a request without any explicit breakpoint does not use prompt caching.
|
|
2282
|
+
|
|
2283
|
+
For models before GPT-5.6 that support extended caching, you can keep cached prefixes active for up to 24 hours:
|
|
2252
2284
|
|
|
2253
2285
|
```ts highlight="7-12"
|
|
2254
2286
|
import { openai, type OpenAILanguageModelChatOptions } from '@ai-sdk/openai';
|
|
2255
2287
|
import { generateText } from 'ai';
|
|
2256
2288
|
|
|
2257
2289
|
const { text, usage } = await generateText({
|
|
2258
|
-
model: openai.chat('gpt-5.
|
|
2290
|
+
model: openai.chat('gpt-5.5'),
|
|
2259
2291
|
prompt: `A 1024-token or longer prompt...`,
|
|
2260
2292
|
providerOptions: {
|
|
2261
2293
|
openai: {
|
|
2262
2294
|
promptCacheKey: 'my-custom-cache-key-123',
|
|
2263
|
-
promptCacheRetention: '24h',
|
|
2295
|
+
promptCacheRetention: '24h',
|
|
2264
2296
|
} satisfies OpenAILanguageModelChatOptions,
|
|
2265
2297
|
},
|
|
2266
2298
|
});
|
|
@@ -2374,32 +2406,36 @@ The following optional provider options are available for OpenAI completion mode
|
|
|
2374
2406
|
|
|
2375
2407
|
### Model Capabilities
|
|
2376
2408
|
|
|
2377
|
-
| Model | Image Input
|
|
2378
|
-
| --------------------- |
|
|
2379
|
-
| `gpt-5.
|
|
2380
|
-
| `gpt-5.
|
|
2381
|
-
| `gpt-5.
|
|
2382
|
-
| `gpt-5.
|
|
2383
|
-
| `gpt-5.
|
|
2384
|
-
| `gpt-5.
|
|
2385
|
-
| `gpt-5.
|
|
2386
|
-
| `gpt-5.
|
|
2387
|
-
| `gpt-5.
|
|
2388
|
-
| `gpt-5.
|
|
2389
|
-
| `gpt-5.
|
|
2390
|
-
| `gpt-5.
|
|
2391
|
-
| `gpt-5.
|
|
2392
|
-
| `gpt-5-
|
|
2393
|
-
| `gpt-5`
|
|
2394
|
-
| `gpt-5-
|
|
2395
|
-
| `gpt-5
|
|
2396
|
-
| `gpt-5-
|
|
2397
|
-
| `gpt-5
|
|
2398
|
-
| `gpt-
|
|
2399
|
-
| `gpt-
|
|
2400
|
-
| `gpt-
|
|
2401
|
-
| `gpt-
|
|
2402
|
-
| `gpt-
|
|
2409
|
+
| Model | Image Input | Audio Input | Object Generation | Tool Usage |
|
|
2410
|
+
| --------------------- | ----------- | ----------- | ----------------- | ---------- |
|
|
2411
|
+
| `gpt-5.6` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2412
|
+
| `gpt-5.6-luna` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2413
|
+
| `gpt-5.6-sol` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2414
|
+
| `gpt-5.6-terra` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2415
|
+
| `gpt-5.5` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2416
|
+
| `gpt-5.4-pro` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2417
|
+
| `gpt-5.4` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2418
|
+
| `gpt-5.4-mini` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2419
|
+
| `gpt-5.4-nano` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2420
|
+
| `gpt-5.3-chat-latest` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2421
|
+
| `gpt-5.2-pro` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2422
|
+
| `gpt-5.2-chat-latest` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2423
|
+
| `gpt-5.2` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2424
|
+
| `gpt-5.1-codex-mini` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2425
|
+
| `gpt-5.1-codex` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2426
|
+
| `gpt-5.1-chat-latest` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2427
|
+
| `gpt-5.1` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2428
|
+
| `gpt-5-pro` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2429
|
+
| `gpt-5` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2430
|
+
| `gpt-5-mini` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2431
|
+
| `gpt-5-nano` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2432
|
+
| `gpt-5-codex` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2433
|
+
| `gpt-5-chat-latest` | <Check /> | <Cross /> | <Cross /> | <Cross /> |
|
|
2434
|
+
| `gpt-4.1` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2435
|
+
| `gpt-4.1-mini` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2436
|
+
| `gpt-4.1-nano` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2437
|
+
| `gpt-4o` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2438
|
+
| `gpt-4o-mini` | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
2403
2439
|
|
|
2404
2440
|
<Note>
|
|
2405
2441
|
The table above lists popular models. Please see the [OpenAI
|
|
@@ -2475,11 +2511,11 @@ The following optional provider options are available for OpenAI embedding model
|
|
|
2475
2511
|
|
|
2476
2512
|
### Model Capabilities
|
|
2477
2513
|
|
|
2478
|
-
| Model | Default Dimensions | Custom Dimensions
|
|
2479
|
-
| ------------------------ | ------------------ |
|
|
2480
|
-
| `text-embedding-3-large` | 3072 | <Check
|
|
2481
|
-
| `text-embedding-3-small` | 1536 | <Check
|
|
2482
|
-
| `text-embedding-ada-002` | 1536 | <Cross
|
|
2514
|
+
| Model | Default Dimensions | Custom Dimensions |
|
|
2515
|
+
| ------------------------ | ------------------ | ----------------- |
|
|
2516
|
+
| `text-embedding-3-large` | 3072 | <Check /> |
|
|
2517
|
+
| `text-embedding-3-small` | 1536 | <Check /> |
|
|
2518
|
+
| `text-embedding-ada-002` | 1536 | <Cross /> |
|
|
2483
2519
|
|
|
2484
2520
|
## Image Models
|
|
2485
2521
|
|
|
@@ -2709,12 +2745,12 @@ The following provider options are available:
|
|
|
2709
2745
|
|
|
2710
2746
|
### Model Capabilities
|
|
2711
2747
|
|
|
2712
|
-
| Model | Transcription
|
|
2713
|
-
| ------------------------ |
|
|
2714
|
-
| `whisper-1` | <Check
|
|
2715
|
-
| `gpt-4o-mini-transcribe` | <Check
|
|
2716
|
-
| `gpt-4o-transcribe` | <Check
|
|
2717
|
-
| `gpt-realtime-whisper` | <Cross
|
|
2748
|
+
| Model | Transcription | Streaming | Duration | Segments | Language |
|
|
2749
|
+
| ------------------------ | ------------- | --------- | --------- | --------- | --------- |
|
|
2750
|
+
| `whisper-1` | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> |
|
|
2751
|
+
| `gpt-4o-mini-transcribe` | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
2752
|
+
| `gpt-4o-transcribe` | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
2753
|
+
| `gpt-realtime-whisper` | <Cross /> | <Check /> | <Cross /> | <Cross /> | <Cross /> |
|
|
2718
2754
|
|
|
2719
2755
|
## Speech Models
|
|
2720
2756
|
|
|
@@ -2771,8 +2807,8 @@ const result = await generateSpeech({
|
|
|
2771
2807
|
|
|
2772
2808
|
### Model Capabilities
|
|
2773
2809
|
|
|
2774
|
-
| Model | Instructions
|
|
2775
|
-
| ----------------- |
|
|
2776
|
-
| `tts-1` | <Check
|
|
2777
|
-
| `tts-1-hd` | <Check
|
|
2778
|
-
| `gpt-4o-mini-tts` | <Check
|
|
2810
|
+
| Model | Instructions |
|
|
2811
|
+
| ----------------- | ------------ |
|
|
2812
|
+
| `tts-1` | <Check /> |
|
|
2813
|
+
| `tts-1-hd` | <Check /> |
|
|
2814
|
+
| `gpt-4o-mini-tts` | <Check /> |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.11",
|
|
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.3",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.7"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "22.19.19",
|
|
@@ -6,6 +6,7 @@ export type OpenAIChatUsage = {
|
|
|
6
6
|
total_tokens?: number | null;
|
|
7
7
|
prompt_tokens_details?: {
|
|
8
8
|
cached_tokens?: number | null;
|
|
9
|
+
cache_write_tokens?: number | null;
|
|
9
10
|
} | null;
|
|
10
11
|
completion_tokens_details?: {
|
|
11
12
|
reasoning_tokens?: number | null;
|
|
@@ -37,15 +38,17 @@ export function convertOpenAIChatUsage(
|
|
|
37
38
|
const promptTokens = usage.prompt_tokens ?? 0;
|
|
38
39
|
const completionTokens = usage.completion_tokens ?? 0;
|
|
39
40
|
const cachedTokens = usage.prompt_tokens_details?.cached_tokens ?? 0;
|
|
41
|
+
const cacheWriteTokens =
|
|
42
|
+
usage.prompt_tokens_details?.cache_write_tokens ?? undefined;
|
|
40
43
|
const reasoningTokens =
|
|
41
44
|
usage.completion_tokens_details?.reasoning_tokens ?? 0;
|
|
42
45
|
|
|
43
46
|
return {
|
|
44
47
|
inputTokens: {
|
|
45
48
|
total: promptTokens,
|
|
46
|
-
noCache: promptTokens - cachedTokens,
|
|
49
|
+
noCache: promptTokens - cachedTokens - (cacheWriteTokens ?? 0),
|
|
47
50
|
cacheRead: cachedTokens,
|
|
48
|
-
cacheWrite:
|
|
51
|
+
cacheWrite: cacheWriteTokens,
|
|
49
52
|
},
|
|
50
53
|
outputTokens: {
|
|
51
54
|
total: completionTokens,
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
UnsupportedFunctionalityError,
|
|
3
3
|
type SharedV4Warning,
|
|
4
4
|
type LanguageModelV4Prompt,
|
|
5
|
+
type SharedV4ProviderOptions,
|
|
5
6
|
} from '@ai-sdk/provider';
|
|
6
7
|
import type { OpenAIChatPrompt } from './openai-chat-prompt';
|
|
7
8
|
import {
|
|
@@ -15,6 +16,16 @@ function serializeToolCallArguments(input: unknown): string {
|
|
|
15
16
|
return JSON.stringify(input === undefined ? {} : input);
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
type OpenAIPromptCacheBreakpoint = { mode: 'explicit' };
|
|
20
|
+
|
|
21
|
+
function getPromptCacheBreakpoint(
|
|
22
|
+
providerOptions: SharedV4ProviderOptions | undefined,
|
|
23
|
+
): OpenAIPromptCacheBreakpoint | undefined {
|
|
24
|
+
return providerOptions?.openai?.promptCacheBreakpoint as
|
|
25
|
+
| OpenAIPromptCacheBreakpoint
|
|
26
|
+
| undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
export function convertToOpenAIChatMessages({
|
|
19
30
|
prompt,
|
|
20
31
|
systemMessageMode = 'system',
|
|
@@ -28,16 +39,44 @@ export function convertToOpenAIChatMessages({
|
|
|
28
39
|
const messages: OpenAIChatPrompt = [];
|
|
29
40
|
const warnings: Array<SharedV4Warning> = [];
|
|
30
41
|
|
|
31
|
-
for (const { role, content } of prompt) {
|
|
42
|
+
for (const { role, content, providerOptions } of prompt) {
|
|
32
43
|
switch (role) {
|
|
33
44
|
case 'system': {
|
|
34
45
|
switch (systemMessageMode) {
|
|
35
46
|
case 'system': {
|
|
36
|
-
|
|
47
|
+
const promptCacheBreakpoint =
|
|
48
|
+
getPromptCacheBreakpoint(providerOptions);
|
|
49
|
+
messages.push({
|
|
50
|
+
role: 'system',
|
|
51
|
+
content:
|
|
52
|
+
promptCacheBreakpoint == null
|
|
53
|
+
? content
|
|
54
|
+
: [
|
|
55
|
+
{
|
|
56
|
+
type: 'text',
|
|
57
|
+
text: content,
|
|
58
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
});
|
|
37
62
|
break;
|
|
38
63
|
}
|
|
39
64
|
case 'developer': {
|
|
40
|
-
|
|
65
|
+
const promptCacheBreakpoint =
|
|
66
|
+
getPromptCacheBreakpoint(providerOptions);
|
|
67
|
+
messages.push({
|
|
68
|
+
role: 'developer',
|
|
69
|
+
content:
|
|
70
|
+
promptCacheBreakpoint == null
|
|
71
|
+
? content
|
|
72
|
+
: [
|
|
73
|
+
{
|
|
74
|
+
type: 'text',
|
|
75
|
+
text: content,
|
|
76
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|
|
41
80
|
break;
|
|
42
81
|
}
|
|
43
82
|
case 'remove': {
|
|
@@ -58,7 +97,11 @@ export function convertToOpenAIChatMessages({
|
|
|
58
97
|
}
|
|
59
98
|
|
|
60
99
|
case 'user': {
|
|
61
|
-
if (
|
|
100
|
+
if (
|
|
101
|
+
content.length === 1 &&
|
|
102
|
+
content[0].type === 'text' &&
|
|
103
|
+
getPromptCacheBreakpoint(content[0].providerOptions) == null
|
|
104
|
+
) {
|
|
62
105
|
messages.push({ role: 'user', content: content[0].text });
|
|
63
106
|
break;
|
|
64
107
|
}
|
|
@@ -68,9 +111,21 @@ export function convertToOpenAIChatMessages({
|
|
|
68
111
|
content: content.map((part, index) => {
|
|
69
112
|
switch (part.type) {
|
|
70
113
|
case 'text': {
|
|
71
|
-
|
|
114
|
+
const promptCacheBreakpoint = getPromptCacheBreakpoint(
|
|
115
|
+
part.providerOptions,
|
|
116
|
+
);
|
|
117
|
+
return {
|
|
118
|
+
type: 'text',
|
|
119
|
+
text: part.text,
|
|
120
|
+
...(promptCacheBreakpoint != null && {
|
|
121
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
122
|
+
}),
|
|
123
|
+
};
|
|
72
124
|
}
|
|
73
125
|
case 'file': {
|
|
126
|
+
const promptCacheBreakpoint = getPromptCacheBreakpoint(
|
|
127
|
+
part.providerOptions,
|
|
128
|
+
);
|
|
74
129
|
switch (part.data.type) {
|
|
75
130
|
case 'reference': {
|
|
76
131
|
return {
|
|
@@ -81,6 +136,9 @@ export function convertToOpenAIChatMessages({
|
|
|
81
136
|
provider: 'openai',
|
|
82
137
|
}),
|
|
83
138
|
},
|
|
139
|
+
...(promptCacheBreakpoint != null && {
|
|
140
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
141
|
+
}),
|
|
84
142
|
};
|
|
85
143
|
}
|
|
86
144
|
case 'text': {
|
|
@@ -103,6 +161,9 @@ export function convertToOpenAIChatMessages({
|
|
|
103
161
|
|
|
104
162
|
detail: part.providerOptions?.openai?.imageDetail,
|
|
105
163
|
},
|
|
164
|
+
...(promptCacheBreakpoint != null && {
|
|
165
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
166
|
+
}),
|
|
106
167
|
};
|
|
107
168
|
} else if (topLevel === 'audio') {
|
|
108
169
|
if (part.data.type === 'url') {
|
|
@@ -121,6 +182,9 @@ export function convertToOpenAIChatMessages({
|
|
|
121
182
|
data: convertToBase64(part.data.data),
|
|
122
183
|
format: 'wav',
|
|
123
184
|
},
|
|
185
|
+
...(promptCacheBreakpoint != null && {
|
|
186
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
187
|
+
}),
|
|
124
188
|
};
|
|
125
189
|
}
|
|
126
190
|
case 'audio/mp3':
|
|
@@ -131,6 +195,9 @@ export function convertToOpenAIChatMessages({
|
|
|
131
195
|
data: convertToBase64(part.data.data),
|
|
132
196
|
format: 'mp3',
|
|
133
197
|
},
|
|
198
|
+
...(promptCacheBreakpoint != null && {
|
|
199
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
200
|
+
}),
|
|
134
201
|
};
|
|
135
202
|
}
|
|
136
203
|
|
|
@@ -161,6 +228,9 @@ export function convertToOpenAIChatMessages({
|
|
|
161
228
|
filename: part.filename ?? `part-${index}.pdf`,
|
|
162
229
|
file_data: `data:application/pdf;base64,${convertToBase64(part.data.data)}`,
|
|
163
230
|
},
|
|
231
|
+
...(promptCacheBreakpoint != null && {
|
|
232
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
233
|
+
}),
|
|
164
234
|
};
|
|
165
235
|
}
|
|
166
236
|
}
|
|
@@ -175,6 +245,12 @@ export function convertToOpenAIChatMessages({
|
|
|
175
245
|
|
|
176
246
|
case 'assistant': {
|
|
177
247
|
let text = '';
|
|
248
|
+
const textParts: Array<{
|
|
249
|
+
type: 'text';
|
|
250
|
+
text: string;
|
|
251
|
+
prompt_cache_breakpoint?: OpenAIPromptCacheBreakpoint;
|
|
252
|
+
}> = [];
|
|
253
|
+
let hasPromptCacheBreakpoint = false;
|
|
178
254
|
const toolCalls: Array<{
|
|
179
255
|
id: string;
|
|
180
256
|
type: 'function';
|
|
@@ -184,7 +260,18 @@ export function convertToOpenAIChatMessages({
|
|
|
184
260
|
for (const part of content) {
|
|
185
261
|
switch (part.type) {
|
|
186
262
|
case 'text': {
|
|
263
|
+
const promptCacheBreakpoint = getPromptCacheBreakpoint(
|
|
264
|
+
part.providerOptions,
|
|
265
|
+
);
|
|
187
266
|
text += part.text;
|
|
267
|
+
textParts.push({
|
|
268
|
+
type: 'text',
|
|
269
|
+
text: part.text,
|
|
270
|
+
...(promptCacheBreakpoint != null && {
|
|
271
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
272
|
+
}),
|
|
273
|
+
});
|
|
274
|
+
hasPromptCacheBreakpoint ||= promptCacheBreakpoint != null;
|
|
188
275
|
break;
|
|
189
276
|
}
|
|
190
277
|
case 'tool-call': {
|
|
@@ -203,7 +290,11 @@ export function convertToOpenAIChatMessages({
|
|
|
203
290
|
|
|
204
291
|
messages.push({
|
|
205
292
|
role: 'assistant',
|
|
206
|
-
content:
|
|
293
|
+
content: hasPromptCacheBreakpoint
|
|
294
|
+
? textParts
|
|
295
|
+
: toolCalls.length > 0
|
|
296
|
+
? text || null
|
|
297
|
+
: text,
|
|
207
298
|
tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
208
299
|
});
|
|
209
300
|
|
|
@@ -216,6 +307,13 @@ export function convertToOpenAIChatMessages({
|
|
|
216
307
|
continue;
|
|
217
308
|
}
|
|
218
309
|
const output = toolResponse.output;
|
|
310
|
+
const promptCacheBreakpoint =
|
|
311
|
+
(output.type === 'content'
|
|
312
|
+
? output.value
|
|
313
|
+
.map(part => getPromptCacheBreakpoint(part.providerOptions))
|
|
314
|
+
.find(breakpoint => breakpoint != null)
|
|
315
|
+
: getPromptCacheBreakpoint(output.providerOptions)) ??
|
|
316
|
+
getPromptCacheBreakpoint(toolResponse.providerOptions);
|
|
219
317
|
|
|
220
318
|
let contentValue: string;
|
|
221
319
|
switch (output.type) {
|
|
@@ -236,7 +334,16 @@ export function convertToOpenAIChatMessages({
|
|
|
236
334
|
messages.push({
|
|
237
335
|
role: 'tool',
|
|
238
336
|
tool_call_id: toolResponse.toolCallId,
|
|
239
|
-
content:
|
|
337
|
+
content:
|
|
338
|
+
promptCacheBreakpoint == null
|
|
339
|
+
? contentValue
|
|
340
|
+
: [
|
|
341
|
+
{
|
|
342
|
+
type: 'text',
|
|
343
|
+
text: contentValue,
|
|
344
|
+
prompt_cache_breakpoint: promptCacheBreakpoint,
|
|
345
|
+
},
|
|
346
|
+
],
|
|
240
347
|
});
|
|
241
348
|
}
|
|
242
349
|
break;
|
|
@@ -92,6 +92,7 @@ export const openaiChatResponseSchema = lazySchema(() =>
|
|
|
92
92
|
prompt_tokens_details: z
|
|
93
93
|
.object({
|
|
94
94
|
cached_tokens: z.number().nullish(),
|
|
95
|
+
cache_write_tokens: z.number().nullish(),
|
|
95
96
|
})
|
|
96
97
|
.nullish(),
|
|
97
98
|
completion_tokens_details: z
|
|
@@ -180,6 +181,7 @@ export const openaiChatChunkSchema = lazySchema(() =>
|
|
|
180
181
|
prompt_tokens_details: z
|
|
181
182
|
.object({
|
|
182
183
|
cached_tokens: z.number().nullish(),
|
|
184
|
+
cache_write_tokens: z.number().nullish(),
|
|
183
185
|
})
|
|
184
186
|
.nullish(),
|
|
185
187
|
completion_tokens_details: z
|