fix: 收紧LLM输出格式提示
This commit is contained in:
@@ -47,6 +47,14 @@ describe("LLM prompt builders", () => {
|
||||
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", () => {
|
||||
const prompt = `${ARTICLE_OPTIMIZER_SYSTEM_PROMPT}\n${buildArticleOptimizerPrompt(articleInput, factCard)}`;
|
||||
|
||||
@@ -60,6 +68,14 @@ describe("LLM prompt builders", () => {
|
||||
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", () => {
|
||||
const prompt = `${QUALITY_INSPECTOR_SYSTEM_PROMPT}\n${buildQualityInspectorPrompt({
|
||||
article: {
|
||||
@@ -92,6 +108,35 @@ describe("LLM prompt builders", () => {
|
||||
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", () => {
|
||||
const prompt = `${TARGETED_REWRITER_SYSTEM_PROMPT}\n${buildTargetedRewritePrompt({
|
||||
article: {
|
||||
|
||||
@@ -25,6 +25,78 @@ const PLATFORM_GUIDANCE: Record<PublishPlatform, string> = {
|
||||
"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) {
|
||||
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.",
|
||||
"Do not include confirmed_by_user.",
|
||||
"",
|
||||
FACT_CARD_OUTPUT_CONTRACT,
|
||||
"",
|
||||
"字段要求:",
|
||||
"- core_claims 只放原文明示、可作为后续优化硬约束的事实。",
|
||||
"- forbidden_claims 放行业第一、最强、知名客户、显著提升、保证转化等无法验证或高风险主张。",
|
||||
@@ -89,6 +163,8 @@ export function buildArticleOptimizerPrompt(
|
||||
"Return an OptimizedArticle JSON object with these exact keys:",
|
||||
"title, summary, body_markdown, image_suggestions, changed_sections, requires_user_confirmation.",
|
||||
"",
|
||||
OPTIMIZED_ARTICLE_OUTPUT_CONTRACT,
|
||||
"",
|
||||
formatPlatformGuidance(input.platform),
|
||||
"",
|
||||
"输出要求:",
|
||||
@@ -119,6 +195,7 @@ export function buildQualityInspectorPrompt(input: {
|
||||
"Return a JSON object with a checks array.",
|
||||
"Each check must include rule_id, status, evidence, reason, suggested_fix, and target_agent.",
|
||||
"Only use rule_id values already present in deterministicChecks.",
|
||||
QA_OUTPUT_CONTRACT,
|
||||
"不得把 deterministic fail 降级。",
|
||||
"",
|
||||
formatPlatformGuidance(input.platform),
|
||||
@@ -146,6 +223,7 @@ export function buildTargetedRewritePrompt(input: {
|
||||
}) {
|
||||
return [
|
||||
"Return an OptimizedArticle JSON object.",
|
||||
OPTIMIZED_ARTICLE_OUTPUT_CONTRACT,
|
||||
"Rewrite only the fields needed for failedChecks.",
|
||||
"",
|
||||
"按 rule_id 执行修复动作:",
|
||||
|
||||
Reference in New Issue
Block a user