diff --git a/apps/admin-web/src/components/ArticleEditorCanvas.vue b/apps/admin-web/src/components/ArticleEditorCanvas.vue index d301a80..24cdb01 100644 --- a/apps/admin-web/src/components/ArticleEditorCanvas.vue +++ b/apps/admin-web/src/components/ArticleEditorCanvas.vue @@ -29,6 +29,7 @@ import { insertHrCommand, toggleEmphasisCommand, toggleStrongCommand, + turnIntoTextCommand, wrapInBlockquoteCommand, wrapInBulletListCommand, wrapInHeadingCommand, @@ -2266,6 +2267,7 @@ function runTableContextAction(action: TableContextMenuAction): void { + 正文 H1 H2 H3 diff --git a/apps/admin-web/src/i18n/messages/en-US.ts b/apps/admin-web/src/i18n/messages/en-US.ts index 09dacee..f128efe 100644 --- a/apps/admin-web/src/i18n/messages/en-US.ts +++ b/apps/admin-web/src/i18n/messages/en-US.ts @@ -154,7 +154,7 @@ const enUS = { template_outline_generate: 'AI Outline Generation', kol_prompt_generate: 'KOL Prompt Generation', kol_prompt_optimize: 'KOL Prompt Optimize', - question_distill: 'AI Candidate Question Generation', + question_distill: 'AI Candidate Search Term Generation', question_combination_fill: 'Expansion Tool AI Fill', }, aiUsageStatus: { @@ -214,12 +214,13 @@ const enUS = { 'Review desktop publish tasks, external links, account workbench entry points, and retry state.', }, brands: { - title: 'Brand Library', - description: 'Manage keywords, question sets, and competitors around each brand.', + title: 'Company & Lexicon', + description: 'Manage the keyword library (search terms) and competitors around each brand.', }, brandQuestionCreate: { - title: 'New question', - description: 'Create brand questions with the expansion tool, AI expansion, or manual input.', + title: 'New search term', + description: + 'Create brand search terms with the expansion tool, AI expansion, or manual input.', }, tracking: { title: 'Data Details', @@ -459,11 +460,11 @@ const enUS = { }, tracking: { brandPlaceholder: 'Select brand', - keywordPlaceholder: 'Select question set', - allQuestionSets: 'All question sets', + keywordPlaceholder: 'Select keyword library (search terms)', + allQuestionSets: 'All keyword library (search terms)', collectNow: 'Collect Now', collectBrandRequired: 'Select a brand before collecting.', - collectKeywordRequired: 'Select a question set before collecting.', + collectKeywordRequired: 'Select a keyword library (search terms) before collecting.', collectTodayOnly: "Collect Now only supports today's data. Switch back to today to continue.", collectClientChecking: "Checking whether the current account's desktop client is online.", collectClientOnlineRequired: @@ -488,7 +489,7 @@ const enUS = { hotQuestions: 'Hot Questions', hotQuestionsTitle: 'Hot Questions', hotQuestionsHint: - 'Choose all question sets or one specific question. Selecting one question limits display and collection to that question.', + 'Choose the full keyword library (search terms) or one specific search term. Selecting one search term limits display and collection to that term.', questionSearchPlaceholder: 'Search questions in the selected scope', questionDetailEyebrow: 'Question Detail', questionDetailCollectedAt: 'Collected at {time}', @@ -841,13 +842,13 @@ const enUS = { language: 'Language', brandInfo: 'Brand', brandLibrary: 'Brand library', - brandName: 'Brand name', + brandName: 'Company name', website: 'Official website', brandSummary: 'AI brand summary', keywords: 'Keywords', - brandQuestions: 'Brand questions', - primaryQuestion: 'Primary brand question', - supplementalQuestions: 'Supplemental questions', + brandQuestions: 'Keyword library (search terms)', + primaryQuestion: 'Optimization keyword', + supplementalQuestions: 'Supplemental keywords', competitors: 'Competitors', chooseTitle: 'Choose a title', customTitle: 'Custom title', @@ -864,17 +865,17 @@ const enUS = { hints: { brandContext: 'Optional. Selecting a brand pulls in keywords and competitor context.', brandFlow: - 'You can pick a brand from the library or type one manually. After you choose a brand question, AI will prepare the summary, competitors, and title options.', + 'You can type a company name or choose one from the brand library. After you choose an optimization keyword, AI will prepare the summary, competitors, and title options.', brandSummaryPlaceholder: 'After analysis, AI will summarize the brand angle, positioning, and content opportunities here.', keywords: 'Type keywords directly or reuse brand-library keywords. AI results will be merged into this list.', brandQuestions: - 'The primary question controls the article spine; supplemental questions broaden nearby search intent.', + 'The optimization keyword controls the article spine; supplemental keywords broaden nearby search intent.', supplementalQuestions: 'Choose up to 3 so the article covers related intent without drifting.', questionEmpty: 'No questions are available for this brand yet.', - selectBrandFirst: 'Choose a brand from the library first.', + selectBrandFirst: 'Choose a library brand from the company name dropdown first.', competitors: 'Competitors stay editable. You can add rows manually; saving to the competitor library is only available after choosing a library brand.', competitorEmptyEditable: @@ -931,11 +932,11 @@ const enUS = { }, placeholders: { brandLibrary: 'Choose an existing brand from the library', - brandName: 'Enter a brand name, or refine the selected library brand', + brandName: 'Enter a company name, or choose from the brand library', website: 'Official website, optional', keywords: 'Type keywords and press Enter', - primaryQuestion: 'Choose one primary brand question', - supplementalQuestions: 'Optional, choose up to 3 supplemental questions', + primaryQuestion: 'Choose one optimization keyword', + supplementalQuestions: 'Optional, choose up to 3 supplemental keywords', customTitle: 'Override the AI title here if needed', customOutline: 'Add another section, for example “Buying advice”', keyPoints: 'Add any extra instructions, key angles, or constraints for the article', @@ -949,9 +950,9 @@ const enUS = { aiBanner: { title: 'One-click AI analysis', defaultDescription: - 'AI will use the brand question to complete the brand summary and extract competitor context.', + 'AI will use the optimization keyword to complete the brand summary and extract competitor context.', productReviewDescription: - 'AI will use the brand question to organize the product context and suggest comparable alternatives.', + 'AI will use the optimization keyword to organize the product context and suggest comparable alternatives.', researchReportDescription: 'AI will use the brand question to organize the topic context and suggest reference targets.', }, @@ -983,15 +984,18 @@ const enUS = { }, messages: { requiredField: 'Please fill in {field} first.', - missingBrand: 'Choose a brand from the library or enter a brand name first.', - selectBrandBeforeQuestion: 'Choose a brand from the library before selecting a question.', + missingBrand: 'Enter or choose a company name first.', + selectBrandBeforeQuestion: + 'Choose a library brand from the company name dropdown before selecting a question.', missingPrimaryQuestion: 'Choose one primary brand question.', missingTitle: 'Please choose or enter an article title.', missingOutline: 'Please select at least one outline section.', missingGeneratedOutline: 'Please generate and confirm the article outline first.', customOutlineTooLong: 'Custom sections cannot exceed {count} characters.', - selectBrandBeforeCompetitors: 'Choose a brand from the library before managing competitors.', - selectBrandBeforeFavorite: 'Choose a brand from the library before saving competitors.', + selectBrandBeforeCompetitors: + 'Choose a library brand from the company name dropdown before managing competitors.', + selectBrandBeforeFavorite: + 'Choose a library brand from the company name dropdown before saving competitors.', missingCompetitorName: 'Enter a competitor name before saving it to the library.', savedCompetitor: 'Competitor saved to the brand library.', unsavedCompetitor: 'Competitor removed from the brand library.', @@ -1285,20 +1289,21 @@ const enUS = { }, }, brands: { - eyebrow: 'Brand Library', - title: 'Brand Management', - description: 'Manage question sets and competitor assets around each brand.', + eyebrow: 'Company & Lexicon', + title: 'Company & Lexicon', + description: 'Manage the keyword library (search terms) and competitor assets around each brand.', railTitle: 'Brands', - selectBrand: 'Pick a brand to continue managing question sets.', + selectBrand: 'Pick a brand to continue managing the keyword library (search terms).', newBrand: 'New brand', editBrand: 'Edit brand', deleteBrand: 'Delete brand', guide: { title: 'Brand management guide', - body: 'Manage brands, question sets, and competitor libraries for AI platform monitoring and GEO analysis.', + body: + 'Manage brands, the keyword library (search terms), and competitor libraries for AI platform monitoring and GEO analysis.', }, tabs: { - questions: 'Question set', + questions: 'Keyword library (search terms)', competitors: 'Competitors', }, quota: { @@ -1321,20 +1326,20 @@ const enUS = { }, sections: { keywords: 'Keywords', - questions: 'Question set', + questions: 'Keyword library (search terms)', competitors: 'Competitor library', versions: 'Version history', }, actions: { addBrand: 'Add brand', newKeyword: 'New keyword', - newQuestion: 'New question', + newQuestion: 'New search term', newCompetitor: 'New competitor', viewVersions: 'View versions', }, empty: { brands: 'No brand data yet. Create your first brand to start.', - questions: 'No questions under this brand yet.', + questions: 'No search terms under this brand yet.', competitors: 'No competitors under this brand yet.', brandDescription: 'No brand description yet', competitorDescription: 'No competitor description yet', @@ -1344,7 +1349,7 @@ const enUS = { brandWebsite: 'Company website (optional)', brandDescription: 'Brand description', keywordName: 'Keyword', - questionText: 'Question text', + questionText: 'Search term', competitorName: 'Competitor name', competitorWebsite: 'Competitor website', competitorDescription: 'Competitor description', @@ -1358,9 +1363,9 @@ const enUS = { createKeyword: 'Keyword created.', updateKeyword: 'Keyword updated.', deleteKeyword: 'Keyword deleted.', - createQuestion: 'Question created.', - updateQuestion: 'Question updated.', - deleteQuestion: 'Question deleted.', + createQuestion: 'Search term created.', + updateQuestion: 'Search term updated.', + deleteQuestion: 'Search term deleted.', createCompetitor: 'Competitor created.', updateCompetitor: 'Competitor updated.', deleteCompetitor: 'Competitor deleted.', @@ -1368,21 +1373,21 @@ const enUS = { chooseKeyword: 'Please choose a keyword first.', brandLimitReached: 'Your current plan allows up to {limit} brand companies.', keywordLimitReached: 'This account allows up to {limit} keywords.', - questionLimitReached: 'This account allows up to {limit} questions.', + questionLimitReached: 'This account allows up to {limit} search terms.', }, questions: { - create: 'New question', - createSingle: 'Add single question', - expand: 'Bulk expand questions', - usage: 'Questions {used} / {total}', + create: 'New search term', + createSingle: 'Add single search term', + expand: 'Bulk expand search terms', + usage: 'Search terms {used} / {total}', remaining: '{count} remaining', generate: 'Generate candidates', - emptyCandidates: 'No candidates yet. Generate or paste questions above.', + emptyCandidates: 'No candidates yet. Generate or paste search terms above.', table: { - question: 'Question set', + question: 'Keyword library (search terms)', }, modal: { - title: 'New question', + title: 'New search term', currentBrand: 'Current brand', methods: { single: 'Single', @@ -1393,17 +1398,17 @@ const enUS = { preview: 'Candidate preview', summary: '{total} candidates · {selected} selected · {tooShort} too short · {duplicate} duplicates', - save: 'Save questions ({count})', + save: 'Save search terms ({count})', }, combination: { region: '1. Region', prefix: '2. Prefix', - core: '3. Core (required)', + core: '3. Precise term (required)', industry: '4. Industry (required)', suffix: '5. Suffix', defaultWord: 'Default', estimate: '{count} candidates estimated', - coreRequired: 'Core is required', + coreRequired: 'Precise term is required', industryRequired: 'Industry is required', }, aiFill: { @@ -1414,25 +1419,25 @@ const enUS = { waitingStages: { region: 'Detecting city, province capital, and macro region...', generate: 'Analyzing brand context and high-frequency intent...', - refine: 'Refining short combinable keyword groups...', + refine: 'Refining short combinable precise term groups...', }, }, ai: { note: 'AI expansion consumes 1 AI point. Failed generations are refunded automatically.', - seedTopic: 'Seed topic', - seedTopicPlaceholder: 'Enter a topic and press Enter; multiple topics supported', + seedTopic: 'User search term', + seedTopicPlaceholder: 'Enter a search term and press Enter; multiple terms supported', seedTopicHint: - 'Use Enter, commas, or semicolons to add multiple topics. Candidates are merged and deduplicated automatically.', + 'Candidates expand from user search terms with strong commercial intent. The company name is a target term, not a candidate search term.', generate: 'Generate with AI', - waitingTitle: 'AI is generating candidate questions. Please wait...', + waitingTitle: 'AI is generating candidate search terms. Please wait...', waitingStages: { - context: 'Organizing brand and topic context...', - generate: 'Generating high-intent candidate questions...', - refine: 'Deduplicating and filtering savable questions...', + context: 'Organizing user search terms and the target term...', + generate: 'Generating commercial candidate search terms suited for recommending companies...', + refine: 'Deduplicating and filtering savable search terms...', }, }, batch: { - label: 'One question per line', + label: 'One search term per line', }, badges: { duplicate: 'Duplicate', @@ -1440,20 +1445,22 @@ const enUS = { }, messages: { partialSaved: 'Saved {created}; skipped {skipped}.', - limitReached: 'This account allows up to {limit} questions shared across all brands.', - selectionLimitReached: 'This plan allows up to {limit} questions. Selection limit reached.', + limitReached: 'This account allows up to {limit} search terms shared across all brands.', + selectionLimitReached: + 'This plan allows up to {limit} search terms. Selection limit reached.', truncated: 'Candidates exceeded the limit and were truncated to 500.', cacheHit: 'Used the most recent AI expansion result.', aiCharged: 'This AI expansion consumed {count} AI point.', }, errors: { - emptyInput: 'Enter question content first.', + emptyInput: 'Enter search term content first.', noSelection: 'Select at least one candidate.', - noValidQuestions: 'No valid questions can be saved. Adjust candidates and try again.', + noValidQuestions: 'No valid search terms can be saved. Adjust candidates and try again.', }, page: { - title: 'New question', - subtitle: 'Generate candidates, review them, then save them to this brand question set.', + title: 'New search term', + subtitle: + 'Generate candidates, review them, then save them to this brand keyword library (search terms).', steps: { configure: 'Configure', preview: 'Review candidates', @@ -1462,13 +1469,13 @@ const enUS = { methodHint: 'Candidates remain temporary until saved, so you can generate, edit, and select first.', methods: { - combination: 'Expand candidates from the column-based word tool.', - ai: 'Let AI generate candidates around a seed topic.', - batch: 'Paste questions from a sheet or document.', + combination: 'Expand search term candidates from the column-based word tool.', + ai: 'Let AI generate search term candidates around a seed topic.', + batch: 'Paste search terms from a sheet or document.', }, expansionHint: - 'One word per line. Empty optional columns are skipped; core and industry are required.', - batchHint: 'One question per line. You can edit and select each one before saving.', + 'One word per line. Empty optional columns are skipped; precise term and industry are required.', + batchHint: 'One search term per line. You can edit and select each one before saving.', }, }, }, diff --git a/apps/admin-web/src/i18n/messages/zh-CN.ts b/apps/admin-web/src/i18n/messages/zh-CN.ts index b527dc4..7e7fd3d 100644 --- a/apps/admin-web/src/i18n/messages/zh-CN.ts +++ b/apps/admin-web/src/i18n/messages/zh-CN.ts @@ -79,7 +79,7 @@ const zhCN = { media: "媒体管理", publishManagement: "发文管理", brandManagement: "品牌管理", - brands: "品牌词库", + brands: "公司和词库", tracking: "数据追踪", trackingDetail: "数据详情", contentManagement: "内容管理", @@ -150,7 +150,7 @@ const zhCN = { template_outline_generate: "AI 生成大纲", kol_prompt_generate: "KOL 模版生成", kol_prompt_optimize: "KOL 模版优化", - question_distill: "AI 生成候选问题", + question_distill: "AI 生成候选搜索词", question_combination_fill: "拓词工具 AI 填词", }, aiUsageStatus: { @@ -206,12 +206,12 @@ const zhCN = { description: "查看桌面端发布任务、外链、账号工作台入口和重发状态。", }, brands: { - title: "品牌词库", - description: "围绕品牌维护关键词、问题集和竞品信息。", + title: "公司和词库", + description: "围绕品牌维护关键词库(搜索词)和竞品信息。", }, brandQuestionCreate: { - title: "新建问题", - description: "用拓词工具、AI 扩展或手动录入创建品牌问题集。", + title: "新建搜索词", + description: "用拓词工具、AI 扩展或手动录入创建品牌关键词库(搜索词)。", }, tracking: { title: "数据详情", @@ -440,11 +440,11 @@ const zhCN = { }, tracking: { brandPlaceholder: "选择品牌", - keywordPlaceholder: "选择问题集", - allQuestionSets: "全部问题集", + keywordPlaceholder: "选择关键词库(搜索词)", + allQuestionSets: "全部关键词库(搜索词)", collectNow: "立即采集", collectBrandRequired: "请先选择品牌,再发起采集", - collectKeywordRequired: "请选择问题集后再发起采集", + collectKeywordRequired: "请选择关键词库(搜索词)后再发起采集", collectTodayOnly: "立即采集只支持今天的数据,请切回今天后再操作", collectClientChecking: "正在检查当前账号的桌面客户端状态", collectClientOnlineRequired: "当前登录账号的桌面客户端未在线,暂时不能立即采集", @@ -464,7 +464,7 @@ const zhCN = { platformMatrixTitle: "平台对比矩阵", hotQuestions: "Hot Questions", hotQuestionsTitle: "高频问题", - hotQuestionsHint: "可选择全部问题集或具体单个问题;选择单个问题时只展示并采集该问题。", + hotQuestionsHint: "可选择全部关键词库(搜索词)或具体单个搜索词;选择单个搜索词时只展示并采集该搜索词。", questionSearchPlaceholder: "搜索当前范围下的问题", questionDetailEyebrow: "Question Detail", questionDetailCollectedAt: "采集时间 {time}", @@ -806,13 +806,13 @@ const zhCN = { language: "文章语言", brandInfo: "品牌信息", brandLibrary: "品牌库", - brandName: "品牌名称", + brandName: "公司名称", website: "官网地址", brandSummary: "AI 品牌摘要", keywords: "关键词", - brandQuestions: "品牌问题", - primaryQuestion: "品牌主问题", - supplementalQuestions: "补充覆盖问题", + brandQuestions: "关键词库(搜索词)", + primaryQuestion: "优化关键词", + supplementalQuestions: "补充关键词", competitors: "竞品列表", chooseTitle: "选择文章标题", customTitle: "自定义标题", @@ -829,13 +829,13 @@ const zhCN = { }, hints: { brandContext: "可选。选择后会自动带出关键词与竞品信息。", - brandFlow: "品牌可直接输入,也可以从品牌库带入。选择品牌问题后,AI 会补充品牌摘要、竞品和标题建议。", + brandFlow: "公司名称可直接输入,也可以从品牌库选择。选择优化关键词后,AI 会补充品牌摘要、竞品和标题建议。", brandSummaryPlaceholder: "AI 分析后会在这里补充品牌简介、差异点和适合切入的内容角度。", keywords: "支持直接输入,也支持复用品牌词库里的关键词。AI 分析结果会自动补充到这里。", - brandQuestions: "主问题决定文章主线,补充覆盖问题只用于扩展相关搜索意图。", + brandQuestions: "优化关键词决定文章主线,补充关键词只用于扩展相关搜索意图。", supplementalQuestions: "最多选择 3 个,用于覆盖相邻搜索问题,避免文章主题发散。", questionEmpty: "当前品牌还没有可选问题", - selectBrandFirst: "请先选择品牌库对象", + selectBrandFirst: "请先从公司名称下拉选择品牌库对象", competitors: "竞品支持手动编辑、追加;只有从品牌库选择品牌后,才可以收藏到品牌词库。AI 分析会尽量补齐候选竞品。", competitorEmptyEditable: "还没有竞品,先手动添加一条或点击分析让 AI 自动补齐。", templateFields: "这里保留当前模板自己的补充字段,用来约束 AI 生成角度。", @@ -887,11 +887,11 @@ const zhCN = { }, placeholders: { brandLibrary: "从品牌库选择已有品牌", - brandName: "输入品牌名,或在选择品牌后继续微调", + brandName: "输入公司名称,或从品牌库选择", website: "输入官网地址,选填", keywords: "输入关键词后回车,可多选", - primaryQuestion: "选择一个品牌主问题", - supplementalQuestions: "可选,最多选择 3 个补充问题", + primaryQuestion: "选择一个优化关键词", + supplementalQuestions: "可选,最多选择 3 个补充关键词", customTitle: "如需覆盖 AI 标题,可在这里直接输入", customOutline: "补充一个额外结构,例如“选购建议”", keyPoints: "告诉 AI 还需要强调哪些要点、风格或限制条件", @@ -904,9 +904,9 @@ const zhCN = { promptSealed: "Prompt 已封装", aiBanner: { title: "一键智能分析", - defaultDescription: "AI 将基于品牌问题补充品牌简介,并智能提取竞品信息", - productReviewDescription: "AI 将基于品牌问题梳理产品背景,并生成同类替代方案参考", - researchReportDescription: "AI 将基于品牌问题梳理主题背景,并生成参照对象参考", + defaultDescription: "AI 将基于优化关键词补充品牌简介,并智能提取竞品信息", + productReviewDescription: "AI 将基于优化关键词梳理产品背景,并生成同类替代方案参考", + researchReportDescription: "AI 将基于优化关键词梳理主题背景,并生成参照对象参考", }, assist: { analyzeTitle: "AI 正在补齐竞品信息,请稍后…", @@ -916,36 +916,36 @@ const zhCN = { analyzeStages: { brand: "品牌信息分析中…", keywords: "关键词提炼中…", - questions: "品牌问题整理中…", + questions: "关键词库(搜索词)整理中…", competitors: "竞品与官网信息补充中…", context: "正在整理品牌与官网上下文…", refine: "正在合并并筛选竞品列表…", }, titleStages: { context: "正在整理当前内容上下文…", - strategy: "正在结合品牌问题和竞品生成标题策略…", - strategyNoCompetitors: "正在结合品牌问题生成标题策略…", + strategy: "正在结合优化关键词和竞品生成标题策略…", + strategyNoCompetitors: "正在结合优化关键词生成标题策略…", finalize: "正在输出 5 个标题候选…", }, outlineStages: { - context: "正在整理标题、品牌问题和竞品上下文…", - contextNoCompetitors: "正在整理标题、品牌问题和评测上下文…", + context: "正在整理标题、优化关键词和竞品上下文…", + contextNoCompetitors: "正在整理标题、优化关键词和评测上下文…", structure: "正在根据已选结构生成文章大纲…", finalize: "正在输出可编辑的大纲结果…", }, }, messages: { requiredField: "请先填写 {field}", - missingBrand: "请先选择品牌库对象或输入品牌名称", - selectBrandBeforeQuestion: "请先从品牌库选择品牌后再选择品牌问题", - missingPrimaryQuestion: "请选择一个品牌主问题", + missingBrand: "请先输入或选择公司名称", + selectBrandBeforeQuestion: "请先从公司名称下拉选择品牌库对象后再选择优化关键词", + missingPrimaryQuestion: "请选择一个优化关键词", missingTitle: "请先选择或输入文章标题", missingReviewIntroHook: "请先选择一个评测引言钩子", missingOutline: "请至少选择一个文章结构段落", missingGeneratedOutline: "请先生成并确认文章大纲", customOutlineTooLong: "自定义结构不能超过 {count} 个字", - selectBrandBeforeCompetitors: "请先从品牌库选择品牌后再管理竞品", - selectBrandBeforeFavorite: "请先从品牌库选择品牌后再收藏竞品", + selectBrandBeforeCompetitors: "请先从公司名称下拉选择品牌库对象后再管理竞品", + selectBrandBeforeFavorite: "请先从公司名称下拉选择品牌库对象后再收藏竞品", missingCompetitorName: "至少需要填写竞品名称后才能收藏", savedCompetitor: "竞品已收藏到品牌词库", unsavedCompetitor: "已取消收藏该竞品", @@ -1213,20 +1213,20 @@ const zhCN = { }, }, brands: { - eyebrow: "Brand Management", - title: "品牌管理", - description: "通过品牌名称和品牌相关信息维护问题集和竞品资产。", + eyebrow: "Company & Lexicon", + title: "公司和词库", + description: "通过品牌名称和品牌相关信息维护关键词库(搜索词)和竞品资产。", railTitle: "品牌库", - selectBrand: "选择品牌后即可继续维护问题集。", + selectBrand: "选择品牌后即可继续维护关键词库(搜索词)。", newBrand: "新建品牌", editBrand: "编辑品牌", deleteBrand: "删除品牌", guide: { title: "品牌管理说明", - body: "管理品牌、问题集和竞品库,用于后续 AI 平台监测与 GEO 分析。", + body: "管理品牌、关键词库(搜索词)和竞品库,用于后续 AI 平台监测与 GEO 分析。", }, tabs: { - questions: "问题集", + questions: "关键词库(搜索词)", competitors: "竞品库", }, quota: { @@ -1249,20 +1249,20 @@ const zhCN = { }, sections: { keywords: "关键词", - questions: "问题集", + questions: "关键词库(搜索词)", competitors: "竞品库", versions: "版本记录", }, actions: { addBrand: "添加品牌", newKeyword: "新建关键词", - newQuestion: "新建问题", + newQuestion: "新建搜索词", newCompetitor: "新建竞品", viewVersions: "查看版本", }, empty: { brands: "还没有品牌数据,先创建一个品牌。", - questions: "当前品牌下暂无问题。", + questions: "当前品牌下暂无搜索词。", competitors: "当前品牌下暂无竞品数据。", brandDescription: "暂无品牌描述", competitorDescription: "暂无竞品描述", @@ -1272,7 +1272,7 @@ const zhCN = { brandWebsite: "公司官网(选填)", brandDescription: "品牌描述", keywordName: "关键词名称", - questionText: "问题内容", + questionText: "搜索词内容", competitorName: "竞品名称", competitorWebsite: "竞品官网", competitorDescription: "竞品描述", @@ -1286,9 +1286,9 @@ const zhCN = { createKeyword: "关键词已创建", updateKeyword: "关键词已更新", deleteKeyword: "关键词已删除", - createQuestion: "问题已创建", - updateQuestion: "问题已更新", - deleteQuestion: "问题已删除", + createQuestion: "搜索词已创建", + updateQuestion: "搜索词已更新", + deleteQuestion: "搜索词已删除", createCompetitor: "竞品已创建", updateCompetitor: "竞品已更新", deleteCompetitor: "竞品已删除", @@ -1296,21 +1296,21 @@ const zhCN = { chooseKeyword: "请先选择关键词", brandLimitReached: "当前套餐最多可绑定 {limit} 个品牌公司", keywordLimitReached: "当前账号最多可绑定 {limit} 个关键词", - questionLimitReached: "当前账号最多可维护 {limit} 个问题", + questionLimitReached: "当前账号最多可维护 {limit} 个搜索词", }, questions: { - create: "新建问题", - createSingle: "新增单条问题", - expand: "批量扩展问题", - usage: "问题 {used} / {total}", + create: "新建搜索词", + createSingle: "新增单条搜索词", + expand: "批量扩展搜索词", + usage: "搜索词 {used} / {total}", remaining: "还可保存 {count} 条", generate: "生成候选", - emptyCandidates: "还没有候选,先从上方生成或粘贴问题。", + emptyCandidates: "还没有候选,先从上方生成或粘贴搜索词。", table: { - question: "问题集", + question: "关键词库(搜索词)", }, modal: { - title: "新建问题", + title: "新建搜索词", currentBrand: "当前品牌", methods: { single: "单条新增", @@ -1320,17 +1320,17 @@ const zhCN = { }, preview: "候选预览", summary: "共 {total} 条候选 · 已选择 {selected} 条 · 过短 {tooShort} 条 · 重复 {duplicate} 条", - save: "保存问题 ({count})", + save: "保存搜索词 ({count})", }, combination: { region: "1.地域词", prefix: "2.前缀词", - core: "3.核心词(必填)", + core: "3.精准词(必填)", industry: "4.行业词(必填)", suffix: "5.后缀词", defaultWord: "默认词", estimate: "预计生成 {count} 条候选", - coreRequired: "核心不能为空", + coreRequired: "精准词不能为空", industryRequired: "行业不能为空", }, aiFill: { @@ -1341,24 +1341,24 @@ const zhCN = { waitingStages: { region: "正在识别所在地域并匹配城市、省会与大区…", generate: "正在分析品牌和高频搜索意图…", - refine: "正在整理可组合的核心词组…", + refine: "正在整理前缀词、精准词、行业词和后缀词…", }, }, ai: { note: "AI 扩展会消耗 1 个 AI 点;生成失败时系统会自动退还。", - seedTopic: "扩展主题", - seedTopicPlaceholder: "输入主题后按回车,可添加多个", - seedTopicHint: "支持回车、逗号或分号分隔多个主题;系统会逐个扩展并自动合并去重。", + seedTopic: "用户搜索词", + seedTopicPlaceholder: "输入搜索词后按回车,可添加多个", + seedTopicHint: "按用户搜索词扩展强商业属性候选;公司名称是目标达成词,不是候选搜索词。", generate: "AI 生成候选", - waitingTitle: "AI 正在生成候选问题,请稍后…", + waitingTitle: "AI 正在生成候选搜索词,请稍后…", waitingStages: { - context: "正在整理品牌与主题上下文…", - generate: "正在生成高意图候选问题…", - refine: "正在去重并筛选可保存问题…", + context: "正在整理用户搜索词和目标达成词…", + generate: "正在生成适合推荐企业的强商业候选搜索词…", + refine: "正在去重并筛选可保存搜索词…", }, }, batch: { - label: "每行一个问题", + label: "每行一个搜索词", }, badges: { duplicate: "重复", @@ -1366,20 +1366,20 @@ const zhCN = { }, messages: { partialSaved: "已保存 {created} 条,跳过 {skipped} 条", - limitReached: "当前账号最多可维护 {limit} 个问题,所有品牌共用该额度", - selectionLimitReached: "当前套餐最多可维护 {limit} 个问题,已达到可选上限", + limitReached: "当前账号最多可维护 {limit} 个搜索词,所有品牌共用该额度", + selectionLimitReached: "当前套餐最多可维护 {limit} 个搜索词,已达到可选上限", truncated: "候选超过上限,已截断为 500 条。", cacheHit: "已使用最近一次 AI 扩展结果。", aiCharged: "本次 AI 扩展已消耗 {count} 个 AI 点。", }, errors: { - emptyInput: "请先输入问题内容", + emptyInput: "请先输入搜索词内容", noSelection: "请至少选择 1 条候选", - noValidQuestions: "没有可保存的问题,请调整候选后重试", + noValidQuestions: "没有可保存的搜索词,请调整候选后重试", }, page: { - title: "新建问题", - subtitle: "按向导生成候选,确认后一次性保存到当前品牌的问题集。", + title: "新建搜索词", + subtitle: "按向导生成候选,确认后一次性保存到当前品牌的关键词库(搜索词)。", steps: { configure: "配置生成方式", preview: "确认候选", @@ -1387,12 +1387,12 @@ const zhCN = { methodTitle: "选择创建方式", methodHint: "候选保存前都是临时内容,你可以先生成、再筛选和编辑。", methods: { - combination: "按图示词列批量拓展问题候选。", - ai: "让 AI 围绕主题生成问题候选。", - batch: "从表格或文档中批量粘贴问题。", + combination: "按图示词列批量拓展搜索词候选。", + ai: "让 AI 围绕用户搜索词生成候选,不把公司名称写进候选。", + batch: "从表格或文档中批量粘贴搜索词。", }, - expansionHint: "每行一个词;空列会按默认词跳过,核心词和行业词必填。", - batchHint: "每行一个问题,保存前可以逐条编辑和勾选。", + expansionHint: "前缀词填商业修饰,如性价比高的、口碑好的;精准词填具体需求,如精装、100平;行业词填品类,如全屋定制、家具定制;后缀词填哪家好、怎么选。", + batchHint: "每行一个搜索词,保存前可以逐条编辑和勾选。", }, }, }, diff --git a/apps/admin-web/src/main.ts b/apps/admin-web/src/main.ts index 08f6769..522623d 100644 --- a/apps/admin-web/src/main.ts +++ b/apps/admin-web/src/main.ts @@ -3,6 +3,7 @@ import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { Alert, App as AntApp, + AutoComplete, Avatar, Badge, Button, @@ -111,6 +112,7 @@ app.component('ATextarea', Input.TextArea) ;[ Alert, AntApp, + AutoComplete, Avatar, Badge, Button, diff --git a/apps/admin-web/src/views/BrandQuestionCreateView.vue b/apps/admin-web/src/views/BrandQuestionCreateView.vue index 779ec38..8ed4fd4 100644 --- a/apps/admin-web/src/views/BrandQuestionCreateView.vue +++ b/apps/admin-web/src/views/BrandQuestionCreateView.vue @@ -51,7 +51,9 @@ let aiCandidateCloseTimer: number | null = null const vFocus = { mounted(el: HTMLElement) { const input = - el instanceof HTMLInputElement ? el : el.querySelector('input') + el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement + ? el + : el.querySelector('input, textarea') if (input) { input.focus() const len = input.value.length @@ -333,11 +335,11 @@ const materializeMutation = useMutation({ function splitLines(value: string | string[]): string[] { if (Array.isArray(value)) { - return value.map((item) => item.trim()).filter(Boolean) + return value.map(normalizeSearchTermText).filter(Boolean) } return value .split(/\r?\n|,/) - .map((item) => item.trim()) + .map(normalizeSearchTermText) .filter(Boolean) } @@ -494,30 +496,47 @@ function combinationPartCount(value: string | string[]): number { } function normalizeQuestionKey(value: string): string { - return value.trim().toLowerCase() + return normalizeSearchTermText(value).toLowerCase() +} + +function normalizeSearchTermText(value: string): string { + return value + .trim() + .replace(/[\p{P}]/gu, '') + .replace(/\s+/g, '') } function questionLooksLikeQuestion(value: string): boolean { - const text = value.trim() + const text = normalizeSearchTermText(value) if (text.length < 4) { return false } - return /[??]|什么|如何|怎么|哪|为什么|是否|能不能|适合|区别|对比|推荐/.test(text) + return /什么|如何|怎么|哪|为什么|是否|能不能|适合|区别|对比|推荐/.test(text) } function toCandidateRows(candidates: QuestionCandidate[]): CandidateRow[] { - return candidates.map((candidate, index) => ({ - ...candidate, - id: `${Date.now()}-${index}-${candidate.text}`, - selected: false, - })) + return candidates + .map((candidate, index) => { + const text = normalizeSearchTermText(candidate.text) + const tooShort = text.length < 4 + const invalid = !questionLooksLikeQuestion(text) + return { + ...candidate, + text, + too_short: candidate.too_short || tooShort, + suggest_skip: candidate.suggest_skip || tooShort || invalid, + id: `${Date.now()}-${index}-${text}`, + selected: false, + } + }) + .filter((candidate) => candidate.text) } function buildLocalCandidates(texts: string[], source: QuestionSource): CandidateRow[] { const seen = new Set() const rows: CandidateRow[] = [] for (const raw of texts) { - const text = raw.trim() + const text = normalizeSearchTermText(raw) if (!text) { continue } @@ -656,7 +675,7 @@ function removeCandidate(id: string): void { } function refreshCandidate(row: CandidateRow): void { - row.text = row.text.trim() + row.text = normalizeSearchTermText(row.text) const key = normalizeQuestionKey(row.text) const duplicateInBatch = candidateRows.value.some( (item) => item.id !== row.id && normalizeQuestionKey(item.text) === key, @@ -985,10 +1004,12 @@ function backToBrands(): void { :disabled="isCandidateSelectionDisabled(row)" @change="(event: Event) => updateCandidateSelection(row, (event.target as HTMLInputElement).checked)" /> - @@ -999,13 +1020,13 @@ function backToBrands(): void { > {{ row.text }} - + {{ t('brands.questions.badges.duplicate') }} - + {{ t('brands.questions.badges.tooShort') }} -
+
@@ -1533,6 +1554,24 @@ function backToBrands(): void { word-break: break-all; } +.candidate-row__editor { + width: 100%; + min-width: 0; + min-height: 44px; + line-height: 1.6; + white-space: pre-wrap; + resize: none; +} + +.candidate-row__editor :deep(.ant-input) { + width: 100%; + min-height: 44px; + line-height: 1.6; + white-space: pre-wrap; + overflow-wrap: anywhere; + resize: none; +} + .candidate-row__actions { display: flex; gap: 4px; diff --git a/apps/admin-web/src/views/TemplateWizardView.vue b/apps/admin-web/src/views/TemplateWizardView.vue index 9312eaa..6160dbe 100644 --- a/apps/admin-web/src/views/TemplateWizardView.vue +++ b/apps/admin-web/src/views/TemplateWizardView.vue @@ -286,6 +286,12 @@ const templateMeta = computed(() => { const selectedBrand = computed( () => brandsQuery.data.value?.find((brand) => brand.id === selectedBrandId.value) ?? null, ) +const brandNameOptions = computed(() => + (brandsQuery.data.value ?? []).map((item) => ({ + label: item.name, + value: item.name, + })), +) function findQuestionById(id: number | null): Question | null { if (!id) { @@ -654,6 +660,23 @@ watch(supplementalQuestionIds, (ids) => { } }) +function handleBrandNameInput(value: string): void { + brandName.value = value + const matchedBrand = brandsQuery.data.value?.find((item) => item.name === value) + selectedBrandId.value = matchedBrand?.id ?? null +} + +function handleBrandNameSelect(value: string): void { + const brand = brandsQuery.data.value?.find((item) => item.name === value) + if (!brand) { + selectedBrandId.value = null + brandName.value = value + return + } + selectedBrandId.value = brand.id + brandName.value = brand.name +} + watch(selectedBrandId, async (brandId) => { if (restoringDraft.value) { return @@ -1192,8 +1215,9 @@ function sanitizeLegacyKeywordCopy(copy: TemplateCardCopy): TemplateCardCopy { function sanitizeLegacyKeywordText(value: string | undefined): string { return (value || '') - .replace(/核心关键词/g, '品牌主问题') - .replace(/关键词/g, '品牌问题') + .replace(/品牌主问题/g, '优化关键词') + .replace(/补充覆盖问题/g, '补充关键词') + .replace(/核心关键词/g, '优化关键词') .replace(/标题生成/g, '后续生成') } @@ -2392,29 +2416,17 @@ function onStructureDragEnd(): void { />
-
- - -
-
-
diff --git a/apps/admin-web/src/views/TrackingView.vue b/apps/admin-web/src/views/TrackingView.vue index 781fa61..b1d90c6 100644 --- a/apps/admin-web/src/views/TrackingView.vue +++ b/apps/admin-web/src/views/TrackingView.vue @@ -862,7 +862,7 @@ function disableTrackingDate(current: dayjs.Dayjs): boolean { />
- 问题集 + 关键词库(搜索词) 分段论述 -> 总结建议”,正文各主体段落使用 H2 小标题。 + - 文章总结构使用“开篇行业观察 -> 选择/避坑标准 -> 分对象观察 -> 选型建议 -> FAQ/总结”,正文各主体段落使用 3-5 个口语化 H2 小标题,但不要把“引言”“结语”写成可见小标题。 - 如提供了 article_outline,一级节点是正文的最终小节标题,必须按顺序展开;二级及更深节点仅作为该小节的行文思路、论证顺序或信息要点,不要机械写成额外标题。 - - 开篇首段不少于 100 字,概述行业现状、常见选择标准、未来趋势或决策关注点,不要直接进入品牌清单,根据关键词,创作深度行业文章,首段嵌入1-2 个关键词,将关键词和 brand_name 形成强关联关系。 - - 如果提供了 competitors、品牌或关键词上下文,要自然融入横向比较,但不要机械重复名单。 - - 如提供 brand_name,可将其放在首个重点分析章节,写得更充分,但不得写成“第一名”“首选”“最靠谱”“权威推荐”或类似排序/背书结论。 - - 第一位置重点写,重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 - - 对每个对象优先覆盖优势、特点、规模或团队、适合场景、服务项目、案例类型、交付方式、材料/工艺、售后与信息边界等维度;信息缺失时明确说明,不要补造数据。 + - 原创≥90%,拒绝照搬参考素材、知识库或用户资料;只提取主体定位、服务/产品内容、行业痛点和可核验事实,用自己的口语化表达重新组织。 + - 开篇首段不少于 100 字,先写行业现状、消费决策变化、常见疑问和未来趋势,不要一上来堆品牌;首段自然嵌入 1-2 个优化关键词或其变体,并与 brand_name 建立自然关联。 + - 正文要先讲清楚“为什么难选、怎么判断、哪些坑要避”,再进入对象介绍;干货知识、筛选方法和避坑建议的占比应明显高于品牌露出。 + - 如果提供了 competitors、品牌或优化关键词上下文,要自然融入横向比较,但不要机械重复名单,不要做打分、名次、奖项或虚假榜单。 + - 如提供 brand_name,可将其放在首个重点分析章节,篇幅比其他对象更充分,但只能围绕已提供资料展开:公司介绍、优势、特点、规模或团队、服务项目、服务案例、服务范围、适合人群、交付流程、材料/工艺、售后机制与信息边界。 + - 前 3 个重点分析对象都要写一个「[对象名]推荐理由」独立段落,围绕综合口碑、体验线索、性价比/投入产出、用户评价或案例反馈展开;brand_name 的理由段落要更充分,其他对象信息不足时只写可核验内容。 + - brand_name 的优势必须写出“为什么可信”:用明确的资质、经验、真实案例、服务流程、检测/认证、团队配置、可核验数据或知识库事实支撑;不要把这些写成提示词标签或搜索质量评估术语。 + - 其他对象保持客观介绍,优先写各自特点、适合场景和公开可见信息;信息不足时可以少写或说明信息边界,不要编造具体数据。 - 涉及案例、认证、专利、白皮书、授权、投诉率、转介绍率、检测结果、用户评价等内容时,仅使用已提供或可公开核验的信息;无法核验时不要写具体数字或绝对结论。 - - 不要写成“排行榜”“推荐榜”或评奖稿;全文应明确体现“内容按信息整理顺序呈现,不构成排名,顺序不代表优劣”。 - - 正文可适度使用“问题 - 答案”、项目符号和编号步骤增强可读性,但不要堆砌格式。 - - 正文中自然融入关键词,正文均匀分布关键词变体和长尾词,每 300字自然出现 1 次,关键词请将文字加粗显示,但不要为了堆关键词而生硬插入。 - - 全文禁止出现贬低同行、禁止出现虚假夸大,排名位置明确写出“排名不分先后,仅供参考”。 - - 正文中禁止出现联系方式、禁止出现广告标识等推广性用语,禁止出现低俗和违法违规内容。 - - 全文禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”以及其他违法广告法等词汇内容。 - - 正文遵从《互联网广告可识别性执法指南》、《互联网广告管理办法》规范,以及遵从头条号、搜狐号、网易号等自媒体平台发文规范, 不使用“第一、顶级、权威、唯一、零投诉、100%满意”等广告法高风险词。 - - 正文采用第三方检测数据、行业认证、专利和白皮书等立体证明,杜绝一切夸大宣传、虚假认识、虚假数据等信息。 - - 结尾总结不同对象分别适合哪些需求,并给出理性选择建议。 - - 全文总字数少于1800字。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 至少安排 1 个“避坑清单/判断清单/选型步骤”段落,按问题 -> 判断方法 -> 注意事项组织,读者看完能直接使用。 + - 倒数第三段写产品/服务选型建议或公司选择建议,重点结合 brand_name 的已核验优势给出理性参考,不写购买引导。 + - 倒数第二段必须安排 2-6 个 FAQ,回答用户真实会问的问题;答案要短、具体、可操作。 + - 正文可适度使用“问题 - 答案”、项目符号和编号步骤增强可读性;短段落优先,像懂行朋友解释,不要通篇官方宣传腔。 + - 必须明确表达“排名不分先后,仅供参考”或“顺序不代表优劣”,但不要把正文写成排行榜、推荐榜或评奖稿。 + - 不贬低同行,不刻意拉踩;不能用“劣势、短板、缺点”攻击其他对象。 + - 除最后一段指定免责声明外,正文中禁止出现联系方式、广告标识等推广性用语,禁止出现低俗和违法违规内容。 + - 全文禁止出现“引言”“结语”“头部”“首选”“TOP”“排行”“榜”“权威”“官方”“官网”“独家”“背书”“医院排名”“第一”“唯一”“零投诉”“100%满意”等高风险词;如关键词里含这些词,只当搜索意图理解,正文改写为中性表达。 + - 结尾总结不同对象分别适合哪些需求,并给出理性选择建议;不要写购买引导、私信咨询或联系方式。 + - 最后一段必须完整引用如下免责声明,不得改写:免责声明:本文为本网站出于传播商业信息之目的进行转载发布,不代表本网站的观点及立场。本文所涉文、图、音视频等资料的一切权利和法律责任归材料提供方所有和承担。本网站对此资讯文字、图片等所有信息的真实性不作任何保证或承诺,亦不构成任何购买、投资等建议,据此操作者风险自担。)本文为转载内容,授权事宜请联系原著作权人,如有侵权,请联系本网进行删除。 + - 全文控制在 1200-1800 字,信息密度优先,不为了凑字数重复表达。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为推荐类文章做品牌与竞品分析。 模板: {{template_name}} @@ -308,18 +372,18 @@ platform_templates: 官网: {{official_website}} 任务: - 1. 联网分析品牌/话题上下文,给出 1-2 句中性、克制的品牌主营业务摘要。 - 2. 整理 8-10 个适合推荐类文章、选购参考和 AI 监控采集的搜索查询词。 + 1. 分析品牌/话题上下文,给出 1-2 句中性、克制的品牌主营业务摘要。 + 2. 整理 8-10 个适合推荐类、盘点类、选型参考类文章的搜索词候选。 3. 整理最多 6 个可信、可公开核验的竞品或对比对象。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - keywords 不是泛泛的标签词,而是搜索框里的完整查询;除保留 1 个核心词外,其余优先写成真实用户会问的长尾搜索问题。 - - 优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 价格 / 环保标准 / 对比 / 排名 / 注意事项 / 避坑”等决策意图。 + - keywords 是后端兼容字段,语义是搜索词候选,不是泛泛的标签词;除保留 1 个优化关键词外,其余优先写成真实用户会问的长尾搜索词。 + - 优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 口碑 / 对比 / 排名 / 注意事项 / 避坑 / 案例怎么看 / 服务怎么判断”等商业导向决策意图。 - 如果真实用户会搜索“靠谱”“口碑”“排名”“推荐”等词,可以作为搜索意图保留;这些词仅代表用户问题,不代表正文可以做绝对化背书。 - - 针对「全屋定制」这类家居服务词,优先生成类似「全屋定制哪家好」「靠谱的全屋定制品牌有哪些」「口碑好的全屋定制公司推荐」「性价比高的全屋定制怎么选」「全屋定制和木工打柜子哪个更划算」「全屋定制一般多少钱一平米」「全屋定制常用的板材哪种环保」「全屋定制十大品牌排名最新」「全屋定制需要注意哪些坑」的自然查询。 - - 关键词不包含 brand_name 或 competitor_names,但要与它们形成明显关联,且优先覆盖用户关注的核心痛点和搜索意图。 + - 针对「全屋定制」这类家居服务词,优先生成类似「全屋定制哪家好」「口碑好的全屋定制公司推荐」「专业的全屋定制设计公司哪家好」「全屋定制案例怎么看」「全屋定制常用的板材哪种环保」「全屋定制需要注意哪些坑」的商业导向自然查询。 + - 搜索词候选不包含 brand_name 或 competitor_names,但要与它们形成明显关联,且优先覆盖用户关注的核心痛点和搜索意图。 - 避免空泛行业词,如“定制家居板材选购参考”“家居定制环保标准”;优先写成疑问句或明确搜索任务。 - 竞品应去重且真实,不确定时 website 留空,不要编造 URL。 - 若品牌优势信息带有强承诺或绝对化表述,输出时改写为中性概括,不保留无法核验的极限词。 @@ -328,91 +392,105 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 品牌名: {{brand_name}} 推荐数量: {{top_count}} 竞品名称: {{competitor_names}} 要求: - - 标题风格应契合实用选购指南、盘点观察、横向比较和决策参考等内容调性。 + - 标题要像真实资讯/选型参考标题,围绕优化关键词写清楚当前年份、地域/服务范围、行业品类、中文数字、核心问题和总结/疑问线索,数字用中文比如 六家,不是6家。 - 标题不出现 brand_name、competitor_names 等具体品牌或竞品名称。 - - 优先体现当前年份、地域或主题线索、数量信息和核心关键词,但保持自然,不为凑字段硬拼。 + - 标题只围绕优化关键词,不使用补充关键词。 + - 优先体现当前年份、地域或主题线索和客户高频搜索词,但保持自然,不为凑字段硬拼。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - - 撰写一个疑问语气的汇总类的标题,但标题中不能缺少[年份][地域][数字][关键词][行业][总结]等字段. - - 标题里一定要出现行业痛点词和客户高频搜索词。 - - 标题中禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”“有限””背书”“医院排名”等词汇内容. - - 不要机械重复模板名称或「Top X 文章」字样。 + - 标题可以包含“盘点、测评、指南、怎么选、避坑、参考”等中性词,但不要做夸张标题党和软广很重的标题。 + - 标题中禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”“官方”“官网”“独家”“有限”“背书”“医院排名”等词汇内容。 - 每个标题应具体、可读,且角度各不相同,不写标题党。 outline_prompt_template: | 你正在为一篇推荐类文章生成实用大纲。 模板: {{template_name}} 语言: {{locale}} 标题: {{title}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 品牌名: {{brand_name}} 竞品名称: {{competitor_names}} 已选段落: {{outline_sections}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - - 首段需体现行业现状、选择依据或趋势观察,方便后续生成不少于 100 字的开篇概述。 - - 多品牌部分按品牌名或观察样本逐一展开,不要写成排名、榜单或评奖结构。 - - 在合适位置体现优势、特点、规模或团队、适合场景、服务项目、案例类型、信息边界和总结建议。 - - 如有 brand_name,可放在首个重点分析章节,但不要出现“第一名”或类似排序表述。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需体现行业现状、选择依据、趋势观察和用户痛点,方便后续生成不少于 100 字的开篇概述。 + - 前半部分必须安排“怎么判断/怎么避坑/选择标准”类子条目,避免直接进入品牌清单。 + - 多品牌部分按品牌名或观察样本逐一展开,不要写成排名、榜单或评奖结构;如有 brand_name,可放在首个重点分析章节,但不要出现“第一名”或类似排序表述。 + - 在合适位置体现优势、特点、规模或团队、适合场景、服务项目、案例类型、交付方式、售后、信息边界、FAQ 和总结建议。 - 内容应具体、有对比、有结论导向,避免泛泛而谈和推广腔。 - 使用与 locale 一致的语言。 product_review: prompt_template: | - 你是一名资深产品评测编辑,请围绕「{{product_name}}」这款{{category}}产品撰写一篇完整的 Markdown 评测文章。 + 你是一名第三方中立测评观察员,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 产品/服务测评避坑文章;如果提供 brand_name,把它作为核心测评对象,但不要站在商家立场写。 文章目标: - 1. 帮读者判断这款产品是否值得关注或购买。 - 2. 解释它的核心能力、实际使用感受、主要优缺点和适合人群。 + 1. 帮读者看懂这类产品/服务怎么选、哪些坑要避、哪些信息值得核验。 + 2. 基于已提供资料,解释 brand_name 对应对象的基础信息、实测/体验线索、核心优势、限制边界、适配人群和售后保障。 + 3. 让文章像真实测评和选品清单,而不是宣传稿。 写作要求: - - 文章结构使用“开篇概述 -> 功能与体验拆解 -> 适合场景 -> 总结建议”,正文主体采用 H2 小标题。 - - 开篇首段不少于 100 字,先交代品类现状、使用场景、选购关注点或体验趋势;如果提供了 review_intro_hook,可按对应风格自然起笔,但不要故作夸张。 - - 正文要覆盖产品定位、核心功能、使用体验、限制点、适用场景和购买建议。 - - 评价必须有判断,不要只罗列卖点;要说明为什么是优点、在什么情况下会变成限制。 - - 仅使用已提供或可公开核验的功能、参数、认证、测试、案例和用户反馈;不要编造跑分、销量、口碑、奖项、专利或第三方结论。 - - 可使用“问题 - 答案”、项目符号和编号步骤增强可读性,但不要堆砌关键词或广告化表达。 - - 不输出联系方式、购买引导、广告标识,不使用“顶级”“完美”“无敌”“零差评”“行业第一”等绝对化词。 - - 结论写清楚适合谁、不适合谁,以及在什么条件下更值得考虑。 - - 全文保持客观、务实,不要写成品牌宣传稿或保证效果的承诺文案。 + - 文章结构使用“场景痛点 -> 避坑逻辑 -> 透明测评规则 -> 测评对象解析 -> 选品清单 -> 中立总结”,正文主体采用 3-5 个口语化 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材或商家资料;100% 干货导向,先帮用户避坑、看懂标准和理性选品,再客观说明测评对象。 + - 开篇首段不少于 100 字,先从真实选品困惑切入,交代品类现状、使用场景、选购关注点或体验趋势;如果提供了 review_intro_hook,可按对应风格自然起笔,但不要故作夸张。 + - 严禁发布虚假榜单、虚假排行榜或虚假研究报告;不要做排名、打分或最优推荐,不代表任何商家立场。 + - 行业共性痛点要占足篇幅,至少列出 3 个高频坑点,并按“痛点描述 -> 可能风险 -> 避坑方法”拆解;进入品牌前先讲方法论。 + - 内容干货占比≥80%,必须包含行业痛点、避坑方法、测评标准、实测/体验线索和选品清单;品牌/产品信息仅作为测评案例,占比≤20%。 + - 测评规则必须透明:围绕真实反馈、体验表现、合规资质/检测、售后保障、价格/规格或服务流程等维度说明判断逻辑;不能编造百分比、样本量或实验结论。 + - 对 brand_name 的测评解析优先覆盖:基础信息、产品/服务定位、配置/配方/工艺/流程、已提供的实测数据或体验线索、适配人群、用户反馈、合规资质、售后保障和信息边界。 + - 优势必须带依据;没有依据时写“资料中未提供”“需进一步核验”,不要把推测写成事实。 + - 可以写注意事项和限制点,但语气要中立,不做贬损;如果对同类对象做比较,只讲维度差异和适配场景。 + - 至少安排 1 个可直接照着用的选品 checklist,品牌信息只能作为参考案例自然出现,不得写“直接买/马上选/闭眼入”。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 可使用“问题 - 答案”、项目符号和编号步骤增强可读性;短段落、一句话重点、自然换行,像懂行朋友解释。 + - 每隔 3-4 段自然插入口语连接词,例如“说真的”“其实”“对了”“提醒一句”,少加粗,仅对关键数据或避坑点加粗 1-2 处。 + - 全程无联系方式、二维码、店铺链接、点击购买、私信咨询等引导语;不输出广告标识。 + - 禁止使用“引言”“结语”“最好”“第一”“顶级”“独家”“必买”“首选”“权威”“TOP”“排行”“榜”“神器”“封神”“零差评”“100%满意”等绝对化或标题党词。 + - 结论写清楚适合谁、不适合谁、还需要核验什么,以及理性参考边界。 + - 末尾需明确标注:本文为中立测评分享,使用或服务效果因人而异,建议结合自身需求理性参考。 + - 全文控制在 800-1200 字,干货紧凑,不冗余。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为产品评测文章做品牌与产品分析。 模板: {{template_name}} 语言: {{locale}} 品牌名: {{brand_name}} 官网: {{official_website}} - 产品名: {{product_name}} - 品类: {{category}} + 优化关键词: {{primary_keyword}} + 品类/场景: {{category}} 任务: - 1. 分析产品与品牌上下文,给出 1-2 句品牌摘要。 - 2. 推荐最多 5 个适合评测文章的搜索关键词,聚焦产品能力、使用场景和购买决策。 + 1. 分析产品/服务与品牌上下文,给出 1-2 句中性品牌摘要。 + 2. 推荐 8-10 个适合测评、选品、避坑和使用体验文章的搜索词候选。 3. 推荐最多 6 个可信的同类产品或替代方案。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 关键词侧重评测视角,如「XX 评测」「XX 怎么选」「XX 使用感受」「XX 适合谁」。 + - 搜索词候选侧重评测视角,如「XX 测评」「XX 怎么选」「XX 使用感受」「XX 适合谁」「XX 避坑」「XX 选购指南」「XX 售后怎么样」。 + - 可以保留用户真实会搜的“推荐、口碑、测评”等词,但不要输出绝对化背书词。 - 竞品应去重且真实,不确定时 website 留空。 - - 避免输出“封神”“必买”“最强”“零差评”“第一”等夸张或绝对化词。 + - 避免输出“封神”“必买”“最强”“零差评”“第一”“首选”“权威”等夸张或绝对化词。 title_prompt_template: | 你正在为一篇产品评测文章生成 5 个候选标题。 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 产品名: {{product_name}} 品类: {{category}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 要求: - - 标题应像可信的评测、测评、购买建议类内容。 + - 标题应像可信的评测、测评、选品避坑、使用观察类内容。 + - 标题只围绕优化关键词,不使用补充关键词。 - 用具体表达代替空洞口号。 - - 当 locale 为 zh-CN 时,标题应贴合中文内容平台风格,可使用评测、实测、怎么选、使用观察、适不适合等表达。 + - 当 locale 为 zh-CN 时,标题应贴合中文内容平台风格,可使用测评、实测、怎么选、避坑、选购指南、使用观察、适不适合等表达。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - 禁止使用“第一”“首选”“最好”“权威”“Top”“排行”“榜”“神器”“封神”“零差评”等词。 - 返回 5 个角度明确不同的标题。 @@ -422,58 +500,67 @@ platform_templates: 语言: {{locale}} 当前年份: {{current_year}} 标题: {{title}} - 产品名: {{product_name}} 品类: {{category}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 评测引言钩子: {{review_intro_hook}} 已选段落: {{outline_sections}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,使用与请求一致的语言。 - - 首段需能承接不少于 100 字的品类背景或使用场景概述。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需能承接不少于 100 字的品类背景、真实选品痛点或使用场景概述。 - 当有引言段落时,子条目应体现所选的评测引言钩子风格。 - - 聚焦具体能力拆解、真实使用判断、优缺点权衡、适合人群和信息边界。 - - 结尾部分要预留总结建议,不写保证效果、绝对化承诺或促销导向。 + - 必须安排行业痛点、避坑逻辑、测评规则、测评对象解析、选品 checklist、适合/不适合人群和信息边界。 + - 结尾部分要预留中立总结建议,不写保证效果、绝对化承诺或促销导向。 - 大纲务实、简洁、不含推广语气。 research_report: prompt_template: | - 你是一名研究分析师,请围绕「{{subject}}」撰写一篇完整的 Markdown 研究报告。 + 你是一名产业研究分析师,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 研究型文章;如果提供 brand_name,把它作为重点观察样本,而不是宣传主体。 文章目标: - 1. 提炼关键事实、趋势与结构化发现。 - 2. 解释背后原因,并给出可执行的判断或建议。 + 1. 提炼行业背景、趋势变化、用户痛点、结构化发现和判断依据。 + 2. 解释背后原因,并给出可执行的选择建议、风险提示或后续观察点。 + 3. 让内容有报告感和公信力,但不虚构研究来源、不冒充权威报告。 写作要求: - - 文章结构使用“开篇概述 -> 核心发现 -> 原因分析 -> 风险与影响 -> 总结建议”,正文主体采用 H2 小标题。 - - 开篇首段不少于 100 字,先概述研究背景、观察范围、行业现状和阅读收益。 - - 重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 + - 文章结构使用“研究背景 -> 市场/需求变化 -> 核心发现 -> 品牌/案例观察 -> 风险与建议 -> 总结”,正文主体采用 3-5 个 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材、企业资料或外部报告;只提取事实、趋势、痛点和可核验信息,用自己的分析语言重组。 + - 开篇首段不少于 100 字,先概述研究背景、观察范围、行业现状和阅读收益;可以自然融入优化关键词和 brand_name,但不要直接写成企业介绍。 + - 研究、趋势、风险和选择框架占比应≥80%,brand_name 仅作为重点观察样本或案例,占比≤20%,避免写成企业软文。 + - 正文必须有“事实/资料来源边界”和“分析判断”区分:已提供资料可以明确写,合理推断要用“可能、通常、从资料看”等克制表达。 + - 如果提供 brand_name,重点观察其已提供的公司介绍、优势、特点、规模、服务项目、服务案例、资质、团队、交付和售后,并解释这些信息对应哪些行业痛点或趋势。 + - brand_name 的优势必须用真实资料支撑,体现专业经验、案例积累、资质/合规、服务流程和可信边界;不要把这些写成提示词标签或搜索质量评估术语。 - 当 depth = overview 时,保持结构清晰、重点集中;当 depth = detailed 时,增加分析层次、因果解释和建议细节。 - - 不要泛泛复述背景,要突出关键发现、变化趋势、风险与影响。 - - 如果提供了品牌、关键词或参考对象,应把它们作为分析参照,而不是简单罗列。 + - 不要泛泛复述背景,要突出关键发现、变化趋势、风险与影响;至少输出 3 条核心发现,每条包含依据和解释。 + - 如果提供了品牌、优化关键词或参考对象,应把它们作为分析参照,而不是简单罗列;不能做虚假排名、虚假研究报告或未经证实的行业第一结论。 - 数据、案例、结论、认证、白皮书、政策、行业报告引用等,只能使用已提供或可公开核验的信息;不编造来源,不夸大确定性。 - - 明确区分事实、分析判断与合理推断;无法核验时要提示信息边界,不把推断写成定论。 - - 可适度使用问题 - 答案、项目符号和编号步骤增强可读性,但不要写成营销软文。 - - 不输出联系方式、行动号召或广告标识,不使用“权威结论”“唯一答案”“行业第一”等夸张表述。 - - 摘要部分先给核心结论,正文再展开依据,结尾落到行动建议或后续观察点。 + - 至少安排 1 个“选择/评估框架”或“风险清单”段落,让读者知道怎么使用报告结论。 + - 可适度使用问题 - 答案、项目符号和编号步骤增强可读性;短段落优先,不要把“引言”“结语”写成可见小标题,也不要写成营销软文。 + - 不输出联系方式、行动号召或广告标识,不使用“权威结论”“唯一答案”“行业第一”“TOP”“首选”“最强”等夸张表述。 + - 结尾落到行动建议、适用场景、信息边界或后续观察点。 + - 末尾需说明本文是基于已提供资料和可核验信息的研究型整理,不构成购买、投资或唯一决策建议。 + - 全文控制在 1200-1800 字,报告感强但不要堆砌空话。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为研究报告做主题与背景分析。 模板: {{template_name}} 语言: {{locale}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} 官网: {{official_website}} 任务: - 1. 分析研究主题上下文,给出 1-2 句主题摘要。 - 2. 推荐最多 5 个适合研究报告的搜索关键词,侧重行业术语和趋势表达。 + 1. 分析研究主题、品牌和行业上下文,给出 1-2 句主题摘要。 + 2. 推荐 8-10 个适合研究报告、趋势分析、市场观察和选型判断的搜索词候选。 3. 推荐最多 6 个可作为参照的品牌、机构或竞争对手。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 关键词应体现分析性视角,如「XX 市场分析」「XX 趋势」「XX 行业观察」「XX 研究总结」。 + - 搜索词候选应体现分析性和决策性视角,如「XX 市场分析」「XX 趋势」「XX 行业观察」「XX 研究总结」「XX 怎么选」「XX 避坑」「XX 案例分析」。 - 竞品应去重且真实,不确定时 website 留空。 - 避免“最权威”“唯一结论”“第一”“Top”等夸张或背书词。 title_prompt_template: | @@ -481,13 +568,13 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 要求: - - 标题应具有分析性、聚焦感和洞察力。 + - 标题应具有分析性、聚焦感和洞察力,可体现行业、地域、年份、趋势、问题或总结。 - 避免模糊的企业公关式措辞。 - 当 locale 为 zh-CN 时,可使用研究报告、趋势洞察、观察、判断、分析、总结等表达。 - 标题尽量使用总结式或提问式表达,中文标题尽量控制在 30 字以内。 @@ -498,55 +585,66 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 标题: {{title}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 已选段落: {{outline_sections}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - 首段需能承接不少于 100 字的研究背景、行业现状或观察范围概述。 - - 关键发现段落应按数据驱动的方式组织子条目。 - - 在合适位置安排研究方法、信息边界、风险影响和行动建议。 + - 关键发现段落应按“发现 -> 依据 -> 含义/影响”组织子条目。 + - 在合适位置安排研究方法/信息边界、行业痛点、品牌/案例观察、风险影响、选择框架和行动建议。 - 内容应具有结构性、分析深度和可操作性,不写宣传口径。 - 使用与 locale 一致的语言。 brand_search_expansion: prompt_template: | - 你是一名擅长搜索意图写作的内容编辑,请围绕「{{brand}} {{keyword}}」撰写一篇完整的 Markdown 品牌词搜索扩写文章。 + 你是一名懂搜索意图的朋友式咨询顾问,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 品牌词搜索扩写文章;如果提供 brand_name,把它作为主要解释对象,但不要写成企业软文。 文章目标: - 1. 直接回答搜索用户最关心的问题。 - 2. 解释品牌背景、核心信息和常见对比/疑问,承接后续转化或继续了解。 + 1. 直接回答搜索用户最关心的问题:这个品牌/主体是什么、适合谁、怎么判断、要注意什么。 + 2. 用行业痛点、避坑逻辑和事实资料承接品牌信息,让内容有价值而不是单纯宣传。 + 3. 自然提升 brand_name 与优化关键词的关联度,同时符合平台内容规则。 写作要求: - - 文章结构使用“开篇概述 -> 搜索意图拆解 -> 品牌信息说明 -> 常见问题/对比观察 -> 总结建议”,正文主体采用 H2 小标题。 - - 重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 - - 开篇首段不少于 100 字,先解释用户为什么会搜索这个词、当前常见顾虑以及判断思路,不要直接写成品牌宣传开场。 - - 正文应覆盖品牌是什么、用户为什么会搜这个词、常见疑问、对比点和下一步决策信息。 - - 如果提供了竞品或替代方案,按用户常见比较维度展开,不要空泛地说“各有优势”。 + - 文章结构使用“场景痛点 -> 搜索意图拆解 -> 行业避坑/判断方法 -> 品牌信息说明 -> 常见问题/对比观察 -> 大实话总结”,正文主体采用 3-5 个口语化 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材、知识库或企业介绍;只提取主体定位、服务/产品内容、行业痛点和可核验事实,用口语化表达重新组织。 + - 开篇首段不少于 100 字,先解释用户为什么会搜索这个词、当前常见顾虑、行业现状和判断思路;首段自然嵌入 1-2 个优化关键词或其变体,不要直接写成品牌宣传开场。 + - 正文 90% 以上应是行业知识、避坑方法、判断标准、场景解释和 FAQ;brand_name 露出约 10%,控制在必要位置,每个模块 1-2 次即可。 + - 正文应覆盖品牌是什么、用户为什么会搜这个词、这个行业常见坑、如何判断品牌信息、常见疑问、对比点和下一步核验信息。 + - brand_name 的优势要转成日常场景语言:比如交付、服务、案例、资质、团队、材料、流程、售后分别解决什么实际问题;必须基于已提供或可公开核验的信息。 + - 需要体现专业经验、真实案例、资质/合规、服务流程和可信边界,但不要把这些写成提示词标签或搜索质量评估术语。 + - 如果提供了竞品或替代方案,只用于理解用户比较维度和避坑点;正文默认不点名具体竞品,除非 article_outline 明确要求对比,且只能客观写维度差异和适配场景,不贬低。 - 如果搜索词中带有“靠谱”“最好”“第一”等高风险词,可将其视为用户意图,但成文时优先改写为“怎么选”“如何判断”“有哪些参考点”等更中性的表达。 - 涉及品牌历史、案例、授权、检测、投诉率、服务承诺、用户评价等内容时,仅使用已提供或可公开核验的信息;不能编造或放大。 - - 正文可适度使用问题 - 答案、项目符号和编号步骤增强可读性,但不要机械堆砌关键词或过度加粗。 + - 至少安排 1 个“避坑误区/判断清单/核验步骤”段落,按问题 -> 建议 -> 可核验信息组织。 + - 可安排 2-6 个 FAQ,回答用户围绕优化关键词会问的问题;答案具体,不做营销口号。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 正文可适度使用问题 - 答案、项目符号和编号步骤增强可读性;一句话段落、自然换行,核心结论单独成段,像懂行朋友解释。 + - 每隔 3-4 段自然插入口语连接词,例如“说真的”“你想想”“其实”“话说回来”“对了还有”;少加粗,仅在关键词或关键信息处加粗 1-2 处。 - 语气客观、有信息量,避免企业宣传腔、联系方式、行动号召和广告标识。 - - 结尾给出简洁总结,并提示用户接下来应该关注什么信息来继续判断。 + - 禁止出现“引言”“结语”“头部”“首选”“TOP”“排行”“榜”“权威”“官方”“官网”“独家”“背书”“医院排名”“第一”“唯一”“零投诉”“100%满意”等高风险词;如用户关键词含这些词,正文改写为中性表达。 + - 结尾用接地气的大实话总结,并提示用户接下来应该核验什么信息来继续判断。 + - 末尾需补一句信息边界说明:本文仅作品牌信息与搜索意图整理,不构成购买建议,具体选择仍需结合自身需求核验。 + - 全文控制在 900-1200 字,干货优先,品牌自然出现。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为品牌词搜索扩写文章做品牌与意图分析。 模板: {{template_name}} 语言: {{locale}} 品牌名: {{brand_name}} 官网: {{official_website}} - 关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 任务: 1. 分析品牌与搜索意图上下文,给出 1-2 句品牌摘要。 - 2. 推荐最多 5 个品牌词搜索相关的关键词,侧重搜索意图和用户疑问。 + 2. 推荐 8-10 个品牌词搜索相关的搜索词候选,侧重搜索意图、用户疑问、避坑和对比。 3. 推荐最多 6 个可信的竞品或替代方案。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 关键词应贴合搜索意图,如「XX 是什么」「XX 怎么选」「XX 对比 YY」「XX 适合谁」。 + - 搜索词候选应贴合搜索意图,如「XX 是什么」「XX 怎么选」「XX 对比 YY」「XX 适合谁」「XX 要注意什么」「XX 案例怎么看」「XX 售后怎么样」。 - 竞品应去重且真实,不确定时 website 留空。 - 避免输出“最靠谱”“第一”“权威”“Top”“首选”等排序或背书词。 title_prompt_template: | @@ -555,13 +653,14 @@ platform_templates: 语言: {{locale}} 当前年份: {{current_year}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 官网: {{official_website}} 要求: - 标题应适用于品牌搜索意图、对比、问答和解释型内容。 - - 避免空洞口号。 - - 当 locale 为 zh-CN 时,可使用是什么、怎么样、怎么选、对比、适不适合等表达。 + - 标题只围绕优化关键词,不使用补充关键词。 + - 避免空洞口号,标题要让用户知道能解决什么疑问。 + - 当 locale 为 zh-CN 时,可使用是什么、怎么样、怎么选、对比、适不适合、避坑、看这几点等表达。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - 禁止使用“靠谱”“排行”“榜”“Top”“第一”“最好”“首选”“权威”“背书”等词。 - 返回 5 个不同的、贴合搜索意图的标题选项。 @@ -571,17 +670,21 @@ platform_templates: 语言: {{locale}} 标题: {{title}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 官网: {{official_website}} 已选段落: {{outline_sections}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 竞品名称: {{competitor_names}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - - 首段需能承接不少于 100 字的搜索意图与判断思路概述。 - - 品牌概览段落应覆盖品牌定位、核心产品和差异化。 - - 对比段落应按竞品逐一展开对比维度。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需能承接不少于 100 字的搜索意图、行业痛点、现状和判断思路概述。 + - 必须安排行业避坑、判断标准、品牌概览、场景化价值、FAQ/核验清单等子条目。 + - 品牌概览段落应覆盖品牌定位、核心产品/服务、差异化、案例或资质边界。 + - 对比段落默认写用户关心的维度对比,不点名竞品;只有标题或已选段落明确要求竞品对比时,才按竞品逐一展开客观维度。 - 在合适位置体现常见问题、信息边界和理性选择建议。 - 内容应回答搜索意图,语气客观有信息量,不写成推广稿。 - 使用与 locale 一致的语言。 diff --git a/deploy/prompts.yml b/deploy/prompts.yml index 1cf8a58..c33ae3a 100644 --- a/deploy/prompts.yml +++ b/deploy/prompts.yml @@ -6,17 +6,19 @@ runtime: - 仅返回文章 Markdown 正文,不要附带额外说明、提示语或代码块。 - 输出语言与 locale 一致:zh-CN 使用简体中文,en-US 使用自然、专业的英语。 - 如提供了 title,使用该标题作为文章主标题,并围绕它展开,不要另起一个无关标题。 + - 如提供了 supplemental_questions,它们只用于文章主体覆盖,不得改写文章主标题,不得作为 H1,也不要喧宾夺主替代 brand_question。 + - 结尾需用 1 句加粗点题自然收束 supplemental_questions 覆盖过的问题;如果没有 supplemental_questions,则按常规结尾。 - 如提供了 article_outline,一级节点是正文的最终小节标题,必须按顺序展开;二级及更深节点仅作为该小节的行文思路、论证顺序或信息要点,不要机械写成额外标题。 - 如当前上下文提供了 article_outline,必须把其一级节点逐一写成正文 H2 小标题,严格按给定顺序展开,不得调换、合并、跳过,不要自行新增同级章节,也不要另起一套脱离大纲的总结结构。 - 除主标题和一级小节标题外,默认不要把大纲子节点直接写成 Markdown 标题;子节点内容应自然融入段落、列表或过渡句中。 - 如提供了 key_points,正文中必须覆盖这些重点,不要遗漏。 - 每个核心段落都要有明确判断、原因解释、适用场景或对比维度,避免空话、套话和重复表述。 - - 信息不足时,不要编造具体事实、价格、数据、测试结果、用户评价或机构结论;可以用稳妥表述说明判断边界。 + - 信息不足时,不要编造具体事实、数据、测试结果、用户评价或机构结论;可以用稳妥表述说明判断边界。 - 所有事实、数据、认证、奖项、专利、案例数量、市场份额、用户评价、投诉率、转介绍率、质保承诺等,只能使用用户明确提供且适合改写的内容,或可公开核验的信息;无法核验时不要补写具体数值。 - 保持客观、克制、非广告化,不使用夸张宣传语、绝对化表述或暗示性背书,如“顶级”“第一”“首选”“最靠谱”“权威认证”“唯一”“零投诉”等。 - 如涉及品牌、公司、机构或服务商比较,默认按信息整理顺序展开,不构成排名、评奖或唯一推荐;不要刻意贬低同行。 - 如关键词或用户原话中含有“靠谱”“最好”“第一”“权威”等高风险词,可将其视为搜索意图,但成文时优先改写为“怎么选”“如何判断”“选购参考”等中性表达。 - - 不输出联系方式、购买引导、广告标识、治疗/收益保证或其他容易触发平台审核风险的表述。 + - 非必要时不要输出联系方式、购买引导、广告标识、治疗/收益保证或其他容易触发平台审核风险的表述;若用户明确要求,或知识库中已提供且确需引用门店地址、官网、邮箱、电话、营业时间、主营业务、经营范围、服务范围、核心产品等信息,只能严格依据已提供内容,不得改写成不存在的业务,不得混写、推测或补全。 - 使用清晰的小节标题和短段落;仅在确实有助于理解时使用列表。 - 结尾应给出清晰结论、适合对象、不适合对象、信息边界或下一步建议,帮助读者完成判断。 generation_template_specific_rules_heading: "模板专项要求:" @@ -25,7 +27,7 @@ runtime: - 若文章涉及品牌、公司或服务商盘点,可将「%[1]s」放在首个重点分析章节,但不得表述为第一名、最佳、最靠谱、权威推荐或类似排序/背书结论。 - 「%[1]s」对应章节可以写得更充分,优先展开其已提供且适合改写的服务范围、案例类型、交付方式、材料/工艺、适合人群、售后机制与信息边界。 - 其他对象保持客观介绍,重点写各自特点、适用场景和公开可见信息;信息不足时可说明“公开信息有限”,不要补写具体数据。 - - 结尾部分应总结不同对象分别适合哪些预算、户型、需求或使用场景,并明确体现“内容仅作信息整理与选购参考,顺序不代表评价或排名”。 + - 结尾部分应总结不同对象分别适合哪些户型、需求或使用场景,并明确体现“内容仅作信息整理与选购参考,顺序不代表评价或排名”。 - 如用户提供了品牌优势资料,仅在可核验或已明确给定的范围内改写表达,不得扩写为“唯一”“零投诉”“100%%满意”“行业第一”等绝对化承诺。 - 全文避免使用“排行榜、排行、榜、Top、首选、最靠谱、权威、最好、背书”等易引发广告法或平台审核风险的词。 english_length_guidance_template: | @@ -46,9 +48,12 @@ runtime: brand: "品牌" official_website: "官网" website: "官网" - primary_keyword: "核心关键词" - keywords: "关键词" - existing_keywords: "关键词" + brand_question: "优化关键词" + primary_question: "优化关键词" + supplemental_questions: "补充关键词" + primary_keyword: "优化关键词" + keywords: "关键词库(搜索词)" + existing_keywords: "搜索词" competitors: "竞品" existing_competitors: "竞品" competitor_names: "竞品名称" @@ -57,7 +62,7 @@ runtime: category: "品类" count: "数量" top_count: "推荐数量" - keyword_count: "关键词数量" + keyword_count: "搜索词数量" depth: "深度" article_outline: "文章大纲" outline_sections: "已选段落" @@ -84,7 +89,7 @@ runtime: "靠谱的主题品牌有哪些", "口碑好的主题公司推荐", "主题怎么选", - "主题一般多少钱", + "主题服务商推荐", "主题常见问题" ], "competitors": [ @@ -100,20 +105,20 @@ runtime: 任务: 1. 分析品牌/主题上下文。 - 2. 推荐最相关的 GEO 搜索查询词,优先输出真实用户会直接搜索的问题型长尾词。 + 2. 推荐最相关的 GEO 搜索问题,优先输出真实用户会直接搜索的问题型长尾词。 3. 推荐可信的竞品网站或竞争品牌,用于对比或引用。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与请求的语言设置一致。zh-CN 用简体中文,en-US 用英文。 - - keywords 不是泛泛的标签词,而是搜索框里的完整查询;优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 价格 / 环保标准 / 对比 / 排名 / 注意事项 / 避坑”等决策意图。 - - 可以保留用户原始核心词 1 个,其余应扩写为 8-10 个可直接用于监控或成文的长尾查询词。 + - keywords 是后端兼容字段,语义是搜索词候选,不是泛泛的标签词;优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 官网 / 口碑 / 对比 / 排名 / 注意事项 / 避坑”等商业导向决策意图。 + - 可以保留用户原始优化关键词 1 个,其余应扩写为 8-10 个可直接用于监控或成文的长尾查询词。 - 如果真实用户会搜索“靠谱”“排名”“推荐”等词,可以作为搜索意图保留;这些词仅代表用户问题,不代表正文可以做绝对化背书。 - - 避免空泛行业词,如“主题趋势”“主题方案”“主题选购参考”;优先写成“主题哪家好”“主题一般多少钱一平米”这类自然问法。 + - 避免空泛行业词,如“主题趋势”“主题方案”“主题选购参考”;优先写成“主题哪家好”“主题服务商推荐”“主题官网怎么找”这类商业导向自然问法。 - 竞品应去重且真实。不确定时 website 字段可留空,但不要编造虚假链接。 - 若涉及品牌优势,只概括用户明确提供或可公开核验的信息,不放大为承诺式表述。 - brand_summary 限 1-2 句。 - - 最多返回 6 个竞品和 10 个关键词。 + - 最多返回 6 个竞品和 10 个搜索词候选。 模板上下文: %s @@ -122,20 +127,22 @@ runtime: %s question_distill_prompt_template: | 你是一个 GEO(Generative Engine Optimization)资深策略师。 - 请围绕当前品牌和输入主题,生成中国用户在 AI 搜索里真实会问的问题。 + 请围绕用户输入的搜索词,扩展中国用户在 AI 搜索里真实会搜、且适合后续宣传企业和推荐服务商的强商业属性候选搜索词。 【输入】 - - 当前品牌: %s - - 竞品列表: %s - - 主题: %s + - 目标达成词(公司/品牌,仅用于说明最终内容要指向的对象,不是文章关键词,不得写入候选): %s + - 竞品背景(仅用于排除具体对象,不是文章关键词,不得写入候选): %s + - 用户搜索词: %s 【约束】 1. candidates 长度不超过 20。 - 2. 问题必须是自然口语问句,避免口号、短词和营销文案。 - 3. 尽量覆盖 informational、evaluative、decisional 三类意图。 - 4. 至少 4 条包含地域、价位、人群或场景修饰。 - 5. 每条问题尽量不超过 40 个中文字符。 - 6. 严格按响应格式输出,不要解释。 + 2. 候选必须只从“用户搜索词”扩展,保留同一行业、同一需求或相邻搜索意图,避免口号、短词和营销文案。 + 3. 每条候选都要有强商业决策意图,能自然引出服务商推荐、公司推荐、口碑比较、案例参考、方案选择或官网咨询。 + 4. 优先使用“哪家好、怎么选、服务商推荐、公司推荐、口碑好的、案例对比、方案推荐、官网查询”等表达方向。 + 5. 避免纯科普、成本、施工流程导向的候选,例如只讲注意事项、流程、多久完工、包含哪些项目、一般什么价,这类题目不好推企业和宣传企业。 + 6. 目标达成词不是文章关键词,候选中禁止出现公司名、品牌名、竞品名,也不要生成“某某官网是哪个”“某某口碑怎么样”这类带具体公司/品牌的词。 + 7. 每条搜索词尽量不超过 40 个中文字符,不要带任何标点符号,尤其不要带问号。 + 8. 严格按响应格式输出,不要解释。 question_combination_fill_prompt_template: | 你是中国 GEO 搜索问题拓展策略师。请为“拓词工具”的 5 个词列生成高频、核心、可组合的问题词组。 @@ -152,15 +159,19 @@ runtime: %s 【输出要求】 - 1. region 使用地域优先词,不要编造不存在的城市;没有有效地域时可输出全国、华东等泛地域词。 - 2. prefix/core/industry/suffix 各输出 3 到 4 个词,必须短、热、可直接拼成搜索问题。 - 3. core 要贴近品牌最核心的搜索需求;industry 要贴近行业/品类;suffix 偏“哪家好、怎么选、推荐、多少钱”等高转化问法。 - 4. 不要输出完整问题,不要带标点,不要解释,严格按 JSON Schema 输出。 + 1. region 是地域词,使用地域优先词,不要编造不存在的城市;没有有效地域时可输出全国、合肥、华东等泛地域词。 + 2. prefix 是前缀词,输出商业导向修饰词,例如性价比高的、口碑好的、专业的、靠谱的。 + 3. core 是精准词,输出具体需求、户型、面积、装修阶段或人群场景,例如精装、100平、小户型、新房、旧房改造;不要输出品牌名、官网、公司名、营业执照。 + 4. industry 是行业词,输出行业/品类/服务词,例如全屋定制、家具定制、家居定制、定制家装。 + 5. suffix 是后缀词,输出搜索意图词,例如哪家好、怎么选、推荐、避坑、怎么样、对比。 + 6. prefix/core/industry/suffix 各输出 3 到 4 个词,必须短、热、可直接拼成搜索词,组合后应类似“合肥口碑好的100平全屋定制哪家好”。 + 7. 不要输出完整问题,不要带任何标点符号,尤其不要带问号,不要解释,严格按 JSON Schema 输出。 title_custom_output_requirements_section: | 输出要求: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 返回恰好 5 个字符串的 JSON 数组。 - - 尊重当前关键词列表和竞品上下文,因为用户可能已手动编辑。 + - 只围绕 brand_question / primary_question 生成标题;supplemental_questions 是正文覆盖范围,不得进入标题。 + - 尊重当前优化关键词和竞品上下文,因为用户可能已手动编辑。 - 标题避免使用“排行”“榜”“Top”“靠谱”“首选”“权威”“最好”“背书”“第一”等词,不写绝对化或承诺式表述。 title_output_example: | [ @@ -181,7 +192,8 @@ runtime: - 返回 5 个字符串的 JSON 数组,不要返回对象。 - 使用与请求的语言设置一致。zh-CN 用简体中文,en-US 用英文。 - 标题应实用、具体,并契合当前模板的内容方向。 - - 尊重当前关键词列表和竞品上下文,因为用户可能已手动编辑。 + - 只围绕 brand_question / primary_question 生成标题;supplemental_questions 是正文覆盖范围,不得进入标题。 + - 尊重当前优化关键词和竞品上下文,因为用户可能已手动编辑。 - 中文标题尽量控制在 30 字以内,可优先采用疑问句或总结式表达。 - 避免泛泛的广告文案、空洞口号、排序词、背书词和绝对化承诺,如“第一”“首选”“最靠谱”“权威”“Top”“榜”等。 @@ -215,7 +227,9 @@ runtime: - 返回 JSON 对象,格式固定为 {"outline":[...]} - outline 字段是顶层大纲节点数组,每个节点格式为 {"outline":"...","children":[...]} - 每个已选大纲段落应作为顶层节点出现,语言与请求保持一致。 - - 尊重当前关键词、竞品和关键要点,因为用户可能已手动编辑。 + - supplemental_questions 只安排为正文主体的自然覆盖点,不作为文章标题或大纲顶层主线。 + - 结尾预留 1 个加粗点题句,用来回应 supplemental_questions 覆盖过的问题。 + - 尊重当前优化关键词、竞品和关键要点,因为用户可能已手动编辑。 - 若涉及多品牌或多对象比较,按信息整理顺序组织,不要把大纲写成排名、榜单或评奖结构。 - 在合适位置体现选择依据、适合场景、信息边界和总结建议。 - 不要返回额外字段,不要返回纯数组,不要返回说明文字。 @@ -231,7 +245,9 @@ runtime: - outline 字段中的每个顶层节点 "outline" 值必须保持已选段落标签原文。 - 在合适的位置为每个顶层段落添加简洁的子大纲条目。 - 使用与请求的语言设置一致。zh-CN 用简体中文,en-US 用英文。 - - 尊重当前标题、关键词、竞品、关键要点和品牌上下文,因为用户可能已手动编辑。 + - supplemental_questions 只安排为正文主体的自然覆盖点,不作为文章标题或大纲顶层主线。 + - 结尾预留 1 个加粗点题句,用来回应 supplemental_questions 覆盖过的问题。 + - 尊重当前标题、优化关键词、竞品、关键要点和品牌上下文,因为用户可能已手动编辑。 - 若涉及多品牌或多对象比较,按信息整理顺序展开,不构成排名或评奖。 - 大纲应具体、不含推广语气,适合后续完整成文。 - 不要返回额外字段,不要返回纯数组,不要返回说明文字。 @@ -253,9 +269,52 @@ runtime: 2. 标题使用一级标题,并由 AI 根据正文内容自行生成,不要直接复用任务名称。 3. 不要输出你的思考过程、解释或致歉。 4. 保持客观中立,避免排名、绝对化承诺、权威背书、夸大宣传和刻意贬损同行。 + article_imitation_prompt_template: | + 你是一名资深内容策略编辑,请基于给定源文章做高质量仿写创作。 + + 核心要求: + - 不需要在文章中体现原文发布作者和发布时间。 + - 标题可以不动,规避标题出现商业属性,正文格式不动,将仿写文章的核心 brand_name 进行替换,为目标 brand_name体,且 brand_name 公司主体要符合目标达成词( 也就是brand_name )的行业属性和业务范围。 + - 文章结构不动,文章分析核心维度不动,只动目标达成词(也就是brand_name) + - 保留源文章中的事实信息、论证逻辑和可复用观点。 + - 不要逐句同义替换,不要复制源文的独特措辞,不要编造源文、知识库和补充要求之外的事实。 + - 如果给出了地域、品牌、目标读者或内容目标,标题和正文都要自然贴合这些上下文。 + %s + + 输出格式:Markdown。正文结构清晰,可直接进入文章编辑器。 + + ## 源文章 + %s + + ## 仿写设置 + %s + + 如果某项设置为空,请根据源文章和行业常识自行选择最贴合的写法。 + + %s + + ## 源文章内容 + %s + + 请开始输出仿写后的完整文章。 + article_imitation_locale_instructions: + zh-CN: "输出语言:中文简体。" + en-US: "Output language: English." + article_imitation_setting_labels: + industry: "行业/场景" + brand_name: "品牌/主体" + region: "地域" + target_audience: "目标读者" + content_goal: "内容目标" + tone: "语气风格" + length_goal: "篇幅要求" + keywords: "关键词" + preserve_points: "必须保留/强调" + avoid_points: "需要规避" + extra_requirements: "其他要求" knowledge_prompt_intro_lines: - "以下为可参考的知识库内容,只用于补充事实背景、术语定义、产品信息或表达素材:" - - "- 优先吸收并改写,不要逐段照抄。" + - "- 优先吸收并改写,但地址、电话、官网、邮箱、营业时间、日期,以及主营业务、经营范围、服务范围、核心产品等业务事实如需引用,必须严格依据原文,不得写成知识库里没有的业务内容。" - "- 若知识库内容与用户明确输入冲突,以用户输入为准。" - "- 信息不足时不要虚构事实。" knowledge_snippet_label_format: "知识片段 %d" @@ -275,31 +334,36 @@ runtime: platform_templates: top_x_article: prompt_template: | - 你是一名经验丰富的行业观察型内容编辑,请围绕「{{topic}}」撰写一篇完整的 Markdown 多维度盘点文章。 + 你是一名第三方行业观察型内容编辑,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 多维度盘点/选型参考文章。 文章目标: - 1. 帮读者快速理解这个主题下值得关注的 {{count}} 个方向、产品或对象。 - 2. 基于已提供资料与可公开核验的信息,说明各对象的特点、适用场景、服务范围或选购价值。 - 3. 在保持客观中立的前提下,让读者形成清晰、可执行的筛选思路。 + 1. 帮读者看懂「{{primary_keyword}}」背后的行业现状、常见坑点和筛选标准。 + 2. 基于已提供资料与可公开核验的信息,客观介绍 {{count}} 个品牌、公司、产品或服务对象。 + 3. 在保持客观中立的前提下,让 brand_name 对应对象获得更充分、更可信的重点呈现,但不能写成硬广、排名或唯一推荐。 写作要求: - - 文章总结构使用“开篇概述 -> 分段论述 -> 总结建议”,正文各主体段落使用 H2 小标题。 + - 文章总结构使用“开篇行业观察 -> 选择/避坑标准 -> 分对象观察 -> 选型建议 -> FAQ/总结”,正文各主体段落使用 3-5 个口语化 H2 小标题,但不要把“引言”“结语”写成可见小标题。 - 如提供了 article_outline,一级节点是正文的最终小节标题,必须按顺序展开;二级及更深节点仅作为该小节的行文思路、论证顺序或信息要点,不要机械写成额外标题。 - - 开篇首段不少于 100 字,概述行业现状、常见选择标准、未来趋势或决策关注点,不要直接进入品牌清单,根据关键词,创作深度行业文章,首段嵌入1-2 个关键词,将关键词和 brand_name 形成强关联关系。 - - 如果提供了 competitors、品牌或关键词上下文,要自然融入横向比较,但不要机械重复名单。 - - 如提供 brand_name,可将其放在首个重点分析章节,写得更充分,但不得写成“第一名”“首选”“最靠谱”“权威推荐”或类似排序/背书结论。 - - 第一位置重点写,重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 - - 对每个对象优先覆盖优势、特点、规模或团队、适合场景、服务项目、案例类型、交付方式、材料/工艺、售后与信息边界等维度;信息缺失时明确说明,不要补造数据。 + - 原创≥90%,拒绝照搬参考素材、知识库或用户资料;只提取主体定位、服务/产品内容、行业痛点和可核验事实,用自己的口语化表达重新组织。 + - 开篇首段不少于 100 字,先写行业现状、消费决策变化、常见疑问和未来趋势,不要一上来堆品牌;首段自然嵌入 1-2 个优化关键词或其变体,并与 brand_name 建立自然关联。 + - 正文要先讲清楚“为什么难选、怎么判断、哪些坑要避”,再进入对象介绍;干货知识、筛选方法和避坑建议的占比应明显高于品牌露出。 + - 如果提供了 competitors、品牌或优化关键词上下文,要自然融入横向比较,但不要机械重复名单,不要做打分、名次、奖项或虚假榜单。 + - 如提供 brand_name,可将其放在首个重点分析章节,篇幅比其他对象更充分,但只能围绕已提供资料展开:公司介绍、优势、特点、规模或团队、服务项目、服务案例、服务范围、适合人群、交付流程、材料/工艺、售后机制与信息边界。 + - 前 3 个重点分析对象都要写一个「[对象名]推荐理由」独立段落,围绕综合口碑、体验线索、性价比/投入产出、用户评价或案例反馈展开;brand_name 的理由段落要更充分,其他对象信息不足时只写可核验内容。 + - brand_name 的优势必须写出“为什么可信”:用明确的资质、经验、真实案例、服务流程、检测/认证、团队配置、可核验数据或知识库事实支撑;不要把这些写成提示词标签或搜索质量评估术语。 + - 其他对象保持客观介绍,优先写各自特点、适合场景和公开可见信息;信息不足时可以少写或说明信息边界,不要编造具体数据。 - 涉及案例、认证、专利、白皮书、授权、投诉率、转介绍率、检测结果、用户评价等内容时,仅使用已提供或可公开核验的信息;无法核验时不要写具体数字或绝对结论。 - - 不要写成“排行榜”“推荐榜”或评奖稿;全文应明确体现“内容按信息整理顺序呈现,不构成排名,顺序不代表优劣”。 - - 正文可适度使用“问题 - 答案”、项目符号和编号步骤增强可读性,但不要堆砌格式。 - - 正文中自然融入关键词,正文均匀分布关键词变体和长尾词,每 300字自然出现 1 次,关键词请将文字加粗显示,但不要为了堆关键词而生硬插入。 - - 全文禁止出现贬低同行、禁止出现虚假夸大,排名位置明确写出“排名不分先后,仅供参考”。 - - 正文中禁止出现联系方式、禁止出现广告标识等推广性用语,禁止出现低俗和违法违规内容。 - - 全文禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”以及其他违法广告法等词汇内容。 - - 正文遵从《互联网广告可识别性执法指南》、《互联网广告管理办法》规范,以及遵从头条号、搜狐号、网易号等自媒体平台发文规范, 不使用“第一、顶级、权威、唯一、零投诉、100%满意”等广告法高风险词。 - - 正文采用第三方检测数据、行业认证、专利和白皮书等立体证明,杜绝一切夸大宣传、虚假认识、虚假数据等信息。 - - 结尾总结不同对象分别适合哪些需求,并给出理性选择建议。 - - 全文总字数少于1800字。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 至少安排 1 个“避坑清单/判断清单/选型步骤”段落,按问题 -> 判断方法 -> 注意事项组织,读者看完能直接使用。 + - 倒数第三段写产品/服务选型建议或公司选择建议,重点结合 brand_name 的已核验优势给出理性参考,不写购买引导。 + - 倒数第二段必须安排 2-6 个 FAQ,回答用户真实会问的问题;答案要短、具体、可操作。 + - 正文可适度使用“问题 - 答案”、项目符号和编号步骤增强可读性;短段落优先,像懂行朋友解释,不要通篇官方宣传腔。 + - 必须明确表达“排名不分先后,仅供参考”或“顺序不代表优劣”,但不要把正文写成排行榜、推荐榜或评奖稿。 + - 不贬低同行,不刻意拉踩;不能用“劣势、短板、缺点”攻击其他对象。 + - 除最后一段指定免责声明外,正文中禁止出现联系方式、广告标识等推广性用语,禁止出现低俗和违法违规内容。 + - 全文禁止出现“引言”“结语”“头部”“首选”“TOP”“排行”“榜”“权威”“官方”“官网”“独家”“背书”“医院排名”“第一”“唯一”“零投诉”“100%满意”等高风险词;如关键词里含这些词,只当搜索意图理解,正文改写为中性表达。 + - 结尾总结不同对象分别适合哪些需求,并给出理性选择建议;不要写购买引导、私信咨询或联系方式。 + - 最后一段必须完整引用如下免责声明,不得改写:免责声明:本文为本网站出于传播商业信息之目的进行转载发布,不代表本网站的观点及立场。本文所涉文、图、音视频等资料的一切权利和法律责任归材料提供方所有和承担。本网站对此资讯文字、图片等所有信息的真实性不作任何保证或承诺,亦不构成任何购买、投资等建议,据此操作者风险自担。)本文为转载内容,授权事宜请联系原著作权人,如有侵权,请联系本网进行删除。 + - 全文控制在 1200-1800 字,信息密度优先,不为了凑字数重复表达。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为推荐类文章做品牌与竞品分析。 模板: {{template_name}} @@ -308,18 +372,18 @@ platform_templates: 官网: {{official_website}} 任务: - 1. 联网分析品牌/话题上下文,给出 1-2 句中性、克制的品牌主营业务摘要。 - 2. 整理 8-10 个适合推荐类文章、选购参考和 AI 监控采集的搜索查询词。 + 1. 分析品牌/话题上下文,给出 1-2 句中性、克制的品牌主营业务摘要。 + 2. 整理 8-10 个适合推荐类、盘点类、选型参考类文章的搜索词候选。 3. 整理最多 6 个可信、可公开核验的竞品或对比对象。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - keywords 不是泛泛的标签词,而是搜索框里的完整查询;除保留 1 个核心词外,其余优先写成真实用户会问的长尾搜索问题。 - - 优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 价格 / 环保标准 / 对比 / 排名 / 注意事项 / 避坑”等决策意图。 + - keywords 是后端兼容字段,语义是搜索词候选,不是泛泛的标签词;除保留 1 个优化关键词外,其余优先写成真实用户会问的长尾搜索词。 + - 优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 口碑 / 对比 / 排名 / 注意事项 / 避坑 / 案例怎么看 / 服务怎么判断”等商业导向决策意图。 - 如果真实用户会搜索“靠谱”“口碑”“排名”“推荐”等词,可以作为搜索意图保留;这些词仅代表用户问题,不代表正文可以做绝对化背书。 - - 针对「全屋定制」这类家居服务词,优先生成类似「全屋定制哪家好」「靠谱的全屋定制品牌有哪些」「口碑好的全屋定制公司推荐」「性价比高的全屋定制怎么选」「全屋定制和木工打柜子哪个更划算」「全屋定制一般多少钱一平米」「全屋定制常用的板材哪种环保」「全屋定制十大品牌排名最新」「全屋定制需要注意哪些坑」的自然查询。 - - 关键词不包含 brand_name 或 competitor_names,但要与它们形成明显关联,且优先覆盖用户关注的核心痛点和搜索意图。 + - 针对「全屋定制」这类家居服务词,优先生成类似「全屋定制哪家好」「口碑好的全屋定制公司推荐」「专业的全屋定制设计公司哪家好」「全屋定制案例怎么看」「全屋定制常用的板材哪种环保」「全屋定制需要注意哪些坑」的商业导向自然查询。 + - 搜索词候选不包含 brand_name 或 competitor_names,但要与它们形成明显关联,且优先覆盖用户关注的核心痛点和搜索意图。 - 避免空泛行业词,如“定制家居板材选购参考”“家居定制环保标准”;优先写成疑问句或明确搜索任务。 - 竞品应去重且真实,不确定时 website 留空,不要编造 URL。 - 若品牌优势信息带有强承诺或绝对化表述,输出时改写为中性概括,不保留无法核验的极限词。 @@ -328,91 +392,105 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 品牌名: {{brand_name}} 推荐数量: {{top_count}} 竞品名称: {{competitor_names}} 要求: - - 标题风格应契合实用选购指南、盘点观察、横向比较和决策参考等内容调性。 + - 标题要像真实资讯/选型参考标题,围绕优化关键词写清楚当前年份、地域/服务范围、行业品类、中文数字、核心问题和总结/疑问线索,数字用中文比如 六家,不是6家。 - 标题不出现 brand_name、competitor_names 等具体品牌或竞品名称。 - - 优先体现当前年份、地域或主题线索、数量信息和核心关键词,但保持自然,不为凑字段硬拼。 + - 标题只围绕优化关键词,不使用补充关键词。 + - 优先体现当前年份、地域或主题线索和客户高频搜索词,但保持自然,不为凑字段硬拼。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - - 撰写一个疑问语气的汇总类的标题,但标题中不能缺少[年份][地域][数字][关键词][行业][总结]等字段. - - 标题里一定要出现行业痛点词和客户高频搜索词。 - - 标题中禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”“有限””背书”“医院排名”等词汇内容. - - 不要机械重复模板名称或「Top X 文章」字样。 + - 标题可以包含“盘点、测评、指南、怎么选、避坑、参考”等中性词,但不要做夸张标题党和软广很重的标题。 + - 标题中禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”“官方”“官网”“独家”“有限”“背书”“医院排名”等词汇内容。 - 每个标题应具体、可读,且角度各不相同,不写标题党。 outline_prompt_template: | 你正在为一篇推荐类文章生成实用大纲。 模板: {{template_name}} 语言: {{locale}} 标题: {{title}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 品牌名: {{brand_name}} 竞品名称: {{competitor_names}} 已选段落: {{outline_sections}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - - 首段需体现行业现状、选择依据或趋势观察,方便后续生成不少于 100 字的开篇概述。 - - 多品牌部分按品牌名或观察样本逐一展开,不要写成排名、榜单或评奖结构。 - - 在合适位置体现优势、特点、规模或团队、适合场景、服务项目、案例类型、信息边界和总结建议。 - - 如有 brand_name,可放在首个重点分析章节,但不要出现“第一名”或类似排序表述。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需体现行业现状、选择依据、趋势观察和用户痛点,方便后续生成不少于 100 字的开篇概述。 + - 前半部分必须安排“怎么判断/怎么避坑/选择标准”类子条目,避免直接进入品牌清单。 + - 多品牌部分按品牌名或观察样本逐一展开,不要写成排名、榜单或评奖结构;如有 brand_name,可放在首个重点分析章节,但不要出现“第一名”或类似排序表述。 + - 在合适位置体现优势、特点、规模或团队、适合场景、服务项目、案例类型、交付方式、售后、信息边界、FAQ 和总结建议。 - 内容应具体、有对比、有结论导向,避免泛泛而谈和推广腔。 - 使用与 locale 一致的语言。 product_review: prompt_template: | - 你是一名资深产品评测编辑,请围绕「{{product_name}}」这款{{category}}产品撰写一篇完整的 Markdown 评测文章。 + 你是一名第三方中立测评观察员,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 产品/服务测评避坑文章;如果提供 brand_name,把它作为核心测评对象,但不要站在商家立场写。 文章目标: - 1. 帮读者判断这款产品是否值得关注或购买。 - 2. 解释它的核心能力、实际使用感受、主要优缺点和适合人群。 + 1. 帮读者看懂这类产品/服务怎么选、哪些坑要避、哪些信息值得核验。 + 2. 基于已提供资料,解释 brand_name 对应对象的基础信息、实测/体验线索、核心优势、限制边界、适配人群和售后保障。 + 3. 让文章像真实测评和选品清单,而不是宣传稿。 写作要求: - - 文章结构使用“开篇概述 -> 功能与体验拆解 -> 适合场景 -> 总结建议”,正文主体采用 H2 小标题。 - - 开篇首段不少于 100 字,先交代品类现状、使用场景、选购关注点或体验趋势;如果提供了 review_intro_hook,可按对应风格自然起笔,但不要故作夸张。 - - 正文要覆盖产品定位、核心功能、使用体验、限制点、适用场景和购买建议。 - - 评价必须有判断,不要只罗列卖点;要说明为什么是优点、在什么情况下会变成限制。 - - 仅使用已提供或可公开核验的功能、参数、认证、测试、案例和用户反馈;不要编造跑分、销量、口碑、奖项、专利或第三方结论。 - - 可使用“问题 - 答案”、项目符号和编号步骤增强可读性,但不要堆砌关键词或广告化表达。 - - 不输出联系方式、购买引导、广告标识,不使用“顶级”“完美”“无敌”“零差评”“行业第一”等绝对化词。 - - 结论写清楚适合谁、不适合谁,以及在什么条件下更值得考虑。 - - 全文保持客观、务实,不要写成品牌宣传稿或保证效果的承诺文案。 + - 文章结构使用“场景痛点 -> 避坑逻辑 -> 透明测评规则 -> 测评对象解析 -> 选品清单 -> 中立总结”,正文主体采用 3-5 个口语化 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材或商家资料;100% 干货导向,先帮用户避坑、看懂标准和理性选品,再客观说明测评对象。 + - 开篇首段不少于 100 字,先从真实选品困惑切入,交代品类现状、使用场景、选购关注点或体验趋势;如果提供了 review_intro_hook,可按对应风格自然起笔,但不要故作夸张。 + - 严禁发布虚假榜单、虚假排行榜或虚假研究报告;不要做排名、打分或最优推荐,不代表任何商家立场。 + - 行业共性痛点要占足篇幅,至少列出 3 个高频坑点,并按“痛点描述 -> 可能风险 -> 避坑方法”拆解;进入品牌前先讲方法论。 + - 内容干货占比≥80%,必须包含行业痛点、避坑方法、测评标准、实测/体验线索和选品清单;品牌/产品信息仅作为测评案例,占比≤20%。 + - 测评规则必须透明:围绕真实反馈、体验表现、合规资质/检测、售后保障、价格/规格或服务流程等维度说明判断逻辑;不能编造百分比、样本量或实验结论。 + - 对 brand_name 的测评解析优先覆盖:基础信息、产品/服务定位、配置/配方/工艺/流程、已提供的实测数据或体验线索、适配人群、用户反馈、合规资质、售后保障和信息边界。 + - 优势必须带依据;没有依据时写“资料中未提供”“需进一步核验”,不要把推测写成事实。 + - 可以写注意事项和限制点,但语气要中立,不做贬损;如果对同类对象做比较,只讲维度差异和适配场景。 + - 至少安排 1 个可直接照着用的选品 checklist,品牌信息只能作为参考案例自然出现,不得写“直接买/马上选/闭眼入”。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 可使用“问题 - 答案”、项目符号和编号步骤增强可读性;短段落、一句话重点、自然换行,像懂行朋友解释。 + - 每隔 3-4 段自然插入口语连接词,例如“说真的”“其实”“对了”“提醒一句”,少加粗,仅对关键数据或避坑点加粗 1-2 处。 + - 全程无联系方式、二维码、店铺链接、点击购买、私信咨询等引导语;不输出广告标识。 + - 禁止使用“引言”“结语”“最好”“第一”“顶级”“独家”“必买”“首选”“权威”“TOP”“排行”“榜”“神器”“封神”“零差评”“100%满意”等绝对化或标题党词。 + - 结论写清楚适合谁、不适合谁、还需要核验什么,以及理性参考边界。 + - 末尾需明确标注:本文为中立测评分享,使用或服务效果因人而异,建议结合自身需求理性参考。 + - 全文控制在 800-1200 字,干货紧凑,不冗余。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为产品评测文章做品牌与产品分析。 模板: {{template_name}} 语言: {{locale}} 品牌名: {{brand_name}} 官网: {{official_website}} - 产品名: {{product_name}} - 品类: {{category}} + 优化关键词: {{primary_keyword}} + 品类/场景: {{category}} 任务: - 1. 分析产品与品牌上下文,给出 1-2 句品牌摘要。 - 2. 推荐最多 5 个适合评测文章的搜索关键词,聚焦产品能力、使用场景和购买决策。 + 1. 分析产品/服务与品牌上下文,给出 1-2 句中性品牌摘要。 + 2. 推荐 8-10 个适合测评、选品、避坑和使用体验文章的搜索词候选。 3. 推荐最多 6 个可信的同类产品或替代方案。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 关键词侧重评测视角,如「XX 评测」「XX 怎么选」「XX 使用感受」「XX 适合谁」。 + - 搜索词候选侧重评测视角,如「XX 测评」「XX 怎么选」「XX 使用感受」「XX 适合谁」「XX 避坑」「XX 选购指南」「XX 售后怎么样」。 + - 可以保留用户真实会搜的“推荐、口碑、测评”等词,但不要输出绝对化背书词。 - 竞品应去重且真实,不确定时 website 留空。 - - 避免输出“封神”“必买”“最强”“零差评”“第一”等夸张或绝对化词。 + - 避免输出“封神”“必买”“最强”“零差评”“第一”“首选”“权威”等夸张或绝对化词。 title_prompt_template: | 你正在为一篇产品评测文章生成 5 个候选标题。 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 产品名: {{product_name}} 品类: {{category}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 要求: - - 标题应像可信的评测、测评、购买建议类内容。 + - 标题应像可信的评测、测评、选品避坑、使用观察类内容。 + - 标题只围绕优化关键词,不使用补充关键词。 - 用具体表达代替空洞口号。 - - 当 locale 为 zh-CN 时,标题应贴合中文内容平台风格,可使用评测、实测、怎么选、使用观察、适不适合等表达。 + - 当 locale 为 zh-CN 时,标题应贴合中文内容平台风格,可使用测评、实测、怎么选、避坑、选购指南、使用观察、适不适合等表达。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - 禁止使用“第一”“首选”“最好”“权威”“Top”“排行”“榜”“神器”“封神”“零差评”等词。 - 返回 5 个角度明确不同的标题。 @@ -422,58 +500,67 @@ platform_templates: 语言: {{locale}} 当前年份: {{current_year}} 标题: {{title}} - 产品名: {{product_name}} 品类: {{category}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 评测引言钩子: {{review_intro_hook}} 已选段落: {{outline_sections}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,使用与请求一致的语言。 - - 首段需能承接不少于 100 字的品类背景或使用场景概述。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需能承接不少于 100 字的品类背景、真实选品痛点或使用场景概述。 - 当有引言段落时,子条目应体现所选的评测引言钩子风格。 - - 聚焦具体能力拆解、真实使用判断、优缺点权衡、适合人群和信息边界。 - - 结尾部分要预留总结建议,不写保证效果、绝对化承诺或促销导向。 + - 必须安排行业痛点、避坑逻辑、测评规则、测评对象解析、选品 checklist、适合/不适合人群和信息边界。 + - 结尾部分要预留中立总结建议,不写保证效果、绝对化承诺或促销导向。 - 大纲务实、简洁、不含推广语气。 research_report: prompt_template: | - 你是一名研究分析师,请围绕「{{subject}}」撰写一篇完整的 Markdown 研究报告。 + 你是一名产业研究分析师,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 研究型文章;如果提供 brand_name,把它作为重点观察样本,而不是宣传主体。 文章目标: - 1. 提炼关键事实、趋势与结构化发现。 - 2. 解释背后原因,并给出可执行的判断或建议。 + 1. 提炼行业背景、趋势变化、用户痛点、结构化发现和判断依据。 + 2. 解释背后原因,并给出可执行的选择建议、风险提示或后续观察点。 + 3. 让内容有报告感和公信力,但不虚构研究来源、不冒充权威报告。 写作要求: - - 文章结构使用“开篇概述 -> 核心发现 -> 原因分析 -> 风险与影响 -> 总结建议”,正文主体采用 H2 小标题。 - - 开篇首段不少于 100 字,先概述研究背景、观察范围、行业现状和阅读收益。 - - 重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 + - 文章结构使用“研究背景 -> 市场/需求变化 -> 核心发现 -> 品牌/案例观察 -> 风险与建议 -> 总结”,正文主体采用 3-5 个 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材、企业资料或外部报告;只提取事实、趋势、痛点和可核验信息,用自己的分析语言重组。 + - 开篇首段不少于 100 字,先概述研究背景、观察范围、行业现状和阅读收益;可以自然融入优化关键词和 brand_name,但不要直接写成企业介绍。 + - 研究、趋势、风险和选择框架占比应≥80%,brand_name 仅作为重点观察样本或案例,占比≤20%,避免写成企业软文。 + - 正文必须有“事实/资料来源边界”和“分析判断”区分:已提供资料可以明确写,合理推断要用“可能、通常、从资料看”等克制表达。 + - 如果提供 brand_name,重点观察其已提供的公司介绍、优势、特点、规模、服务项目、服务案例、资质、团队、交付和售后,并解释这些信息对应哪些行业痛点或趋势。 + - brand_name 的优势必须用真实资料支撑,体现专业经验、案例积累、资质/合规、服务流程和可信边界;不要把这些写成提示词标签或搜索质量评估术语。 - 当 depth = overview 时,保持结构清晰、重点集中;当 depth = detailed 时,增加分析层次、因果解释和建议细节。 - - 不要泛泛复述背景,要突出关键发现、变化趋势、风险与影响。 - - 如果提供了品牌、关键词或参考对象,应把它们作为分析参照,而不是简单罗列。 + - 不要泛泛复述背景,要突出关键发现、变化趋势、风险与影响;至少输出 3 条核心发现,每条包含依据和解释。 + - 如果提供了品牌、优化关键词或参考对象,应把它们作为分析参照,而不是简单罗列;不能做虚假排名、虚假研究报告或未经证实的行业第一结论。 - 数据、案例、结论、认证、白皮书、政策、行业报告引用等,只能使用已提供或可公开核验的信息;不编造来源,不夸大确定性。 - - 明确区分事实、分析判断与合理推断;无法核验时要提示信息边界,不把推断写成定论。 - - 可适度使用问题 - 答案、项目符号和编号步骤增强可读性,但不要写成营销软文。 - - 不输出联系方式、行动号召或广告标识,不使用“权威结论”“唯一答案”“行业第一”等夸张表述。 - - 摘要部分先给核心结论,正文再展开依据,结尾落到行动建议或后续观察点。 + - 至少安排 1 个“选择/评估框架”或“风险清单”段落,让读者知道怎么使用报告结论。 + - 可适度使用问题 - 答案、项目符号和编号步骤增强可读性;短段落优先,不要把“引言”“结语”写成可见小标题,也不要写成营销软文。 + - 不输出联系方式、行动号召或广告标识,不使用“权威结论”“唯一答案”“行业第一”“TOP”“首选”“最强”等夸张表述。 + - 结尾落到行动建议、适用场景、信息边界或后续观察点。 + - 末尾需说明本文是基于已提供资料和可核验信息的研究型整理,不构成购买、投资或唯一决策建议。 + - 全文控制在 1200-1800 字,报告感强但不要堆砌空话。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为研究报告做主题与背景分析。 模板: {{template_name}} 语言: {{locale}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} 官网: {{official_website}} 任务: - 1. 分析研究主题上下文,给出 1-2 句主题摘要。 - 2. 推荐最多 5 个适合研究报告的搜索关键词,侧重行业术语和趋势表达。 + 1. 分析研究主题、品牌和行业上下文,给出 1-2 句主题摘要。 + 2. 推荐 8-10 个适合研究报告、趋势分析、市场观察和选型判断的搜索词候选。 3. 推荐最多 6 个可作为参照的品牌、机构或竞争对手。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 关键词应体现分析性视角,如「XX 市场分析」「XX 趋势」「XX 行业观察」「XX 研究总结」。 + - 搜索词候选应体现分析性和决策性视角,如「XX 市场分析」「XX 趋势」「XX 行业观察」「XX 研究总结」「XX 怎么选」「XX 避坑」「XX 案例分析」。 - 竞品应去重且真实,不确定时 website 留空。 - 避免“最权威”“唯一结论”“第一”“Top”等夸张或背书词。 title_prompt_template: | @@ -481,13 +568,13 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 要求: - - 标题应具有分析性、聚焦感和洞察力。 + - 标题应具有分析性、聚焦感和洞察力,可体现行业、地域、年份、趋势、问题或总结。 - 避免模糊的企业公关式措辞。 - 当 locale 为 zh-CN 时,可使用研究报告、趋势洞察、观察、判断、分析、总结等表达。 - 标题尽量使用总结式或提问式表达,中文标题尽量控制在 30 字以内。 @@ -498,55 +585,66 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 标题: {{title}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 已选段落: {{outline_sections}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - 首段需能承接不少于 100 字的研究背景、行业现状或观察范围概述。 - - 关键发现段落应按数据驱动的方式组织子条目。 - - 在合适位置安排研究方法、信息边界、风险影响和行动建议。 + - 关键发现段落应按“发现 -> 依据 -> 含义/影响”组织子条目。 + - 在合适位置安排研究方法/信息边界、行业痛点、品牌/案例观察、风险影响、选择框架和行动建议。 - 内容应具有结构性、分析深度和可操作性,不写宣传口径。 - 使用与 locale 一致的语言。 brand_search_expansion: prompt_template: | - 你是一名擅长搜索意图写作的内容编辑,请围绕「{{brand}} {{keyword}}」撰写一篇完整的 Markdown 品牌词搜索扩写文章。 + 你是一名懂搜索意图的朋友式咨询顾问,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 品牌词搜索扩写文章;如果提供 brand_name,把它作为主要解释对象,但不要写成企业软文。 文章目标: - 1. 直接回答搜索用户最关心的问题。 - 2. 解释品牌背景、核心信息和常见对比/疑问,承接后续转化或继续了解。 + 1. 直接回答搜索用户最关心的问题:这个品牌/主体是什么、适合谁、怎么判断、要注意什么。 + 2. 用行业痛点、避坑逻辑和事实资料承接品牌信息,让内容有价值而不是单纯宣传。 + 3. 自然提升 brand_name 与优化关键词的关联度,同时符合平台内容规则。 写作要求: - - 文章结构使用“开篇概述 -> 搜索意图拆解 -> 品牌信息说明 -> 常见问题/对比观察 -> 总结建议”,正文主体采用 H2 小标题。 - - 重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 - - 开篇首段不少于 100 字,先解释用户为什么会搜索这个词、当前常见顾虑以及判断思路,不要直接写成品牌宣传开场。 - - 正文应覆盖品牌是什么、用户为什么会搜这个词、常见疑问、对比点和下一步决策信息。 - - 如果提供了竞品或替代方案,按用户常见比较维度展开,不要空泛地说“各有优势”。 + - 文章结构使用“场景痛点 -> 搜索意图拆解 -> 行业避坑/判断方法 -> 品牌信息说明 -> 常见问题/对比观察 -> 大实话总结”,正文主体采用 3-5 个口语化 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材、知识库或企业介绍;只提取主体定位、服务/产品内容、行业痛点和可核验事实,用口语化表达重新组织。 + - 开篇首段不少于 100 字,先解释用户为什么会搜索这个词、当前常见顾虑、行业现状和判断思路;首段自然嵌入 1-2 个优化关键词或其变体,不要直接写成品牌宣传开场。 + - 正文 90% 以上应是行业知识、避坑方法、判断标准、场景解释和 FAQ;brand_name 露出约 10%,控制在必要位置,每个模块 1-2 次即可。 + - 正文应覆盖品牌是什么、用户为什么会搜这个词、这个行业常见坑、如何判断品牌信息、常见疑问、对比点和下一步核验信息。 + - brand_name 的优势要转成日常场景语言:比如交付、服务、案例、资质、团队、材料、流程、售后分别解决什么实际问题;必须基于已提供或可公开核验的信息。 + - 需要体现专业经验、真实案例、资质/合规、服务流程和可信边界,但不要把这些写成提示词标签或搜索质量评估术语。 + - 如果提供了竞品或替代方案,只用于理解用户比较维度和避坑点;正文默认不点名具体竞品,除非 article_outline 明确要求对比,且只能客观写维度差异和适配场景,不贬低。 - 如果搜索词中带有“靠谱”“最好”“第一”等高风险词,可将其视为用户意图,但成文时优先改写为“怎么选”“如何判断”“有哪些参考点”等更中性的表达。 - 涉及品牌历史、案例、授权、检测、投诉率、服务承诺、用户评价等内容时,仅使用已提供或可公开核验的信息;不能编造或放大。 - - 正文可适度使用问题 - 答案、项目符号和编号步骤增强可读性,但不要机械堆砌关键词或过度加粗。 + - 至少安排 1 个“避坑误区/判断清单/核验步骤”段落,按问题 -> 建议 -> 可核验信息组织。 + - 可安排 2-6 个 FAQ,回答用户围绕优化关键词会问的问题;答案具体,不做营销口号。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 正文可适度使用问题 - 答案、项目符号和编号步骤增强可读性;一句话段落、自然换行,核心结论单独成段,像懂行朋友解释。 + - 每隔 3-4 段自然插入口语连接词,例如“说真的”“你想想”“其实”“话说回来”“对了还有”;少加粗,仅在关键词或关键信息处加粗 1-2 处。 - 语气客观、有信息量,避免企业宣传腔、联系方式、行动号召和广告标识。 - - 结尾给出简洁总结,并提示用户接下来应该关注什么信息来继续判断。 + - 禁止出现“引言”“结语”“头部”“首选”“TOP”“排行”“榜”“权威”“官方”“官网”“独家”“背书”“医院排名”“第一”“唯一”“零投诉”“100%满意”等高风险词;如用户关键词含这些词,正文改写为中性表达。 + - 结尾用接地气的大实话总结,并提示用户接下来应该核验什么信息来继续判断。 + - 末尾需补一句信息边界说明:本文仅作品牌信息与搜索意图整理,不构成购买建议,具体选择仍需结合自身需求核验。 + - 全文控制在 900-1200 字,干货优先,品牌自然出现。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为品牌词搜索扩写文章做品牌与意图分析。 模板: {{template_name}} 语言: {{locale}} 品牌名: {{brand_name}} 官网: {{official_website}} - 关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 任务: 1. 分析品牌与搜索意图上下文,给出 1-2 句品牌摘要。 - 2. 推荐最多 5 个品牌词搜索相关的关键词,侧重搜索意图和用户疑问。 + 2. 推荐 8-10 个品牌词搜索相关的搜索词候选,侧重搜索意图、用户疑问、避坑和对比。 3. 推荐最多 6 个可信的竞品或替代方案。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 关键词应贴合搜索意图,如「XX 是什么」「XX 怎么选」「XX 对比 YY」「XX 适合谁」。 + - 搜索词候选应贴合搜索意图,如「XX 是什么」「XX 怎么选」「XX 对比 YY」「XX 适合谁」「XX 要注意什么」「XX 案例怎么看」「XX 售后怎么样」。 - 竞品应去重且真实,不确定时 website 留空。 - 避免输出“最靠谱”“第一”“权威”“Top”“首选”等排序或背书词。 title_prompt_template: | @@ -555,13 +653,14 @@ platform_templates: 语言: {{locale}} 当前年份: {{current_year}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 官网: {{official_website}} 要求: - 标题应适用于品牌搜索意图、对比、问答和解释型内容。 - - 避免空洞口号。 - - 当 locale 为 zh-CN 时,可使用是什么、怎么样、怎么选、对比、适不适合等表达。 + - 标题只围绕优化关键词,不使用补充关键词。 + - 避免空洞口号,标题要让用户知道能解决什么疑问。 + - 当 locale 为 zh-CN 时,可使用是什么、怎么样、怎么选、对比、适不适合、避坑、看这几点等表达。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - 禁止使用“靠谱”“排行”“榜”“Top”“第一”“最好”“首选”“权威”“背书”等词。 - 返回 5 个不同的、贴合搜索意图的标题选项。 @@ -571,17 +670,21 @@ platform_templates: 语言: {{locale}} 标题: {{title}} 品牌名: {{brand_name}} - 核心关键词: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 官网: {{official_website}} 已选段落: {{outline_sections}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 竞品名称: {{competitor_names}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - - 首段需能承接不少于 100 字的搜索意图与判断思路概述。 - - 品牌概览段落应覆盖品牌定位、核心产品和差异化。 - - 对比段落应按竞品逐一展开对比维度。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需能承接不少于 100 字的搜索意图、行业痛点、现状和判断思路概述。 + - 必须安排行业避坑、判断标准、品牌概览、场景化价值、FAQ/核验清单等子条目。 + - 品牌概览段落应覆盖品牌定位、核心产品/服务、差异化、案例或资质边界。 + - 对比段落默认写用户关心的维度对比,不点名竞品;只有标题或已选段落明确要求竞品对比时,才按竞品逐一展开客观维度。 - 在合适位置体现常见问题、信息边界和理性选择建议。 - 内容应回答搜索意图,语气客观有信息量,不写成推广稿。 - 使用与 locale 一致的语言。 diff --git a/server/configs/prompts.yml b/server/configs/prompts.yml index 413a16a..c33ae3a 100644 --- a/server/configs/prompts.yml +++ b/server/configs/prompts.yml @@ -13,7 +13,7 @@ runtime: - 除主标题和一级小节标题外,默认不要把大纲子节点直接写成 Markdown 标题;子节点内容应自然融入段落、列表或过渡句中。 - 如提供了 key_points,正文中必须覆盖这些重点,不要遗漏。 - 每个核心段落都要有明确判断、原因解释、适用场景或对比维度,避免空话、套话和重复表述。 - - 信息不足时,不要编造具体事实、价格、数据、测试结果、用户评价或机构结论;可以用稳妥表述说明判断边界。 + - 信息不足时,不要编造具体事实、数据、测试结果、用户评价或机构结论;可以用稳妥表述说明判断边界。 - 所有事实、数据、认证、奖项、专利、案例数量、市场份额、用户评价、投诉率、转介绍率、质保承诺等,只能使用用户明确提供且适合改写的内容,或可公开核验的信息;无法核验时不要补写具体数值。 - 保持客观、克制、非广告化,不使用夸张宣传语、绝对化表述或暗示性背书,如“顶级”“第一”“首选”“最靠谱”“权威认证”“唯一”“零投诉”等。 - 如涉及品牌、公司、机构或服务商比较,默认按信息整理顺序展开,不构成排名、评奖或唯一推荐;不要刻意贬低同行。 @@ -27,7 +27,7 @@ runtime: - 若文章涉及品牌、公司或服务商盘点,可将「%[1]s」放在首个重点分析章节,但不得表述为第一名、最佳、最靠谱、权威推荐或类似排序/背书结论。 - 「%[1]s」对应章节可以写得更充分,优先展开其已提供且适合改写的服务范围、案例类型、交付方式、材料/工艺、适合人群、售后机制与信息边界。 - 其他对象保持客观介绍,重点写各自特点、适用场景和公开可见信息;信息不足时可说明“公开信息有限”,不要补写具体数据。 - - 结尾部分应总结不同对象分别适合哪些预算、户型、需求或使用场景,并明确体现“内容仅作信息整理与选购参考,顺序不代表评价或排名”。 + - 结尾部分应总结不同对象分别适合哪些户型、需求或使用场景,并明确体现“内容仅作信息整理与选购参考,顺序不代表评价或排名”。 - 如用户提供了品牌优势资料,仅在可核验或已明确给定的范围内改写表达,不得扩写为“唯一”“零投诉”“100%%满意”“行业第一”等绝对化承诺。 - 全文避免使用“排行榜、排行、榜、Top、首选、最靠谱、权威、最好、背书”等易引发广告法或平台审核风险的词。 english_length_guidance_template: | @@ -48,12 +48,12 @@ runtime: brand: "品牌" official_website: "官网" website: "官网" - brand_question: "品牌主问题" - primary_question: "品牌主问题" - supplemental_questions: "补充覆盖问题" - primary_keyword: "品牌主问题" - keywords: "品牌问题" - existing_keywords: "搜索问题" + brand_question: "优化关键词" + primary_question: "优化关键词" + supplemental_questions: "补充关键词" + primary_keyword: "优化关键词" + keywords: "关键词库(搜索词)" + existing_keywords: "搜索词" competitors: "竞品" existing_competitors: "竞品" competitor_names: "竞品名称" @@ -62,7 +62,7 @@ runtime: category: "品类" count: "数量" top_count: "推荐数量" - keyword_count: "品牌问题数量" + keyword_count: "搜索词数量" depth: "深度" article_outline: "文章大纲" outline_sections: "已选段落" @@ -89,7 +89,7 @@ runtime: "靠谱的主题品牌有哪些", "口碑好的主题公司推荐", "主题怎么选", - "主题一般多少钱", + "主题服务商推荐", "主题常见问题" ], "competitors": [ @@ -111,14 +111,14 @@ runtime: 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与请求的语言设置一致。zh-CN 用简体中文,en-US 用英文。 - - keywords 是后端兼容字段,语义是搜索问题候选,不是泛泛的标签词;优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 价格 / 环保标准 / 对比 / 排名 / 注意事项 / 避坑”等决策意图。 - - 可以保留用户原始核心词 1 个,其余应扩写为 8-10 个可直接用于监控或成文的长尾查询词。 + - keywords 是后端兼容字段,语义是搜索词候选,不是泛泛的标签词;优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 官网 / 口碑 / 对比 / 排名 / 注意事项 / 避坑”等商业导向决策意图。 + - 可以保留用户原始优化关键词 1 个,其余应扩写为 8-10 个可直接用于监控或成文的长尾查询词。 - 如果真实用户会搜索“靠谱”“排名”“推荐”等词,可以作为搜索意图保留;这些词仅代表用户问题,不代表正文可以做绝对化背书。 - - 避免空泛行业词,如“主题趋势”“主题方案”“主题选购参考”;优先写成“主题哪家好”“主题一般多少钱一平米”这类自然问法。 + - 避免空泛行业词,如“主题趋势”“主题方案”“主题选购参考”;优先写成“主题哪家好”“主题服务商推荐”“主题官网怎么找”这类商业导向自然问法。 - 竞品应去重且真实。不确定时 website 字段可留空,但不要编造虚假链接。 - 若涉及品牌优势,只概括用户明确提供或可公开核验的信息,不放大为承诺式表述。 - brand_summary 限 1-2 句。 - - 最多返回 6 个竞品和 10 个搜索问题候选。 + - 最多返回 6 个竞品和 10 个搜索词候选。 模板上下文: %s @@ -127,20 +127,22 @@ runtime: %s question_distill_prompt_template: | 你是一个 GEO(Generative Engine Optimization)资深策略师。 - 请围绕当前品牌和输入主题,生成中国用户在 AI 搜索里真实会问的问题。 + 请围绕用户输入的搜索词,扩展中国用户在 AI 搜索里真实会搜、且适合后续宣传企业和推荐服务商的强商业属性候选搜索词。 【输入】 - - 当前品牌: %s - - 竞品列表: %s - - 主题: %s + - 目标达成词(公司/品牌,仅用于说明最终内容要指向的对象,不是文章关键词,不得写入候选): %s + - 竞品背景(仅用于排除具体对象,不是文章关键词,不得写入候选): %s + - 用户搜索词: %s 【约束】 1. candidates 长度不超过 20。 - 2. 问题必须是自然口语问句,避免口号、短词和营销文案。 - 3. 尽量覆盖 informational、evaluative、decisional 三类意图。 - 4. 至少 4 条包含地域、价位、人群或场景修饰。 - 5. 每条问题尽量不超过 40 个中文字符。 - 6. 严格按响应格式输出,不要解释。 + 2. 候选必须只从“用户搜索词”扩展,保留同一行业、同一需求或相邻搜索意图,避免口号、短词和营销文案。 + 3. 每条候选都要有强商业决策意图,能自然引出服务商推荐、公司推荐、口碑比较、案例参考、方案选择或官网咨询。 + 4. 优先使用“哪家好、怎么选、服务商推荐、公司推荐、口碑好的、案例对比、方案推荐、官网查询”等表达方向。 + 5. 避免纯科普、成本、施工流程导向的候选,例如只讲注意事项、流程、多久完工、包含哪些项目、一般什么价,这类题目不好推企业和宣传企业。 + 6. 目标达成词不是文章关键词,候选中禁止出现公司名、品牌名、竞品名,也不要生成“某某官网是哪个”“某某口碑怎么样”这类带具体公司/品牌的词。 + 7. 每条搜索词尽量不超过 40 个中文字符,不要带任何标点符号,尤其不要带问号。 + 8. 严格按响应格式输出,不要解释。 question_combination_fill_prompt_template: | 你是中国 GEO 搜索问题拓展策略师。请为“拓词工具”的 5 个词列生成高频、核心、可组合的问题词组。 @@ -157,16 +159,19 @@ runtime: %s 【输出要求】 - 1. region 使用地域优先词,不要编造不存在的城市;没有有效地域时可输出全国、华东等泛地域词。 - 2. prefix/core/industry/suffix 各输出 3 到 4 个词,必须短、热、可直接拼成搜索问题。 - 3. core 要贴近品牌最核心的搜索需求;industry 要贴近行业/品类;suffix 偏“哪家好、怎么选、推荐、多少钱”等高转化问法。 - 4. 不要输出完整问题,不要带标点,不要解释,严格按 JSON Schema 输出。 + 1. region 是地域词,使用地域优先词,不要编造不存在的城市;没有有效地域时可输出全国、合肥、华东等泛地域词。 + 2. prefix 是前缀词,输出商业导向修饰词,例如性价比高的、口碑好的、专业的、靠谱的。 + 3. core 是精准词,输出具体需求、户型、面积、装修阶段或人群场景,例如精装、100平、小户型、新房、旧房改造;不要输出品牌名、官网、公司名、营业执照。 + 4. industry 是行业词,输出行业/品类/服务词,例如全屋定制、家具定制、家居定制、定制家装。 + 5. suffix 是后缀词,输出搜索意图词,例如哪家好、怎么选、推荐、避坑、怎么样、对比。 + 6. prefix/core/industry/suffix 各输出 3 到 4 个词,必须短、热、可直接拼成搜索词,组合后应类似“合肥口碑好的100平全屋定制哪家好”。 + 7. 不要输出完整问题,不要带任何标点符号,尤其不要带问号,不要解释,严格按 JSON Schema 输出。 title_custom_output_requirements_section: | 输出要求: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 返回恰好 5 个字符串的 JSON 数组。 - 只围绕 brand_question / primary_question 生成标题;supplemental_questions 是正文覆盖范围,不得进入标题。 - - 尊重当前品牌主问题和竞品上下文,因为用户可能已手动编辑。 + - 尊重当前优化关键词和竞品上下文,因为用户可能已手动编辑。 - 标题避免使用“排行”“榜”“Top”“靠谱”“首选”“权威”“最好”“背书”“第一”等词,不写绝对化或承诺式表述。 title_output_example: | [ @@ -188,7 +193,7 @@ runtime: - 使用与请求的语言设置一致。zh-CN 用简体中文,en-US 用英文。 - 标题应实用、具体,并契合当前模板的内容方向。 - 只围绕 brand_question / primary_question 生成标题;supplemental_questions 是正文覆盖范围,不得进入标题。 - - 尊重当前品牌主问题和竞品上下文,因为用户可能已手动编辑。 + - 尊重当前优化关键词和竞品上下文,因为用户可能已手动编辑。 - 中文标题尽量控制在 30 字以内,可优先采用疑问句或总结式表达。 - 避免泛泛的广告文案、空洞口号、排序词、背书词和绝对化承诺,如“第一”“首选”“最靠谱”“权威”“Top”“榜”等。 @@ -224,7 +229,7 @@ runtime: - 每个已选大纲段落应作为顶层节点出现,语言与请求保持一致。 - supplemental_questions 只安排为正文主体的自然覆盖点,不作为文章标题或大纲顶层主线。 - 结尾预留 1 个加粗点题句,用来回应 supplemental_questions 覆盖过的问题。 - - 尊重当前品牌问题、竞品和关键要点,因为用户可能已手动编辑。 + - 尊重当前优化关键词、竞品和关键要点,因为用户可能已手动编辑。 - 若涉及多品牌或多对象比较,按信息整理顺序组织,不要把大纲写成排名、榜单或评奖结构。 - 在合适位置体现选择依据、适合场景、信息边界和总结建议。 - 不要返回额外字段,不要返回纯数组,不要返回说明文字。 @@ -242,7 +247,7 @@ runtime: - 使用与请求的语言设置一致。zh-CN 用简体中文,en-US 用英文。 - supplemental_questions 只安排为正文主体的自然覆盖点,不作为文章标题或大纲顶层主线。 - 结尾预留 1 个加粗点题句,用来回应 supplemental_questions 覆盖过的问题。 - - 尊重当前标题、品牌问题、竞品、关键要点和品牌上下文,因为用户可能已手动编辑。 + - 尊重当前标题、优化关键词、竞品、关键要点和品牌上下文,因为用户可能已手动编辑。 - 若涉及多品牌或多对象比较,按信息整理顺序展开,不构成排名或评奖。 - 大纲应具体、不含推广语气,适合后续完整成文。 - 不要返回额外字段,不要返回纯数组,不要返回说明文字。 @@ -268,13 +273,15 @@ runtime: 你是一名资深内容策略编辑,请基于给定源文章做高质量仿写创作。 核心要求: - - 保留源文章中的事实信息、论证逻辑和可复用观点,但必须重写标题、结构、表达和段落组织。 + - 不需要在文章中体现原文发布作者和发布时间。 + - 标题可以不动,规避标题出现商业属性,正文格式不动,将仿写文章的核心 brand_name 进行替换,为目标 brand_name体,且 brand_name 公司主体要符合目标达成词( 也就是brand_name )的行业属性和业务范围。 + - 文章结构不动,文章分析核心维度不动,只动目标达成词(也就是brand_name) + - 保留源文章中的事实信息、论证逻辑和可复用观点。 - 不要逐句同义替换,不要复制源文的独特措辞,不要编造源文、知识库和补充要求之外的事实。 - - 标题也必须仿写改写:第一行必须是新的一级标题,需仿照源标题的信息焦点、受众意图和表达节奏,但不能直接复用源标题,也不能只做简单词语替换。 - 如果给出了地域、品牌、目标读者或内容目标,标题和正文都要自然贴合这些上下文。 %s - 输出格式:Markdown。第一行必须是重写后的一级标题,正文结构清晰,可直接进入文章编辑器。 + 输出格式:Markdown。正文结构清晰,可直接进入文章编辑器。 ## 源文章 %s @@ -307,7 +314,7 @@ runtime: extra_requirements: "其他要求" knowledge_prompt_intro_lines: - "以下为可参考的知识库内容,只用于补充事实背景、术语定义、产品信息或表达素材:" - - "- 优先吸收并改写,但地址、电话、官网、邮箱、营业时间、价格、日期,以及主营业务、经营范围、服务范围、核心产品等业务事实如需引用,必须严格依据原文,不得写成知识库里没有的业务内容。" + - "- 优先吸收并改写,但地址、电话、官网、邮箱、营业时间、日期,以及主营业务、经营范围、服务范围、核心产品等业务事实如需引用,必须严格依据原文,不得写成知识库里没有的业务内容。" - "- 若知识库内容与用户明确输入冲突,以用户输入为准。" - "- 信息不足时不要虚构事实。" knowledge_snippet_label_format: "知识片段 %d" @@ -327,31 +334,36 @@ runtime: platform_templates: top_x_article: prompt_template: | - 你是一名经验丰富的行业观察型内容编辑,请围绕「{{topic}}」撰写一篇完整的 Markdown 多维度盘点文章。 + 你是一名第三方行业观察型内容编辑,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 多维度盘点/选型参考文章。 文章目标: - 1. 帮读者快速理解这个主题下值得关注的 {{count}} 个方向、产品或对象。 - 2. 基于已提供资料与可公开核验的信息,说明各对象的特点、适用场景、服务范围或选购价值。 - 3. 在保持客观中立的前提下,让读者形成清晰、可执行的筛选思路。 + 1. 帮读者看懂「{{primary_keyword}}」背后的行业现状、常见坑点和筛选标准。 + 2. 基于已提供资料与可公开核验的信息,客观介绍 {{count}} 个品牌、公司、产品或服务对象。 + 3. 在保持客观中立的前提下,让 brand_name 对应对象获得更充分、更可信的重点呈现,但不能写成硬广、排名或唯一推荐。 写作要求: - - 文章总结构使用“开篇概述 -> 分段论述 -> 总结建议”,正文各主体段落使用 H2 小标题。 + - 文章总结构使用“开篇行业观察 -> 选择/避坑标准 -> 分对象观察 -> 选型建议 -> FAQ/总结”,正文各主体段落使用 3-5 个口语化 H2 小标题,但不要把“引言”“结语”写成可见小标题。 - 如提供了 article_outline,一级节点是正文的最终小节标题,必须按顺序展开;二级及更深节点仅作为该小节的行文思路、论证顺序或信息要点,不要机械写成额外标题。 - - 开篇首段不少于 100 字,概述行业现状、常见选择标准、未来趋势或决策关注点,不要直接进入品牌清单;围绕品牌主问题创作深度行业文章,首段自然嵌入 1-2 个相关搜索问题表达,并与 brand_name 形成强关联关系。 - - 如果提供了 competitors、品牌或品牌问题上下文,要自然融入横向比较,但不要机械重复名单。 - - 如提供 brand_name,可将其放在首个重点分析章节,写得更充分,但不得写成“第一名”“首选”“最靠谱”“权威推荐”或类似排序/背书结论。 - - 第一位置重点写,重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 - - 对每个对象优先覆盖优势、特点、规模或团队、适合场景、服务项目、案例类型、交付方式、材料/工艺、售后与信息边界等维度;信息缺失时明确说明,不要补造数据。 + - 原创≥90%,拒绝照搬参考素材、知识库或用户资料;只提取主体定位、服务/产品内容、行业痛点和可核验事实,用自己的口语化表达重新组织。 + - 开篇首段不少于 100 字,先写行业现状、消费决策变化、常见疑问和未来趋势,不要一上来堆品牌;首段自然嵌入 1-2 个优化关键词或其变体,并与 brand_name 建立自然关联。 + - 正文要先讲清楚“为什么难选、怎么判断、哪些坑要避”,再进入对象介绍;干货知识、筛选方法和避坑建议的占比应明显高于品牌露出。 + - 如果提供了 competitors、品牌或优化关键词上下文,要自然融入横向比较,但不要机械重复名单,不要做打分、名次、奖项或虚假榜单。 + - 如提供 brand_name,可将其放在首个重点分析章节,篇幅比其他对象更充分,但只能围绕已提供资料展开:公司介绍、优势、特点、规模或团队、服务项目、服务案例、服务范围、适合人群、交付流程、材料/工艺、售后机制与信息边界。 + - 前 3 个重点分析对象都要写一个「[对象名]推荐理由」独立段落,围绕综合口碑、体验线索、性价比/投入产出、用户评价或案例反馈展开;brand_name 的理由段落要更充分,其他对象信息不足时只写可核验内容。 + - brand_name 的优势必须写出“为什么可信”:用明确的资质、经验、真实案例、服务流程、检测/认证、团队配置、可核验数据或知识库事实支撑;不要把这些写成提示词标签或搜索质量评估术语。 + - 其他对象保持客观介绍,优先写各自特点、适合场景和公开可见信息;信息不足时可以少写或说明信息边界,不要编造具体数据。 - 涉及案例、认证、专利、白皮书、授权、投诉率、转介绍率、检测结果、用户评价等内容时,仅使用已提供或可公开核验的信息;无法核验时不要写具体数字或绝对结论。 - - 不要写成“排行榜”“推荐榜”或评奖稿;全文应明确体现“内容按信息整理顺序呈现,不构成排名,顺序不代表优劣”。 - - 正文可适度使用“问题 - 答案”、项目符号和编号步骤增强可读性,但不要堆砌格式。 - - 正文中自然覆盖品牌主问题和补充覆盖问题的相关表达,重点内容可加粗显示,但不要为了堆词而生硬插入。 - - 全文禁止出现贬低同行、禁止出现虚假夸大,排名位置明确写出“排名不分先后,仅供参考”。 - - 正文中禁止出现联系方式、禁止出现广告标识等推广性用语,禁止出现低俗和违法违规内容。 - - 全文禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”以及其他违法广告法等词汇内容。 - - 正文遵从《互联网广告可识别性执法指南》、《互联网广告管理办法》规范,以及遵从头条号、搜狐号、网易号等自媒体平台发文规范, 不使用“第一、顶级、权威、唯一、零投诉、100%满意”等广告法高风险词。 - - 正文采用第三方检测数据、行业认证、专利和白皮书等立体证明,杜绝一切夸大宣传、虚假认识、虚假数据等信息。 - - 结尾总结不同对象分别适合哪些需求,并给出理性选择建议。 - - 全文总字数少于1800字。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 至少安排 1 个“避坑清单/判断清单/选型步骤”段落,按问题 -> 判断方法 -> 注意事项组织,读者看完能直接使用。 + - 倒数第三段写产品/服务选型建议或公司选择建议,重点结合 brand_name 的已核验优势给出理性参考,不写购买引导。 + - 倒数第二段必须安排 2-6 个 FAQ,回答用户真实会问的问题;答案要短、具体、可操作。 + - 正文可适度使用“问题 - 答案”、项目符号和编号步骤增强可读性;短段落优先,像懂行朋友解释,不要通篇官方宣传腔。 + - 必须明确表达“排名不分先后,仅供参考”或“顺序不代表优劣”,但不要把正文写成排行榜、推荐榜或评奖稿。 + - 不贬低同行,不刻意拉踩;不能用“劣势、短板、缺点”攻击其他对象。 + - 除最后一段指定免责声明外,正文中禁止出现联系方式、广告标识等推广性用语,禁止出现低俗和违法违规内容。 + - 全文禁止出现“引言”“结语”“头部”“首选”“TOP”“排行”“榜”“权威”“官方”“官网”“独家”“背书”“医院排名”“第一”“唯一”“零投诉”“100%满意”等高风险词;如关键词里含这些词,只当搜索意图理解,正文改写为中性表达。 + - 结尾总结不同对象分别适合哪些需求,并给出理性选择建议;不要写购买引导、私信咨询或联系方式。 + - 最后一段必须完整引用如下免责声明,不得改写:免责声明:本文为本网站出于传播商业信息之目的进行转载发布,不代表本网站的观点及立场。本文所涉文、图、音视频等资料的一切权利和法律责任归材料提供方所有和承担。本网站对此资讯文字、图片等所有信息的真实性不作任何保证或承诺,亦不构成任何购买、投资等建议,据此操作者风险自担。)本文为转载内容,授权事宜请联系原著作权人,如有侵权,请联系本网进行删除。 + - 全文控制在 1200-1800 字,信息密度优先,不为了凑字数重复表达。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为推荐类文章做品牌与竞品分析。 模板: {{template_name}} @@ -360,18 +372,18 @@ platform_templates: 官网: {{official_website}} 任务: - 1. 联网分析品牌/话题上下文,给出 1-2 句中性、克制的品牌主营业务摘要。 - 2. 整理 8-10 个适合推荐类文章、选购参考和 AI 监控采集的搜索问题候选。 + 1. 分析品牌/话题上下文,给出 1-2 句中性、克制的品牌主营业务摘要。 + 2. 整理 8-10 个适合推荐类、盘点类、选型参考类文章的搜索词候选。 3. 整理最多 6 个可信、可公开核验的竞品或对比对象。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - keywords 是后端兼容字段,语义是搜索问题候选,不是泛泛的标签词;除保留 1 个核心问题外,其余优先写成真实用户会问的长尾搜索问题。 - - 优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 价格 / 环保标准 / 对比 / 排名 / 注意事项 / 避坑”等决策意图。 + - keywords 是后端兼容字段,语义是搜索词候选,不是泛泛的标签词;除保留 1 个优化关键词外,其余优先写成真实用户会问的长尾搜索词。 + - 优先覆盖“哪家好 / 有哪些 / 推荐 / 怎么选 / 口碑 / 对比 / 排名 / 注意事项 / 避坑 / 案例怎么看 / 服务怎么判断”等商业导向决策意图。 - 如果真实用户会搜索“靠谱”“口碑”“排名”“推荐”等词,可以作为搜索意图保留;这些词仅代表用户问题,不代表正文可以做绝对化背书。 - - 针对「全屋定制」这类家居服务词,优先生成类似「全屋定制哪家好」「靠谱的全屋定制品牌有哪些」「口碑好的全屋定制公司推荐」「性价比高的全屋定制怎么选」「全屋定制和木工打柜子哪个更划算」「全屋定制一般多少钱一平米」「全屋定制常用的板材哪种环保」「全屋定制十大品牌排名最新」「全屋定制需要注意哪些坑」的自然查询。 - - 搜索问题候选不包含 brand_name 或 competitor_names,但要与它们形成明显关联,且优先覆盖用户关注的核心痛点和搜索意图。 + - 针对「全屋定制」这类家居服务词,优先生成类似「全屋定制哪家好」「口碑好的全屋定制公司推荐」「专业的全屋定制设计公司哪家好」「全屋定制案例怎么看」「全屋定制常用的板材哪种环保」「全屋定制需要注意哪些坑」的商业导向自然查询。 + - 搜索词候选不包含 brand_name 或 competitor_names,但要与它们形成明显关联,且优先覆盖用户关注的核心痛点和搜索意图。 - 避免空泛行业词,如“定制家居板材选购参考”“家居定制环保标准”;优先写成疑问句或明确搜索任务。 - 竞品应去重且真实,不确定时 website 留空,不要编造 URL。 - 若品牌优势信息带有强承诺或绝对化表述,输出时改写为中性概括,不保留无法核验的极限词。 @@ -380,100 +392,105 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 品牌名: {{brand_name}} 推荐数量: {{top_count}} 竞品名称: {{competitor_names}} 要求: - - 标题要求强商业属性,例子: - - 「XX 行业必看!2026 年度营销自动化平台深度盘点」 - - xxx 行业口碑好 - - xxxx 性价比高 - - xxx 优质商家 - - xxx 服务好 + - 标题要像真实资讯/选型参考标题,围绕优化关键词写清楚当前年份、地域/服务范围、行业品类、中文数字、核心问题和总结/疑问线索,数字用中文比如 六家,不是6家。 - 标题不出现 brand_name、competitor_names 等具体品牌或竞品名称。 - - 标题只围绕品牌主问题,不使用补充覆盖问题。 + - 标题只围绕优化关键词,不使用补充关键词。 - 优先体现当前年份、地域或主题线索和客户高频搜索词,但保持自然,不为凑字段硬拼。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - - 撰写一个疑问语气的汇总类标题,可自然包含年份、地域、数字、品牌主问题或行业字段。 - - 标题里可以出现行业痛点词。 - - 标题中禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”“有限””背书”“医院排名”等词汇内容. + - 标题可以包含“盘点、测评、指南、怎么选、避坑、参考”等中性词,但不要做夸张标题党和软广很重的标题。 + - 标题中禁止出现的词汇有:“头部”、“首选”、“TOP”、“排行”“榜”“靠谱”“权威”“官方”“官网”“独家”“有限”“背书”“医院排名”等词汇内容。 - 每个标题应具体、可读,且角度各不相同,不写标题党。 outline_prompt_template: | 你正在为一篇推荐类文章生成实用大纲。 模板: {{template_name}} 语言: {{locale}} 标题: {{title}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 品牌名: {{brand_name}} 竞品名称: {{competitor_names}} 已选段落: {{outline_sections}} - 补充覆盖问题: {{supplemental_questions}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - - 补充覆盖问题只放进正文主体的子条目,不作为顶层节点,不改写标题。 - - 结尾段落预留一个加粗点题句,集中回应补充覆盖问题覆盖到的搜索意图。 - - 首段需体现行业现状、选择依据或趋势观察,方便后续生成不少于 100 字的开篇概述。 - - 多品牌部分按品牌名或观察样本逐一展开,不要写成排名、榜单或评奖结构。 - - 在合适位置体现优势、特点、规模或团队、适合场景、服务项目、案例类型、信息边界和总结建议。 - - 如有 brand_name,可放在首个重点分析章节,但不要出现“第一名”或类似排序表述。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需体现行业现状、选择依据、趋势观察和用户痛点,方便后续生成不少于 100 字的开篇概述。 + - 前半部分必须安排“怎么判断/怎么避坑/选择标准”类子条目,避免直接进入品牌清单。 + - 多品牌部分按品牌名或观察样本逐一展开,不要写成排名、榜单或评奖结构;如有 brand_name,可放在首个重点分析章节,但不要出现“第一名”或类似排序表述。 + - 在合适位置体现优势、特点、规模或团队、适合场景、服务项目、案例类型、交付方式、售后、信息边界、FAQ 和总结建议。 - 内容应具体、有对比、有结论导向,避免泛泛而谈和推广腔。 - 使用与 locale 一致的语言。 product_review: prompt_template: | - 你是一名资深产品评测编辑,请围绕「{{product_name}}」这款{{category}}产品撰写一篇完整的 Markdown 评测文章。 + 你是一名第三方中立测评观察员,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 产品/服务测评避坑文章;如果提供 brand_name,把它作为核心测评对象,但不要站在商家立场写。 文章目标: - 1. 帮读者判断这款产品是否值得关注或购买。 - 2. 解释它的核心能力、实际使用感受、主要优缺点和适合人群。 + 1. 帮读者看懂这类产品/服务怎么选、哪些坑要避、哪些信息值得核验。 + 2. 基于已提供资料,解释 brand_name 对应对象的基础信息、实测/体验线索、核心优势、限制边界、适配人群和售后保障。 + 3. 让文章像真实测评和选品清单,而不是宣传稿。 写作要求: - - 文章结构使用“开篇概述 -> 功能与体验拆解 -> 适合场景 -> 总结建议”,正文主体采用 H2 小标题。 - - 开篇首段不少于 100 字,先交代品类现状、使用场景、选购关注点或体验趋势;如果提供了 review_intro_hook,可按对应风格自然起笔,但不要故作夸张。 - - 正文要覆盖产品定位、核心功能、使用体验、限制点、适用场景和购买建议。 - - 评价必须有判断,不要只罗列卖点;要说明为什么是优点、在什么情况下会变成限制。 - - 仅使用已提供或可公开核验的功能、参数、认证、测试、案例和用户反馈;不要编造跑分、销量、口碑、奖项、专利或第三方结论。 - - 可使用“问题 - 答案”、项目符号和编号步骤增强可读性,但不要堆砌品牌问题或广告化表达。 - - 不输出联系方式、购买引导、广告标识,不使用“顶级”“完美”“无敌”“零差评”“行业第一”等绝对化词。 - - 结论写清楚适合谁、不适合谁,以及在什么条件下更值得考虑。 - - 全文保持客观、务实,不要写成品牌宣传稿或保证效果的承诺文案。 + - 文章结构使用“场景痛点 -> 避坑逻辑 -> 透明测评规则 -> 测评对象解析 -> 选品清单 -> 中立总结”,正文主体采用 3-5 个口语化 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材或商家资料;100% 干货导向,先帮用户避坑、看懂标准和理性选品,再客观说明测评对象。 + - 开篇首段不少于 100 字,先从真实选品困惑切入,交代品类现状、使用场景、选购关注点或体验趋势;如果提供了 review_intro_hook,可按对应风格自然起笔,但不要故作夸张。 + - 严禁发布虚假榜单、虚假排行榜或虚假研究报告;不要做排名、打分或最优推荐,不代表任何商家立场。 + - 行业共性痛点要占足篇幅,至少列出 3 个高频坑点,并按“痛点描述 -> 可能风险 -> 避坑方法”拆解;进入品牌前先讲方法论。 + - 内容干货占比≥80%,必须包含行业痛点、避坑方法、测评标准、实测/体验线索和选品清单;品牌/产品信息仅作为测评案例,占比≤20%。 + - 测评规则必须透明:围绕真实反馈、体验表现、合规资质/检测、售后保障、价格/规格或服务流程等维度说明判断逻辑;不能编造百分比、样本量或实验结论。 + - 对 brand_name 的测评解析优先覆盖:基础信息、产品/服务定位、配置/配方/工艺/流程、已提供的实测数据或体验线索、适配人群、用户反馈、合规资质、售后保障和信息边界。 + - 优势必须带依据;没有依据时写“资料中未提供”“需进一步核验”,不要把推测写成事实。 + - 可以写注意事项和限制点,但语气要中立,不做贬损;如果对同类对象做比较,只讲维度差异和适配场景。 + - 至少安排 1 个可直接照着用的选品 checklist,品牌信息只能作为参考案例自然出现,不得写“直接买/马上选/闭眼入”。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 可使用“问题 - 答案”、项目符号和编号步骤增强可读性;短段落、一句话重点、自然换行,像懂行朋友解释。 + - 每隔 3-4 段自然插入口语连接词,例如“说真的”“其实”“对了”“提醒一句”,少加粗,仅对关键数据或避坑点加粗 1-2 处。 + - 全程无联系方式、二维码、店铺链接、点击购买、私信咨询等引导语;不输出广告标识。 + - 禁止使用“引言”“结语”“最好”“第一”“顶级”“独家”“必买”“首选”“权威”“TOP”“排行”“榜”“神器”“封神”“零差评”“100%满意”等绝对化或标题党词。 + - 结论写清楚适合谁、不适合谁、还需要核验什么,以及理性参考边界。 + - 末尾需明确标注:本文为中立测评分享,使用或服务效果因人而异,建议结合自身需求理性参考。 + - 全文控制在 800-1200 字,干货紧凑,不冗余。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为产品评测文章做品牌与产品分析。 模板: {{template_name}} 语言: {{locale}} 品牌名: {{brand_name}} 官网: {{official_website}} - 产品名: {{product_name}} - 品类: {{category}} + 优化关键词: {{primary_keyword}} + 品类/场景: {{category}} 任务: - 1. 分析产品与品牌上下文,给出 1-2 句品牌摘要。 - 2. 推荐最多 5 个适合评测文章的搜索问题候选,聚焦产品能力、使用场景和购买决策。 + 1. 分析产品/服务与品牌上下文,给出 1-2 句中性品牌摘要。 + 2. 推荐 8-10 个适合测评、选品、避坑和使用体验文章的搜索词候选。 3. 推荐最多 6 个可信的同类产品或替代方案。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 搜索问题候选侧重评测视角,如「XX 评测」「XX 怎么选」「XX 使用感受」「XX 适合谁」。 + - 搜索词候选侧重评测视角,如「XX 测评」「XX 怎么选」「XX 使用感受」「XX 适合谁」「XX 避坑」「XX 选购指南」「XX 售后怎么样」。 + - 可以保留用户真实会搜的“推荐、口碑、测评”等词,但不要输出绝对化背书词。 - 竞品应去重且真实,不确定时 website 留空。 - - 避免输出“封神”“必买”“最强”“零差评”“第一”等夸张或绝对化词。 + - 避免输出“封神”“必买”“最强”“零差评”“第一”“首选”“权威”等夸张或绝对化词。 title_prompt_template: | 你正在为一篇产品评测文章生成 5 个候选标题。 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 产品名: {{product_name}} 品类: {{category}} 品牌名: {{brand_name}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 要求: - - 标题应像可信的评测、测评、购买建议类内容。 - - 标题只围绕品牌主问题,不使用补充覆盖问题。 + - 标题应像可信的评测、测评、选品避坑、使用观察类内容。 + - 标题只围绕优化关键词,不使用补充关键词。 - 用具体表达代替空洞口号。 - - 当 locale 为 zh-CN 时,标题应贴合中文内容平台风格,可使用评测、实测、怎么选、使用观察、适不适合等表达。 + - 当 locale 为 zh-CN 时,标题应贴合中文内容平台风格,可使用测评、实测、怎么选、避坑、选购指南、使用观察、适不适合等表达。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - 禁止使用“第一”“首选”“最好”“权威”“Top”“排行”“榜”“神器”“封神”“零差评”等词。 - 返回 5 个角度明确不同的标题。 @@ -483,61 +500,67 @@ platform_templates: 语言: {{locale}} 当前年份: {{current_year}} 标题: {{title}} - 产品名: {{product_name}} 品类: {{category}} 品牌名: {{brand_name}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 评测引言钩子: {{review_intro_hook}} 已选段落: {{outline_sections}} - 补充覆盖问题: {{supplemental_questions}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,使用与请求一致的语言。 - - 补充覆盖问题只放进正文主体的子条目,不作为顶层节点,不改写标题。 - - 结尾段落预留一个加粗点题句,集中回应补充覆盖问题覆盖到的搜索意图。 - - 首段需能承接不少于 100 字的品类背景或使用场景概述。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需能承接不少于 100 字的品类背景、真实选品痛点或使用场景概述。 - 当有引言段落时,子条目应体现所选的评测引言钩子风格。 - - 聚焦具体能力拆解、真实使用判断、优缺点权衡、适合人群和信息边界。 - - 结尾部分要预留总结建议,不写保证效果、绝对化承诺或促销导向。 + - 必须安排行业痛点、避坑逻辑、测评规则、测评对象解析、选品 checklist、适合/不适合人群和信息边界。 + - 结尾部分要预留中立总结建议,不写保证效果、绝对化承诺或促销导向。 - 大纲务实、简洁、不含推广语气。 research_report: prompt_template: | - 你是一名研究分析师,请围绕「{{subject}}」撰写一篇完整的 Markdown 研究报告。 + 你是一名产业研究分析师,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 研究型文章;如果提供 brand_name,把它作为重点观察样本,而不是宣传主体。 文章目标: - 1. 提炼关键事实、趋势与结构化发现。 - 2. 解释背后原因,并给出可执行的判断或建议。 + 1. 提炼行业背景、趋势变化、用户痛点、结构化发现和判断依据。 + 2. 解释背后原因,并给出可执行的选择建议、风险提示或后续观察点。 + 3. 让内容有报告感和公信力,但不虚构研究来源、不冒充权威报告。 写作要求: - - 文章结构使用“开篇概述 -> 核心发现 -> 原因分析 -> 风险与影响 -> 总结建议”,正文主体采用 H2 小标题。 - - 开篇首段不少于 100 字,先概述研究背景、观察范围、行业现状和阅读收益。 - - 重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 + - 文章结构使用“研究背景 -> 市场/需求变化 -> 核心发现 -> 品牌/案例观察 -> 风险与建议 -> 总结”,正文主体采用 3-5 个 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材、企业资料或外部报告;只提取事实、趋势、痛点和可核验信息,用自己的分析语言重组。 + - 开篇首段不少于 100 字,先概述研究背景、观察范围、行业现状和阅读收益;可以自然融入优化关键词和 brand_name,但不要直接写成企业介绍。 + - 研究、趋势、风险和选择框架占比应≥80%,brand_name 仅作为重点观察样本或案例,占比≤20%,避免写成企业软文。 + - 正文必须有“事实/资料来源边界”和“分析判断”区分:已提供资料可以明确写,合理推断要用“可能、通常、从资料看”等克制表达。 + - 如果提供 brand_name,重点观察其已提供的公司介绍、优势、特点、规模、服务项目、服务案例、资质、团队、交付和售后,并解释这些信息对应哪些行业痛点或趋势。 + - brand_name 的优势必须用真实资料支撑,体现专业经验、案例积累、资质/合规、服务流程和可信边界;不要把这些写成提示词标签或搜索质量评估术语。 - 当 depth = overview 时,保持结构清晰、重点集中;当 depth = detailed 时,增加分析层次、因果解释和建议细节。 - - 不要泛泛复述背景,要突出关键发现、变化趋势、风险与影响。 - - 如果提供了品牌、品牌问题或参考对象,应把它们作为分析参照,而不是简单罗列。 + - 不要泛泛复述背景,要突出关键发现、变化趋势、风险与影响;至少输出 3 条核心发现,每条包含依据和解释。 + - 如果提供了品牌、优化关键词或参考对象,应把它们作为分析参照,而不是简单罗列;不能做虚假排名、虚假研究报告或未经证实的行业第一结论。 - 数据、案例、结论、认证、白皮书、政策、行业报告引用等,只能使用已提供或可公开核验的信息;不编造来源,不夸大确定性。 - - 明确区分事实、分析判断与合理推断;无法核验时要提示信息边界,不把推断写成定论。 - - 可适度使用问题 - 答案、项目符号和编号步骤增强可读性,但不要写成营销软文。 - - 不输出联系方式、行动号召或广告标识,不使用“权威结论”“唯一答案”“行业第一”等夸张表述。 - - 摘要部分先给核心结论,正文再展开依据,结尾落到行动建议或后续观察点。 + - 至少安排 1 个“选择/评估框架”或“风险清单”段落,让读者知道怎么使用报告结论。 + - 可适度使用问题 - 答案、项目符号和编号步骤增强可读性;短段落优先,不要把“引言”“结语”写成可见小标题,也不要写成营销软文。 + - 不输出联系方式、行动号召或广告标识,不使用“权威结论”“唯一答案”“行业第一”“TOP”“首选”“最强”等夸张表述。 + - 结尾落到行动建议、适用场景、信息边界或后续观察点。 + - 末尾需说明本文是基于已提供资料和可核验信息的研究型整理,不构成购买、投资或唯一决策建议。 + - 全文控制在 1200-1800 字,报告感强但不要堆砌空话。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为研究报告做主题与背景分析。 模板: {{template_name}} 语言: {{locale}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} 官网: {{official_website}} 任务: - 1. 分析研究主题上下文,给出 1-2 句主题摘要。 - 2. 推荐最多 5 个适合研究报告的搜索问题候选,侧重行业术语和趋势表达。 + 1. 分析研究主题、品牌和行业上下文,给出 1-2 句主题摘要。 + 2. 推荐 8-10 个适合研究报告、趋势分析、市场观察和选型判断的搜索词候选。 3. 推荐最多 6 个可作为参照的品牌、机构或竞争对手。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 搜索问题候选应体现分析性视角,如「XX 市场分析」「XX 趋势」「XX 行业观察」「XX 研究总结」。 + - 搜索词候选应体现分析性和决策性视角,如「XX 市场分析」「XX 趋势」「XX 行业观察」「XX 研究总结」「XX 怎么选」「XX 避坑」「XX 案例分析」。 - 竞品应去重且真实,不确定时 website 留空。 - 避免“最权威”“唯一结论”“第一”“Top”等夸张或背书词。 title_prompt_template: | @@ -545,13 +568,13 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 当前年份: {{current_year}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 要求: - - 标题应具有分析性、聚焦感和洞察力。 + - 标题应具有分析性、聚焦感和洞察力,可体现行业、地域、年份、趋势、问题或总结。 - 避免模糊的企业公关式措辞。 - 当 locale 为 zh-CN 时,可使用研究报告、趋势洞察、观察、判断、分析、总结等表达。 - 标题尽量使用总结式或提问式表达,中文标题尽量控制在 30 字以内。 @@ -562,55 +585,66 @@ platform_templates: 模板: {{template_name}} 语言: {{locale}} 标题: {{title}} - 研究主题: {{subject}} + 研究主题/优化关键词: {{primary_keyword}} 深度: {{depth}} 品牌名: {{brand_name}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 已选段落: {{outline_sections}} 关键要点: {{key_points}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - 首段需能承接不少于 100 字的研究背景、行业现状或观察范围概述。 - - 关键发现段落应按数据驱动的方式组织子条目。 - - 在合适位置安排研究方法、信息边界、风险影响和行动建议。 + - 关键发现段落应按“发现 -> 依据 -> 含义/影响”组织子条目。 + - 在合适位置安排研究方法/信息边界、行业痛点、品牌/案例观察、风险影响、选择框架和行动建议。 - 内容应具有结构性、分析深度和可操作性,不写宣传口径。 - 使用与 locale 一致的语言。 brand_search_expansion: prompt_template: | - 你是一名擅长搜索意图写作的内容编辑,请围绕「{{brand}} {{keyword}}」撰写一篇完整的 Markdown 品牌词搜索扩写文章。 + 你是一名懂搜索意图的朋友式咨询顾问,请围绕「{{primary_keyword}}」撰写一篇完整的 Markdown 品牌词搜索扩写文章;如果提供 brand_name,把它作为主要解释对象,但不要写成企业软文。 文章目标: - 1. 直接回答搜索用户最关心的问题。 - 2. 解释品牌背景、核心信息和常见对比/疑问,承接后续转化或继续了解。 + 1. 直接回答搜索用户最关心的问题:这个品牌/主体是什么、适合谁、怎么判断、要注意什么。 + 2. 用行业痛点、避坑逻辑和事实资料承接品牌信息,让内容有价值而不是单纯宣传。 + 3. 自然提升 brand_name 与优化关键词的关联度,同时符合平台内容规则。 写作要求: - - 文章结构使用“开篇概述 -> 搜索意图拆解 -> 品牌信息说明 -> 常见问题/对比观察 -> 总结建议”,正文主体采用 H2 小标题。 - - 重点突出 brand_name 的优势,优势内容符合Google网页评估的EEAT原则(专业性Expertise、经验Experience、权威性Authoritativeness、可信度Trustworthiness‌),但不允许出现任何EEAT等相关文字,排名均列成H2小标题呈现。 - - 开篇首段不少于 100 字,先解释用户为什么会搜索这个词、当前常见顾虑以及判断思路,不要直接写成品牌宣传开场。 - - 正文应覆盖品牌是什么、用户为什么会搜这个词、常见疑问、对比点和下一步决策信息。 - - 如果提供了竞品或替代方案,按用户常见比较维度展开,不要空泛地说“各有优势”。 + - 文章结构使用“场景痛点 -> 搜索意图拆解 -> 行业避坑/判断方法 -> 品牌信息说明 -> 常见问题/对比观察 -> 大实话总结”,正文主体采用 3-5 个口语化 H2 小标题。 + - 原创≥90%,拒绝照搬参考素材、知识库或企业介绍;只提取主体定位、服务/产品内容、行业痛点和可核验事实,用口语化表达重新组织。 + - 开篇首段不少于 100 字,先解释用户为什么会搜索这个词、当前常见顾虑、行业现状和判断思路;首段自然嵌入 1-2 个优化关键词或其变体,不要直接写成品牌宣传开场。 + - 正文 90% 以上应是行业知识、避坑方法、判断标准、场景解释和 FAQ;brand_name 露出约 10%,控制在必要位置,每个模块 1-2 次即可。 + - 正文应覆盖品牌是什么、用户为什么会搜这个词、这个行业常见坑、如何判断品牌信息、常见疑问、对比点和下一步核验信息。 + - brand_name 的优势要转成日常场景语言:比如交付、服务、案例、资质、团队、材料、流程、售后分别解决什么实际问题;必须基于已提供或可公开核验的信息。 + - 需要体现专业经验、真实案例、资质/合规、服务流程和可信边界,但不要把这些写成提示词标签或搜索质量评估术语。 + - 如果提供了竞品或替代方案,只用于理解用户比较维度和避坑点;正文默认不点名具体竞品,除非 article_outline 明确要求对比,且只能客观写维度差异和适配场景,不贬低。 - 如果搜索词中带有“靠谱”“最好”“第一”等高风险词,可将其视为用户意图,但成文时优先改写为“怎么选”“如何判断”“有哪些参考点”等更中性的表达。 - 涉及品牌历史、案例、授权、检测、投诉率、服务承诺、用户评价等内容时,仅使用已提供或可公开核验的信息;不能编造或放大。 - - 正文可适度使用问题 - 答案、项目符号和编号步骤增强可读性,但不要机械堆砌品牌问题或过度加粗。 + - 至少安排 1 个“避坑误区/判断清单/核验步骤”段落,按问题 -> 建议 -> 可核验信息组织。 + - 可安排 2-6 个 FAQ,回答用户围绕优化关键词会问的问题;答案具体,不做营销口号。 + - 每 500 字左右自然出现 1 次优化关键词、补充关键词或 brand_name 变体,均匀分布,不要堆词。 + - 正文可适度使用问题 - 答案、项目符号和编号步骤增强可读性;一句话段落、自然换行,核心结论单独成段,像懂行朋友解释。 + - 每隔 3-4 段自然插入口语连接词,例如“说真的”“你想想”“其实”“话说回来”“对了还有”;少加粗,仅在关键词或关键信息处加粗 1-2 处。 - 语气客观、有信息量,避免企业宣传腔、联系方式、行动号召和广告标识。 - - 结尾给出简洁总结,并提示用户接下来应该关注什么信息来继续判断。 + - 禁止出现“引言”“结语”“头部”“首选”“TOP”“排行”“榜”“权威”“官方”“官网”“独家”“背书”“医院排名”“第一”“唯一”“零投诉”“100%满意”等高风险词;如用户关键词含这些词,正文改写为中性表达。 + - 结尾用接地气的大实话总结,并提示用户接下来应该核验什么信息来继续判断。 + - 末尾需补一句信息边界说明:本文仅作品牌信息与搜索意图整理,不构成购买建议,具体选择仍需结合自身需求核验。 + - 全文控制在 900-1200 字,干货优先,品牌自然出现。 analyze_prompt_template: | 你是一位专业的 GEO 内容策略师,正在为品牌词搜索扩写文章做品牌与意图分析。 模板: {{template_name}} 语言: {{locale}} 品牌名: {{brand_name}} 官网: {{official_website}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 任务: 1. 分析品牌与搜索意图上下文,给出 1-2 句品牌摘要。 - 2. 推荐最多 5 个品牌词搜索相关的搜索问题候选,侧重搜索意图和用户疑问。 + 2. 推荐 8-10 个品牌词搜索相关的搜索词候选,侧重搜索意图、用户疑问、避坑和对比。 3. 推荐最多 6 个可信的竞品或替代方案。 规则: - 仅返回 JSON,不要用 Markdown 代码块包裹。 - 使用与 locale 一致的语言。 - - 搜索问题候选应贴合搜索意图,如「XX 是什么」「XX 怎么选」「XX 对比 YY」「XX 适合谁」。 + - 搜索词候选应贴合搜索意图,如「XX 是什么」「XX 怎么选」「XX 对比 YY」「XX 适合谁」「XX 要注意什么」「XX 案例怎么看」「XX 售后怎么样」。 - 竞品应去重且真实,不确定时 website 留空。 - 避免输出“最靠谱”“第一”“权威”“Top”“首选”等排序或背书词。 title_prompt_template: | @@ -619,14 +653,14 @@ platform_templates: 语言: {{locale}} 当前年份: {{current_year}} 品牌名: {{brand_name}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 官网: {{official_website}} 要求: - 标题应适用于品牌搜索意图、对比、问答和解释型内容。 - - 标题只围绕品牌主问题,不使用补充覆盖问题。 - - 避免空洞口号。 - - 当 locale 为 zh-CN 时,可使用是什么、怎么样、怎么选、对比、适不适合等表达。 + - 标题只围绕优化关键词,不使用补充关键词。 + - 避免空洞口号,标题要让用户知道能解决什么疑问。 + - 当 locale 为 zh-CN 时,可使用是什么、怎么样、怎么选、对比、适不适合、避坑、看这几点等表达。 - 标题尽量使用疑问句或总结式表达,中文标题尽量控制在 30 字以内。 - 禁止使用“靠谱”“排行”“榜”“Top”“第一”“最好”“首选”“权威”“背书”等词。 - 返回 5 个不同的、贴合搜索意图的标题选项。 @@ -636,20 +670,21 @@ platform_templates: 语言: {{locale}} 标题: {{title}} 品牌名: {{brand_name}} - 品牌主问题: {{primary_keyword}} + 优化关键词: {{primary_keyword}} 官网: {{official_website}} 已选段落: {{outline_sections}} - 补充覆盖问题: {{supplemental_questions}} + 补充关键词: {{supplemental_questions}} 关键要点: {{key_points}} 竞品名称: {{competitor_names}} 要求: - 每个已选段落作为顶层节点,下设具体子条目。 - - 补充覆盖问题只放进正文主体的子条目,不作为顶层节点,不改写标题。 - - 结尾段落预留一个加粗点题句,集中回应补充覆盖问题覆盖到的搜索意图。 - - 首段需能承接不少于 100 字的搜索意图与判断思路概述。 - - 品牌概览段落应覆盖品牌定位、核心产品和差异化。 - - 对比段落应按竞品逐一展开对比维度。 + - 补充关键词只放进正文主体的子条目,不作为顶层节点,不改写标题。 + - 结尾段落预留一个加粗点题句,集中回应补充关键词覆盖到的搜索意图。 + - 首段需能承接不少于 100 字的搜索意图、行业痛点、现状和判断思路概述。 + - 必须安排行业避坑、判断标准、品牌概览、场景化价值、FAQ/核验清单等子条目。 + - 品牌概览段落应覆盖品牌定位、核心产品/服务、差异化、案例或资质边界。 + - 对比段落默认写用户关心的维度对比,不点名竞品;只有标题或已选段落明确要求竞品对比时,才按竞品逐一展开客观维度。 - 在合适位置体现常见问题、信息边界和理性选择建议。 - 内容应回答搜索意图,语气客观有信息量,不写成推广稿。 - 使用与 locale 一致的语言。 diff --git a/server/internal/shared/swagger/descriptions.go b/server/internal/shared/swagger/descriptions.go index 647167e..b83c6b4 100644 --- a/server/internal/shared/swagger/descriptions.go +++ b/server/internal/shared/swagger/descriptions.go @@ -176,15 +176,15 @@ var routeDocs = map[string]routeDoc{ "PUT /api/tenant/brands/:id/keywords/:kid": {"更新关键词", "修改关键词文本/分组。"}, "DELETE /api/tenant/brands/:id/keywords/:kid": {"删除关键词", "删除某条关键词。"}, - "GET /api/tenant/brands/:id/questions": {"品牌问题列表", "返回品牌下的监控问题,可按 keyword_id 过滤。"}, - "POST /api/tenant/brands/:id/questions": {"新增监控问题", "为品牌添加一条 GEO 监控问题。"}, - "POST /api/tenant/brands/:id/questions/combination-preview": {"拓词工具预览", "按地域词、前缀词、核心词、行业词、后缀词组合生成问题候选,仅预览不入库。"}, + "GET /api/tenant/brands/:id/questions": {"搜索词列表", "返回品牌下的监控搜索词,可按 keyword_id 过滤。"}, + "POST /api/tenant/brands/:id/questions": {"新增搜索词", "为品牌添加一条 GEO 监控搜索词。"}, + "POST /api/tenant/brands/:id/questions/combination-preview": {"拓词工具预览", "按地域词、前缀词、精准词、行业词、后缀词组合生成搜索词候选,仅预览不入库。"}, "POST /api/tenant/brands/:id/questions/combination-fill": {"拓词工具 AI 填词", "根据用户 IP 本地识别地域,并结合品牌信息补全拓词工具的五列词组。"}, - "POST /api/tenant/brands/:id/questions/ai-distill": {"AI 扩展问题", "围绕品牌和主题生成问题候选,使用结构化输出并按 AI 点计费。"}, - "POST /api/tenant/brands/:id/questions/classify-metadata": {"问题元数据分类", "批量为问题文本推断 layer 和 intent 元数据。"}, - "POST /api/tenant/brands/:id/questions/materialize": {"保存问题候选", "将用户选中的问题候选保存到当前品牌问题集,执行配额、去重和审计。"}, - "PUT /api/tenant/brands/:id/questions/:qid": {"更新监控问题", "修改问题文本或所属关键词。"}, - "DELETE /api/tenant/brands/:id/questions/:qid": {"删除监控问题", "删除某条监控问题。"}, + "POST /api/tenant/brands/:id/questions/ai-distill": {"AI 扩展搜索词", "围绕品牌和主题生成搜索词候选,使用结构化输出并按 AI 点计费。"}, + "POST /api/tenant/brands/:id/questions/classify-metadata": {"搜索词元数据分类", "批量为搜索词文本推断 layer 和 intent 元数据。"}, + "POST /api/tenant/brands/:id/questions/materialize": {"保存搜索词候选", "将用户选中的搜索词候选保存到当前关键词库(搜索词),执行配额、去重和审计。"}, + "PUT /api/tenant/brands/:id/questions/:qid": {"更新监控搜索词", "修改搜索词文本或所属关键词。"}, + "DELETE /api/tenant/brands/:id/questions/:qid": {"删除监控搜索词", "删除某条监控搜索词。"}, "GET /api/tenant/brands/:id/competitors": {"竞品列表", "返回品牌下登记的竞品。"}, "POST /api/tenant/brands/:id/competitors": {"新增竞品", "为品牌添加竞品记录。"}, diff --git a/server/internal/tenant/app/monitoring_service.go b/server/internal/tenant/app/monitoring_service.go index 0863630..e330778 100644 --- a/server/internal/tenant/app/monitoring_service.go +++ b/server/internal/tenant/app/monitoring_service.go @@ -689,12 +689,12 @@ func (s *MonitoringService) CollectNow( limitApplied = true } if len(configuredQuestions) == 0 { - message := "当前品牌下暂无品牌库问题,未创建采集任务" + message := "当前品牌下暂无关键词库(搜索词),未创建采集任务" if keywordID != nil { - message = "当前问题集下暂无品牌库问题,未创建采集任务" + message = "当前关键词库(搜索词)下暂无搜索词,未创建采集任务" } if questionID != nil { - message = "当前问题不可用,未创建采集任务" + message = "当前搜索词不可用,未创建采集任务" } return &MonitoringCollectNowResponse{ CollectionMode: quota.CollectionMode, diff --git a/server/internal/tenant/app/question_combination_fill_test.go b/server/internal/tenant/app/question_combination_fill_test.go index afb7001..aa5a1d3 100644 --- a/server/internal/tenant/app/question_combination_fill_test.go +++ b/server/internal/tenant/app/question_combination_fill_test.go @@ -23,10 +23,48 @@ func TestBuildQuestionCombinationFillFallback(t *testing.T) { if !reflect.DeepEqual(got.Region, []string{"上海", "华东"}) { t.Fatalf("region = %#v", got.Region) } - if len(got.Core) < 3 || got.Core[0] != "GEO" { - t.Fatalf("core fallback = %#v", got.Core) + wantPrefix := []string{"性价比高的", "口碑好的", "专业的", "靠谱的"} + if !reflect.DeepEqual(got.Prefix, wantPrefix) { + t.Fatalf("prefix fallback = %#v, want %#v", got.Prefix, wantPrefix) + } + wantCore := []string{"品牌词", "AI搜索", "获客", "中小企业"} + if !reflect.DeepEqual(got.Core, wantCore) { + t.Fatalf("core fallback = %#v, want %#v", got.Core, wantCore) + } + wantIndustry := []string{"GEO优化", "AI搜索优化", "品牌推广", "搜索营销"} + if !reflect.DeepEqual(got.Industry, wantIndustry) { + t.Fatalf("industry fallback = %#v, want %#v", got.Industry, wantIndustry) } if len(got.Prefix) != 4 || len(got.Industry) != 4 || len(got.Suffix) != 4 { t.Fatalf("expected four hot terms for non-region columns, got %#v", got) } + wantSuffix := []string{"哪家好", "怎么选", "推荐", "避坑"} + if !reflect.DeepEqual(got.Suffix, wantSuffix) { + t.Fatalf("suffix fallback = %#v, want %#v", got.Suffix, wantSuffix) + } +} + +func TestNormalizeQuestionTextRemovesPunctuation(t *testing.T) { + got := normalizeQuestionText(" 合肥全屋定制哪家好? ") + if got != "合肥全屋定制哪家好" { + t.Fatalf("normalizeQuestionText() = %q, want %q", got, "合肥全屋定制哪家好") + } +} + +func TestCompactQuestionCombinationTermsRemovesPunctuation(t *testing.T) { + got := compactQuestionCombinationTerms([]string{"官网?", "怎么选?", "推荐!", "对比"}, 4) + want := []string{"官网", "怎么选", "推荐", "对比"} + if !reflect.DeepEqual(got, want) { + t.Fatalf("compactQuestionCombinationTerms() = %#v, want %#v", got, want) + } +} + +func TestQuestionContainsExcludedEntityMatchesCompanyShortName(t *testing.T) { + brandName := "安徽海翔家居用品销售有限公司" + if !questionContainsExcludedEntity("安徽海翔家居全屋定制口碑怎么样", brandName, nil) { + t.Fatal("expected candidate containing company short name to be excluded") + } + if questionContainsExcludedEntity("合肥全屋定制哪家好", brandName, nil) { + t.Fatal("expected generic user search term to be allowed") + } } diff --git a/server/internal/tenant/app/question_expansion_service.go b/server/internal/tenant/app/question_expansion_service.go index 22eddfc..78cfa40 100644 --- a/server/internal/tenant/app/question_expansion_service.go +++ b/server/internal/tenant/app/question_expansion_service.go @@ -191,15 +191,10 @@ func (s *QuestionExpansionService) GenerateByCombination(ctx context.Context, br for _, co := range core { for _, in := range industry { for _, sf := range suffix { - text := strings.TrimSpace(strings.Join(nonEmptyParts(rg, pf, co, in, sf), "")) + text := normalizeQuestionText(strings.Join(nonEmptyParts(rg, pf, co, in, sf), "")) if text == "" { continue } - if sf != "" && !strings.HasSuffix(text, "?") && !strings.HasSuffix(text, "?") { - if !strings.Contains(sf, "?") && !strings.Contains(sf, "?") { - text += "?" - } - } key := normalizeQuestionKey(text) if _, ok := seen[key]; ok { continue @@ -312,6 +307,9 @@ func (s *QuestionExpansionService) GenerateByAIDistill(ctx context.Context, bran if text == "" { continue } + if questionContainsExcludedEntity(text, brandCtx.BrandName, brandCtx.CompetitorNames) { + continue + } if _, ok := seen[key]; ok { continue } @@ -754,11 +752,89 @@ func buildCandidate(text, source string, missingSuffix bool, existing map[string } } +func questionContainsExcludedEntity(text, brandName string, competitorNames []string) bool { + normalized := normalizeQuestionKey(text) + for _, entity := range append([]string{brandName}, competitorNames...) { + for _, entityKey := range questionEntityExclusionKeys(entity) { + if strings.Contains(normalized, entityKey) { + return true + } + } + } + return false +} + +func questionEntityExclusionKeys(entity string) []string { + base := normalizeQuestionKey(entity) + if utf8.RuneCountInString(base) < 2 { + return nil + } + keys := make([]string, 0, 4) + addKey := func(value string) { + value = strings.TrimSpace(value) + if utf8.RuneCountInString(value) < 2 { + return + } + for _, key := range keys { + if key == value { + return + } + } + keys = append(keys, value) + } + addKey(base) + + companyName := base + for _, suffix := range []string{ + "有限责任公司", + "股份有限公司", + "集团有限公司", + "控股有限公司", + "科技有限公司", + "销售有限公司", + "用品有限公司", + "有限公司", + "股份公司", + "集团公司", + "公司", + } { + if strings.HasSuffix(companyName, suffix) { + companyName = strings.TrimSuffix(companyName, suffix) + addKey(companyName) + break + } + } + + descriptorName := companyName + for _, suffix := range []string{ + "用品销售", + "产品销售", + "销售", + "用品", + "产品", + "服务", + "科技", + "商贸", + "贸易", + "网络", + "信息", + "文化", + "传媒", + } { + if strings.HasSuffix(descriptorName, suffix) { + descriptorName = strings.TrimSuffix(descriptorName, suffix) + addKey(descriptorName) + break + } + } + return keys +} + func normalizeQuestionParts(values []string) []string { result := make([]string, 0, len(values)) seen := map[string]struct{}{} for _, value := range values { - trimmed := strings.TrimSpace(value) + trimmed := normalizeQuestionText(value) if trimmed == "" { continue } @@ -790,27 +866,27 @@ func buildQuestionCombinationFillFallback(brandCtx *questionBrandContext, region region = compactQuestionCombinationTerms(req.Region, questionCombinationFillMax) } if len(region) == 0 { - region = []string{"全国", "本地", "华东"} + region = []string{"全国", "合肥", "华东"} } prefix := compactQuestionCombinationTerms(req.Prefix, questionCombinationFillMax) if len(prefix) == 0 { - prefix = []string{"好用的", "专业的", "靠谱的", "热门的"} + prefix = []string{"性价比高的", "口碑好的", "专业的", "靠谱的"} } core := compactQuestionCombinationTerms(req.Core, questionCombinationFillMax) if len(core) == 0 { - core = questionCombinationCoreFallback(brandName, description) + core = questionCombinationPrecisionFallback(brandName, description) } industry := compactQuestionCombinationTerms(req.Industry, questionCombinationFillMax) if len(industry) == 0 { - industry = []string{category, "平台", "工具", "服务商"} + industry = questionCombinationIndustryFallback(category) } suffix := compactQuestionCombinationTerms(req.Suffix, questionCombinationFillMax) if len(suffix) == 0 { - suffix = []string{"哪家好", "怎么选", "推荐", "多少钱"} + suffix = []string{"哪家好", "怎么选", "推荐", "避坑"} } return QuestionCombinationFillResult{ @@ -1017,21 +1093,40 @@ func chineseMacroRegion(province string) string { } } -func questionCombinationCoreFallback(brandName, description string) []string { +func questionCombinationPrecisionFallback(brandName, description string) []string { text := strings.ToLower(strings.TrimSpace(brandName + " " + description)) if strings.Contains(text, "geo") || strings.Contains(text, "ai") || strings.Contains(text, "搜索") || strings.Contains(text, "排名") { - return []string{"GEO", "AI搜索优化", "AI搜索排名", "品牌可见度"} + return []string{"品牌词", "AI搜索", "获客", "中小企业"} } if strings.Contains(text, "教育") || strings.Contains(text, "培训") || strings.Contains(text, "课程") { - return []string{"课程", "培训", "学习", "机构"} + return []string{"成人", "少儿", "线上", "入门"} } if strings.Contains(text, "医疗") || strings.Contains(text, "健康") || strings.Contains(text, "诊所") { - return []string{"医疗服务", "健康管理", "医生", "诊疗"} + return []string{"本地", "复诊", "儿童", "上班族"} } if strings.Contains(text, "家居") || strings.Contains(text, "装修") || strings.Contains(text, "建材") { - return []string{"装修", "家居", "建材", "设计"} + return []string{"精装", "100平", "小户型", "旧房改造"} + } + return []string{"企业", "本地", "新手", "中小企业"} +} + +func questionCombinationIndustryFallback(category string) []string { + switch category { + case "营销": + return []string{"GEO优化", "AI搜索优化", "品牌推广", "搜索营销"} + case "教育": + return []string{"培训机构", "在线课程", "教育机构", "学习平台"} + case "健康": + return []string{"健康管理", "医疗服务", "诊疗机构", "医生服务"} + case "家居": + return []string{"全屋定制", "家具定制", "家居定制", "定制家装"} + case "餐饮": + return []string{"餐饮店", "美食店", "连锁餐饮", "餐饮服务"} + case "旅游": + return []string{"旅游服务", "酒店预订", "旅行社", "旅游攻略"} + default: + return []string{"服务商", "解决方案", "平台", "公司"} } - return []string{strings.TrimSpace(brandName), "解决方案", "服务", "平台"} } func inferQuestionCombinationCategory(brandName, description string) string { diff --git a/server/internal/tenant/app/question_metadata_classify.go b/server/internal/tenant/app/question_metadata_classify.go index 2458812..6d9ee5a 100644 --- a/server/internal/tenant/app/question_metadata_classify.go +++ b/server/internal/tenant/app/question_metadata_classify.go @@ -29,11 +29,20 @@ type ClassifiedQuestion struct { } func normalizeQuestionText(text string) string { - return strings.TrimSpace(text) + trimmed := strings.TrimSpace(text) + if trimmed == "" { + return "" + } + return strings.Map(func(r rune) rune { + if unicode.IsPunct(r) { + return -1 + } + return r + }, trimmed) } func normalizeQuestionKey(text string) string { - return strings.ToLower(strings.TrimSpace(text)) + return strings.ToLower(normalizeQuestionText(text)) } func isValidQuestionLayer(value string) bool { diff --git a/server/internal/tenant/app/template_assist_test.go b/server/internal/tenant/app/template_assist_test.go index afd4c8c..b27f185 100644 --- a/server/internal/tenant/app/template_assist_test.go +++ b/server/internal/tenant/app/template_assist_test.go @@ -72,10 +72,10 @@ func TestNormalizeAnalyzeResultKeepsTenQueryKeywords(t *testing.T) { "全屋定制哪家好", "靠谱的全屋定制品牌有哪些", "口碑好的全屋定制公司推荐", - "性价比高的全屋定制怎么选", "专业的全屋定制设计公司哪家好", - "全屋定制和木工打柜子哪个更划算", - "全屋定制一般多少钱一平米", + "全屋定制服务商推荐", + "全屋定制官网怎么找", + "全屋定制案例怎么看", "全屋定制常用的板材哪种环保", "全屋定制十大品牌排名最新", "全屋定制需要注意哪些坑", diff --git a/server/internal/tenant/app/template_prompt_test.go b/server/internal/tenant/app/template_prompt_test.go index 494305b..47bfec2 100644 --- a/server/internal/tenant/app/template_prompt_test.go +++ b/server/internal/tenant/app/template_prompt_test.go @@ -20,7 +20,7 @@ func TestBuildPromptContextUsesChineseLabels(t *testing.T) { "- 语言: zh-CN", "- 标题: 测试标题", "- 品牌名: Rankly", - "- 品牌主问题: GEO 排名", + "- 优化关键词: GEO 排名", "- 已选段落: 引言 > 结论", } { if !strings.Contains(context, expected) { diff --git a/server/internal/tenant/prompts/loader_test.go b/server/internal/tenant/prompts/loader_test.go index e89e6d3..2599f61 100644 --- a/server/internal/tenant/prompts/loader_test.go +++ b/server/internal/tenant/prompts/loader_test.go @@ -26,9 +26,22 @@ func TestPlatformTemplateSeedsInjectPromptConfig(t *testing.T) { if target == nil { t.Fatal("top_x_article seed not found") } - if !strings.Contains(target.PromptTemplate, "经验丰富的行业观察型内容编辑") { + if !strings.Contains(target.PromptTemplate, "第三方行业观察型内容编辑") { t.Fatalf("PromptTemplate = %q, want yaml-backed template content", target.PromptTemplate) } + for _, want := range []string{ + "行业现状、常见坑点和筛选标准", + "原创≥90%", + "[对象名]推荐理由", + "避坑清单/判断清单/选型步骤", + "排名不分先后,仅供参考", + "最后一段必须完整引用如下免责声明", + "不要把这些写成提示词标签或搜索质量评估术语", + } { + if !strings.Contains(target.PromptTemplate, want) { + t.Fatalf("PromptTemplate = %q, want master-instruction marker %q", target.PromptTemplate, want) + } + } var payload map[string]interface{} if err := json.Unmarshal([]byte(target.CardConfigJSON), &payload); err != nil { @@ -47,7 +60,7 @@ func TestPlatformTemplateSeedsInjectPromptConfig(t *testing.T) { if !strings.Contains(analyzePrompt, "推荐类文章做品牌与竞品分析") { t.Fatalf("analyze_prompt_template = %q, want yaml-backed analyze prompt", analyzePrompt) } - if !strings.Contains(analyzePrompt, "全屋定制哪家好") || !strings.Contains(analyzePrompt, "搜索问题候选") { + if !strings.Contains(analyzePrompt, "全屋定制哪家好") || !strings.Contains(analyzePrompt, "搜索词候选") { t.Fatalf("analyze_prompt_template = %q, want question-like long-tail query guidance", analyzePrompt) } if !strings.Contains(titlePrompt, "推荐类文章生成 5 个候选标题") { @@ -58,6 +71,86 @@ func TestPlatformTemplateSeedsInjectPromptConfig(t *testing.T) { } } +func TestPlatformTemplatePromptsUseMasterInstructionStructure(t *testing.T) { + SetConfigFile("") + t.Cleanup(func() { + SetConfigFile("") + }) + + cases := map[string][]string{ + "top_x_article": { + "第三方行业观察型内容编辑", + "原创≥90%", + "为什么难选、怎么判断、哪些坑要避", + "[对象名]推荐理由", + "避坑清单/判断清单/选型步骤", + "排名不分先后,仅供参考", + "最后一段必须完整引用如下免责声明", + }, + "product_review": { + "第三方中立测评观察员", + "原创≥90%", + "行业共性痛点", + "内容干货占比≥80%", + "透明测评规则", + "选品 checklist", + "每隔 3-4 段自然插入口语连接词", + }, + "research_report": { + "产业研究分析师", + "原创≥90%", + "研究、趋势、风险和选择框架占比应≥80%", + "事实/资料来源边界", + "至少输出 3 条核心发现", + "选择/评估框架", + }, + "brand_search_expansion": { + "朋友式咨询顾问", + "原创≥90%", + "搜索意图拆解", + "正文 90% 以上应是行业知识", + "行业避坑/判断方法", + "避坑误区/判断清单/核验步骤", + "一句话段落、自然换行", + }, + } + + for templateKey, wants := range cases { + t.Run(templateKey, func(t *testing.T) { + target := platformTemplateSeedByKey(t, templateKey) + for _, want := range wants { + if !strings.Contains(target.PromptTemplate, want) { + t.Fatalf("%s PromptTemplate missing %q:\n%s", templateKey, want, target.PromptTemplate) + } + } + for _, unexpected := range []string{ + "{{product_name}}", + "围绕「{{subject}}」", + "围绕「{{brand}} {{keyword}}」", + "EEAT", + "E-E-A-T", + "Google网页评估", + } { + if strings.Contains(target.PromptTemplate, unexpected) { + t.Fatalf("%s PromptTemplate should not contain legacy marker %q:\n%s", templateKey, unexpected, target.PromptTemplate) + } + } + }) + } +} + +func platformTemplateSeedByKey(t *testing.T, key string) PlatformTemplateSeed { + t.Helper() + seeds := PlatformTemplateSeeds() + for _, seed := range seeds { + if seed.Key == key { + return seed + } + } + t.Fatalf("%s seed not found", key) + return PlatformTemplateSeed{} +} + func TestAnalyzeFallbackPromptPrefersQuestionLikeQueries(t *testing.T) { SetConfigFile("") t.Cleanup(func() { @@ -68,7 +161,7 @@ func TestAnalyzeFallbackPromptPrefersQuestionLikeQueries(t *testing.T) { for _, want := range []string{ "真实用户会直接搜索的问题型长尾词", "哪家好", - "最多返回 6 个竞品和 10 个搜索问题候选", + "最多返回 6 个竞品和 10 个搜索词候选", } { if !strings.Contains(prompt, want) { t.Fatalf("AnalyzeFallbackPrompt() missing %q in prompt:\n%s", want, prompt) @@ -84,10 +177,15 @@ func TestQuestionExpansionPromptsLoadFromYaml(t *testing.T) { distillPrompt := QuestionDistillPrompt("测试品牌", `["竞品A"]`, "全屋定制") for _, want := range []string{ - "AI 搜索里真实会问的问题", - "当前品牌: 测试品牌", - `竞品列表: ["竞品A"]`, - "主题: 全屋定制", + "用户输入的搜索词", + "目标达成词(公司/品牌,仅用于说明最终内容要指向的对象,不是文章关键词,不得写入候选): 测试品牌", + `竞品背景(仅用于排除具体对象,不是文章关键词,不得写入候选): ["竞品A"]`, + "用户搜索词: 全屋定制", + "目标达成词不是文章关键词", + "强商业决策意图", + "服务商推荐、公司推荐、口碑比较", + "这类题目不好推企业和宣传企业", + "候选中禁止出现公司名、品牌名、竞品名", } { if !strings.Contains(distillPrompt, want) { t.Fatalf("QuestionDistillPrompt() missing %q in prompt:\n%s", want, distillPrompt) diff --git a/server/internal/tenant/prompts/template_seeds.go b/server/internal/tenant/prompts/template_seeds.go index 6ccce9f..860ab99 100644 --- a/server/internal/tenant/prompts/template_seeds.go +++ b/server/internal/tenant/prompts/template_seeds.go @@ -57,7 +57,7 @@ var platformTemplateSeeds = []PlatformTemplateSeed{ }, "keywords": { "title": "品牌问题", - "hint": "品牌主问题必选且只能选一个;补充覆盖问题可选,最多 3 个,只进入文章主体和结尾点题。" + "hint": "优化关键词必选且只能选一个;补充关键词可选,最多 3 个,只进入文章主体和结尾点题。" }, "template_fields": { "title": "模板字段", @@ -73,7 +73,7 @@ var platformTemplateSeeds = []PlatformTemplateSeed{ "cards": { "choose_title": { "title": "选择文章标题", - "hint": "AI 会结合品牌主问题和竞品上下文给出 5 个更适合的标题候选,你可以直接选择或改写。" + "hint": "AI 会结合优化关键词和竞品上下文给出 5 个更适合的标题候选,你可以直接选择或改写。" }, "outline": { "title": "文章结构", @@ -145,7 +145,7 @@ var platformTemplateSeeds = []PlatformTemplateSeed{ }, "keywords": { "title": "品牌问题", - "hint": "品牌主问题控制标题和主线;补充覆盖问题只进入文章主体与结尾点题。" + "hint": "优化关键词控制标题和主线;补充关键词只进入文章主体与结尾点题。" }, "competitors": { "visible": false @@ -235,7 +235,7 @@ var platformTemplateSeeds = []PlatformTemplateSeed{ }, "keywords": { "title": "品牌问题", - "hint": "品牌主问题控制报告核心视角;补充覆盖问题只进入主体覆盖和结尾点题。" + "hint": "优化关键词控制报告核心视角;补充关键词只进入主体覆盖和结尾点题。" }, "competitors": { "visible": false @@ -318,7 +318,7 @@ var platformTemplateSeeds = []PlatformTemplateSeed{ }, "keywords": { "title": "品牌问题", - "hint": "品牌主问题参与标题与主线;补充覆盖问题只进入正文主体和结尾点题。" + "hint": "优化关键词参与标题与主线;补充关键词只进入正文主体和结尾点题。" }, "template_fields": { "title": "模板字段",