feat(good-fences): complete(messages) on a Workers AI model
makeWorkersAiModel narrows the AI binding to one model's chat completion: the harness gets `complete`, not `run` on any model at any cost. gpt-oss-120b replies in the OpenAI shape (checked with a one-off probe), so the text is choices[0].message.content; anything else throws, naming the keys it got. Green: the model counts 3 rs in strawberry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
47a2337afe
commit
ec24f3e8e4
1 file changed
+24
@@ -0,0 +1,24 @@
|
||||
/** @file The model behind `complete(messages)`: Workers AI, through its binding. */
|
||||
|
||||
/** a Workers AI text-generation model with no paid-plan requirement */
|
||||
export const MODEL = "@cf/openai/gpt-oss-120b";
|
||||
|
||||
export type Message = Readonly<{ role: "system" | "user" | "assistant"; content: string }>;
|
||||
|
||||
/** the reply text from an OpenAI-style chat completion */
|
||||
const replyText = (output: unknown): string => {
|
||||
const { choices } = (output ?? {}) as { choices?: { message?: { content?: unknown } }[] };
|
||||
const text = choices?.[0]?.message?.content;
|
||||
if (typeof text !== "string") {
|
||||
throw Error(`no reply text in model output with keys: ${Object.keys(output ?? {}).join(", ")}`);
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
/** `complete(messages)` on a Workers AI model; `ai` is the AI binding */
|
||||
export const makeWorkersAiModel = (ai: Ai, model: string) => ({
|
||||
async complete(messages: readonly Message[]): Promise<string> {
|
||||
const output = await ai.run(model as Parameters<Ai["run"]>[0], { messages: [...messages] });
|
||||
return replyText(output);
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user