diff --git a/src/components/qa-report-panel.tsx b/src/components/qa-report-panel.tsx index d63f093..598a83c 100644 --- a/src/components/qa-report-panel.tsx +++ b/src/components/qa-report-panel.tsx @@ -12,6 +12,24 @@ const statusLabels = { fail: "失败", } as const; +const ruleLabels: Record = { + industry_alignment: "行业一致性", + image_text_match: "图文匹配", + voice_consistency: "表达视角一致性", + platform_fit: "平台适配", + company_name_integrity: "公司名称完整性", + title_quality: "标题质量", + body_quality: "正文质量", + hallucination_risk: "事实幻觉风险", + claim_consistency: "主张一致性", + context_sensitive_terms: "语境敏感词", +}; + +const targetAgentLabels: Record = { + title: "标题改写", + body: "正文改写", +}; + export function QaReportPanel({ report }: QaReportPanelProps) { if (!report) { return ( @@ -33,7 +51,7 @@ export function QaReportPanel({ report }: QaReportPanelProps) { {report.checks.map((check) => (
- {check.rule_id.replace(/_/g, " ")} + {ruleLabels[check.rule_id] ?? check.rule_id} {statusLabels[check.status]} @@ -41,7 +59,11 @@ export function QaReportPanel({ report }: QaReportPanelProps) {

{check.reason}

{check.evidence} {check.suggested_fix && {check.suggested_fix}} - {check.target_agent && {check.target_agent}} + {check.target_agent && ( + + {targetAgentLabels[check.target_agent] ?? check.target_agent} + + )}
))}
diff --git a/src/lib/workflow/__tests__/workflow.test.ts b/src/lib/workflow/__tests__/workflow.test.ts index ddada28..08fa197 100644 --- a/src/lib/workflow/__tests__/workflow.test.ts +++ b/src/lib/workflow/__tests__/workflow.test.ts @@ -133,6 +133,27 @@ describe("workflow nodes", () => { ]); }); + it("returns quality report details in Chinese", () => { + const report = inspectQuality({ + article: { + title: "Example GEO Optimization Guide", + summary: "A factual guide for marketing teams.", + body_markdown: + "Example Technology Co., Ltd. has eight years of GEO optimization experience.", + image_suggestions: [], + changed_sections: [], + requires_user_confirmation: [], + }, + factCard: confirmedFactCard, + platform: "official_site", + sourceImages: [], + }); + + expect(report.checks[0]?.reason).toContain("行业"); + expect(report.checks[0]?.suggested_fix).toContain("行业"); + expect(report.checks[0]?.evidence).not.toContain("Article"); + }); + it("hard-fails incomplete company names, hallucinated numbers, industry drift, and conflicting years", () => { const report = inspectQuality({ article: { diff --git a/src/lib/workflow/quality-inspector.ts b/src/lib/workflow/quality-inspector.ts index 06ba461..5ad715a 100644 --- a/src/lib/workflow/quality-inspector.ts +++ b/src/lib/workflow/quality-inspector.ts @@ -55,9 +55,9 @@ function inspectRule( aligned ? "pass" : "fail", aligned ? factCard.target_industry : article.summary, aligned - ? "Article stays aligned with the confirmed industry." - : "Article drifts from the confirmed industry.", - "Rewrite affected paragraphs around the confirmed industry.", + ? "文章内容与事实卡确认的目标行业一致。" + : "文章内容偏离事实卡确认的目标行业。", + "围绕事实卡确认的目标行业重写相关段落。", aligned ? null : "body", ); } @@ -67,11 +67,11 @@ function inspectRule( return check( ruleId, hasImages ? "pass" : "warn", - hasImages ? "Image topics are available." : "No image descriptions supplied.", + hasImages ? "已有可用于比对的图片主题。" : "未提供图片描述。", hasImages - ? "Image guidance can be compared with article sections." - : "Image-text confidence is low without image descriptions.", - "Add image descriptions or review image placement manually.", + ? "图片建议可以和文章内容进行比对。" + : "缺少图片描述时,图文匹配置信度较低。", + "补充图片描述,或人工检查图片与正文的对应关系。", null, ); } @@ -81,11 +81,11 @@ function inspectRule( return check( ruleId, thirdPartyOfficial ? "warn" : "pass", - thirdPartyOfficial ? "Third-party pronouns found." : "Voice matches platform.", + thirdPartyOfficial ? "发现第三方代词。" : "表达视角符合平台要求。", thirdPartyOfficial - ? "Official-site content should avoid detached third-party voice." - : "No obvious voice mismatch detected.", - "Rewrite in official brand voice.", + ? "官网文章应避免疏离的第三方叙述口吻。" + : "未发现明显的平台口吻不一致问题。", + "改写为更适合官网的品牌表达。", thirdPartyOfficial ? "body" : null, ); } @@ -97,8 +97,8 @@ function inspectRule( ? "pass" : "warn", article.summary, - "Platform fit is based on the generated summary and structure.", - "Review platform-specific framing.", + "平台适配基于生成摘要与文章结构判断。", + "复核文章是否符合目标平台的表达方式和结构。", null, ); } @@ -110,9 +110,9 @@ function inspectRule( hasFullName ? "pass" : "fail", hasFullName ? factCard.company_full_name : article.body_markdown, hasFullName - ? "Confirmed company full name is present." - : "The confirmed company full name is missing or shortened.", - "Use the confirmed company full name at first mention.", + ? "文章中包含事实卡确认的公司全称。" + : "文章缺少事实卡确认的公司全称,或使用了不完整简称。", + "首次出现公司时使用事实卡确认的公司全称。", hasFullName ? null : "body", ); } @@ -123,8 +123,8 @@ function inspectRule( ruleId, badTitle ? "fail" : "pass", article.title, - badTitle ? "Title appears awkward or over-punctuated." : "Title reads naturally.", - "Rewrite title for clarity and grammar.", + badTitle ? "标题存在语义不顺或标点堆砌问题。" : "标题表达自然清晰。", + "重写标题,提升语义清晰度和语法质量。", badTitle ? "title" : null, ); } @@ -134,11 +134,11 @@ function inspectRule( return check( ruleId, longSentence ? "warn" : "pass", - longSentence ? "Long sentence detected." : "Body structure is readable.", + longSentence ? "发现过长句子。" : "正文结构可读。", longSentence - ? "Some sentences are too long for comfortable reading." - : "No severe body grammar issue detected.", - "Split long sentences and clarify references.", + ? "部分句子过长,影响阅读和理解。" + : "未发现严重正文语法问题。", + "拆分长句,并明确指代关系。", longSentence ? "body" : null, ); } @@ -150,11 +150,11 @@ function inspectRule( unsupportedNumber || article.requires_user_confirmation.length > 0 ? "fail" : "pass", unsupportedNumber ? findUnsupportedNumbers(combined, factCard).join(", ") - : "No unsupported numeric claims found.", + : "未发现未确认的数字类事实主张。", unsupportedNumber - ? "Numeric claims are not traceable to the confirmed fact card." - : "Factual claims are traceable to the confirmed fact card.", - "Remove or confirm unsupported claims.", + ? "数字类主张无法追溯到已确认事实卡。" + : "事实主张可以追溯到已确认事实卡。", + "删除未确认主张,或先补充到事实卡并确认。", unsupportedNumber ? "body" : null, ); } @@ -167,11 +167,11 @@ function inspectRule( return check( ruleId, conflicts.length > 0 ? "fail" : "pass", - conflicts.length > 0 ? conflicts.join(", ") : "No conflicting claims found.", + conflicts.length > 0 ? conflicts.join(", ") : "未发现冲突事实。", conflicts.length > 0 - ? "Experience years conflict with the confirmed fact card." - : "Repeated claims are consistent.", - "Normalize years, products, and service claims to confirmed facts.", + ? "经验年限与事实卡确认内容冲突。" + : "重复出现的事实主张保持一致。", + "将年限、产品和服务表述统一为事实卡确认内容。", conflicts.length > 0 ? "body" : null, ); } @@ -179,9 +179,9 @@ function inspectRule( return check( ruleId, /\b(?:sensitive|forbidden)\b/i.test(combined) ? "warn" : "pass", - "Context-sensitive wording scan complete.", - "Sensitive terms need context-aware review when present.", - "Review wording manually instead of deleting terms mechanically.", + "已完成语境敏感词检查。", + "涉及敏感或禁用表达时,需要结合上下文判断。", + "人工复核相关表述,避免机械删除导致语义错误。", null, ); }