workers-ai-provider 3.3.1 → 4.0.0
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/README.md +4 -2
- package/dist/anthropic.d.mts +1 -1
- package/dist/{gateway-delegate-D_zkIp5r.d.mts → gateway-delegate-CAX7trdL.d.mts} +6 -6
- package/dist/{gateway-provider-CQU-v2IO.mjs → gateway-provider-BIZ2bimW.mjs} +2 -2
- package/dist/{gateway-provider-CQU-v2IO.mjs.map → gateway-provider-BIZ2bimW.mjs.map} +1 -1
- package/dist/gateway-provider.mjs +1 -1
- package/dist/google.d.mts +1 -1
- package/dist/google.mjs +2 -2
- package/dist/google.mjs.map +1 -1
- package/dist/index.d.mts +33 -28
- package/dist/index.mjs +85 -38
- package/dist/index.mjs.map +1 -1
- package/dist/openai.d.mts +4 -3
- package/dist/openai.mjs +3 -2
- package/dist/openai.mjs.map +1 -1
- package/package.json +11 -11
- package/src/aisearch-chat-language-model.ts +10 -10
- package/src/client-fallback.ts +11 -11
- package/src/convert-to-workersai-chat-messages.ts +69 -30
- package/src/gateway-delegate.ts +12 -12
- package/src/google.ts +2 -4
- package/src/index.ts +1 -1
- package/src/map-workersai-finish-reason.ts +2 -2
- package/src/map-workersai-usage.ts +4 -4
- package/src/openai.ts +3 -2
- package/src/streaming.ts +18 -18
- package/src/utils.ts +8 -8
- package/src/workersai-chat-language-model.ts +64 -14
- package/src/workersai-embedding-model.ts +6 -6
- package/src/workersai-image-model.ts +6 -6
- package/src/workersai-reranking-model.ts +9 -9
- package/src/workersai-speech-model.ts +7 -7
- package/src/workersai-transcription-model.ts +11 -11
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LanguageModelV4, LanguageModelV4ToolCall } from "@ai-sdk/provider";
|
|
2
2
|
import {
|
|
3
3
|
getToolNames,
|
|
4
4
|
isForcedToolChoice,
|
|
@@ -332,8 +332,8 @@ export function buildJsonSchemaPayload(
|
|
|
332
332
|
// ---------------------------------------------------------------------------
|
|
333
333
|
|
|
334
334
|
export function prepareToolsAndToolChoice(
|
|
335
|
-
tools: Parameters<
|
|
336
|
-
toolChoice: Parameters<
|
|
335
|
+
tools: Parameters<LanguageModelV4["doGenerate"]>[0]["tools"],
|
|
336
|
+
toolChoice: Parameters<LanguageModelV4["doGenerate"]>[0]["toolChoice"],
|
|
337
337
|
) {
|
|
338
338
|
if (tools == null) {
|
|
339
339
|
return { tool_choice: undefined, tools: undefined };
|
|
@@ -476,7 +476,7 @@ function mergePartialToolCalls(partialCalls: PartialToolCall[]) {
|
|
|
476
476
|
return Object.values(mergedCallsByIndex);
|
|
477
477
|
}
|
|
478
478
|
|
|
479
|
-
function processToolCall(toolCall: FlatToolCall | OpenAIToolCall):
|
|
479
|
+
function processToolCall(toolCall: FlatToolCall | OpenAIToolCall): LanguageModelV4ToolCall {
|
|
480
480
|
// OpenAI format: has function.name (the key discriminator)
|
|
481
481
|
const fn =
|
|
482
482
|
"function" in toolCall && typeof toolCall.function === "object" && toolCall.function
|
|
@@ -508,7 +508,7 @@ function processToolCall(toolCall: FlatToolCall | OpenAIToolCall): LanguageModel
|
|
|
508
508
|
};
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
-
export function processToolCalls(output: Record<string, unknown>):
|
|
511
|
+
export function processToolCalls(output: Record<string, unknown>): LanguageModelV4ToolCall[] {
|
|
512
512
|
if (output.tool_calls && Array.isArray(output.tool_calls)) {
|
|
513
513
|
return output.tool_calls.map((toolCall: FlatToolCall | OpenAIToolCall) =>
|
|
514
514
|
processToolCall(toolCall),
|
|
@@ -540,12 +540,12 @@ export function processPartialToolCalls(partialToolCalls: PartialToolCall[]) {
|
|
|
540
540
|
*
|
|
541
541
|
* The recovery logic (which JSON shapes count as a leaked call) lives in
|
|
542
542
|
* `@cloudflare/gateway-core`; this wrapper only layers the framework id on each
|
|
543
|
-
* neutral result so the existing `
|
|
543
|
+
* neutral result so the existing `LanguageModelV4ToolCall` shape is preserved.
|
|
544
544
|
*/
|
|
545
545
|
export function parseLeakedToolCalls(
|
|
546
546
|
text: string,
|
|
547
547
|
knownToolNames: Set<string>,
|
|
548
|
-
):
|
|
548
|
+
): LanguageModelV4ToolCall[] {
|
|
549
549
|
return coreParseLeakedToolCalls(text, knownToolNames).map((call) => ({
|
|
550
550
|
input: call.input,
|
|
551
551
|
toolCallId: createAISDKToolCallId(undefined),
|
|
@@ -584,7 +584,7 @@ export function salvageToolCallsFromText(
|
|
|
584
584
|
tools: Array<{ function: { name?: string } }> | undefined;
|
|
585
585
|
toolChoice: unknown;
|
|
586
586
|
},
|
|
587
|
-
):
|
|
587
|
+
): LanguageModelV4ToolCall[] | null {
|
|
588
588
|
if (!isForcedToolChoice(context.toolChoice)) return null;
|
|
589
589
|
|
|
590
590
|
// Never override real tool calls.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LanguageModelV4, SharedV4Warning, LanguageModelV4StreamPart } from "@ai-sdk/provider";
|
|
2
2
|
import { generateId } from "ai";
|
|
3
3
|
import { convertToWorkersAIChatMessages } from "./convert-to-workersai-chat-messages";
|
|
4
4
|
import { mapWorkersAIFinishReason } from "./map-workersai-finish-reason";
|
|
@@ -24,8 +24,33 @@ type WorkersAIChatConfig = {
|
|
|
24
24
|
isBinding: boolean;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Map the unified `reasoning` call option (spec v4) to Workers AI's
|
|
29
|
+
* `reasoning_effort`. Workers AI accepts "low" | "medium" | "high" | null
|
|
30
|
+
* (null disables reasoning), so `minimal` and `xhigh` are clamped to the
|
|
31
|
+
* nearest supported effort. `provider-default` (and absence) returns
|
|
32
|
+
* undefined so the settings-level `reasoning_effort` still applies.
|
|
33
|
+
*/
|
|
34
|
+
function mapUnifiedReasoningEffort(
|
|
35
|
+
reasoning: Parameters<LanguageModelV4["doGenerate"]>[0]["reasoning"],
|
|
36
|
+
): "low" | "medium" | "high" | null | undefined {
|
|
37
|
+
switch (reasoning) {
|
|
38
|
+
case undefined:
|
|
39
|
+
case "provider-default":
|
|
40
|
+
return undefined;
|
|
41
|
+
case "none":
|
|
42
|
+
return null;
|
|
43
|
+
case "minimal":
|
|
44
|
+
return "low";
|
|
45
|
+
case "xhigh":
|
|
46
|
+
return "high";
|
|
47
|
+
default:
|
|
48
|
+
return reasoning;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class WorkersAIChatLanguageModel implements LanguageModelV4 {
|
|
53
|
+
readonly specificationVersion = "v4";
|
|
29
54
|
readonly defaultObjectGenerationMode = "json";
|
|
30
55
|
|
|
31
56
|
readonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>> = {};
|
|
@@ -59,10 +84,11 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
59
84
|
frequencyPenalty,
|
|
60
85
|
presencePenalty,
|
|
61
86
|
seed,
|
|
62
|
-
|
|
87
|
+
reasoning,
|
|
88
|
+
}: Parameters<LanguageModelV4["doGenerate"]>[0]) {
|
|
63
89
|
const type = responseFormat?.type ?? "text";
|
|
64
90
|
|
|
65
|
-
const warnings:
|
|
91
|
+
const warnings: SharedV4Warning[] = [];
|
|
66
92
|
|
|
67
93
|
if (frequencyPenalty != null) {
|
|
68
94
|
warnings.push({ feature: "frequencyPenalty", type: "unsupported" });
|
|
@@ -72,6 +98,16 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
72
98
|
warnings.push({ feature: "presencePenalty", type: "unsupported" });
|
|
73
99
|
}
|
|
74
100
|
|
|
101
|
+
if (reasoning === "minimal" || reasoning === "xhigh") {
|
|
102
|
+
warnings.push({
|
|
103
|
+
type: "compatibility",
|
|
104
|
+
feature: "reasoning",
|
|
105
|
+
details:
|
|
106
|
+
`Workers AI supports reasoning_effort "low" | "medium" | "high"; ` +
|
|
107
|
+
`"${reasoning}" was mapped to "${reasoning === "minimal" ? "low" : "high"}".`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
75
111
|
const baseArgs = {
|
|
76
112
|
max_tokens: maxOutputTokens,
|
|
77
113
|
model: this.modelId,
|
|
@@ -145,11 +181,20 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
145
181
|
*
|
|
146
182
|
* `reasoning_effort: null` is a valid value ("disable reasoning"), so we
|
|
147
183
|
* check `!== undefined` rather than truthiness.
|
|
184
|
+
*
|
|
185
|
+
* The unified `reasoning` call option (spec v4) is mapped onto
|
|
186
|
+
* `reasoning_effort` between the two: an explicit per-call
|
|
187
|
+
* `providerOptions["workers-ai"].reasoning_effort` wins, then the unified
|
|
188
|
+
* option, then settings.
|
|
148
189
|
*/
|
|
149
190
|
private buildRunInputs(
|
|
150
191
|
args: ReturnType<typeof this.getArgs>["args"],
|
|
151
192
|
messages: ReturnType<typeof convertToWorkersAIChatMessages>["messages"],
|
|
152
|
-
options?: {
|
|
193
|
+
options?: {
|
|
194
|
+
stream?: boolean;
|
|
195
|
+
providerOptions?: Record<string, unknown>;
|
|
196
|
+
reasoning?: Parameters<LanguageModelV4["doGenerate"]>[0]["reasoning"];
|
|
197
|
+
},
|
|
153
198
|
) {
|
|
154
199
|
// The AI SDK types this as `Record<string, JSONObject>` but we defensively
|
|
155
200
|
// accept anything and only treat it as a lookup if it's a plain object.
|
|
@@ -159,10 +204,13 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
159
204
|
rawPerCall !== null && typeof rawPerCall === "object" && !Array.isArray(rawPerCall)
|
|
160
205
|
? (rawPerCall as Record<string, unknown>)
|
|
161
206
|
: {};
|
|
207
|
+
const unifiedReasoningEffort = mapUnifiedReasoningEffort(options?.reasoning);
|
|
162
208
|
const reasoningEffort =
|
|
163
209
|
"reasoning_effort" in perCall
|
|
164
210
|
? perCall.reasoning_effort
|
|
165
|
-
:
|
|
211
|
+
: unifiedReasoningEffort !== undefined
|
|
212
|
+
? unifiedReasoningEffort
|
|
213
|
+
: this.settings.reasoning_effort;
|
|
166
214
|
const chatTemplateKwargs =
|
|
167
215
|
"chat_template_kwargs" in perCall
|
|
168
216
|
? perCall.chat_template_kwargs
|
|
@@ -229,7 +277,7 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
229
277
|
private extractContent(
|
|
230
278
|
outputRecord: Record<string, unknown>,
|
|
231
279
|
args: ReturnType<typeof this.getArgs>["args"],
|
|
232
|
-
warnings:
|
|
280
|
+
warnings: SharedV4Warning[],
|
|
233
281
|
) {
|
|
234
282
|
const choices = outputRecord.choices as
|
|
235
283
|
| Array<{ message?: { reasoning_content?: string; reasoning?: string } }>
|
|
@@ -268,13 +316,14 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
268
316
|
}
|
|
269
317
|
|
|
270
318
|
async doGenerate(
|
|
271
|
-
options: Parameters<
|
|
272
|
-
): Promise<Awaited<ReturnType<
|
|
319
|
+
options: Parameters<LanguageModelV4["doGenerate"]>[0],
|
|
320
|
+
): Promise<Awaited<ReturnType<LanguageModelV4["doGenerate"]>>> {
|
|
273
321
|
const { args, warnings } = this.getArgs(options);
|
|
274
322
|
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
275
323
|
|
|
276
324
|
const inputs = this.buildRunInputs(args, messages, {
|
|
277
325
|
providerOptions: options.providerOptions,
|
|
326
|
+
reasoning: options.reasoning,
|
|
278
327
|
});
|
|
279
328
|
const runOptions = this.getRunOptions();
|
|
280
329
|
|
|
@@ -325,14 +374,15 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
325
374
|
}
|
|
326
375
|
|
|
327
376
|
async doStream(
|
|
328
|
-
options: Parameters<
|
|
329
|
-
): Promise<Awaited<ReturnType<
|
|
377
|
+
options: Parameters<LanguageModelV4["doStream"]>[0],
|
|
378
|
+
): Promise<Awaited<ReturnType<LanguageModelV4["doStream"]>>> {
|
|
330
379
|
const { args, warnings } = this.getArgs(options);
|
|
331
380
|
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
332
381
|
|
|
333
382
|
const inputs = this.buildRunInputs(args, messages, {
|
|
334
383
|
stream: true,
|
|
335
384
|
providerOptions: options.providerOptions,
|
|
385
|
+
reasoning: options.reasoning,
|
|
336
386
|
});
|
|
337
387
|
const runOptions = this.getRunOptions();
|
|
338
388
|
|
|
@@ -381,11 +431,11 @@ export class WorkersAIChatLanguageModel implements LanguageModelV3 {
|
|
|
381
431
|
let reasoningId: string | null = null;
|
|
382
432
|
|
|
383
433
|
return {
|
|
384
|
-
stream: new ReadableStream<
|
|
434
|
+
stream: new ReadableStream<LanguageModelV4StreamPart>({
|
|
385
435
|
start(controller) {
|
|
386
436
|
controller.enqueue({
|
|
387
437
|
type: "stream-start",
|
|
388
|
-
warnings: warnings as
|
|
438
|
+
warnings: warnings as SharedV4Warning[],
|
|
389
439
|
});
|
|
390
440
|
|
|
391
441
|
if (reasoningContent) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
EmbeddingModelV4,
|
|
3
|
+
EmbeddingModelV4CallOptions,
|
|
4
|
+
EmbeddingModelV4Result,
|
|
5
5
|
} from "@ai-sdk/provider";
|
|
6
6
|
import { TooManyEmbeddingValuesForCallError } from "@ai-sdk/provider";
|
|
7
7
|
import { normalizeBindingError } from "./workersai-error";
|
|
@@ -24,8 +24,8 @@ export type WorkersAIEmbeddingSettings = {
|
|
|
24
24
|
[key: string]: unknown;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
export class WorkersAIEmbeddingModel implements
|
|
28
|
-
readonly specificationVersion = "
|
|
27
|
+
export class WorkersAIEmbeddingModel implements EmbeddingModelV4 {
|
|
28
|
+
readonly specificationVersion = "v4";
|
|
29
29
|
readonly modelId: EmbeddingModels;
|
|
30
30
|
private readonly config: WorkersAIEmbeddingConfig;
|
|
31
31
|
private readonly settings: WorkersAIEmbeddingSettings;
|
|
@@ -56,7 +56,7 @@ export class WorkersAIEmbeddingModel implements EmbeddingModelV3 {
|
|
|
56
56
|
async doEmbed({
|
|
57
57
|
values,
|
|
58
58
|
abortSignal,
|
|
59
|
-
}:
|
|
59
|
+
}: EmbeddingModelV4CallOptions): Promise<EmbeddingModelV4Result> {
|
|
60
60
|
if (values.length > this.maxEmbeddingsPerCall) {
|
|
61
61
|
throw new TooManyEmbeddingValuesForCallError({
|
|
62
62
|
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ImageModelV4, SharedV4Warning } from "@ai-sdk/provider";
|
|
2
2
|
import { normalizeBindingError } from "./workersai-error";
|
|
3
3
|
import type { WorkersAIImageSettings } from "./workersai-image-settings";
|
|
4
4
|
import type { ImageGenerationModels } from "./workersai-models";
|
|
@@ -9,8 +9,8 @@ export type WorkersAIImageConfig = {
|
|
|
9
9
|
gateway?: GatewayOptions;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export class WorkersAIImageModel implements
|
|
13
|
-
readonly specificationVersion = "
|
|
12
|
+
export class WorkersAIImageModel implements ImageModelV4 {
|
|
13
|
+
readonly specificationVersion = "v4";
|
|
14
14
|
|
|
15
15
|
get maxImagesPerCall(): number {
|
|
16
16
|
return this.settings.maxImagesPerCall ?? 1;
|
|
@@ -33,12 +33,12 @@ export class WorkersAIImageModel implements ImageModelV3 {
|
|
|
33
33
|
aspectRatio,
|
|
34
34
|
seed,
|
|
35
35
|
abortSignal,
|
|
36
|
-
}: Parameters<
|
|
37
|
-
Awaited<ReturnType<
|
|
36
|
+
}: Parameters<ImageModelV4["doGenerate"]>[0]): Promise<
|
|
37
|
+
Awaited<ReturnType<ImageModelV4["doGenerate"]>>
|
|
38
38
|
> {
|
|
39
39
|
const { width, height } = getDimensionsFromSizeString(size);
|
|
40
40
|
|
|
41
|
-
const warnings: Array<
|
|
41
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
42
42
|
|
|
43
43
|
if (aspectRatio != null) {
|
|
44
44
|
warnings.push({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RerankingModelV4, SharedV4Warning } from "@ai-sdk/provider";
|
|
2
2
|
import { normalizeBindingError } from "./workersai-error";
|
|
3
3
|
import type { WorkersAIRerankingSettings } from "./workersai-reranking-settings";
|
|
4
4
|
import type { RerankingModels } from "./workersai-models";
|
|
@@ -10,7 +10,7 @@ export type WorkersAIRerankingConfig = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Workers AI reranking model implementing the AI SDK's `
|
|
13
|
+
* Workers AI reranking model implementing the AI SDK's `RerankingModelV4` interface.
|
|
14
14
|
*
|
|
15
15
|
* Supports BGE reranker models (`@cf/baai/bge-reranker-base`, `bge-reranker-v2-m3`).
|
|
16
16
|
*
|
|
@@ -18,8 +18,8 @@ export type WorkersAIRerankingConfig = {
|
|
|
18
18
|
* - Input: `{ query, contexts: [{ text }], top_k? }`
|
|
19
19
|
* - Output: `{ response: [{ id, score }] }`
|
|
20
20
|
*/
|
|
21
|
-
export class WorkersAIRerankingModel implements
|
|
22
|
-
readonly specificationVersion = "
|
|
21
|
+
export class WorkersAIRerankingModel implements RerankingModelV4 {
|
|
22
|
+
readonly specificationVersion = "v4";
|
|
23
23
|
|
|
24
24
|
get provider(): string {
|
|
25
25
|
return this.config.provider;
|
|
@@ -32,11 +32,11 @@ export class WorkersAIRerankingModel implements RerankingModelV3 {
|
|
|
32
32
|
) {}
|
|
33
33
|
|
|
34
34
|
async doRerank(
|
|
35
|
-
options: Parameters<
|
|
36
|
-
): Promise<Awaited<ReturnType<
|
|
35
|
+
options: Parameters<RerankingModelV4["doRerank"]>[0],
|
|
36
|
+
): Promise<Awaited<ReturnType<RerankingModelV4["doRerank"]>>> {
|
|
37
37
|
const { documents, query, topN, abortSignal } = options;
|
|
38
38
|
|
|
39
|
-
const warnings: Array<
|
|
39
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
40
40
|
|
|
41
41
|
// Convert AI SDK documents to Workers AI contexts format
|
|
42
42
|
const contexts = documentsToContexts(documents, warnings);
|
|
@@ -100,8 +100,8 @@ export class WorkersAIRerankingModel implements RerankingModelV3 {
|
|
|
100
100
|
* - `{ type: 'object', values: JSONObject[] }` — JSON objects (stringified for Workers AI)
|
|
101
101
|
*/
|
|
102
102
|
function documentsToContexts(
|
|
103
|
-
documents: Parameters<
|
|
104
|
-
warnings: Array<
|
|
103
|
+
documents: Parameters<RerankingModelV4["doRerank"]>[0]["documents"],
|
|
104
|
+
warnings: Array<SharedV4Warning>,
|
|
105
105
|
): Array<{ text: string }> {
|
|
106
106
|
if (documents.type === "text") {
|
|
107
107
|
return documents.values.map((text) => ({ text }));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SpeechModelV4, SharedV4Warning } from "@ai-sdk/provider";
|
|
2
2
|
import { apiCallErrorFromResponse, normalizeBindingError } from "./workersai-error";
|
|
3
3
|
import type { WorkersAISpeechSettings } from "./workersai-speech-settings";
|
|
4
4
|
import type { SpeechModels } from "./workersai-models";
|
|
@@ -10,13 +10,13 @@ export type WorkersAISpeechConfig = {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Workers AI speech (text-to-speech) model implementing the AI SDK's `
|
|
13
|
+
* Workers AI speech (text-to-speech) model implementing the AI SDK's `SpeechModelV4` interface.
|
|
14
14
|
*
|
|
15
15
|
* Currently supports Deepgram Aura-1 (`@cf/deepgram/aura-1`).
|
|
16
16
|
* The model accepts `{ text, voice?, speed? }` and returns raw audio bytes.
|
|
17
17
|
*/
|
|
18
|
-
export class WorkersAISpeechModel implements
|
|
19
|
-
readonly specificationVersion = "
|
|
18
|
+
export class WorkersAISpeechModel implements SpeechModelV4 {
|
|
19
|
+
readonly specificationVersion = "v4";
|
|
20
20
|
|
|
21
21
|
get provider(): string {
|
|
22
22
|
return this.config.provider;
|
|
@@ -29,11 +29,11 @@ export class WorkersAISpeechModel implements SpeechModelV3 {
|
|
|
29
29
|
) {}
|
|
30
30
|
|
|
31
31
|
async doGenerate(
|
|
32
|
-
options: Parameters<
|
|
33
|
-
): Promise<Awaited<ReturnType<
|
|
32
|
+
options: Parameters<SpeechModelV4["doGenerate"]>[0],
|
|
33
|
+
): Promise<Awaited<ReturnType<SpeechModelV4["doGenerate"]>>> {
|
|
34
34
|
const { text, voice, speed, abortSignal } = options;
|
|
35
35
|
|
|
36
|
-
const warnings: Array<
|
|
36
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
37
37
|
|
|
38
38
|
if (options.instructions) {
|
|
39
39
|
warnings.push({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TranscriptionModelV4, SharedV4Warning } from "@ai-sdk/provider";
|
|
2
2
|
import type { WorkersAITranscriptionSettings } from "./workersai-transcription-settings";
|
|
3
3
|
import type { TranscriptionModels } from "./workersai-models";
|
|
4
4
|
import { createRunBinary, type CreateRunConfig } from "./utils";
|
|
@@ -21,14 +21,14 @@ export type WorkersAITranscriptionConfig = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Workers AI transcription model implementing the AI SDK's `
|
|
24
|
+
* Workers AI transcription model implementing the AI SDK's `TranscriptionModelV4` interface.
|
|
25
25
|
*
|
|
26
26
|
* Supports:
|
|
27
27
|
* - Whisper models (`@cf/openai/whisper`, `whisper-tiny-en`, `whisper-large-v3-turbo`)
|
|
28
28
|
* - Deepgram Nova-3 (`@cf/deepgram/nova-3`) — uses a different input/output format
|
|
29
29
|
*/
|
|
30
|
-
export class WorkersAITranscriptionModel implements
|
|
31
|
-
readonly specificationVersion = "
|
|
30
|
+
export class WorkersAITranscriptionModel implements TranscriptionModelV4 {
|
|
31
|
+
readonly specificationVersion = "v4";
|
|
32
32
|
|
|
33
33
|
get provider(): string {
|
|
34
34
|
return this.config.provider;
|
|
@@ -41,11 +41,11 @@ export class WorkersAITranscriptionModel implements TranscriptionModelV3 {
|
|
|
41
41
|
) {}
|
|
42
42
|
|
|
43
43
|
async doGenerate(
|
|
44
|
-
options: Parameters<
|
|
45
|
-
): Promise<Awaited<ReturnType<
|
|
44
|
+
options: Parameters<TranscriptionModelV4["doGenerate"]>[0],
|
|
45
|
+
): Promise<Awaited<ReturnType<TranscriptionModelV4["doGenerate"]>>> {
|
|
46
46
|
const { audio, mediaType, abortSignal } = options;
|
|
47
47
|
|
|
48
|
-
const warnings: Array<
|
|
48
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
49
49
|
|
|
50
50
|
// The AI SDK always converts audio to Uint8Array via
|
|
51
51
|
// convertDataContentToUint8Array before calling doGenerate.
|
|
@@ -114,8 +114,8 @@ export class WorkersAITranscriptionModel implements TranscriptionModelV3 {
|
|
|
114
114
|
|
|
115
115
|
private normalizeWhisperResponse(
|
|
116
116
|
raw: Record<string, unknown>,
|
|
117
|
-
warnings: Array<
|
|
118
|
-
): Awaited<ReturnType<
|
|
117
|
+
warnings: Array<SharedV4Warning>,
|
|
118
|
+
): Awaited<ReturnType<TranscriptionModelV4["doGenerate"]>> {
|
|
119
119
|
const text = (raw.text as string) ?? "";
|
|
120
120
|
|
|
121
121
|
// Build segments from Whisper's various formats
|
|
@@ -199,8 +199,8 @@ export class WorkersAITranscriptionModel implements TranscriptionModelV3 {
|
|
|
199
199
|
|
|
200
200
|
private normalizeNova3Response(
|
|
201
201
|
raw: Record<string, unknown>,
|
|
202
|
-
warnings: Array<
|
|
203
|
-
): Awaited<ReturnType<
|
|
202
|
+
warnings: Array<SharedV4Warning>,
|
|
203
|
+
): Awaited<ReturnType<TranscriptionModelV4["doGenerate"]>> {
|
|
204
204
|
// Nova-3 format: { results: { channels: [{ alternatives: [{ transcript, words }] }] } }
|
|
205
205
|
const results = raw.results as Record<string, unknown> | undefined;
|
|
206
206
|
const channels = results?.channels as
|