workers-ai-provider 0.0.11 → 0.0.13
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/dist/index.d.ts +19 -5
- package/dist/index.js +75 -81
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +15 -9
- package/src/map-workersai-usage.ts +11 -0
- package/src/workersai-chat-language-model.ts +65 -75
- package/src/workersai-chat-settings.ts +2 -1
- package/src/workersai-error.ts +1 -5
- package/src/workersai-models.ts +9 -0
package/dist/index.d.ts
CHANGED
@@ -9,21 +9,31 @@ interface WorkersAIChatSettings {
|
|
9
9
|
safePrompt?: boolean;
|
10
10
|
/**
|
11
11
|
* Optionally set Cloudflare AI Gateway options.
|
12
|
+
* @deprecated
|
12
13
|
*/
|
13
14
|
gateway?: GatewayOptions;
|
14
15
|
}
|
15
16
|
|
17
|
+
/**
|
18
|
+
* The names of the BaseAiTextGeneration models.
|
19
|
+
*/
|
20
|
+
type TextGenerationModels = Exclude<value2key<AiModels, BaseAiTextGeneration>, value2key<AiModels, BaseAiTextToImage>>;
|
21
|
+
type value2key<T, V> = {
|
22
|
+
[K in keyof T]: T[K] extends V ? K : never;
|
23
|
+
}[keyof T];
|
24
|
+
|
16
25
|
type WorkersAIChatConfig = {
|
17
26
|
provider: string;
|
18
27
|
binding: Ai;
|
28
|
+
gateway?: GatewayOptions;
|
19
29
|
};
|
20
30
|
declare class WorkersAIChatLanguageModel implements LanguageModelV1 {
|
21
31
|
readonly specificationVersion = "v1";
|
22
32
|
readonly defaultObjectGenerationMode = "json";
|
23
|
-
readonly modelId:
|
33
|
+
readonly modelId: TextGenerationModels;
|
24
34
|
readonly settings: WorkersAIChatSettings;
|
25
35
|
private readonly config;
|
26
|
-
constructor(modelId:
|
36
|
+
constructor(modelId: TextGenerationModels, settings: WorkersAIChatSettings, config: WorkersAIChatConfig);
|
27
37
|
get provider(): string;
|
28
38
|
private getArgs;
|
29
39
|
doGenerate(options: Parameters<LanguageModelV1["doGenerate"]>[0]): Promise<Awaited<ReturnType<LanguageModelV1["doGenerate"]>>>;
|
@@ -31,24 +41,28 @@ declare class WorkersAIChatLanguageModel implements LanguageModelV1 {
|
|
31
41
|
}
|
32
42
|
|
33
43
|
interface WorkersAI {
|
34
|
-
(modelId:
|
44
|
+
(modelId: TextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;
|
35
45
|
/**
|
36
46
|
* Creates a model for text generation.
|
37
47
|
**/
|
38
|
-
chat(modelId:
|
48
|
+
chat(modelId: TextGenerationModels, settings?: WorkersAIChatSettings): WorkersAIChatLanguageModel;
|
39
49
|
}
|
40
50
|
interface WorkersAISettings {
|
41
51
|
/**
|
42
52
|
* Provide an `env.AI` binding to use for the AI inference.
|
43
53
|
* You can set up an AI bindings in your Workers project
|
44
54
|
* by adding the following this to `wrangler.toml`:
|
45
|
-
|
55
|
+
|
46
56
|
```toml
|
47
57
|
[ai]
|
48
58
|
binding = "AI"
|
49
59
|
```
|
50
60
|
**/
|
51
61
|
binding: Ai;
|
62
|
+
/**
|
63
|
+
* Optionally set Cloudflare AI Gateway options.
|
64
|
+
*/
|
65
|
+
gateway?: GatewayOptions;
|
52
66
|
}
|
53
67
|
/**
|
54
68
|
* Create a Workers AI provider instance.
|
package/dist/index.js
CHANGED
@@ -6,7 +6,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
6
6
|
import {
|
7
7
|
UnsupportedFunctionalityError as UnsupportedFunctionalityError2
|
8
8
|
} from "@ai-sdk/provider";
|
9
|
-
import { z
|
9
|
+
import { z } from "zod";
|
10
10
|
|
11
11
|
// src/convert-to-workersai-chat-messages.ts
|
12
12
|
import {
|
@@ -94,25 +94,22 @@ function convertToWorkersAIChatMessages(prompt) {
|
|
94
94
|
return messages;
|
95
95
|
}
|
96
96
|
|
97
|
-
// src/workersai-error.ts
|
98
|
-
import {
|
99
|
-
createJsonErrorResponseHandler
|
100
|
-
} from "@ai-sdk/provider-utils";
|
101
|
-
import { z } from "zod";
|
102
|
-
var workersAIErrorDataSchema = z.object({
|
103
|
-
object: z.literal("error"),
|
104
|
-
message: z.string(),
|
105
|
-
type: z.string(),
|
106
|
-
param: z.string().nullable(),
|
107
|
-
code: z.string().nullable()
|
108
|
-
});
|
109
|
-
var workersAIFailedResponseHandler = createJsonErrorResponseHandler({
|
110
|
-
errorSchema: workersAIErrorDataSchema,
|
111
|
-
errorToMessage: (data) => data.message
|
112
|
-
});
|
113
|
-
|
114
97
|
// src/workersai-chat-language-model.ts
|
115
98
|
import { events } from "fetch-event-stream";
|
99
|
+
|
100
|
+
// src/map-workersai-usage.ts
|
101
|
+
function mapWorkersAIUsage(output) {
|
102
|
+
const usage = output.usage ?? {
|
103
|
+
prompt_tokens: 0,
|
104
|
+
completion_tokens: 0
|
105
|
+
};
|
106
|
+
return {
|
107
|
+
promptTokens: usage.prompt_tokens,
|
108
|
+
completionTokens: usage.completion_tokens
|
109
|
+
};
|
110
|
+
}
|
111
|
+
|
112
|
+
// src/workersai-chat-language-model.ts
|
116
113
|
var WorkersAIChatLanguageModel = class {
|
117
114
|
constructor(modelId, settings, config) {
|
118
115
|
__publicField(this, "specificationVersion", "v1");
|
@@ -175,7 +172,8 @@ var WorkersAIChatLanguageModel = class {
|
|
175
172
|
return {
|
176
173
|
args: {
|
177
174
|
...baseArgs,
|
178
|
-
response_format: { type: "json_object" }
|
175
|
+
response_format: { type: "json_object" },
|
176
|
+
tools: void 0
|
179
177
|
},
|
180
178
|
warnings
|
181
179
|
};
|
@@ -205,95 +203,90 @@ var WorkersAIChatLanguageModel = class {
|
|
205
203
|
}
|
206
204
|
async doGenerate(options) {
|
207
205
|
const { args, warnings } = this.getArgs(options);
|
208
|
-
const
|
206
|
+
const output = await this.config.binding.run(
|
209
207
|
args.model,
|
210
208
|
{
|
211
|
-
messages: args.messages
|
209
|
+
messages: args.messages,
|
210
|
+
max_tokens: args.max_tokens,
|
211
|
+
temperature: args.temperature,
|
212
|
+
tools: args.tools,
|
213
|
+
top_p: args.top_p
|
212
214
|
},
|
213
|
-
{
|
214
|
-
gateway: this.settings.gateway
|
215
|
-
}
|
215
|
+
{ gateway: this.config.gateway ?? this.settings.gateway }
|
216
216
|
);
|
217
|
-
if (
|
217
|
+
if (output instanceof ReadableStream) {
|
218
218
|
throw new Error("This shouldn't happen");
|
219
219
|
}
|
220
220
|
return {
|
221
|
-
text:
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
// })),
|
221
|
+
text: output.response,
|
222
|
+
toolCalls: output.tool_calls?.map((toolCall) => ({
|
223
|
+
toolCallType: "function",
|
224
|
+
toolCallId: toolCall.name,
|
225
|
+
toolName: toolCall.name,
|
226
|
+
args: JSON.stringify(toolCall.arguments || {})
|
227
|
+
})),
|
229
228
|
finishReason: "stop",
|
230
229
|
// TODO: mapWorkersAIFinishReason(response.finish_reason),
|
231
230
|
rawCall: { rawPrompt: args.messages, rawSettings: args },
|
232
|
-
usage:
|
233
|
-
// TODO: mapWorkersAIUsage(response.usage),
|
234
|
-
promptTokens: 0,
|
235
|
-
completionTokens: 0
|
236
|
-
},
|
231
|
+
usage: mapWorkersAIUsage(output),
|
237
232
|
warnings
|
238
233
|
};
|
239
234
|
}
|
240
235
|
async doStream(options) {
|
241
236
|
const { args, warnings } = this.getArgs(options);
|
242
|
-
const
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
237
|
+
const response = await this.config.binding.run(
|
238
|
+
args.model,
|
239
|
+
{
|
240
|
+
messages: args.messages,
|
241
|
+
max_tokens: args.max_tokens,
|
242
|
+
stream: true,
|
243
|
+
temperature: args.temperature,
|
244
|
+
tools: args.tools,
|
245
|
+
top_p: args.top_p
|
246
|
+
},
|
247
|
+
{ gateway: this.config.gateway ?? this.settings.gateway }
|
248
|
+
);
|
247
249
|
if (!(response instanceof ReadableStream)) {
|
248
250
|
throw new Error("This shouldn't happen");
|
249
251
|
}
|
252
|
+
const chunkEvent = events(new Response(response));
|
253
|
+
let usage = { promptTokens: 0, completionTokens: 0 };
|
250
254
|
return {
|
251
|
-
stream:
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
for await (const singleChunk of chunks) {
|
257
|
-
if (!singleChunk.data) {
|
258
|
-
continue;
|
259
|
-
}
|
260
|
-
if (singleChunk.data === "[DONE]") {
|
261
|
-
controller.enqueue({
|
262
|
-
type: "finish",
|
263
|
-
finishReason: "stop",
|
264
|
-
usage: {
|
265
|
-
promptTokens: 0,
|
266
|
-
completionTokens: 0
|
267
|
-
}
|
268
|
-
});
|
269
|
-
return;
|
270
|
-
}
|
271
|
-
const data = JSON.parse(singleChunk.data);
|
272
|
-
controller.enqueue({
|
273
|
-
type: "text-delta",
|
274
|
-
textDelta: data.response ?? "DATALOSS"
|
275
|
-
});
|
255
|
+
stream: new ReadableStream({
|
256
|
+
async start(controller) {
|
257
|
+
for await (const event of chunkEvent) {
|
258
|
+
if (!event.data) {
|
259
|
+
continue;
|
276
260
|
}
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
261
|
+
if (event.data === "[DONE]") {
|
262
|
+
break;
|
263
|
+
}
|
264
|
+
const chunk = JSON.parse(event.data);
|
265
|
+
if (chunk.usage) {
|
266
|
+
usage = mapWorkersAIUsage(chunk);
|
267
|
+
}
|
268
|
+
chunk.response.length && controller.enqueue({
|
269
|
+
type: "text-delta",
|
270
|
+
textDelta: chunk.response
|
284
271
|
});
|
285
272
|
}
|
286
|
-
|
287
|
-
|
273
|
+
controller.enqueue({
|
274
|
+
type: "finish",
|
275
|
+
finishReason: "stop",
|
276
|
+
usage
|
277
|
+
});
|
278
|
+
controller.close();
|
279
|
+
}
|
280
|
+
}),
|
288
281
|
rawCall: { rawPrompt: args.messages, rawSettings: args },
|
289
282
|
warnings
|
290
283
|
};
|
291
284
|
}
|
292
285
|
};
|
293
|
-
var workersAIChatResponseSchema =
|
294
|
-
response:
|
286
|
+
var workersAIChatResponseSchema = z.object({
|
287
|
+
response: z.string()
|
295
288
|
});
|
296
|
-
var workersAIChatChunkSchema =
|
289
|
+
var workersAIChatChunkSchema = z.instanceof(Uint8Array);
|
297
290
|
function prepareToolsAndToolChoice(mode) {
|
298
291
|
const tools = mode.tools?.length ? mode.tools : void 0;
|
299
292
|
if (tools == null) {
|
@@ -341,7 +334,8 @@ function prepareToolsAndToolChoice(mode) {
|
|
341
334
|
function createWorkersAI(options) {
|
342
335
|
const createChatModel = (modelId, settings = {}) => new WorkersAIChatLanguageModel(modelId, settings, {
|
343
336
|
provider: "workersai.chat",
|
344
|
-
binding: options.binding
|
337
|
+
binding: options.binding,
|
338
|
+
gateway: options.gateway
|
345
339
|
});
|
346
340
|
const provider = function(modelId, settings) {
|
347
341
|
if (new.target) {
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../src/workersai-chat-language-model.ts","../src/convert-to-workersai-chat-messages.ts","../src/workersai-error.ts","../src/index.ts"],"sourcesContent":["import {\n type LanguageModelV1,\n type LanguageModelV1CallWarning,\n type LanguageModelV1FinishReason,\n type LanguageModelV1StreamPart,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport type {\n ParseResult,\n createEventSourceResponseHandler,\n createJsonResponseHandler,\n postJsonToApi,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport { mapWorkersAIFinishReason } from \"./map-workersai-finish-reason\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport { workersAIFailedResponseHandler } from \"./workersai-error\";\n\nimport { events } from \"fetch-event-stream\";\n\ntype WorkersAIChatConfig = {\n provider: string;\n binding: Ai;\n};\n\nexport class WorkersAIChatLanguageModel implements LanguageModelV1 {\n readonly specificationVersion = \"v1\";\n readonly defaultObjectGenerationMode = \"json\";\n\n readonly modelId: BaseAiTextGenerationModels;\n readonly settings: WorkersAIChatSettings;\n\n private readonly config: WorkersAIChatConfig;\n\n constructor(\n modelId: BaseAiTextGenerationModels,\n settings: WorkersAIChatSettings,\n config: WorkersAIChatConfig\n ) {\n this.modelId = modelId;\n this.settings = settings;\n this.config = config;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private getArgs({\n mode,\n prompt,\n maxTokens,\n temperature,\n topP,\n frequencyPenalty,\n presencePenalty,\n seed,\n }: Parameters<LanguageModelV1[\"doGenerate\"]>[0]) {\n const type = mode.type;\n\n const warnings: LanguageModelV1CallWarning[] = [];\n\n if (frequencyPenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"frequencyPenalty\",\n });\n }\n\n if (presencePenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"presencePenalty\",\n });\n }\n\n const baseArgs = {\n // model id:\n model: this.modelId,\n\n // model specific settings:\n safe_prompt: this.settings.safePrompt,\n\n // standardized settings:\n max_tokens: maxTokens,\n temperature,\n top_p: topP,\n random_seed: seed,\n\n // messages:\n messages: convertToWorkersAIChatMessages(prompt),\n };\n\n switch (type) {\n case \"regular\": {\n return {\n args: { ...baseArgs, ...prepareToolsAndToolChoice(mode) },\n warnings,\n };\n }\n\n case \"object-json\": {\n return {\n args: {\n ...baseArgs,\n response_format: { type: \"json_object\" },\n },\n warnings,\n };\n }\n\n case \"object-tool\": {\n return {\n args: {\n ...baseArgs,\n tool_choice: \"any\",\n tools: [{ type: \"function\", function: mode.tool }],\n },\n warnings,\n };\n }\n\n // @ts-expect-error - this is unreachable code\n // TODO: fixme\n case \"object-grammar\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"object-grammar mode\",\n });\n }\n\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported type: ${exhaustiveCheck}`);\n }\n }\n }\n\n async doGenerate(\n options: Parameters<LanguageModelV1[\"doGenerate\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doGenerate\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const response = await this.config.binding.run(args.model, {\n messages: args.messages,\n }, \n {\n gateway: this.settings.gateway\n });\n\n if (response instanceof ReadableStream) {\n throw new Error(\"This shouldn't happen\");\n }\n\n return {\n text: response.response,\n // TODO: tool calls\n // toolCalls: response.tool_calls?.map((toolCall) => ({\n // toolCallType: \"function\",\n // toolCallId: toolCall.name, // TODO: what can the id be?\n // toolName: toolCall.name,\n // args: JSON.stringify(toolCall.arguments || {}),\n // })),\n finishReason: \"stop\", // TODO: mapWorkersAIFinishReason(response.finish_reason),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n usage: {\n // TODO: mapWorkersAIUsage(response.usage),\n promptTokens: 0,\n completionTokens: 0,\n },\n warnings,\n };\n }\n\n async doStream(\n options: Parameters<LanguageModelV1[\"doStream\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doStream\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const decoder = new TextDecoder();\n\n const response = await this.config.binding.run(args.model, {\n messages: args.messages,\n stream: true,\n });\n\n if (!(response instanceof ReadableStream)) {\n throw new Error(\"This shouldn't happen\");\n }\n\n return {\n stream: response.pipeThrough(\n new TransformStream<\n ParseResult<z.infer<typeof workersAIChatChunkSchema>>,\n LanguageModelV1StreamPart\n >({\n async transform(chunk, controller) {\n const chunkToText = decoder.decode(chunk as unknown as Uint8Array);\n const chunks = events(new Response(chunkToText));\n for await (const singleChunk of chunks) {\n if (!singleChunk.data) {\n continue;\n }\n if (singleChunk.data === \"[DONE]\") {\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: {\n promptTokens: 0,\n completionTokens: 0,\n },\n });\n return;\n }\n const data = JSON.parse(singleChunk.data);\n\n controller.enqueue({\n type: \"text-delta\",\n textDelta: data.response ?? \"DATALOSS\",\n });\n }\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: {\n promptTokens: 0,\n completionTokens: 0,\n },\n });\n },\n })\n ),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n warnings,\n };\n }\n}\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatResponseSchema = z.object({\n response: z.string(),\n});\n\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatChunkSchema = z.instanceof(Uint8Array);\n\nfunction prepareToolsAndToolChoice(\n mode: Parameters<LanguageModelV1[\"doGenerate\"]>[0][\"mode\"] & {\n type: \"regular\";\n }\n) {\n // when the tools array is empty, change it to undefined to prevent errors:\n const tools = mode.tools?.length ? mode.tools : undefined;\n\n if (tools == null) {\n return { tools: undefined, tool_choice: undefined };\n }\n\n const mappedTools = tools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n // @ts-expect-error - description is not a property of tool\n description: tool.description,\n // @ts-expect-error - parameters is not a property of tool\n parameters: tool.parameters,\n },\n }));\n\n const toolChoice = mode.toolChoice;\n\n if (toolChoice == null) {\n return { tools: mappedTools, tool_choice: undefined };\n }\n\n const type = toolChoice.type;\n\n switch (type) {\n case \"auto\":\n return { tools: mappedTools, tool_choice: type };\n case \"none\":\n return { tools: mappedTools, tool_choice: type };\n case \"required\":\n return { tools: mappedTools, tool_choice: \"any\" };\n\n // workersAI does not support tool mode directly,\n // so we filter the tools and force the tool choice through 'any'\n case \"tool\":\n return {\n tools: mappedTools.filter(\n (tool) => tool.function.name === toolChoice.toolName\n ),\n tool_choice: \"any\",\n };\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported tool choice type: ${exhaustiveCheck}`);\n }\n }\n}\n","import {\n type LanguageModelV1Prompt,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n// TODO\nexport function convertToWorkersAIChatMessages(\n prompt: LanguageModelV1Prompt\n): WorkersAIChatPrompt {\n const messages: WorkersAIChatPrompt = [];\n\n for (const { role, content } of prompt) {\n switch (role) {\n case \"system\": {\n messages.push({ role: \"system\", content });\n break;\n }\n\n case \"user\": {\n messages.push({\n role: \"user\",\n content: content\n .map((part) => {\n switch (part.type) {\n case \"text\": {\n return part.text;\n }\n case \"image\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"image-part\",\n });\n }\n }\n })\n .join(\"\"),\n });\n break;\n }\n\n case \"assistant\": {\n let text = \"\";\n const toolCalls: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }> = [];\n\n for (const part of content) {\n switch (part.type) {\n case \"text\": {\n text += part.text;\n break;\n }\n case \"tool-call\": {\n toolCalls.push({\n id: part.toolCallId,\n type: \"function\",\n function: {\n name: part.toolName,\n arguments: JSON.stringify(part.args),\n },\n });\n break;\n }\n default: {\n const exhaustiveCheck = part satisfies never;\n throw new Error(`Unsupported part: ${exhaustiveCheck}`);\n }\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: text,\n tool_calls:\n toolCalls.length > 0\n ? toolCalls.map(({ function: { name, arguments: args } }) => ({\n id: \"null\",\n type: \"function\",\n function: { name, arguments: args },\n }))\n : undefined,\n });\n\n break;\n }\n case \"tool\": {\n for (const toolResponse of content) {\n messages.push({\n role: \"tool\",\n name: toolResponse.toolName,\n content: JSON.stringify(toolResponse.result),\n });\n }\n break;\n }\n default: {\n const exhaustiveCheck = role satisfies never;\n throw new Error(`Unsupported role: ${exhaustiveCheck}`);\n }\n }\n }\n\n return messages;\n}\n","import {\n createJsonErrorResponseHandler,\n type ResponseHandler,\n} from \"@ai-sdk/provider-utils\";\nimport type { APICallError } from \"ai\";\nimport { z } from \"zod\";\n\nconst workersAIErrorDataSchema = z.object({\n object: z.literal(\"error\"),\n message: z.string(),\n type: z.string(),\n param: z.string().nullable(),\n code: z.string().nullable(),\n});\n\nexport type WorkersAIErrorData = z.infer<typeof workersAIErrorDataSchema>;\n\nexport const workersAIFailedResponseHandler: ResponseHandler<APICallError> =\n createJsonErrorResponseHandler({\n errorSchema: workersAIErrorDataSchema,\n errorToMessage: (data) => data.message,\n });\n","import { WorkersAIChatLanguageModel } from \"./workersai-chat-language-model\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\n\nexport interface WorkersAI {\n (\n modelId: BaseAiTextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n\n /**\n * Creates a model for text generation.\n **/\n chat(\n modelId: BaseAiTextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n}\n\nexport interface WorkersAISettings {\n /**\n * Provide an `env.AI` binding to use for the AI inference. \n * You can set up an AI bindings in your Workers project \n * by adding the following this to `wrangler.toml`: \n \n ```toml\n[ai]\nbinding = \"AI\"\n ``` \n **/\n binding: Ai;\n}\n\n/**\n * Create a Workers AI provider instance.\n **/\nexport function createWorkersAI(options: WorkersAISettings): WorkersAI {\n const createChatModel = (\n modelId: BaseAiTextGenerationModels,\n settings: WorkersAIChatSettings = {}\n ) =>\n new WorkersAIChatLanguageModel(modelId, settings, {\n provider: \"workersai.chat\",\n binding: options.binding,\n });\n\n const provider = function (\n modelId: BaseAiTextGenerationModels,\n settings?: WorkersAIChatSettings\n ) {\n if (new.target) {\n throw new Error(\n \"The WorkersAI model function cannot be called with the new keyword.\"\n );\n }\n\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n\n return provider;\n}\n"],"mappings":"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","names":["UnsupportedFunctionalityError","z","UnsupportedFunctionalityError","z"]}
|
1
|
+
{"version":3,"sources":["../src/workersai-chat-language-model.ts","../src/convert-to-workersai-chat-messages.ts","../src/map-workersai-usage.ts","../src/index.ts"],"sourcesContent":["import {\n type LanguageModelV1,\n type LanguageModelV1CallWarning,\n type LanguageModelV1StreamPart,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport { z } from \"zod\";\nimport { convertToWorkersAIChatMessages } from \"./convert-to-workersai-chat-messages\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\nimport { events } from \"fetch-event-stream\";\nimport { mapWorkersAIUsage } from \"./map-workersai-usage\";\n\ntype WorkersAIChatConfig = {\n provider: string;\n binding: Ai;\n gateway?: GatewayOptions;\n};\n\nexport class WorkersAIChatLanguageModel implements LanguageModelV1 {\n readonly specificationVersion = \"v1\";\n readonly defaultObjectGenerationMode = \"json\";\n\n readonly modelId: TextGenerationModels;\n readonly settings: WorkersAIChatSettings;\n\n private readonly config: WorkersAIChatConfig;\n\n constructor(\n modelId: TextGenerationModels,\n settings: WorkersAIChatSettings,\n config: WorkersAIChatConfig\n ) {\n this.modelId = modelId;\n this.settings = settings;\n this.config = config;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private getArgs({\n mode,\n prompt,\n maxTokens,\n temperature,\n topP,\n frequencyPenalty,\n presencePenalty,\n seed,\n }: Parameters<LanguageModelV1[\"doGenerate\"]>[0]) {\n const type = mode.type;\n\n const warnings: LanguageModelV1CallWarning[] = [];\n\n if (frequencyPenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"frequencyPenalty\",\n });\n }\n\n if (presencePenalty != null) {\n warnings.push({\n type: \"unsupported-setting\",\n setting: \"presencePenalty\",\n });\n }\n\n const baseArgs = {\n // model id:\n model: this.modelId,\n\n // model specific settings:\n safe_prompt: this.settings.safePrompt,\n\n // standardized settings:\n max_tokens: maxTokens,\n temperature,\n top_p: topP,\n random_seed: seed,\n\n // messages:\n messages: convertToWorkersAIChatMessages(prompt),\n };\n\n switch (type) {\n case \"regular\": {\n return {\n args: { ...baseArgs, ...prepareToolsAndToolChoice(mode) },\n warnings,\n };\n }\n\n case \"object-json\": {\n return {\n args: {\n ...baseArgs,\n response_format: { type: \"json_object\" },\n tools: undefined,\n },\n warnings,\n };\n }\n\n case \"object-tool\": {\n return {\n args: {\n ...baseArgs,\n tool_choice: \"any\",\n tools: [{ type: \"function\", function: mode.tool }],\n },\n warnings,\n };\n }\n\n // @ts-expect-error - this is unreachable code\n // TODO: fixme\n case \"object-grammar\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"object-grammar mode\",\n });\n }\n\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported type: ${exhaustiveCheck}`);\n }\n }\n }\n\n async doGenerate(\n options: Parameters<LanguageModelV1[\"doGenerate\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doGenerate\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const output = await this.config.binding.run(\n args.model,\n {\n messages: args.messages,\n max_tokens: args.max_tokens,\n temperature: args.temperature,\n tools: args.tools,\n top_p: args.top_p,\n },\n { gateway: this.config.gateway ?? this.settings.gateway }\n );\n\n if (output instanceof ReadableStream) {\n throw new Error(\"This shouldn't happen\");\n }\n\n return {\n text: output.response,\n toolCalls: output.tool_calls?.map((toolCall) => ({\n toolCallType: \"function\",\n toolCallId: toolCall.name,\n toolName: toolCall.name,\n args: JSON.stringify(toolCall.arguments || {}),\n })),\n finishReason: \"stop\", // TODO: mapWorkersAIFinishReason(response.finish_reason),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n usage: mapWorkersAIUsage(output),\n warnings,\n };\n }\n\n async doStream(\n options: Parameters<LanguageModelV1[\"doStream\"]>[0]\n ): Promise<Awaited<ReturnType<LanguageModelV1[\"doStream\"]>>> {\n const { args, warnings } = this.getArgs(options);\n\n const response = await this.config.binding.run(\n args.model,\n {\n messages: args.messages,\n max_tokens: args.max_tokens,\n stream: true,\n temperature: args.temperature,\n tools: args.tools,\n top_p: args.top_p,\n },\n { gateway: this.config.gateway ?? this.settings.gateway }\n );\n\n if (!(response instanceof ReadableStream)) {\n throw new Error(\"This shouldn't happen\");\n }\n\n const chunkEvent = events(new Response(response));\n let usage = { promptTokens: 0, completionTokens: 0 };\n\n return {\n stream: new ReadableStream<LanguageModelV1StreamPart>({\n async start(controller) {\n for await (const event of chunkEvent) {\n if (!event.data) {\n continue;\n }\n if (event.data === \"[DONE]\") {\n break;\n }\n const chunk = JSON.parse(event.data);\n if (chunk.usage) {\n usage = mapWorkersAIUsage(chunk);\n }\n chunk.response.length &&\n controller.enqueue({\n type: \"text-delta\",\n textDelta: chunk.response,\n });\n }\n controller.enqueue({\n type: \"finish\",\n finishReason: \"stop\",\n usage: usage,\n });\n controller.close();\n },\n }),\n rawCall: { rawPrompt: args.messages, rawSettings: args },\n warnings,\n };\n }\n}\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatResponseSchema = z.object({\n response: z.string(),\n});\n\n// limited version of the schema, focussed on what is needed for the implementation\n// this approach limits breakages when the API changes and increases efficiency\nconst workersAIChatChunkSchema = z.instanceof(Uint8Array);\n\nfunction prepareToolsAndToolChoice(\n mode: Parameters<LanguageModelV1[\"doGenerate\"]>[0][\"mode\"] & {\n type: \"regular\";\n }\n) {\n // when the tools array is empty, change it to undefined to prevent errors:\n const tools = mode.tools?.length ? mode.tools : undefined;\n\n if (tools == null) {\n return { tools: undefined, tool_choice: undefined };\n }\n\n const mappedTools = tools.map((tool) => ({\n type: \"function\",\n function: {\n name: tool.name,\n // @ts-expect-error - description is not a property of tool\n description: tool.description,\n // @ts-expect-error - parameters is not a property of tool\n parameters: tool.parameters,\n },\n }));\n\n const toolChoice = mode.toolChoice;\n\n if (toolChoice == null) {\n return { tools: mappedTools, tool_choice: undefined };\n }\n\n const type = toolChoice.type;\n\n switch (type) {\n case \"auto\":\n return { tools: mappedTools, tool_choice: type };\n case \"none\":\n return { tools: mappedTools, tool_choice: type };\n case \"required\":\n return { tools: mappedTools, tool_choice: \"any\" };\n\n // workersAI does not support tool mode directly,\n // so we filter the tools and force the tool choice through 'any'\n case \"tool\":\n return {\n tools: mappedTools.filter(\n (tool) => tool.function.name === toolChoice.toolName\n ),\n tool_choice: \"any\",\n };\n default: {\n const exhaustiveCheck = type satisfies never;\n throw new Error(`Unsupported tool choice type: ${exhaustiveCheck}`);\n }\n }\n}\n","import {\n type LanguageModelV1Prompt,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport type { WorkersAIChatPrompt } from \"./workersai-chat-prompt\";\n\n// TODO\nexport function convertToWorkersAIChatMessages(\n prompt: LanguageModelV1Prompt\n): WorkersAIChatPrompt {\n const messages: WorkersAIChatPrompt = [];\n\n for (const { role, content } of prompt) {\n switch (role) {\n case \"system\": {\n messages.push({ role: \"system\", content });\n break;\n }\n\n case \"user\": {\n messages.push({\n role: \"user\",\n content: content\n .map((part) => {\n switch (part.type) {\n case \"text\": {\n return part.text;\n }\n case \"image\": {\n throw new UnsupportedFunctionalityError({\n functionality: \"image-part\",\n });\n }\n }\n })\n .join(\"\"),\n });\n break;\n }\n\n case \"assistant\": {\n let text = \"\";\n const toolCalls: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }> = [];\n\n for (const part of content) {\n switch (part.type) {\n case \"text\": {\n text += part.text;\n break;\n }\n case \"tool-call\": {\n toolCalls.push({\n id: part.toolCallId,\n type: \"function\",\n function: {\n name: part.toolName,\n arguments: JSON.stringify(part.args),\n },\n });\n break;\n }\n default: {\n const exhaustiveCheck = part satisfies never;\n throw new Error(`Unsupported part: ${exhaustiveCheck}`);\n }\n }\n }\n\n messages.push({\n role: \"assistant\",\n content: text,\n tool_calls:\n toolCalls.length > 0\n ? toolCalls.map(({ function: { name, arguments: args } }) => ({\n id: \"null\",\n type: \"function\",\n function: { name, arguments: args },\n }))\n : undefined,\n });\n\n break;\n }\n case \"tool\": {\n for (const toolResponse of content) {\n messages.push({\n role: \"tool\",\n name: toolResponse.toolName,\n content: JSON.stringify(toolResponse.result),\n });\n }\n break;\n }\n default: {\n const exhaustiveCheck = role satisfies never;\n throw new Error(`Unsupported role: ${exhaustiveCheck}`);\n }\n }\n }\n\n return messages;\n}\n","export function mapWorkersAIUsage(output: AiTextGenerationOutput | AiTextToImageOutput) {\n\tconst usage = (output as { usage: { prompt_tokens: number, completion_tokens: number} }).usage ?? {\n\t\tprompt_tokens: 0,\n\t\tcompletion_tokens: 0,\n\t};\n\n\treturn {\n\t\tpromptTokens: usage.prompt_tokens,\n\t\tcompletionTokens: usage.completion_tokens\n\t}\n}\n","import { WorkersAIChatLanguageModel } from \"./workersai-chat-language-model\";\nimport type { WorkersAIChatSettings } from \"./workersai-chat-settings\";\nimport type { TextGenerationModels } from \"./workersai-models\";\n\nexport interface WorkersAI {\n (\n modelId: TextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n\n /**\n * Creates a model for text generation.\n **/\n chat(\n modelId: TextGenerationModels,\n settings?: WorkersAIChatSettings\n ): WorkersAIChatLanguageModel;\n}\n\nexport interface WorkersAISettings {\n /**\n * Provide an `env.AI` binding to use for the AI inference.\n * You can set up an AI bindings in your Workers project\n * by adding the following this to `wrangler.toml`:\n\n ```toml\n[ai]\nbinding = \"AI\"\n ```\n **/\n binding: Ai;\n /**\n * Optionally set Cloudflare AI Gateway options.\n */\n gateway?: GatewayOptions;\n}\n\n/**\n * Create a Workers AI provider instance.\n **/\nexport function createWorkersAI(options: WorkersAISettings): WorkersAI {\n const createChatModel = (\n modelId: TextGenerationModels,\n settings: WorkersAIChatSettings = {}\n ) =>\n new WorkersAIChatLanguageModel(modelId, settings, {\n provider: \"workersai.chat\",\n binding: options.binding,\n gateway: options.gateway,\n });\n\n const provider = function (\n modelId: TextGenerationModels,\n settings?: WorkersAIChatSettings\n ) {\n if (new.target) {\n throw new Error(\n \"The WorkersAI model function cannot be called with the new keyword.\"\n );\n }\n\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n\n return provider;\n}\n"],"mappings":"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","names":["UnsupportedFunctionalityError","UnsupportedFunctionalityError"]}
|
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "workers-ai-provider",
|
3
3
|
"description": "Workers AI Provider for the vercel AI SDK",
|
4
4
|
"type": "module",
|
5
|
-
"version": "0.0.
|
5
|
+
"version": "0.0.13",
|
6
6
|
"main": "dist/index.js",
|
7
7
|
"types": "dist/index.d.ts",
|
8
8
|
"repository": {
|
@@ -41,6 +41,6 @@
|
|
41
41
|
"serverless"
|
42
42
|
],
|
43
43
|
"devDependencies": {
|
44
|
-
"@cloudflare/workers-types": "^4.
|
44
|
+
"@cloudflare/workers-types": "^4.20250214.0"
|
45
45
|
}
|
46
46
|
}
|
package/src/index.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import { WorkersAIChatLanguageModel } from "./workersai-chat-language-model";
|
2
2
|
import type { WorkersAIChatSettings } from "./workersai-chat-settings";
|
3
|
+
import type { TextGenerationModels } from "./workersai-models";
|
3
4
|
|
4
5
|
export interface WorkersAI {
|
5
6
|
(
|
6
|
-
modelId:
|
7
|
+
modelId: TextGenerationModels,
|
7
8
|
settings?: WorkersAIChatSettings
|
8
9
|
): WorkersAIChatLanguageModel;
|
9
10
|
|
@@ -11,23 +12,27 @@ export interface WorkersAI {
|
|
11
12
|
* Creates a model for text generation.
|
12
13
|
**/
|
13
14
|
chat(
|
14
|
-
modelId:
|
15
|
+
modelId: TextGenerationModels,
|
15
16
|
settings?: WorkersAIChatSettings
|
16
17
|
): WorkersAIChatLanguageModel;
|
17
18
|
}
|
18
19
|
|
19
20
|
export interface WorkersAISettings {
|
20
21
|
/**
|
21
|
-
* Provide an `env.AI` binding to use for the AI inference.
|
22
|
-
* You can set up an AI bindings in your Workers project
|
23
|
-
* by adding the following this to `wrangler.toml`:
|
24
|
-
|
22
|
+
* Provide an `env.AI` binding to use for the AI inference.
|
23
|
+
* You can set up an AI bindings in your Workers project
|
24
|
+
* by adding the following this to `wrangler.toml`:
|
25
|
+
|
25
26
|
```toml
|
26
27
|
[ai]
|
27
28
|
binding = "AI"
|
28
|
-
```
|
29
|
+
```
|
29
30
|
**/
|
30
31
|
binding: Ai;
|
32
|
+
/**
|
33
|
+
* Optionally set Cloudflare AI Gateway options.
|
34
|
+
*/
|
35
|
+
gateway?: GatewayOptions;
|
31
36
|
}
|
32
37
|
|
33
38
|
/**
|
@@ -35,16 +40,17 @@ binding = "AI"
|
|
35
40
|
**/
|
36
41
|
export function createWorkersAI(options: WorkersAISettings): WorkersAI {
|
37
42
|
const createChatModel = (
|
38
|
-
modelId:
|
43
|
+
modelId: TextGenerationModels,
|
39
44
|
settings: WorkersAIChatSettings = {}
|
40
45
|
) =>
|
41
46
|
new WorkersAIChatLanguageModel(modelId, settings, {
|
42
47
|
provider: "workersai.chat",
|
43
48
|
binding: options.binding,
|
49
|
+
gateway: options.gateway,
|
44
50
|
});
|
45
51
|
|
46
52
|
const provider = function (
|
47
|
-
modelId:
|
53
|
+
modelId: TextGenerationModels,
|
48
54
|
settings?: WorkersAIChatSettings
|
49
55
|
) {
|
50
56
|
if (new.target) {
|
@@ -0,0 +1,11 @@
|
|
1
|
+
export function mapWorkersAIUsage(output: AiTextGenerationOutput | AiTextToImageOutput) {
|
2
|
+
const usage = (output as { usage: { prompt_tokens: number, completion_tokens: number} }).usage ?? {
|
3
|
+
prompt_tokens: 0,
|
4
|
+
completion_tokens: 0,
|
5
|
+
};
|
6
|
+
|
7
|
+
return {
|
8
|
+
promptTokens: usage.prompt_tokens,
|
9
|
+
completionTokens: usage.completion_tokens
|
10
|
+
}
|
11
|
+
}
|
@@ -1,40 +1,34 @@
|
|
1
1
|
import {
|
2
2
|
type LanguageModelV1,
|
3
3
|
type LanguageModelV1CallWarning,
|
4
|
-
type LanguageModelV1FinishReason,
|
5
4
|
type LanguageModelV1StreamPart,
|
6
5
|
UnsupportedFunctionalityError,
|
7
6
|
} from "@ai-sdk/provider";
|
8
|
-
import type {
|
9
|
-
ParseResult,
|
10
|
-
createEventSourceResponseHandler,
|
11
|
-
createJsonResponseHandler,
|
12
|
-
postJsonToApi,
|
13
|
-
} from "@ai-sdk/provider-utils";
|
14
7
|
import { z } from "zod";
|
15
8
|
import { convertToWorkersAIChatMessages } from "./convert-to-workersai-chat-messages";
|
16
|
-
import { mapWorkersAIFinishReason } from "./map-workersai-finish-reason";
|
17
9
|
import type { WorkersAIChatSettings } from "./workersai-chat-settings";
|
18
|
-
import {
|
10
|
+
import type { TextGenerationModels } from "./workersai-models";
|
19
11
|
|
20
12
|
import { events } from "fetch-event-stream";
|
13
|
+
import { mapWorkersAIUsage } from "./map-workersai-usage";
|
21
14
|
|
22
15
|
type WorkersAIChatConfig = {
|
23
16
|
provider: string;
|
24
17
|
binding: Ai;
|
18
|
+
gateway?: GatewayOptions;
|
25
19
|
};
|
26
20
|
|
27
21
|
export class WorkersAIChatLanguageModel implements LanguageModelV1 {
|
28
22
|
readonly specificationVersion = "v1";
|
29
23
|
readonly defaultObjectGenerationMode = "json";
|
30
24
|
|
31
|
-
readonly modelId:
|
25
|
+
readonly modelId: TextGenerationModels;
|
32
26
|
readonly settings: WorkersAIChatSettings;
|
33
27
|
|
34
28
|
private readonly config: WorkersAIChatConfig;
|
35
29
|
|
36
30
|
constructor(
|
37
|
-
modelId:
|
31
|
+
modelId: TextGenerationModels,
|
38
32
|
settings: WorkersAIChatSettings,
|
39
33
|
config: WorkersAIChatConfig
|
40
34
|
) {
|
@@ -105,6 +99,7 @@ export class WorkersAIChatLanguageModel implements LanguageModelV1 {
|
|
105
99
|
args: {
|
106
100
|
...baseArgs,
|
107
101
|
response_format: { type: "json_object" },
|
102
|
+
tools: undefined,
|
108
103
|
},
|
109
104
|
warnings,
|
110
105
|
};
|
@@ -141,33 +136,33 @@ export class WorkersAIChatLanguageModel implements LanguageModelV1 {
|
|
141
136
|
): Promise<Awaited<ReturnType<LanguageModelV1["doGenerate"]>>> {
|
142
137
|
const { args, warnings } = this.getArgs(options);
|
143
138
|
|
144
|
-
const
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
139
|
+
const output = await this.config.binding.run(
|
140
|
+
args.model,
|
141
|
+
{
|
142
|
+
messages: args.messages,
|
143
|
+
max_tokens: args.max_tokens,
|
144
|
+
temperature: args.temperature,
|
145
|
+
tools: args.tools,
|
146
|
+
top_p: args.top_p,
|
147
|
+
},
|
148
|
+
{ gateway: this.config.gateway ?? this.settings.gateway }
|
149
|
+
);
|
150
150
|
|
151
|
-
if (
|
151
|
+
if (output instanceof ReadableStream) {
|
152
152
|
throw new Error("This shouldn't happen");
|
153
153
|
}
|
154
154
|
|
155
155
|
return {
|
156
|
-
text:
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
// })),
|
156
|
+
text: output.response,
|
157
|
+
toolCalls: output.tool_calls?.map((toolCall) => ({
|
158
|
+
toolCallType: "function",
|
159
|
+
toolCallId: toolCall.name,
|
160
|
+
toolName: toolCall.name,
|
161
|
+
args: JSON.stringify(toolCall.arguments || {}),
|
162
|
+
})),
|
164
163
|
finishReason: "stop", // TODO: mapWorkersAIFinishReason(response.finish_reason),
|
165
164
|
rawCall: { rawPrompt: args.messages, rawSettings: args },
|
166
|
-
usage:
|
167
|
-
// TODO: mapWorkersAIUsage(response.usage),
|
168
|
-
promptTokens: 0,
|
169
|
-
completionTokens: 0,
|
170
|
-
},
|
165
|
+
usage: mapWorkersAIUsage(output),
|
171
166
|
warnings,
|
172
167
|
};
|
173
168
|
}
|
@@ -177,59 +172,54 @@ export class WorkersAIChatLanguageModel implements LanguageModelV1 {
|
|
177
172
|
): Promise<Awaited<ReturnType<LanguageModelV1["doStream"]>>> {
|
178
173
|
const { args, warnings } = this.getArgs(options);
|
179
174
|
|
180
|
-
const
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
175
|
+
const response = await this.config.binding.run(
|
176
|
+
args.model,
|
177
|
+
{
|
178
|
+
messages: args.messages,
|
179
|
+
max_tokens: args.max_tokens,
|
180
|
+
stream: true,
|
181
|
+
temperature: args.temperature,
|
182
|
+
tools: args.tools,
|
183
|
+
top_p: args.top_p,
|
184
|
+
},
|
185
|
+
{ gateway: this.config.gateway ?? this.settings.gateway }
|
186
|
+
);
|
186
187
|
|
187
188
|
if (!(response instanceof ReadableStream)) {
|
188
189
|
throw new Error("This shouldn't happen");
|
189
190
|
}
|
190
191
|
|
191
|
-
|
192
|
-
|
193
|
-
new TransformStream<
|
194
|
-
ParseResult<z.infer<typeof workersAIChatChunkSchema>>,
|
195
|
-
LanguageModelV1StreamPart
|
196
|
-
>({
|
197
|
-
async transform(chunk, controller) {
|
198
|
-
const chunkToText = decoder.decode(chunk as unknown as Uint8Array);
|
199
|
-
const chunks = events(new Response(chunkToText));
|
200
|
-
for await (const singleChunk of chunks) {
|
201
|
-
if (!singleChunk.data) {
|
202
|
-
continue;
|
203
|
-
}
|
204
|
-
if (singleChunk.data === "[DONE]") {
|
205
|
-
controller.enqueue({
|
206
|
-
type: "finish",
|
207
|
-
finishReason: "stop",
|
208
|
-
usage: {
|
209
|
-
promptTokens: 0,
|
210
|
-
completionTokens: 0,
|
211
|
-
},
|
212
|
-
});
|
213
|
-
return;
|
214
|
-
}
|
215
|
-
const data = JSON.parse(singleChunk.data);
|
192
|
+
const chunkEvent = events(new Response(response));
|
193
|
+
let usage = { promptTokens: 0, completionTokens: 0 };
|
216
194
|
|
195
|
+
return {
|
196
|
+
stream: new ReadableStream<LanguageModelV1StreamPart>({
|
197
|
+
async start(controller) {
|
198
|
+
for await (const event of chunkEvent) {
|
199
|
+
if (!event.data) {
|
200
|
+
continue;
|
201
|
+
}
|
202
|
+
if (event.data === "[DONE]") {
|
203
|
+
break;
|
204
|
+
}
|
205
|
+
const chunk = JSON.parse(event.data);
|
206
|
+
if (chunk.usage) {
|
207
|
+
usage = mapWorkersAIUsage(chunk);
|
208
|
+
}
|
209
|
+
chunk.response.length &&
|
217
210
|
controller.enqueue({
|
218
211
|
type: "text-delta",
|
219
|
-
textDelta:
|
212
|
+
textDelta: chunk.response,
|
220
213
|
});
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
},
|
231
|
-
})
|
232
|
-
),
|
214
|
+
}
|
215
|
+
controller.enqueue({
|
216
|
+
type: "finish",
|
217
|
+
finishReason: "stop",
|
218
|
+
usage: usage,
|
219
|
+
});
|
220
|
+
controller.close();
|
221
|
+
},
|
222
|
+
}),
|
233
223
|
rawCall: { rawPrompt: args.messages, rawSettings: args },
|
234
224
|
warnings,
|
235
225
|
};
|
package/src/workersai-error.ts
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
import {
|
2
2
|
createJsonErrorResponseHandler,
|
3
|
-
type ResponseHandler,
|
4
3
|
} from "@ai-sdk/provider-utils";
|
5
|
-
import type { APICallError } from "ai";
|
6
4
|
import { z } from "zod";
|
7
5
|
|
8
6
|
const workersAIErrorDataSchema = z.object({
|
@@ -13,9 +11,7 @@ const workersAIErrorDataSchema = z.object({
|
|
13
11
|
code: z.string().nullable(),
|
14
12
|
});
|
15
13
|
|
16
|
-
export
|
17
|
-
|
18
|
-
export const workersAIFailedResponseHandler: ResponseHandler<APICallError> =
|
14
|
+
export const workersAIFailedResponseHandler =
|
19
15
|
createJsonErrorResponseHandler({
|
20
16
|
errorSchema: workersAIErrorDataSchema,
|
21
17
|
errorToMessage: (data) => data.message,
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/**
|
2
|
+
* The names of the BaseAiTextGeneration models.
|
3
|
+
*/
|
4
|
+
export type TextGenerationModels = Exclude<
|
5
|
+
value2key<AiModels, BaseAiTextGeneration>,
|
6
|
+
value2key<AiModels, BaseAiTextToImage>
|
7
|
+
>;
|
8
|
+
|
9
|
+
type value2key<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];
|