refactor: remove json_schema response format, simplify to json_object only

This commit is contained in:
MythEclipse
2026-06-03 00:40:42 +07:00
parent 6da8a32c9b
commit b7d4e66600
2 changed files with 14 additions and 96 deletions
@@ -56,15 +56,8 @@ export interface LlmCallOpts {
temperature?: number; temperature?: number;
/** Top-p (defaults to 0.95). */ /** Top-p (defaults to 0.95). */
top_p?: number; top_p?: number;
/** Force JSON output. When true, wraps schema in json_schema response_format. */ /** Force JSON output via response_format: { type: "json_object" }. */
jsonResponse?: jsonResponse?: { type: "json_object" };
| { type: "json_object" }
| {
type: "json_schema";
name: string;
schema: Record<string, unknown>;
strict: boolean;
};
/** Extra retries beyond DEFAULT_RETRIES (default 2). */ /** Extra retries beyond DEFAULT_RETRIES (default 2). */
retries?: number; retries?: number;
} }
@@ -91,39 +84,18 @@ export async function llmChat(
retries = DEFAULT_RETRIES, retries = DEFAULT_RETRIES,
} = opts; } = opts;
const responseFormat: const params: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = {
| { type: "json_object" } model,
| { messages,
type: "json_schema"; temperature,
json_schema: { top_p,
name: string; max_tokens,
schema: Record<string, unknown>; stream: false,
strict: boolean; };
};
}
| undefined = jsonResponse
? jsonResponse.type === "json_schema"
? {
type: "json_schema",
json_schema: {
name: jsonResponse.name,
schema: jsonResponse.schema,
strict: jsonResponse.strict,
},
}
: jsonResponse
: undefined;
const params: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = if (jsonResponse) {
{ (params as unknown as Record<string, unknown>).response_format = jsonResponse;
model, }
messages,
temperature,
top_p,
max_tokens,
stream: false,
...(responseFormat ? { response_format: responseFormat } : {}),
} as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming;
return retryWithBackoff( return retryWithBackoff(
async () => { async () => {
@@ -161,55 +161,6 @@ function deriveRecommendedAction(
return "review"; return "review";
} }
/**
* JSON Schema for OpenAI's response_format: { type: "json_schema" }.
* This enforces the exact structure the LLM must output (R2).
*/
const MODERATION_JSON_SCHEMA = {
type: "object",
properties: {
results: {
type: "array",
items: {
type: "object",
properties: {
message_id: { type: "string" },
status: { type: "string", enum: ["clean", "warn", "flagged"] },
flags: { type: "array", items: { type: "string" } },
score: { type: "number", minimum: 0, maximum: 1 },
analysis: { type: "string" },
categories: { type: "array", items: { type: "string" } },
severity: {
type: "string",
enum: ["none", "low", "medium", "high", "critical"],
},
confidence: { type: "number", minimum: 0, maximum: 1 },
recommended_action: {
type: "string",
enum: ["none", "monitor", "warn", "review", "delete", "escalate"],
},
policy_version: { type: "string" },
evidence: { type: "array", items: { type: "string" } },
},
required: [
"message_id",
"status",
"flags",
"score",
"severity",
"confidence",
"recommended_action",
"policy_version",
"evidence",
"analysis",
],
additionalProperties: false,
},
},
},
required: ["results"],
additionalProperties: false,
};
/** /**
* Helper to extract JSON from a potentially conversational or markdown-wrapped string. * Helper to extract JSON from a potentially conversational or markdown-wrapped string.
@@ -736,12 +687,7 @@ async function callModerationLLM(
const completion = await llmChat({ const completion = await llmChat({
messages: [{ role: "user", content }], messages: [{ role: "user", content }],
max_tokens: 16384, max_tokens: 16384,
jsonResponse: { jsonResponse: { type: "json_object" },
type: "json_schema",
name: "moderation_result",
schema: MODERATION_JSON_SCHEMA,
strict: true,
},
retries: 0, retries: 0,
}); });