fix(good-fences): give the model room to answer

gpt-oss-120b reasons before it answers, and Workers AI's default
max_tokens (256) ran out mid-thought: finish_reason "length", content
null. Ask for 4096, and when there's no reply text, say which choice
and message keys came back instead.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dckcandClaude Opus 5.5 committed 2026-10-09 00:21:44 -05:00
1 parent 37faa92649
commit 4a85143a66
1 file changed
+14 -4
+14 -4
View File
@@ -3,14 +3,24 @@
/** a Workers AI text-generation model with no paid-plan requirement */ /** a Workers AI text-generation model with no paid-plan requirement */
export const MODEL = "@cf/openai/gpt-oss-120b"; export const MODEL = "@cf/openai/gpt-oss-120b";
/** room for a reasoning model to think and then answer; the default, 256,
* runs out mid-thought (`finish_reason: length`) */
const MAX_TOKENS = 4096;
export type Message = Readonly<{ role: "system" | "user" | "assistant"; content: string }>; export type Message = Readonly<{ role: "system" | "user" | "assistant"; content: string }>;
/** the reply text from an OpenAI-style chat completion */ /** the reply text from an OpenAI-style chat completion */
const replyText = (output: unknown): string => { const replyText = (output: unknown): string => {
const { choices } = (output ?? {}) as { choices?: { message?: { content?: unknown } }[] }; const { choices } = (output ?? {}) as {
const text = choices?.[0]?.message?.content; choices?: { message?: { content?: unknown }; finish_reason?: unknown }[];
};
const [choice] = choices ?? [];
const text = choice?.message?.content;
if (typeof text !== "string") { if (typeof text !== "string") {
throw Error(`no reply text in model output with keys: ${Object.keys(output ?? {}).join(", ")}`); const where = choice
? `choice with finish_reason ${String(choice.finish_reason)} and message keys: ${Object.keys(choice.message ?? {}).join(", ")}`
: `model output with keys: ${Object.keys(output ?? {}).join(", ")}`;
throw Error(`no reply text in ${where}`);
} }
return text; return text;
}; };
@@ -18,7 +28,7 @@ const replyText = (output: unknown): string => {
/** `complete(messages)` on a Workers AI model; `ai` is the AI binding */ /** `complete(messages)` on a Workers AI model; `ai` is the AI binding */
export const makeWorkersAiModel = (ai: Ai, model: string) => ({ export const makeWorkersAiModel = (ai: Ai, model: string) => ({
async complete(messages: readonly Message[]): Promise<string> { async complete(messages: readonly Message[]): Promise<string> {
const output = await ai.run(model as Parameters<Ai["run"]>[0], { messages: [...messages] }); const output = await ai.run(model as Parameters<Ai["run"]>[0], { messages: [...messages], max_tokens: MAX_TOKENS });
return replyText(output); return replyText(output);
}, },
}); });