@ai-sdk/openai 4.0.84 → 4.0.85
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 +27 -0
- package/dist/index.d.ts +56 -42
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +213 -19
- package/dist/index.js.map +1 -1
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +39 -10
- package/package.json +5 -5
- package/src/files/openai-files.ts +1 -1
- package/src/index.ts +2 -0
- package/src/openai-batch.ts +2 -0
- package/src/openai-decision-model-options.ts +19 -0
- package/src/openai-decision-model.ts +285 -0
- package/src/openai-provider.ts +20 -7
- package/src/skills/openai-skills.ts +5 -1
- package/src/transcription/openai-transcription-model.ts +1 -1
package/docs/03-openai.mdx
CHANGED
|
@@ -36,6 +36,15 @@ const openai = createOpenAI({
|
|
|
36
36
|
|
|
37
37
|
You can use the following optional settings to customize the OpenAI provider instance:
|
|
38
38
|
|
|
39
|
+
- **batchResultDownloads** _object_
|
|
40
|
+
|
|
41
|
+
Settings for downloading JSON Lines batch results.
|
|
42
|
+
- **maxLineBytes** _number_
|
|
43
|
+
|
|
44
|
+
Maximum UTF-8 bytes per row, excluding the LF delimiter. Defaults to 64 MiB
|
|
45
|
+
(67,108,864 bytes). Must be a positive safe integer. Oversized rows throw a
|
|
46
|
+
`DownloadError` and cancel the download.
|
|
47
|
+
|
|
39
48
|
- **baseURL** _string_
|
|
40
49
|
|
|
41
50
|
Use a different URL prefix for API calls, e.g. to use proxy servers.
|
|
@@ -3472,8 +3481,8 @@ const result = await generateSpeech({
|
|
|
3472
3481
|
## Decision Models
|
|
3473
3482
|
|
|
3474
3483
|
Create an experimental decision model with `openai.decisionModel(modelId)`.
|
|
3475
|
-
It uses the
|
|
3476
|
-
|
|
3484
|
+
It uses the native [Decisions API](https://developers.openai.com/api/docs/guides/decisions)
|
|
3485
|
+
to answer Choice, Score, and Boolean questions with `gpt-6-luna`.
|
|
3477
3486
|
|
|
3478
3487
|
```ts
|
|
3479
3488
|
import { openai } from '@ai-sdk/openai';
|
|
@@ -3496,17 +3505,37 @@ const { answers } = await experimental_decide({
|
|
|
3496
3505
|
});
|
|
3497
3506
|
```
|
|
3498
3507
|
|
|
3499
|
-
Scores are
|
|
3500
|
-
returned exactly as supplied.
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
not guaranteed to be calibrated. Apply thresholds in application code, for example
|
|
3508
|
+
Scores are probability-weighted fractional positions on the ordered rubric, starting
|
|
3509
|
+
at zero. Choice labels are returned exactly as supplied. Choice and Score answers
|
|
3510
|
+
include probability distributions. Boolean questions use the API's predicate
|
|
3511
|
+
primitive and return P(true). Apply thresholds in application code, for example
|
|
3504
3512
|
`answers.requestsRefund.probability >= 0.5`.
|
|
3505
3513
|
|
|
3514
|
+
Structured state, instructions, and criterion descriptions are serialized as JSON
|
|
3515
|
+
text. Score levels receive zero-based index labels. Non-null Boolean criteria are
|
|
3516
|
+
appended to predicate instructions under `Criteria for true:` and `Criteria for false:`.
|
|
3517
|
+
String criteria are passed through; structured criteria are serialized as JSON text.
|
|
3518
|
+
|
|
3506
3519
|
The factory respects `createOpenAI` settings, including custom fetch and base URL.
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3520
|
+
Set `providerOptions.openai.safetyIdentifier` to an opaque end-user identifier for
|
|
3521
|
+
safety monitoring (up to 128 characters). For example:
|
|
3522
|
+
|
|
3523
|
+
```ts
|
|
3524
|
+
providerOptions: {
|
|
3525
|
+
openai: { safetyIdentifier: 'user-123' } satisfies OpenAIDecisionModelOptions,
|
|
3526
|
+
}
|
|
3527
|
+
```
|
|
3528
|
+
|
|
3529
|
+
Import `OpenAIDecisionModelOptions` from `@ai-sdk/openai` when using the type above.
|
|
3530
|
+
Other OpenAI options are unsupported and produce warnings. Native confidence
|
|
3531
|
+
values are available in `providerMetadata.openai.confidence`, keyed by question ID.
|
|
3532
|
+
Input and output token counts are available in `usage`. The full native token usage
|
|
3533
|
+
(including cache, reasoning, and total counts) is preserved in
|
|
3534
|
+
`providerMetadata.openai.usage`. Response headers, the returned model ID, and the
|
|
3535
|
+
raw response body are preserved. If OpenAI refuses a question, the entire call
|
|
3536
|
+
throws `InvalidResponseDataError` with the question name and the raw response in
|
|
3537
|
+
`error.data`. Invalid answers also fail the entire decision.
|
|
3538
|
+
See [Decisions](/docs/ai-sdk-core/decisions).
|
|
3510
3539
|
|
|
3511
3540
|
Decision models can also be accessed through `customProvider` aliases or
|
|
3512
3541
|
`createProviderRegistry().decisionModel('provider:model')`. Direct string IDs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/openai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.85",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,15 +35,15 @@
|
|
|
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.23",
|
|
39
|
+
"@ai-sdk/provider-utils": "5.0.55"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@ai-sdk/test-server": "2.0.
|
|
42
|
+
"@ai-sdk/test-server": "2.0.4",
|
|
43
43
|
"@types/node": "22.19.19",
|
|
44
44
|
"@vercel/ai-tsconfig": "0.0.0",
|
|
45
45
|
"tsdown": "^0.23.0",
|
|
46
|
-
"typescript": "
|
|
46
|
+
"typescript": "6.0.3",
|
|
47
47
|
"zod": "3.25.76"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
@@ -148,7 +148,7 @@ export class OpenAIFiles implements FilesV4 {
|
|
|
148
148
|
} else {
|
|
149
149
|
const fileBytes = convertInlineFileDataToUint8Array(data);
|
|
150
150
|
|
|
151
|
-
const blob = new Blob([fileBytes], {
|
|
151
|
+
const blob = new Blob([fileBytes as Uint8Array<ArrayBuffer>], {
|
|
152
152
|
type: mediaType,
|
|
153
153
|
});
|
|
154
154
|
|
package/src/index.ts
CHANGED
|
@@ -60,3 +60,5 @@ export type {
|
|
|
60
60
|
OpenaiResponsesSourceDocumentProviderMetadata,
|
|
61
61
|
} from './responses/openai-responses-provider-metadata';
|
|
62
62
|
export { VERSION } from './version';
|
|
63
|
+
export type { OpenAIDecisionModelId } from './openai-decision-model';
|
|
64
|
+
export type { OpenAIDecisionModelOptions } from './openai-decision-model-options';
|
package/src/openai-batch.ts
CHANGED
|
@@ -181,6 +181,7 @@ export class OpenAIBatch implements BatchV4<OpenAIBatchModelIds> {
|
|
|
181
181
|
private readonly options: {
|
|
182
182
|
provider: string;
|
|
183
183
|
config: OpenAIConfig;
|
|
184
|
+
maxLineBytes?: number;
|
|
184
185
|
},
|
|
185
186
|
) {
|
|
186
187
|
this.provider = options.provider;
|
|
@@ -466,6 +467,7 @@ export class OpenAIBatch implements BatchV4<OpenAIBatchModelIds> {
|
|
|
466
467
|
failedResponseHandler: openaiFailedResponseHandler,
|
|
467
468
|
successfulResponseHandler: createJsonLinesResponseHandler(
|
|
468
469
|
openaiBatchResultLineSchema,
|
|
470
|
+
{ maxLineBytes: this.options.maxLineBytes },
|
|
469
471
|
),
|
|
470
472
|
abortSignal: options.abortSignal,
|
|
471
473
|
fetch: this.options.config.fetch,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lazySchema,
|
|
3
|
+
zodSchema,
|
|
4
|
+
type InferSchema,
|
|
5
|
+
} from '@ai-sdk/provider-utils';
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
|
|
8
|
+
export const openaiDecisionModelOptions = lazySchema(() =>
|
|
9
|
+
zodSchema(
|
|
10
|
+
z.object({
|
|
11
|
+
/** An opaque end-user identifier for safety monitoring, up to 128 characters. */
|
|
12
|
+
safetyIdentifier: z.string().max(128).optional(),
|
|
13
|
+
}),
|
|
14
|
+
),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export type OpenAIDecisionModelOptions = InferSchema<
|
|
18
|
+
typeof openaiDecisionModelOptions
|
|
19
|
+
>;
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InvalidResponseDataError,
|
|
3
|
+
type Experimental_DecisionModelV4 as DecisionModelV4,
|
|
4
|
+
type Experimental_DecisionModelV4Answer as DecisionModelV4Answer,
|
|
5
|
+
type Experimental_DecisionModelV4Input as DecisionModelV4Input,
|
|
6
|
+
} from '@ai-sdk/provider';
|
|
7
|
+
import {
|
|
8
|
+
combineHeaders,
|
|
9
|
+
createJsonResponseHandler,
|
|
10
|
+
postJsonToApi,
|
|
11
|
+
parseProviderOptions,
|
|
12
|
+
serializeModelOptions,
|
|
13
|
+
WORKFLOW_DESERIALIZE,
|
|
14
|
+
WORKFLOW_SERIALIZE,
|
|
15
|
+
} from '@ai-sdk/provider-utils';
|
|
16
|
+
import { z } from 'zod/v4';
|
|
17
|
+
import {
|
|
18
|
+
prepareOpenAIConfigForWorkflowDeserialize,
|
|
19
|
+
type OpenAIConfig,
|
|
20
|
+
} from './openai-config';
|
|
21
|
+
import { openaiFailedResponseHandler } from './openai-error';
|
|
22
|
+
import { openaiDecisionModelOptions } from './openai-decision-model-options';
|
|
23
|
+
|
|
24
|
+
export type OpenAIDecisionModelId = 'gpt-6-luna' | (string & {});
|
|
25
|
+
|
|
26
|
+
const probability = z.number().min(0).max(1);
|
|
27
|
+
const responseSchema = z.object({
|
|
28
|
+
model: z.string().nullish(),
|
|
29
|
+
usage: z
|
|
30
|
+
.object({
|
|
31
|
+
input_tokens: z.number().nullish(),
|
|
32
|
+
input_tokens_details: z
|
|
33
|
+
.object({
|
|
34
|
+
cached_tokens: z.number().nullish(),
|
|
35
|
+
cache_write_tokens: z.number().nullish(),
|
|
36
|
+
})
|
|
37
|
+
.nullish(),
|
|
38
|
+
output_tokens: z.number().nullish(),
|
|
39
|
+
output_tokens_details: z
|
|
40
|
+
.object({
|
|
41
|
+
reasoning_tokens: z.number().nullish(),
|
|
42
|
+
})
|
|
43
|
+
.nullish(),
|
|
44
|
+
total_tokens: z.number().nullish(),
|
|
45
|
+
})
|
|
46
|
+
.nullish(),
|
|
47
|
+
answers: z.array(
|
|
48
|
+
z.discriminatedUnion('type', [
|
|
49
|
+
z.object({ type: z.literal('refusal'), name: z.string().nullable() }),
|
|
50
|
+
z.object({
|
|
51
|
+
type: z.literal('predicate'),
|
|
52
|
+
name: z.string(),
|
|
53
|
+
probability,
|
|
54
|
+
}),
|
|
55
|
+
z.object({
|
|
56
|
+
type: z.literal('choice'),
|
|
57
|
+
name: z.string(),
|
|
58
|
+
choice: z.string(),
|
|
59
|
+
confidence: probability.nullish(),
|
|
60
|
+
probabilities: z.array(z.object({ value: z.string(), probability })),
|
|
61
|
+
}),
|
|
62
|
+
z.object({
|
|
63
|
+
type: z.literal('score'),
|
|
64
|
+
name: z.string(),
|
|
65
|
+
score: z.number(),
|
|
66
|
+
confidence: probability.nullish(),
|
|
67
|
+
probabilities: z.array(
|
|
68
|
+
z.object({ value: z.number().int().nonnegative(), probability }),
|
|
69
|
+
),
|
|
70
|
+
}),
|
|
71
|
+
]),
|
|
72
|
+
),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
function toText(input: DecisionModelV4Input): string {
|
|
76
|
+
return typeof input === 'string' ? input : JSON.stringify(input);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export class DecisionOpenAIModel implements DecisionModelV4 {
|
|
80
|
+
readonly specificationVersion = 'v4';
|
|
81
|
+
readonly supportedQuestionTypes = ['choice', 'score', 'boolean'] as const;
|
|
82
|
+
|
|
83
|
+
constructor(
|
|
84
|
+
readonly modelId: OpenAIDecisionModelId,
|
|
85
|
+
private readonly config: OpenAIConfig,
|
|
86
|
+
) {}
|
|
87
|
+
|
|
88
|
+
get provider() {
|
|
89
|
+
return this.config.provider;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static [WORKFLOW_SERIALIZE](model: DecisionOpenAIModel) {
|
|
93
|
+
return serializeModelOptions({
|
|
94
|
+
modelId: model.modelId,
|
|
95
|
+
config: model.config,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
100
|
+
modelId: OpenAIDecisionModelId;
|
|
101
|
+
config: Parameters<typeof prepareOpenAIConfigForWorkflowDeserialize>[0];
|
|
102
|
+
}) {
|
|
103
|
+
return new DecisionOpenAIModel(
|
|
104
|
+
options.modelId,
|
|
105
|
+
prepareOpenAIConfigForWorkflowDeserialize(options.config),
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** @deprecated Use `doDecide` instead. */
|
|
110
|
+
doEvaluate(options: Parameters<DecisionModelV4['doDecide']>[0]) {
|
|
111
|
+
return this.doDecide(options);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async doDecide({
|
|
115
|
+
state,
|
|
116
|
+
questions,
|
|
117
|
+
headers,
|
|
118
|
+
abortSignal,
|
|
119
|
+
providerOptions,
|
|
120
|
+
}: Parameters<DecisionModelV4['doDecide']>[0]): Promise<
|
|
121
|
+
Awaited<ReturnType<DecisionModelV4['doDecide']>>
|
|
122
|
+
> {
|
|
123
|
+
const openaiOptions = await parseProviderOptions({
|
|
124
|
+
provider: 'openai',
|
|
125
|
+
providerOptions,
|
|
126
|
+
schema: openaiDecisionModelOptions,
|
|
127
|
+
});
|
|
128
|
+
const {
|
|
129
|
+
value: response,
|
|
130
|
+
rawValue,
|
|
131
|
+
responseHeaders,
|
|
132
|
+
} = await postJsonToApi({
|
|
133
|
+
url: this.config.url({ path: '/decisions', modelId: this.modelId }),
|
|
134
|
+
headers: combineHeaders(this.config.headers?.(), headers),
|
|
135
|
+
body: {
|
|
136
|
+
model: this.modelId,
|
|
137
|
+
safety_identifier: openaiOptions?.safetyIdentifier,
|
|
138
|
+
input: toText(state),
|
|
139
|
+
questions: Object.entries(questions).map(([name, question]) => {
|
|
140
|
+
const instructions = toText(question.instructions);
|
|
141
|
+
switch (question.type) {
|
|
142
|
+
case 'boolean':
|
|
143
|
+
return {
|
|
144
|
+
type: 'predicate',
|
|
145
|
+
name,
|
|
146
|
+
instructions: [
|
|
147
|
+
instructions,
|
|
148
|
+
question.criteria?.true == null
|
|
149
|
+
? undefined
|
|
150
|
+
: `Criteria for true:\n${toText(question.criteria.true)}`,
|
|
151
|
+
question.criteria?.false == null
|
|
152
|
+
? undefined
|
|
153
|
+
: `Criteria for false:\n${toText(question.criteria.false)}`,
|
|
154
|
+
]
|
|
155
|
+
.filter(part => part !== undefined)
|
|
156
|
+
.join('\n\n'),
|
|
157
|
+
};
|
|
158
|
+
case 'choice':
|
|
159
|
+
return {
|
|
160
|
+
type: 'choice',
|
|
161
|
+
name,
|
|
162
|
+
instructions,
|
|
163
|
+
choices: Object.entries(question.criteria).map(
|
|
164
|
+
([value, description]) => ({
|
|
165
|
+
value,
|
|
166
|
+
...(description == null
|
|
167
|
+
? {}
|
|
168
|
+
: { description: toText(description) }),
|
|
169
|
+
}),
|
|
170
|
+
),
|
|
171
|
+
};
|
|
172
|
+
case 'score':
|
|
173
|
+
return {
|
|
174
|
+
type: 'score',
|
|
175
|
+
name,
|
|
176
|
+
instructions,
|
|
177
|
+
levels: question.criteria.map((description, index) => ({
|
|
178
|
+
// Score criteria have no separate labels; indices identify each level.
|
|
179
|
+
label: String(index),
|
|
180
|
+
...(description == null
|
|
181
|
+
? {}
|
|
182
|
+
: { description: toText(description) }),
|
|
183
|
+
})),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}),
|
|
187
|
+
},
|
|
188
|
+
abortSignal,
|
|
189
|
+
fetch: this.config.fetch,
|
|
190
|
+
failedResponseHandler: openaiFailedResponseHandler,
|
|
191
|
+
successfulResponseHandler: createJsonResponseHandler(responseSchema),
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const answers = Object.fromEntries(
|
|
195
|
+
response.answers.map((answer): [string, DecisionModelV4Answer] => {
|
|
196
|
+
if (answer.type === 'refusal') {
|
|
197
|
+
throw new InvalidResponseDataError({
|
|
198
|
+
data: rawValue,
|
|
199
|
+
message:
|
|
200
|
+
answer.name === null
|
|
201
|
+
? 'OpenAI Decisions refused an unnamed question.'
|
|
202
|
+
: `OpenAI Decisions refused question ${JSON.stringify(answer.name)}.`,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
if (answer.type === 'predicate') {
|
|
206
|
+
return [
|
|
207
|
+
answer.name,
|
|
208
|
+
{ type: 'boolean', probability: answer.probability },
|
|
209
|
+
];
|
|
210
|
+
}
|
|
211
|
+
const probabilities = Object.fromEntries(
|
|
212
|
+
answer.probabilities.map(({ value, probability }) => [
|
|
213
|
+
value,
|
|
214
|
+
probability,
|
|
215
|
+
]),
|
|
216
|
+
);
|
|
217
|
+
if (Object.keys(probabilities).length !== answer.probabilities.length) {
|
|
218
|
+
throw new InvalidResponseDataError({
|
|
219
|
+
data: rawValue,
|
|
220
|
+
message: 'Decisions returned duplicate probability values.',
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return [
|
|
224
|
+
answer.name,
|
|
225
|
+
answer.type === 'choice'
|
|
226
|
+
? { type: 'choice', choice: answer.choice, probabilities }
|
|
227
|
+
: { type: 'score', score: answer.score, probabilities },
|
|
228
|
+
];
|
|
229
|
+
}),
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const names = response.answers.map(answer => answer.name);
|
|
233
|
+
if (
|
|
234
|
+
names.length !== Object.keys(questions).length ||
|
|
235
|
+
new Set(names).size !== names.length ||
|
|
236
|
+
names.some(
|
|
237
|
+
name =>
|
|
238
|
+
typeof name !== 'string' ||
|
|
239
|
+
!Object.prototype.hasOwnProperty.call(questions, name),
|
|
240
|
+
)
|
|
241
|
+
) {
|
|
242
|
+
throw new InvalidResponseDataError({
|
|
243
|
+
data: rawValue,
|
|
244
|
+
message: 'Decisions must return exactly one answer for every question.',
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
answers,
|
|
250
|
+
usage:
|
|
251
|
+
response.usage == null
|
|
252
|
+
? undefined
|
|
253
|
+
: {
|
|
254
|
+
inputTokens: response.usage.input_tokens ?? undefined,
|
|
255
|
+
outputTokens: response.usage.output_tokens ?? undefined,
|
|
256
|
+
},
|
|
257
|
+
// The Decisions API reports probabilities and scores to two decimal places.
|
|
258
|
+
rounding: { probabilityDecimals: 2, scoreDecimals: 2 },
|
|
259
|
+
warnings: Object.keys(providerOptions?.openai ?? {})
|
|
260
|
+
.filter(option => option !== 'safetyIdentifier')
|
|
261
|
+
.map(option => ({
|
|
262
|
+
type: 'unsupported',
|
|
263
|
+
feature: `providerOptions.openai.${option}`,
|
|
264
|
+
})),
|
|
265
|
+
providerMetadata: {
|
|
266
|
+
openai: {
|
|
267
|
+
...(response.usage == null ? {} : { usage: response.usage }),
|
|
268
|
+
confidence: Object.fromEntries(
|
|
269
|
+
response.answers.flatMap(answer =>
|
|
270
|
+
(answer.type === 'choice' || answer.type === 'score') &&
|
|
271
|
+
answer.confidence != null
|
|
272
|
+
? [[answer.name, answer.confidence]]
|
|
273
|
+
: [],
|
|
274
|
+
),
|
|
275
|
+
),
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
response: {
|
|
279
|
+
modelId: response.model ?? this.modelId,
|
|
280
|
+
headers: responseHeaders,
|
|
281
|
+
body: rawValue,
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}
|
package/src/openai-provider.ts
CHANGED
|
@@ -20,7 +20,10 @@ import {
|
|
|
20
20
|
type FetchFunction,
|
|
21
21
|
type WebSocketConstructor,
|
|
22
22
|
} from '@ai-sdk/provider-utils';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
DecisionOpenAIModel,
|
|
25
|
+
type OpenAIDecisionModelId,
|
|
26
|
+
} from './openai-decision-model';
|
|
24
27
|
import { OpenAIChatLanguageModel } from './chat/openai-chat-language-model';
|
|
25
28
|
import type { OpenAIChatModelId } from './chat/openai-chat-language-model-options';
|
|
26
29
|
import { OpenAICompletionLanguageModel } from './completion/openai-completion-language-model';
|
|
@@ -50,10 +53,10 @@ import { VERSION } from './version';
|
|
|
50
53
|
export interface OpenAIProvider extends ProviderV4 {
|
|
51
54
|
(modelId: OpenAIResponsesModelId): LanguageModelV4;
|
|
52
55
|
|
|
53
|
-
/** Creates an experimental Choice/Score/Boolean decision model using the
|
|
54
|
-
decisionModel(modelId:
|
|
56
|
+
/** Creates an experimental Choice/Score/Boolean decision model using the Decisions API. */
|
|
57
|
+
decisionModel(modelId: OpenAIDecisionModelId): DecisionModelV4;
|
|
55
58
|
/** @deprecated Use `decisionModel` instead. */
|
|
56
|
-
evaluationModel(modelId:
|
|
59
|
+
evaluationModel(modelId: OpenAIDecisionModelId): DecisionModelV4 & {
|
|
57
60
|
doEvaluate: DecisionModelV4['doDecide'];
|
|
58
61
|
};
|
|
59
62
|
|
|
@@ -159,6 +162,12 @@ export interface OpenAIProvider extends ProviderV4 {
|
|
|
159
162
|
}
|
|
160
163
|
|
|
161
164
|
export interface OpenAIProviderSettings {
|
|
165
|
+
/** Settings for downloading JSON Lines batch results. */
|
|
166
|
+
batchResultDownloads?: {
|
|
167
|
+
/** Maximum UTF-8 bytes per row, excluding LF. Defaults to 64 MiB. */
|
|
168
|
+
maxLineBytes?: number;
|
|
169
|
+
};
|
|
170
|
+
|
|
162
171
|
/**
|
|
163
172
|
* Base URL for the OpenAI API calls.
|
|
164
173
|
*/
|
|
@@ -336,6 +345,7 @@ export function createOpenAI(
|
|
|
336
345
|
const createBatch = () =>
|
|
337
346
|
new OpenAIBatch({
|
|
338
347
|
provider: `${providerName}.batch`,
|
|
348
|
+
maxLineBytes: options.batchResultDownloads?.maxLineBytes,
|
|
339
349
|
config: {
|
|
340
350
|
provider: `${providerName}.responses`,
|
|
341
351
|
baseURL,
|
|
@@ -356,9 +366,12 @@ export function createOpenAI(
|
|
|
356
366
|
provider.chat = createChatModel;
|
|
357
367
|
provider.completion = createCompletionModel;
|
|
358
368
|
provider.responses = createResponsesModel;
|
|
359
|
-
provider.decisionModel = (modelId:
|
|
360
|
-
new
|
|
361
|
-
|
|
369
|
+
provider.decisionModel = (modelId: OpenAIDecisionModelId) =>
|
|
370
|
+
new DecisionOpenAIModel(modelId, {
|
|
371
|
+
baseURL,
|
|
372
|
+
url: ({ path }) => `${baseURL}${path}`,
|
|
373
|
+
headers: getHeaders,
|
|
374
|
+
fetch: options.fetch,
|
|
362
375
|
provider: `${providerName}.decision`,
|
|
363
376
|
});
|
|
364
377
|
provider.evaluationModel =
|
|
@@ -41,7 +41,11 @@ export class OpenAISkills implements SkillsV4 {
|
|
|
41
41
|
|
|
42
42
|
for (const file of params.files) {
|
|
43
43
|
const content = convertInlineFileDataToUint8Array(file.data);
|
|
44
|
-
formData.append(
|
|
44
|
+
formData.append(
|
|
45
|
+
'files[]',
|
|
46
|
+
new Blob([content as Uint8Array<ArrayBuffer>]),
|
|
47
|
+
file.path,
|
|
48
|
+
);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
const { value: response } = await postFormDataToApi({
|
|
@@ -180,7 +180,7 @@ export class OpenAITranscriptionModel implements TranscriptionModelV4 {
|
|
|
180
180
|
const formData = new FormData();
|
|
181
181
|
const blob =
|
|
182
182
|
audio instanceof Uint8Array
|
|
183
|
-
? new Blob([audio])
|
|
183
|
+
? new Blob([audio as Uint8Array<ArrayBuffer>])
|
|
184
184
|
: new Blob([convertBase64ToUint8Array(audio)]);
|
|
185
185
|
|
|
186
186
|
formData.append('model', this.modelId);
|