209 lines
7.8 KiB
TypeScript
209 lines
7.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
ARTICLE_OPTIMIZER_SYSTEM_PROMPT,
|
|
FACT_EXTRACTOR_SYSTEM_PROMPT,
|
|
QUALITY_INSPECTOR_SYSTEM_PROMPT,
|
|
RENWEI_COPY_OPTIMIZER_SYSTEM_PROMPT,
|
|
TARGETED_REWRITER_SYSTEM_PROMPT,
|
|
buildArticleOptimizerPrompt,
|
|
buildFactExtractorPrompt,
|
|
buildQualityInspectorPrompt,
|
|
buildRenweiCopyOptimizationPrompt,
|
|
buildTargetedRewritePrompt,
|
|
} from "../prompts";
|
|
|
|
const articleInput = {
|
|
title: "探寻AIGC短视频培训选哪家,各品牌实力大比拼",
|
|
body: "伟思德鲁管理咨询(深圳)有限公司提供AIGC短视频培训,文章提到客户案例和出海内容生产。",
|
|
images: [{ type: "description" as const, content: "AIGC短视频工作流示意图" }],
|
|
platform: "official_site" as const,
|
|
user_instructions: "改成官网文章,避免虚构客户案例。",
|
|
};
|
|
|
|
const factCard = {
|
|
company_full_name: "伟思德鲁管理咨询(深圳)有限公司",
|
|
company_short_names: ["伟思德鲁", "伟思德鲁管理咨询"],
|
|
brand_names: ["伟思德鲁管理咨询"],
|
|
product_names: ["AIGC短视频培训"],
|
|
target_industry: "AIGC短视频培训",
|
|
target_audience: "品牌商家、内容创作者、出海企业",
|
|
experience_years: null,
|
|
core_claims: ["提供AIGC短视频培训"],
|
|
forbidden_claims: ["行业第一", "服务过500强客户"],
|
|
image_topics: ["AIGC短视频工作流示意图"],
|
|
uncertain_items: [],
|
|
is_ready_for_optimization: true,
|
|
confirmed_by_user: true,
|
|
} as const;
|
|
|
|
describe("LLM prompt builders", () => {
|
|
it("fact extraction prompt names customer risk categories and uncertainty rules", () => {
|
|
const prompt = `${FACT_EXTRACTOR_SYSTEM_PROMPT}\n${buildFactExtractorPrompt(articleInput)}`;
|
|
|
|
expect(prompt).toContain("客户案例");
|
|
expect(prompt).toContain("资质荣誉");
|
|
expect(prompt).toContain("经验年限");
|
|
expect(prompt).toContain("uncertain_items");
|
|
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", () => {
|
|
const prompt = `${ARTICLE_OPTIMIZER_SYSTEM_PROMPT}\n${buildArticleOptimizerPrompt(articleInput, factCard)}`;
|
|
|
|
expect(prompt).toContain("official_site");
|
|
expect(prompt).toContain("官网文章");
|
|
expect(prompt).toContain("第一方品牌口吻");
|
|
expect(prompt).toContain("输出中文标题");
|
|
expect(prompt).toContain("禁止使用英文模板词");
|
|
expect(prompt).toContain("实质性重写");
|
|
expect(prompt).toContain("不得新增客户案例");
|
|
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: {
|
|
title: "伟思德鲁 AIGC短视频培训",
|
|
summary: "官网文章摘要",
|
|
body_markdown: "正文",
|
|
image_suggestions: [],
|
|
changed_sections: [],
|
|
requires_user_confirmation: [],
|
|
},
|
|
factCard,
|
|
platform: "official_site",
|
|
deterministicChecks: [
|
|
{
|
|
rule_id: "hallucination_risk",
|
|
status: "pass",
|
|
evidence: "未发现",
|
|
reason: "本地规则通过",
|
|
suggested_fix: "",
|
|
target_agent: null,
|
|
},
|
|
],
|
|
})}`;
|
|
|
|
expect(prompt).toContain("不得把 deterministic fail 降级");
|
|
expect(prompt).toContain("行业漂移");
|
|
expect(prompt).toContain("公司名不一致");
|
|
expect(prompt).toContain("未确认案例");
|
|
expect(prompt).toContain("平台口吻严重错误");
|
|
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: {
|
|
title: "Bad title!!!",
|
|
summary: "摘要",
|
|
body_markdown: "正文",
|
|
image_suggestions: [],
|
|
changed_sections: [],
|
|
requires_user_confirmation: [],
|
|
},
|
|
factCard,
|
|
failedChecks: [
|
|
{
|
|
rule_id: "title_quality",
|
|
status: "fail",
|
|
evidence: "Bad title!!!",
|
|
reason: "标题问题",
|
|
suggested_fix: "重写标题",
|
|
target_agent: "title",
|
|
},
|
|
],
|
|
})}`;
|
|
|
|
expect(prompt).toContain("industry_alignment");
|
|
expect(prompt).toContain("company_name_integrity");
|
|
expect(prompt).toContain("hallucination_risk");
|
|
expect(prompt).toContain("claim_consistency");
|
|
expect(prompt).toContain("title_quality");
|
|
expect(prompt).toContain("body_quality");
|
|
expect(prompt).toContain("不得新增事实");
|
|
});
|
|
|
|
it("renwei copy prompt keeps the author present and defaults to small edits", () => {
|
|
const prompt = `${RENWEI_COPY_OPTIMIZER_SYSTEM_PROMPT}\n${buildRenweiCopyOptimizationPrompt({
|
|
source_text: "我观察到大家越来越难进入心流了。",
|
|
goal: "保留原意,减少 AI 味",
|
|
intensity: "light",
|
|
user_instructions: "保留作者的口语感。",
|
|
})}`;
|
|
|
|
expect(prompt).toContain("少动");
|
|
expect(prompt).toContain("保留作者");
|
|
expect(prompt).toContain("手迹");
|
|
expect(prompt).toContain("不凭空新增时间、地点、数字、案例");
|
|
expect(prompt).toContain("不写过度金句");
|
|
expect(prompt).toContain("逐处说明");
|
|
expect(prompt).toContain("只检查被改动句子");
|
|
expect(prompt).toContain("source_text");
|
|
});
|
|
|
|
it("renwei copy prompt describes all result fields and intensity modes", () => {
|
|
const prompt = buildRenweiCopyOptimizationPrompt({
|
|
source_text: "这是一段文案。",
|
|
goal: "更自然",
|
|
intensity: "conversational",
|
|
user_instructions: "",
|
|
});
|
|
|
|
expect(prompt).toContain("optimized_text");
|
|
expect(prompt).toContain("change_notes");
|
|
expect(prompt).toContain("ai_taste_checks");
|
|
expect(prompt).toContain("warnings");
|
|
expect(prompt).toContain("light");
|
|
expect(prompt).toContain("medium");
|
|
expect(prompt).toContain("conversational");
|
|
});
|
|
});
|