fix(strategy): LLM 底稿去掉写作说明并禁止成稿出现章节对齐套话

Made-with: Cursor
This commit is contained in:
hub-gif 2026-04-21 17:09:58 +08:00
parent 4cf73e7602
commit b7056fe627
3 changed files with 190 additions and 79 deletions

View File

@ -122,6 +122,7 @@ STRATEGY_SYSTEM = f"""你是市场策略顾问,根据**结构化监测摘要**
**对外成稿与禁止技术泄露硬性**
- 正文须为**可直接对业务或合作方阅读**的正式策略文档对外前仍须按需脱敏**禁止**出现反引号代码体JSON 键名英文字段名内部数据结构名源码或仓库路径类文件名任务 ID工作台规则骨架等系统痕迹**禁止**照抄底稿中以 *成稿**回答**占位**骨架* 开头的**元说明句**须改写为正式业务表述
- **禁止**在正文使用**写作指导式**套话读者不应看到作者须知例如须与 §2/§2.1 一致 §2.1 类目列可对上为后文埋伏笔回扣 §2承接 §2勿重复 §×须直接写**实质策略内容**勿解释章节之间如何对齐
- **一级标题**用文书式例如 `# 「{{keyword}}」市场策略建议书(草案)`,其中 `keyword` 取自本消息 JSON 的同名字段;**勿**使用「草稿」「底稿」「归纳用」等对内用词。
- **附录**中的采集范围等信息用**中文短句**列表页约采集第 310 **禁止** `page_start=` 等键值对或英文键名
@ -148,8 +149,8 @@ STRATEGY_SYSTEM = f"""你是市场策略顾问,根据**结构化监测摘要**
**分节要求与底稿章节一一对应勿省略**
- **策略范围与前提**回答**这份策略是针对什么做的**监测任务本品角色战场主推类目**本阶段目标类型**时间成功标准与业务表单及备注对齐`strategy_decisions_substantive` false 时须写清假设前提与推荐目标类型可含 AE 选项 true 时未填项不得与已填决策矛盾**禁止**与后文 §2.1§ 自相矛盾
- **摘要**除范围样本外**阶段重点**须含 12 **可执行动作**且能回扣 §2 中的优先痛点非空泛加强运营**承接**上文策略范围与前提已定的边界
- **顾客是谁****禁止**重复报告中的细类词频分品类样本量展开文本挖掘方法 **少量结论句**谁搜关心什么即可**1.3 本品聚焦**须写清本期主攻人群/场景 **§2.1** 的对应关系
- **摘要**除范围样本外**阶段重点**须含 12 **可执行动作**指向优先痛点非空泛加强运营与上文策略范围与前提边界一致****在正文写回扣 §2承接上文等指导语
- **顾客是谁****禁止**重复报告中的细类词频分品类样本量展开文本挖掘方法 **少量结论句**谁搜关心什么决策场景**1.3 本品聚焦**须写清本期主攻人群/场景/细类**** §2.1 可对上类作者提示
- ****** §2.1** 一张表类目/细类本决策适用| 用户痛点简述| 策略动作 | 具体怎么做 | 如何验证须覆盖监测已支撑的主要维度**按类目分行**口感/质地分线分量/规格信任与价格等依数据取舍**类目列 + 痛点简述列**遵守§2 条款**禁止**再写独立痛点与证据表价值对表负向归因子节 § 重复的内容一律并入本表或删去
- ****** §3.1**品类与时机检索/样本购买理由可结合 brief 写价带锚点一句**禁止** §3.2转化障碍与应对若与购买相关的障碍与应对已在 §2.1 表内§3.1 **勿再复述**
- ****品牌承诺与调性须能落到**可感知触点**如商详第几屏包装客服首句避免只有形容词

View File

@ -214,11 +214,27 @@ def build_strategy_draft_markdown(
"",
]
if not for_llm_input
else [
"*监测任务边界与业务角色:表单已填则写成短句;未填时由归纳稿基于监测摘要提出**假设性**表述。*",
"*阶段目标类型可列 AE 备选(上市验证 / 份额追赶 / 价盘防守 / 新场景或新人群 / 其它),并写明推荐倾向。*",
"",
]
else []
)
_table_main_cat = (
"*(待填:如饼干线 / 面包线 / 多线并行;未定写「待业务定类」)*"
if not for_llm_input
else "*(待确认)*"
)
_table_goal_type = (
"*(成稿从规划文档「目标类型选项」择一或组合,并与下列成功标准一致)*"
if not for_llm_input
else "*(待确认)*"
)
_summary_user_side = (
"- **用户侧***(一两句结论即可:讨论焦点与负向主题;**按细类分句**归纳,**勿**混成「全站用户」一句;**勿**展开与报告重复的细类统计、词频。)*"
if not for_llm_input
else "- **用户侧**:—"
)
_summary_stage = (
"- **阶段重点***(须含 12 条**可执行动作**,回扣 §2 优先痛点;**尽量点明适用类目/主推线**;勿仅写「加强运营」。)*"
if not for_llm_input
else "- **阶段重点**:—"
)
lines.extend(
[
@ -231,8 +247,8 @@ def build_strategy_draft_markdown(
f"| **策略服务对象(本品角色)** | {_scope_cell(pr_role, '待填:新品 / 追赶 / 防守 / 拓品类 …')} |",
f"| **一句话战场** | {_scope_cell(bf_line, '在哪个需求场景、与谁抢同一批用户?')} |",
f"| **目标客群/场景** | {_scope_cell(aud, '可选')} |",
"| **主推类目/细类** | *(待填:如饼干线 / 面包线 / 多线并行;未定写「待业务定类」)* |",
"| **本阶段策略目标类型** | *(成稿从规划文档「目标类型选项」择一或组合,并与下列成功标准一致)* |",
f"| **主推类目/细类** | {_table_main_cat} |",
f"| **本阶段策略目标类型** | {_table_goal_type} |",
f"| **时间范围** | {_scope_cell(th, '如本季度 / 未来 12 周')} |",
f"| **成功标准(可量化)** | {_scope_cell(sc, '搜索位次、转化、复购等')} |",
"",
@ -246,8 +262,8 @@ def build_strategy_draft_markdown(
if merged_n is not None or comm_n is not None
else "样本规模见附录。"
),
"- **用户侧***(一两句结论即可:讨论焦点与负向主题;**按细类分句**归纳,**勿**混成「全站用户」一句;**勿**展开与报告重复的细类统计、词频。)*",
"- **阶段重点***(须含 12 条**可执行动作**,回扣 §2 优先痛点;**尽量点明适用类目/主推线**;勿仅写「加强运营」。)*",
_summary_user_side,
_summary_stage,
"",
"## 一、顾客是谁",
"",
@ -263,28 +279,40 @@ def build_strategy_draft_markdown(
lines.append("- **一句话战场***(在哪个需求场景、与谁抢同一批用户?)*")
lines.extend(
[
"- **典型路径***(成稿:搜索 → 列表比价 → 详情与配料 → 评价 → 下单/复购。)*",
"",
"*成稿须与 §2 一致:写清「谁在什么任务下检索、决策」及**主攻类目/细类**(与 §2.1 类目列可对上),为后文「针对痛点怎么做」埋伏笔。*",
(
"- **典型路径**:搜索 → 列表比价 → 商详与配料 → 评价 → 下单/复购。"
if for_llm_input
else "- **典型路径***(成稿:搜索 → 列表比价 → 详情与配料 → 评价 → 下单/复购。)*"
),
"",
*(
[]
if for_llm_input
else [
"*成稿须与 §2 一致:写清「谁在什么任务下检索、决策」及**主攻类目/细类**(与 §2.1 类目列可对上),为后文「针对痛点怎么做」埋伏笔。*",
"",
]
),
"### 1.2 细类讨论焦点(评论文本分析)",
"",
]
)
if use_ch8_probe:
lines.extend(
[
"*当前任务以**第八章评论侧文本挖掘**为主呈现时,此处**不**逐条罗列关注词子串命中次数。*",
"",
"- **饼干 / 糕点 / 面点等***(骨架占位;成稿**分细类**各一句归纳用户关心点,**勿**合并成模糊「全池」一句;**勿**复述 §8 词频与条数。)*",
"",
]
)
if not for_llm_input:
lines.extend(
[
"*当前任务以**第八章评论侧文本挖掘**为主呈现时,此处**不**逐条罗列关注词子串命中次数。*",
"",
"- **饼干 / 糕点 / 面点等***(骨架占位;成稿**分细类**各一句归纳用户关心点,**勿**合并成模糊「全池」一句;**勿**复述 §8 词频与条数。)*",
"",
]
)
else:
lines.append(
"*简报中**不再**附带预设关注词/场景子串统计;评论侧请依据同任务《竞品分析报告》**第八章第二节**(文本挖掘探针,若已启用)及抽样原文撰写本节。*"
)
lines.append("")
if not for_llm_input:
lines.append(
"*简报中**不再**附带预设关注词/场景子串统计;评论侧请依据同任务《竞品分析报告》**第八章第二节**(文本挖掘探针,若已启用)及抽样原文撰写本节。*"
)
lines.append("")
mix = brief.get("category_mix_top") or []
if mix:
@ -299,8 +327,14 @@ def build_strategy_draft_markdown(
[
"### 1.3 本品聚焦(占位)",
"",
"*成稿写清本期**主攻人群/场景/类目或主推细类**与 §2.1「类目/细类」列的对应关系。*",
"",
*(
[]
if for_llm_input
else [
"*成稿写清本期**主攻人群/场景/类目或主推细类**与 §2.1「类目/细类」列的对应关系。*",
"",
]
),
_goal_bullet("本品角色", str(d.get("product_role") or ""), "新品 / 追赶 / 防守 / 拓品类 …"),
_goal_bullet(
"目标客群",
@ -320,16 +354,18 @@ def build_strategy_draft_markdown(
[
"## 二、产品价值与用户痛点",
"",
"*本节**仅**用下表写清**针对痛点要怎么做****类目** + 痛点简述 + 动作 + 落地 + 验证)。**不再**单设「痛点表 / 价值对表 / 负向归因」子节,避免与 §三、§八重复。*",
"",
(
"*「用户痛点(简述)」须与监测摘要 / 策略线索 / 报告节选**可核对****禁止**编造「用户反馈『……』」式引语,除非原句已出现在上述输入中。*"
*(
[]
if for_llm_input
else "*「用户痛点(简述)」须与 `structured_brief` / 策略线索 / 报告节选**可核对****禁止**编造「用户反馈『……』」式引语,除非原句已出现在上述输入中。*"
else [
"*本节**仅**用下表写清**针对痛点要怎么做****类目** + 痛点简述 + 动作 + 落地 + 验证)。**不再**单设「痛点表 / 价值对表 / 负向归因」子节,避免与 §三、§八重复。*",
"",
"*「用户痛点(简述)」须与 `structured_brief` / 策略线索 / 报告节选**可核对****禁止**编造「用户反馈『……』」式引语,除非原句已出现在上述输入中。*",
"",
"*「类目/细类」列:写明本行决策**适用于哪一类**(如饼干/面包/全检索池);多细类须**分行****禁止**用一句「全站」覆盖彼此冲突的策略;类目未定可写「待业务定类」并附分类假设。*",
"",
]
),
"",
"*「类目/细类」列:写明本行决策**适用于哪一类**(如饼干/面包/全检索池);多细类须**分行****禁止**用一句「全站」覆盖彼此冲突的策略;类目未定可写「待业务定类」并附分类假设。*",
"",
"### 2.1 针对痛点要怎么做",
"",
"| 类目/细类(本决策适用) | 用户痛点(简述) | 策略动作 | 具体怎么做(触点/话术/规格/渠道) | 如何验证 |",
@ -374,7 +410,11 @@ def build_strategy_draft_markdown(
elif merged_n is not None:
lines.append(f"- **深入样本 SKU 数**{_num(merged_n)}")
else:
lines.append("- **品类与时机***(成稿结合摘要与监测范围。)*")
lines.append(
"- **品类与时机**:—"
if for_llm_input
else "- **品类与时机***(成稿结合摘要与监测范围。)*"
)
lines.append("")
if pst.get("n"):
src = _esc(brief.get("price_stats_source")) or ""
@ -387,12 +427,16 @@ def build_strategy_draft_markdown(
]
)
else:
lines.append("*摘要中无价带统计,成稿可结合本批次价格数据在 §3.1 补一句锚点;**勿**重复 §2 已写的应对动作。*")
if for_llm_input:
lines.append("- **价带摘录**:监测摘要中暂无统计表,可结合同任务报告补一句购买锚点。")
else:
lines.append("*摘要中无价带统计,成稿可结合本批次价格数据在 §3.1 补一句锚点;**勿**重复 §2 已写的应对动作。*")
lines.append("")
lines.append(
if not for_llm_input:
lines.append(
"*成稿在 §3.1 末尾用 12 句**承接** §2 优先痛点并写购买理由;**若**多细类并存,**分句**写清购买理由与主推;价带/规格类动作已在 §2 表内则此处**勿再展开一遍**。*"
)
lines.append("")
)
lines.append("")
lines.extend(
[
@ -400,15 +444,28 @@ def build_strategy_draft_markdown(
"",
"### 4.1 品牌承诺与调性(占位)",
"",
"*成稿:承诺与调性须能落到**触点**(商详/包装/客服首句等)上的**具体句子****若**多类目话术不同,按 §2.1 类目**分句**,勿仅形容词。*",
"",
*(
[]
if for_llm_input
else [
"*成稿:承诺与调性须能落到**触点**(商详/包装/客服首句等)上的**具体句子****若**多类目话术不同,按 §2.1 类目**分句**,勿仅形容词。*",
"",
]
),
"- **一句话***(占位)*",
"- **调性**:透明、可验证、合规控糖叙事(成稿可细化)。",
(
"- **调性**:透明、可验证、合规控糖叙事。"
if for_llm_input
else "- **调性**:透明、可验证、合规控糖叙事(成稿可细化)。"
),
"",
"### 4.2 信任与证据",
"",
"- *(成稿:评价、配料、可核验表述边界。)*",
"",
*(
["- *(评价、配料、可核验表述边界。)*", ""]
if for_llm_input
else ["- *(成稿:评价、配料、可核验表述边界。)*", ""]
),
"**主定位(与表单一致)**",
"",
f"- {_pos_mark(pos, 'top')} **贴顶**:中高位或头部价位带。",
@ -449,16 +506,33 @@ def build_strategy_draft_markdown(
if n_brand:
lines.append(n_brand)
if not n_shop and not n_brand:
lines.append("*本摘要未含集中度指标,请结合本批次竞争结构数据补全。*")
lines.append(
"- **竞争结构**:监测摘要未含集中度摘录。"
if for_llm_input
else "*本摘要未含集中度指标,请结合本批次竞争结构数据补全。*"
)
lines.extend(
[
"",
"- **环境自测**:头部强势时是侧翼还是正面替代?格局分散时是否用细分场景切入?",
*(
[]
if for_llm_input
else [
"",
"- **环境自测**:头部强势时是侧翼还是正面替代?格局分散时是否用细分场景切入?",
]
),
"",
"### 5.2 差异化方向(占位)",
"",
"*成稿:相对竞品**多做什么/少做什么**,写**可执行的一步****若**差异因细类而异,**分类目**写(非空泛「更好」)。*",
"",
*(
[]
if for_llm_input
else [
"*成稿:相对竞品**多做什么/少做什么**,写**可执行的一步****若**差异因细类而异,**分类目**写(非空泛「更好」)。*",
"",
]
),
"| 差异点 | 说明 | 风险 |",
"|--------|------|------|",
"| | *待填* | |",
@ -467,16 +541,21 @@ def build_strategy_draft_markdown(
)
lines.append("### 5.3 竞争应对")
lines.append("")
lines.append(
"*成稿:在表单倾向基础上,写清**跟价/不跟价时具体话术或机制**(一句即可)。*"
)
lines.append("")
if not for_llm_input:
lines.append(
"*成稿:在表单倾向基础上,写清**跟价/不跟价时具体话术或机制**(一句即可)。*"
)
lines.append("")
stance = _esc(d.get("competitive_stance") or "").strip()
stance_line = {
"flank": "- **本品倾向**:侧翼切入,避免与头部正面硬碰。",
"head_on": "- **本品倾向**:正面替代,对标头部主战场。",
"both": "- **本品倾向**:分层推进(部分场景侧翼、部分场景正面)。",
"undecided": "- **本品倾向***(表单未选;成稿时据数据写清倾向)*",
"undecided": (
"- **本品倾向***(待确认)*"
if for_llm_input
else "- **本品倾向***(表单未选;成稿时据数据写清倾向)*"
),
}.get(stance)
if stance_line:
lines.append(stance_line)
@ -498,8 +577,14 @@ def build_strategy_draft_markdown(
"",
"### 6.2 路径",
"",
"*成稿:路径须与 **§2.1 针对痛点要怎么做** 可对齐;营销/总体策略为**动词句**,回扣痛点;**多类目并行**时**分线**写目标或写清主线/副线。*",
"",
*(
[]
if for_llm_input
else [
"*成稿:路径须与 **§2.1 针对痛点要怎么做** 可对齐;营销/总体策略为**动词句**,回扣痛点;**多类目并行**时**分线**写目标或写清主线/副线。*",
"",
]
),
_goal_bullet(
"营销策略",
str(d.get("marketing_strategy") or ""),
@ -527,9 +612,15 @@ def build_strategy_draft_markdown(
[
"## 七、品牌四线:建设 · 打造 · 运营 · 体验",
"",
"*与表单「4P 策略支柱」对应:产品 / 定价 / 渠道 / 传播。)*",
"*成稿:**每条线**至少一句——服务哪类痛点、本阶段**具体做哪一步****尽量**与 §2.1「类目/细类」可对上,多类目则**分句**(勿四条同一泛化句)。*",
"",
*(
[]
if for_llm_input
else [
"*与表单「4P 策略支柱」对应:产品 / 定价 / 渠道 / 传播。)*",
"*成稿:**每条线**至少一句——服务哪类痛点、本阶段**具体做哪一步****尽量**与 §2.1「类目/细类」可对上,多类目则**分句**(勿四条同一泛化句)。*",
"",
]
),
"### 7.1 品牌建设",
"",
f"- {_pillar_cell(pp)}",
@ -549,14 +640,10 @@ def build_strategy_draft_markdown(
]
)
if use_ch8_probe:
if use_ch8_probe and not for_llm_input:
pst_sig = brief.get("price_promotion_signals") or {}
has_promo = isinstance(pst_sig, dict) and bool(pst_sig)
promo_hint = (
"*促销与活动线索:须与摘要中的价差与活动信号及报告第六章已有归纳一致;无则勿编造具体满减门槛。*"
if for_llm_input
else "*促销与活动线索:须与摘要 `price_promotion_signals` 及第六章/第九章已有归纳一致;无则勿编造具体满减门槛。*"
)
promo_hint = "*促销与活动线索:须与摘要 `price_promotion_signals` 及第六章/第九章已有归纳一致;无则勿编造具体满减门槛。*"
lines.extend(
[
"",
@ -571,8 +658,14 @@ def build_strategy_draft_markdown(
[
"## 八、战术支柱",
"",
"*成稿:四支柱分别回扣 **痛点→动作→落地**(可与 §2.1 呼应,避免纯重复);**若**产品/定价/促销因类目策略不同,**分细类**写子条,勿一条盖全站。*",
"",
*(
[]
if for_llm_input
else [
"*成稿:四支柱分别回扣 **痛点→动作→落地**(可与 §2.1 呼应,避免纯重复);**若**产品/定价/促销因类目策略不同,**分细类**写子条,勿一条盖全站。*",
"",
]
),
"### 8.1 产品策略",
"",
f"- *(表单产品支柱:{_pillar_cell(pp)}*",
@ -583,13 +676,15 @@ def build_strategy_draft_markdown(
"",
"### 8.3 促销与活动策略",
"",
"*须写促销**原则**(券/到手价/跟价节奏);**满减、满折、跨店**等:能引用的写清来源;监测未捕获具体门槛时写「待与运营/后台对齐」,**勿**整节留空,**勿**编造门槛数字。*",
(
"*与监测摘要中的促销与价差信号、报告第六章一致;勿虚构活动。*"
*(
[]
if for_llm_input
else "*与 `price_promotion_signals`、报告第六章一致;勿虚构活动。*"
else [
"*须写促销**原则**(券/到手价/跟价节奏);**满减、满折、跨店**等:能引用的写清来源;监测未捕获具体门槛时写「待与运营/后台对齐」,**勿**整节留空,**勿**编造门槛数字。*",
"*与 `price_promotion_signals`、报告第六章一致;勿虚构活动。*",
"",
]
),
"",
"### 8.4 渠道与传播",
"",
f"- *(渠道/传播:{_pillar_cell(pch)} / {_pillar_cell(pcm)}*",
@ -609,14 +704,26 @@ def build_strategy_draft_markdown(
_risk_line(rp, "价格带是否含大促/异常挂价?(需核对清洗规则)"),
_risk_line(rc, "列表集中度与深入样本品牌是否不一致?(需解释渠道差异)"),
"",
"*成稿:每条风险尽量带**应对动作或验证计划**(抽样、核对规则),勿只列标题。*",
"",
"*业务备注见下节。*",
"",
*(
[]
if for_llm_input
else [
"*成稿:每条风险尽量带**应对动作或验证计划**(抽样、核对规则),勿只列标题。*",
"",
"*业务备注见下节。*",
"",
]
),
"## 十、下一步与节奏",
"",
"*成稿:下列为**可执行任务**(可补负责人/时间);与 §2.1 / §六 优先级一致;可含「按类目核对主图/商详与 §2.1 表」类项。*",
"",
*(
[]
if for_llm_input
else [
"*成稿:下列为**可执行任务**(可补负责人/时间);与 §2.1 / §六 优先级一致;可含「按类目核对主图/商详与 §2.1 表」类项。*",
"",
]
),
"- [ ] 锁定主推款与对标;过法务与合规。",
"- [ ] 统一对外数据口径与话术。",
"- [ ] 下轮监测更新后迭代策略。",

View File

@ -42,6 +42,9 @@ class StrategyDraftTests(SimpleTestCase):
self.assertNotIn("strategy_hints", md)
self.assertIn("监测摘要自动线索", md)
self.assertIn("列表页约第 13 页", md)
self.assertNotIn("埋伏笔", md)
self.assertNotIn("成稿须与 §2", md)
self.assertNotIn("回扣 §2", md)
def test_build_contains_sections_and_notes(self) -> None:
brief = {