feat: add hybrid llm quality inspection
This commit is contained in:
@@ -8,7 +8,13 @@ import type {
|
||||
QaReport,
|
||||
QualityRuleId,
|
||||
} from "../domain/types";
|
||||
import { qaReportSchema } from "../domain/validation";
|
||||
import { qaCheckSchema, qaReportSchema } from "../domain/validation";
|
||||
import { generateValidatedJson } from "../llm/client";
|
||||
import {
|
||||
QUALITY_INSPECTOR_SYSTEM_PROMPT,
|
||||
buildQualityInspectorPrompt,
|
||||
} from "../llm/prompts";
|
||||
import { z } from "zod";
|
||||
|
||||
const REQUIRED_RULES: QualityRuleId[] = [
|
||||
"industry_alignment",
|
||||
@@ -23,6 +29,10 @@ const REQUIRED_RULES: QualityRuleId[] = [
|
||||
"context_sensitive_terms",
|
||||
];
|
||||
|
||||
const llmQaPatchSchema = z.object({
|
||||
checks: z.array(qaCheckSchema).default([]),
|
||||
});
|
||||
|
||||
export interface InspectQualityInput {
|
||||
article: OptimizedArticle;
|
||||
factCard: ConfirmedFactCard;
|
||||
@@ -41,6 +51,57 @@ export function inspectQuality(input: InspectQualityInput): QaReport {
|
||||
return qaReportSchema.parse({ overall_status, checks });
|
||||
}
|
||||
|
||||
export async function inspectQualityWithLlm(
|
||||
input: InspectQualityInput,
|
||||
): Promise<QaReport> {
|
||||
const deterministicReport = inspectQuality(input);
|
||||
const llmPatch = await generateValidatedJson({
|
||||
schema: llmQaPatchSchema,
|
||||
system: QUALITY_INSPECTOR_SYSTEM_PROMPT,
|
||||
prompt: buildQualityInspectorPrompt({
|
||||
article: input.article,
|
||||
factCard: input.factCard,
|
||||
platform: input.platform,
|
||||
deterministicChecks: deterministicReport.checks,
|
||||
}),
|
||||
temperature: 0.1,
|
||||
});
|
||||
|
||||
if (!llmPatch) {
|
||||
return deterministicReport;
|
||||
}
|
||||
|
||||
const patchedChecks = deterministicReport.checks.map((deterministicCheck) => {
|
||||
const llmCheck = llmPatch.checks.find(
|
||||
(check) => check.rule_id === deterministicCheck.rule_id,
|
||||
);
|
||||
if (!llmCheck) {
|
||||
return deterministicCheck;
|
||||
}
|
||||
if (deterministicCheck.status === "fail") {
|
||||
return deterministicCheck;
|
||||
}
|
||||
return {
|
||||
...deterministicCheck,
|
||||
status: llmCheck.status,
|
||||
evidence: llmCheck.evidence,
|
||||
reason: llmCheck.reason,
|
||||
suggested_fix: llmCheck.suggested_fix,
|
||||
target_agent: llmCheck.target_agent,
|
||||
};
|
||||
});
|
||||
|
||||
const overall_status: CheckStatus = patchedChecks.some(
|
||||
(check) => check.status === "fail",
|
||||
)
|
||||
? "fail"
|
||||
: patchedChecks.some((check) => check.status === "warn")
|
||||
? "warn"
|
||||
: "pass";
|
||||
|
||||
return qaReportSchema.parse({ overall_status, checks: patchedChecks });
|
||||
}
|
||||
|
||||
function inspectRule(
|
||||
ruleId: QualityRuleId,
|
||||
{ article, factCard, platform, sourceImages }: InspectQualityInput,
|
||||
|
||||
Reference in New Issue
Block a user