fix(llm): restore matrix/comment/price group advisor prompts and callers

Re-add MATRIX/COMMENT/PRICE_GROUPS_SYSTEM and generate_*_group_summaries_llm
removed in afe2748; align comment-group prompt with shop in attribution
prefix. Default report_config now includes the three llm_*_summaries flags.

Made-with: Cursor
This commit is contained in:
hub-gif 2026-04-14 11:08:24 +08:00
parent dd5fa8a407
commit 15ba8b3370
2 changed files with 136 additions and 0 deletions

View File

@ -168,6 +168,9 @@ def get_default_report_config() -> dict[str, Any]:
return {
"llm_comment_sentiment": False,
"llm_section_bridges": False,
"llm_matrix_group_summaries": False,
"llm_comment_group_summaries": False,
"llm_price_group_summaries": False,
"comment_focus_words": list(jcr.COMMENT_FOCUS_WORDS),
"comment_scenario_groups": [
{"label": lbl, "triggers": list(trs)}

View File

@ -270,3 +270,136 @@ def generate_strategy_draft_markdown_llm(
raw = json.dumps(payload, ensure_ascii=False)
user = STRATEGY_USER_PREFIX + raw
return _call_llm(STRATEGY_SYSTEM, user)
MATRIX_GROUPS_SYSTEM = """你是竞品分析顾问。输入为 JSON``keyword`` 与 ``groups`` 数组。
每个 group ``group``细分类目名``sku_count````price_stats``该细类深入合并行可解析展示价的 min/max/median/mean/n **§6按细类价盘** 分位数表同源无则 n=0 或缺字段
``lines``该细类下若干 SKU 的标题/卖点/配料**摘录**均来自页面抓取拼接可能截断
**为每个细类**输出一小段 Markdown全部 groups 都要写顺序与输入一致
- ``#### `` + 与该 group 字段**完全一致**的细类名作为小节标题(不要使用 ``##`` 一级标题);
- 每段约 **100200 **中文**主体**归纳该细类下**卖点表述共性****配料类型/宣称共性**摘录中无配料则写配料摘录较少**品牌格局**可一句概括仅依据摘录中可见品牌/系列勿编造销量排名
- **价带/价位** ``price_stats.n`` 为大于 0 的整数**仅允许**用该对象里的数值写价带 minmax中位数且须与 ``price_stats`` **完全一致****禁止**价格带未明确未体现具体价位多为中端**与上述数值相矛盾**的表述 n=0 或无可信数值**不要猜测价位**可写一句深入样本可解析数值价不足价盘以 **§6** 表格为准
- **禁止**输出 Markdown 表格禁止逐条复述 SKU 明细表勿编造功效认证
- ``lines`` 很少明确写样本较少归纳供启发
总输出约 **8003500 **细类多则偏长仅输出正文 Markdown不要用代码围栏包裹全文"""
MATRIX_GROUPS_USER_PREFIX = (
"请根据以下 JSON 撰写竞品报告第五章末「细类要点归纳」正文Markdown\n\n"
)
def generate_matrix_group_summaries_llm(
groups: list[dict[str, Any]], *, keyword: str
) -> str:
trimmed: list[dict[str, Any]] = []
for g in groups:
if not isinstance(g, dict):
continue
g2 = dict(g)
ln = g2.get("lines")
if isinstance(ln, list) and len(ln) > 22:
g2["lines"] = ln[:22]
trimmed.append(g2)
payload = {"keyword": keyword, "groups": trimmed}
raw = json.dumps(payload, ensure_ascii=False)
if len(raw) > 95_000:
for g2 in trimmed:
ln = g2.get("lines")
if isinstance(ln, list) and len(ln) > 12:
g2["lines"] = ln[:12]
raw = json.dumps({"keyword": keyword, "groups": trimmed}, ensure_ascii=False)
user = MATRIX_GROUPS_USER_PREFIX + raw
return _call_llm(MATRIX_GROUPS_SYSTEM, user)
COMMENT_GROUPS_SYSTEM = """你是用户研究与品类顾问。输入为 JSON``keyword`` 与 ``groups``。
每个 group ``group`` §5 矩阵一致的细分类目名``comment_flat_rows````effective_text_lines``
``focus_hit_lines``关注词子串命中摘要 §8.3 同源``sample_text_snippets``评价短摘录已截断
摘录行通常以 ``细类SKU品名店铺`` 开头细类可与本 group 名对照**品名/SKU/店铺**表示该句具体出自哪条链接归纳时若引用原话**须交代是哪家店哪条 SKU哪款品名上的反馈**勿只写有用户说口感差而不指代产品
**为每个细类**输出一小段 Markdown全部 groups 都要写顺序与输入一致
- ``#### `` + 与该 group 字段**完全一致**的细类名作为小节标题(不要使用 ``##`` 一级标题);
- 每段约 **100220 **中文归纳该细类下**消费者在讨论什么**口感价格物流功效疑虑等**关注词命中反映的诉求**勿编造摘录中未出现的品牌医学结论
- **禁止**输出 Markdown 表格禁止逐条复述全部评价
- ``effective_text_lines`` 很少明确写样本较少归纳供启发
总输出约 **6003200 **仅输出正文 Markdown不要用代码围栏包裹全文"""
COMMENT_GROUPS_USER_PREFIX = (
"请根据以下 JSON 撰写竞品报告第八章末「细类评论与关注词要点归纳」正文Markdown\n\n"
)
def generate_comment_group_summaries_llm(
groups: list[dict[str, Any]], *, keyword: str
) -> str:
trimmed: list[dict[str, Any]] = []
for g in groups:
if not isinstance(g, dict):
continue
g2 = dict(g)
sn = g2.get("sample_text_snippets")
if isinstance(sn, list) and len(sn) > 16:
g2["sample_text_snippets"] = sn[:16]
fh = g2.get("focus_hit_lines")
if isinstance(fh, list) and len(fh) > 14:
g2["focus_hit_lines"] = fh[:14]
trimmed.append(g2)
payload = {"keyword": keyword, "groups": trimmed}
raw = json.dumps(payload, ensure_ascii=False)
if len(raw) > 95_000:
for g2 in trimmed:
sn = g2.get("sample_text_snippets")
if isinstance(sn, list) and len(sn) > 10:
g2["sample_text_snippets"] = sn[:10]
raw = json.dumps({"keyword": keyword, "groups": trimmed}, ensure_ascii=False)
user = COMMENT_GROUPS_USER_PREFIX + raw
return _call_llm(COMMENT_GROUPS_SYSTEM, user)
PRICE_GROUPS_SYSTEM = """你是定价与渠道顾问。输入为 JSON``keyword`` 与 ``groups``。
每个 group ``group``细分类目名 §5 矩阵§6按细类价盘小节一致``sku_count````price_stats``该细类可解析展示价的 min/max/median/mean/n §6 各细类 Markdown 分位数表同源
``listing_snippets``若干标题标价券后详情价摘录来自合并表字段已截断
**为每个细类**输出一小段 Markdown全部 groups 都要写顺序与输入一致
- ``#### `` + 与该 group 字段**完全一致**的细类名作为小节标题;
- 每段约 **80200 **中文**只写价盘与价差** ``price_stats`` 概括价带/离散度 minmax中位数相对集中或拉得开 ``listing_snippets`` 归纳**标价 vs 券后 vs 详情价**是否常一致是否常见券后低于标价价差幅度的大致印象**可一句**联系标题里**显式出现的规格数字**如克重件数解释**价高/价差大是否可能来自大规格或组合装**仅当摘录里确有数字时写勿展开成宣称解读
- **硬性禁止**本章不是卖点章不要列举或归纳0 蔗糖 / GI / 全麦 / 代餐 / 孕妇 / 控糖**营销宣称或场景关键词**不要写配料功效品牌叙事用户画像这些若出现应留给报告 **§5 细类要点归纳** **§7**
- **禁止** Markdown 表格禁止罗列全部 SKU勿编造未出现的到手价销量排名
- ``price_stats`` n=0 或缺失该细类无可解析数值价从略
总输出约 **5002800 **仅输出正文 Markdown不要用代码围栏包裹全文"""
PRICE_GROUPS_USER_PREFIX = (
"请根据以下 JSON 撰写竞品报告第六章末「细类价盘要点归纳」正文Markdown"
"本章只写**数值价带与标价/券后/详情价关系**,勿写卖点宣称关键词归纳。\n\n"
)
def generate_price_group_summaries_llm(
groups: list[dict[str, Any]], *, keyword: str
) -> str:
trimmed: list[dict[str, Any]] = []
for g in groups:
if not isinstance(g, dict):
continue
g2 = dict(g)
sn = g2.get("listing_snippets")
if isinstance(sn, list) and len(sn) > 14:
g2["listing_snippets"] = sn[:14]
trimmed.append(g2)
payload = {"keyword": keyword, "groups": trimmed}
raw = json.dumps(payload, ensure_ascii=False)
if len(raw) > 95_000:
for g2 in trimmed:
sn = g2.get("listing_snippets")
if isinstance(sn, list) and len(sn) > 8:
g2["listing_snippets"] = sn[:8]
raw = json.dumps({"keyword": keyword, "groups": trimmed}, ensure_ascii=False)
user = PRICE_GROUPS_USER_PREFIX + raw
return _call_llm(PRICE_GROUPS_SYSTEM, user)