refactor: remove json_schema response format, simplify to json_object only
This commit is contained in:
@@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user