fix: 收紧LLM输出格式提示

This commit is contained in:
Codex
2026-06-24 10:13:56 +08:00
parent 1802f3dd9d
commit ca70c81637
2 changed files with 123 additions and 0 deletions
+45
View File
@@ -47,6 +47,14 @@ describe("LLM prompt builders", () => {
expect(prompt).toContain("图片主题"); expect(prompt).toContain("图片主题");
}); });
it("fact extraction prompt explicitly forbids object items in string arrays", () => {
const prompt = `${FACT_EXTRACTOR_SYSTEM_PROMPT}\n${buildFactExtractorPrompt(articleInput)}`;
expect(prompt).toContain("uncertain_items must be string[]");
expect(prompt).toContain("core_claims must be string[]");
expect(prompt).toContain("Do not return objects inside string arrays");
});
it("article optimizer prompt includes platform templates and Chinese output rules", () => { it("article optimizer prompt includes platform templates and Chinese output rules", () => {
const prompt = `${ARTICLE_OPTIMIZER_SYSTEM_PROMPT}\n${buildArticleOptimizerPrompt(articleInput, factCard)}`; const prompt = `${ARTICLE_OPTIMIZER_SYSTEM_PROMPT}\n${buildArticleOptimizerPrompt(articleInput, factCard)}`;
@@ -60,6 +68,14 @@ describe("LLM prompt builders", () => {
expect(prompt).toContain("forbidden_claims"); expect(prompt).toContain("forbidden_claims");
}); });
it("article optimizer prompt explicitly describes optional array shapes", () => {
const prompt = `${ARTICLE_OPTIMIZER_SYSTEM_PROMPT}\n${buildArticleOptimizerPrompt(articleInput, factCard)}`;
expect(prompt).toContain("changed_sections must be string[]");
expect(prompt).toContain("requires_user_confirmation must be string[]");
expect(prompt).toContain("image_suggestions must be []");
});
it("quality inspector prompt encodes fail and warn standards for all risk gates", () => { it("quality inspector prompt encodes fail and warn standards for all risk gates", () => {
const prompt = `${QUALITY_INSPECTOR_SYSTEM_PROMPT}\n${buildQualityInspectorPrompt({ const prompt = `${QUALITY_INSPECTOR_SYSTEM_PROMPT}\n${buildQualityInspectorPrompt({
article: { article: {
@@ -92,6 +108,35 @@ describe("LLM prompt builders", () => {
expect(prompt).toContain("warn 标准"); expect(prompt).toContain("warn 标准");
}); });
it("quality inspector prompt explicitly describes enum outputs", () => {
const prompt = `${QUALITY_INSPECTOR_SYSTEM_PROMPT}\n${buildQualityInspectorPrompt({
article: {
title: "伟思德鲁 AIGC短视频培训",
summary: "官网文章摘要",
body_markdown: "正文",
image_suggestions: [],
changed_sections: [],
requires_user_confirmation: [],
},
factCard,
platform: "official_site",
deterministicChecks: [
{
rule_id: "title_quality",
status: "pass",
evidence: "标题自然",
reason: "本地规则通过",
suggested_fix: "",
target_agent: null,
},
],
})}`;
expect(prompt).toContain("status must be one of pass, warn, fail");
expect(prompt).toContain("rule_id must reuse the exact English rule_id");
expect(prompt).toContain("target_agent must be title, body, fact_card, or null");
});
it("targeted rewrite prompt gives rule-specific repair actions", () => { it("targeted rewrite prompt gives rule-specific repair actions", () => {
const prompt = `${TARGETED_REWRITER_SYSTEM_PROMPT}\n${buildTargetedRewritePrompt({ const prompt = `${TARGETED_REWRITER_SYSTEM_PROMPT}\n${buildTargetedRewritePrompt({
article: { article: {
+78
View File
@@ -25,6 +25,78 @@ const PLATFORM_GUIDANCE: Record<PublishPlatform, string> = {
"recommendation_list / 推荐榜单:推荐榜单口吻,必须解释推荐依据;不得制造榜单排名、奖项或第三方认证。", "recommendation_list / 推荐榜单:推荐榜单口吻,必须解释推荐依据;不得制造榜单排名、奖项或第三方认证。",
}; };
const FACT_CARD_OUTPUT_CONTRACT = [
"Output type contract:",
"- company_full_name, target_industry, target_audience must be strings.",
"- experience_years must be a number or null.",
"- company_short_names, brand_names, product_names, core_claims, forbidden_claims, image_topics, uncertain_items must be string[].",
"- core_claims must be string[].",
"- uncertain_items must be string[].",
"- Do not return objects inside string arrays; put the readable claim text directly in the array.",
"Example:",
JSON.stringify(
{
company_full_name: "示例科技有限公司",
company_short_names: ["示例科技"],
brand_names: ["示例品牌"],
product_names: ["GEO内容优化平台"],
target_industry: "GEO内容优化",
target_audience: "市场团队",
experience_years: null,
core_claims: ["提供GEO内容优化服务"],
forbidden_claims: ["行业第一"],
image_topics: ["产品后台截图"],
uncertain_items: ["客户案例缺少来源"],
},
null,
2,
),
].join("\n");
const OPTIMIZED_ARTICLE_OUTPUT_CONTRACT = [
"Output type contract:",
"- title, summary, body_markdown must be strings.",
"- image_suggestions must be [].",
"- changed_sections must be string[].",
"- requires_user_confirmation must be string[].",
"- Do not return objects inside string arrays; put the readable item text directly in the array.",
"Example:",
JSON.stringify(
{
title: "示例科技 GEO 内容优化方案",
summary: "围绕事实卡重写后的官网文章摘要。",
body_markdown: "## 服务能力\n示例科技有限公司提供GEO内容优化服务。",
image_suggestions: [],
changed_sections: ["title", "body"],
requires_user_confirmation: ["客户案例需要确认"],
},
null,
2,
),
].join("\n");
const QA_OUTPUT_CONTRACT = [
"Output type contract:",
"- Return { checks: QaCheck[] }.",
"- rule_id must reuse the exact English rule_id from deterministicChecks.",
"- status must be one of pass, warn, fail.",
"- evidence, reason, suggested_fix must be strings.",
"- target_agent must be title, body, fact_card, or null.",
"Example check:",
JSON.stringify(
{
rule_id: "title_quality",
status: "warn",
evidence: "标题偏营销化",
reason: "官网标题需要更克制",
suggested_fix: "改成事实型标题",
target_agent: "title",
},
null,
2,
),
].join("\n");
function formatPlatformGuidance(selected: PublishPlatform) { function formatPlatformGuidance(selected: PublishPlatform) {
return [ return [
"平台模板选项:", "平台模板选项:",
@@ -69,6 +141,8 @@ export function buildFactExtractorPrompt(input: ArticleInput) {
"company_full_name, company_short_names, brand_names, product_names, target_industry, target_audience, experience_years, core_claims, forbidden_claims, image_topics, uncertain_items.", "company_full_name, company_short_names, brand_names, product_names, target_industry, target_audience, experience_years, core_claims, forbidden_claims, image_topics, uncertain_items.",
"Do not include confirmed_by_user.", "Do not include confirmed_by_user.",
"", "",
FACT_CARD_OUTPUT_CONTRACT,
"",
"字段要求:", "字段要求:",
"- core_claims 只放原文明示、可作为后续优化硬约束的事实。", "- core_claims 只放原文明示、可作为后续优化硬约束的事实。",
"- forbidden_claims 放行业第一、最强、知名客户、显著提升、保证转化等无法验证或高风险主张。", "- forbidden_claims 放行业第一、最强、知名客户、显著提升、保证转化等无法验证或高风险主张。",
@@ -89,6 +163,8 @@ export function buildArticleOptimizerPrompt(
"Return an OptimizedArticle JSON object with these exact keys:", "Return an OptimizedArticle JSON object with these exact keys:",
"title, summary, body_markdown, image_suggestions, changed_sections, requires_user_confirmation.", "title, summary, body_markdown, image_suggestions, changed_sections, requires_user_confirmation.",
"", "",
OPTIMIZED_ARTICLE_OUTPUT_CONTRACT,
"",
formatPlatformGuidance(input.platform), formatPlatformGuidance(input.platform),
"", "",
"输出要求:", "输出要求:",
@@ -119,6 +195,7 @@ export function buildQualityInspectorPrompt(input: {
"Return a JSON object with a checks array.", "Return a JSON object with a checks array.",
"Each check must include rule_id, status, evidence, reason, suggested_fix, and target_agent.", "Each check must include rule_id, status, evidence, reason, suggested_fix, and target_agent.",
"Only use rule_id values already present in deterministicChecks.", "Only use rule_id values already present in deterministicChecks.",
QA_OUTPUT_CONTRACT,
"不得把 deterministic fail 降级。", "不得把 deterministic fail 降级。",
"", "",
formatPlatformGuidance(input.platform), formatPlatformGuidance(input.platform),
@@ -146,6 +223,7 @@ export function buildTargetedRewritePrompt(input: {
}) { }) {
return [ return [
"Return an OptimizedArticle JSON object.", "Return an OptimizedArticle JSON object.",
OPTIMIZED_ARTICLE_OUTPUT_CONTRACT,
"Rewrite only the fields needed for failedChecks.", "Rewrite only the fields needed for failedChecks.",
"", "",
"按 rule_id 执行修复动作:", "按 rule_id 执行修复动作:",