项目内部分享版 / 对话策略项目 · 三模块

对话策略项目:破冰 · 反向评论 · 评论意向 三条线同步

这不是讲一堆 prompt 工程术语,而是讲清楚:我们如何把"在抖音上对潜客做触达"这件事,拆成三套独立可演进、可灰度的对话策略模块——破冰私信、反向评论、评论意向分析——再让它们共用一份事实手册(brand_profile + memory)。

一句话结论(截至 2026-06-01):三模块全部在线上最新版——破冰 v30(5/29 v26 上线后四轮快速迭代到 v30)、反评 v14(销售路线持续迭代)、意向 v10(四轴稳定)。共用一份事实手册,闭环跑通;破冰本周重点是 v30 价格口径(投影→每平方米 284 一平)灰度。
0

三大模块全景

对话策略项目目前由三个独立模块组成——共用一份「事实手册」(brand_profile + customer memory),共用一个意向分析上游,但生成路径、模型、人设、约束都不同。

破冰提示词 · DM 主通道

破冰 / 培育 / 决策

高意向评论 → DM 私信,把潜客从冷启动聊到加微。

Langfuse
dm.ice_break.system
dm.nurture.system
dm.decision.system
调用 chatReply / generateColdOpener
模型 qwen3-235b(对话路)
人设 小艳(2026-05-14 由小艾改名,黑名单同步更新)
骨架 8 段 + 8 slot 注入 + sanitizeReply + post ban check
v34 · 当前生产 v25 末轮回归 95.6%(583 / 610);v26 新增 §(B) 预算 / §(T) 信任 / §(C) 收口三段 + 4 slot,5/29→6/1 又迭代四轮到 v30(价格口径投影→每平方米 284 一平)。7d 调用 1,160 次。
反向评论提示词 · 公开通道

反向评论生成

同行视频下留一条评论,钩对方私信咨询(不主动 DM,避开 stranger-DM 风控)。

Langfuse
comment.reverse-comment-system-py-single
调用 Python agent
worker/scripts/local_reverse_comment_agent.py
挑候选 pickCandidates(peer-filter + off-topic 正则)
骨架 单 skeleton · 4 步话术(称呼 → 视频引用 → 销售肯定 → 反问 + 私信钩子)
自检 <<unhookable>>(重级土建 / 家电品牌选购 / 物流维权 一票否决)+ <<retry>>(错称呼 / 「家人们」/ 凭空猜户型 → 重写)
v20 · 当前生产 v4(2026-05-13)切销售视角后持续迭代到 v14;TS multi-skeleton 路径已下线,统一走 Python single-skeleton。7d 调用 273 次(最低,受 30d cooldown 约束)。
意向分析提示词 · 分流闸门

评论意向四轴分类

评论池入口打分 → 决定走 DM 还是反评、还是丢弃。服务于破冰 + 反评两条下游链路。

Langfuse
analyze.comments.system
analyze.decision_signal.system
调用 analyzeCommentssrc/lib/llm.ts
模型 deepseek-v4-flash(分析路)
输出 type / specificity / freshness / category 四轴 + keywords + 推理 reason
关键规则 category=off_topic 在 deriveIntent() short-circuit 到 label='无关'(家电 / 数码 / 促销询券防漏网)
v11 · 当前生产 v1 单值 → v10 四轴 + reasons;7d 调用 2,373 次(最高,是破冰的 2.0 倍、反评的 9 倍——上游本就该最忙)。★ 改动风险 HIGH。
关键点:意向分析模块是另外两个模块的上游。它打的分既决定"这条评论值不值得发 DM",也决定"这条评论值不值得反评"——所以一改它,破冰和反评的候选池都跟着动。版本变更必须 dry-run 历史评论分布,避免任一档塞爆 80%。

三模块横切对照表

维度 破冰模块 反评模块 意向模块
触达通道 DM 私信(一对一) 同行视频下公开留评(一对多旁观) —(不直接触达,只打分分流)
上游输入 意向打分 ≥ 阈值的评论 同行视频评论池 + peer-filter + off-topic 全量 douyin comments
Langfuse prompt dm.ice_break.system
dm.nurture.system
dm.decision.system
comment.reverse-comment-system-py-single analyze.comments.system
analyze.decision_signal.system
实现位置 TS · chatReply / generateColdOpener Python agent · local_reverse_comment_agent.py TS · analyzeComments
模型 qwen3-235b(对话路) 配置项(Python 端可换) deepseek-v4-flash(分析路)
骨架颗粒度 6 段 + 8 slot(高自由度,LLM 负责风格 + 应变) skeleton + 4 步话术 + 5 slot(低自由度,LLM 必须按骨架走) 4 轴 JSON(结构化输出,下游公式合成分数)
自检层 sanitizeReply(协议字节)+ post ban check(v16) <<unhookable>>(一票否决)+ <<retry>>(重写) deriveIntent() + off_topic short-circuit
数据出口 message_queue: pending_approval → 审批 → ADB / WDA → DM reverse_comment_queue → WDA 留评 → status 回写 高意向 → DM 候选池 / 中意向 → 反评候选池 / 无关 → 丢回
当前版本 v34 · 当前生产(v26 上线后四轮迭代 / v25 末轮 95.6%) v20 · 当前生产(v4 销售路线后持续迭代) v11 · 当前生产(v1 单值 → v10 四轴)
7d 调用量 1,160 · Langfuse observations 273 · 受 30d cooldown 约束 2,373 · 上游本就该最忙
改动风险 中(有 ban check 兜底,单条翻车不致命) 高(公开通道翻车 → 整个号当天废) HIGH(同时影响 DM + 反评候选池分布)

「当前版本」「7d 调用量」两行 + 顶部三张卡片由 scripts/build-dialogue-strategy-progress.ts 自动从 Langfuse 拉取(production label 版本 + 近 7 天 observations),数据更新于 2026-06-17

怎么用这张表:横向读 = 看一个维度(比如"模型")在三模块怎么取舍;纵向读 = 看一个模块(比如反评)从输入到输出的完整画像。任一改动前先在表里定位,确认它会动到哪几格;意向那一列改动一次,破冰和反评两列的"上游输入"都跟着变。
1

三模块案例汇总

每个模块拿出最有代表性的 3 组证据 + 一条端到端链路示意。三模块共用同一个评论池入口(意向打分上游),但生成器、自检方式、出口完全不同——下面分 A / B / C 三块各自展开。

A · 破冰模块案例:v25 末轮 95.6%,现已迭代到 v30

证据 1

v25 末轮 95.6%

v25 末轮真实生产:583 / 610。剩下 27 条全是账号 cookie 缺失没发出,不是 prompt 自身翻车——凭据齐就稳。v26(2026-05-29 13:03 promote)之后骨架不动、五天内又迭代四轮到 v30,本周观察 v30 价格口径灰度结果。Langfuse 上 dm.ice_break.system 7d 调用 1,160 次。

证据 2

人设守住了

5/14 把人设从「小艾」改成「小艳」,同时把同音字、谐音字全加进黑名单。连查 30 条真实对话,没有一条出现「小艾」「AI 助手」「作为大模型」。

证据 3

协议字节 0 漏

DeepSeek V3 系列偶尔漏 function_call / tool_use 字节当正文发。sanitizeReply 这层挡在 prompt 外,命中即降级,换模型也不去掉。

1

取上下文

视频文案 + 评论 + 客户 memory(自然语言短句)。

2

取 prompt

Langfuse 取 production label 当前版本(v30)。

3

LLM 生成

chat 走 qwen3-235b,analysis 走 deepseek-v4-flash。

4

后置安检

ban check + 协议字节扫,命中即拦下不发。

5

落库发送

写 conversations / messages,回写 contacted 防重复。

给同事的讲法:破冰模块我们不追求一步全自动,而是先把每一段独立做稳——模型负责说话风格,prompt 负责什么时候说,brand_profile 负责说什么具体事实,后置 ban check 负责出门前再扫一遍。

B · 反评模块案例:v4 切销售路线 → v14 持续迭代

证据 1

视角换了一刀就稳

v1-v3 一直让模型用"内容创作者评论"的语气,结果留评像水军、钩不到 DM。v4(2026-05-13 与夏夏 Lark 对齐)把视角统一切到"销售来对方视频底下接活"——4 步话术固定:称呼 + 视频引用 + 销售肯定 + 反问 + 私信钩子。v5-v14 在这个骨架上持续打磨称呼锁、unhookable 触发面、私信钩子句式,现版本 v14(最近 5/18 promote)。Langfuse 上 7d 调用 273 次。

证据 2

<<unhookable>> 拦得稳

原评论涉及承重墙 / 自建房 / 家电品牌选购 / 物流维权时,模型必须只输出 <<unhookable>>。运营再也不会拿到"我们卖油烟机"这种翻车文案。

证据 3

称呼锁守住性别

昵称末位男性后缀(哥/叔/师傅)→ 原样保留整名;末位女性后缀(姐/姨/嫂)→ 原样保留;含典型男/女字 → "{昵称}哥/姐";性别不明 → 裸名直呼;英文 emoji → "朋友"。错性别即 <<retry>>

1

挑候选

pickCandidates 用 peer-filter + off-topic 正则在同行视频评论池过滤。

2

写队列

命中候选写 reverse_comment_queue,每个 sec_uid 30 天 cooldown。

3

Python 生成

local_reverse_comment_agent.py 拉 Langfuse prompt,注入 skeleton。

4

骨架自检

命中 <<unhookable>> 拒;命中 <<retry>> 重写。

5

WDA 留评

iPhone WebDriverAgent 串行在同行视频下留评 + 回写状态。

给同事的讲法:反评和破冰最大的区别——破冰里 LLM 负责"风格 + 应变",反评里 LLM 必须严格按 skeleton 走,自由度压到最小。因为反评是公开的,"哥/姐/家人们/我们卖油烟机"翻车一次,整个号当天就废。

C · 意向模块案例:v10 四轴稳定输出

证据 1

四轴结构化输出(v10)

每条评论输出 {type, specificity, freshness, category, keywords, type_reason, category_reason} 七字段 JSON。下游 deriveIntent() 用前 3 轴合成 score,公式留在代码层——PM 改不到 prompt 也能调权重。v10 是 v1(单值 intent)到现在的第 10 次大改。Langfuse 7d 调用 2,373 次(是另两模块上游,量最大)。

证据 2

off_topic short-circuit

category 命中 off_topic 时 deriveIntent() 直接 short-circuit 到 label='无关'。家电 / 数码 / 促销询券("618 蹲一波")一次性拦截,不进高意向队列。

证据 3

正则与 LLM 双层防线

peer-filter(同行画像)+ off-topic 正则在 LLM 调用前先过一遍——省 token,也兜住 LLM 偶发漏判。规则在 src/lib/peer-filter.ts 共享给反评和破冰两条链路。

1

拉评论池

Cron 抓 douyin comments 最近一批,待打分。

2

正则预筛

peer-filter + off-topic 正则先扫一遍,过滤同行 / 家电 / 促销。

3

LLM 四轴

analyze.comments.system 给 deepseek-v4-flash,输出四轴 JSON。

4

合成 score

deriveIntent() 按公式算 score + label,off_topic 直接到"无关"。

5

分流

高意向 → DM 候选;中意向 → 反评候选;无关 → 丢回评论池。

给同事的讲法:意向分析是另外两个模块的上游。它打的分既决定"这条评论值不值得发 DM",也决定"这条评论值不值得反评"——所以改它必须 dry-run ≥15 条历史评论看分布,任一档分布 >80% 都是定义有问题。
2

三模块拆解

这不是一条 prompt 从头写到尾,而是多个 prompt 在不同时机被取出、装配、生成、净化、安检。下面 6 张图按"双通道全景 → 三模块内部架构 → 破冰 7 步深挖 → Prompt 解剖 → 模型路由 → 三条规则"逐层放大。Panel ① 给共享/分叉结构、Panel ② 把三模块并列展开、Panel ③ ④ 是破冰深度 zoom-in(反评 + 意向的等价细节嵌在同一个 Panel 里)。

① 全景图:对话策略的运转逻辑

整套对话策略的核心洞察:LLM 是"会自由发挥的销售实习生",它知道怎么聊,但不知道我们家具体卖什么、价格多少、品牌哪几个。因此方向反过来——中央放一份「事实手册」(brand_profile + customer memory),所有 prompt 在装配时从手册取值。LLM 只负责说话风格,事实层归 PMM。这是这条通道在多品牌、多活动节奏下能稳定运转的根因。

闹钟
Vercel Cron
每 30 分钟拉一批新评论
评论池 + 三路分析(便宜模型先筛)
deepseek-v4-flash
  • analyze.intent   意图分 0–1,过阈值才放行
  • analyze.signals   决策信号检测("想看方案/报个价")
  • analyze.stage   装修阶段分类(写回 conversations.stage
  • Langfuse trace + token 成本归因全程跟踪
高意向才进入路由
状态机 · 公告板
conversations.stage
[stage=ice_break] dm.ice_break.system"看您家在装修,方便聊聊柜体偏好吗?"
[stage=nurture] dm.nurture.system"上次您提到偏好竹板,板材这块我整理了一下…"
[stage=decision] dm.decision.system"那今天把您家 50㎡(按平方 284 一平)三档方案先发您?"
规则 · 一个用户同时只能有一条活跃会话
· 同一条评论 4h 内只允许 claim 一次
· stage 字段由 analyze.stage 写回,
  chatReply 按字段取对应 prompt Supabase conversations
+ message_queue
DM 主通道:qwen3-235b 生成  |  反评公开通道:Python agent + WDA 留评
DM 主通道 · 破冰模块
Prompt 装配
Langfuse 拉 production label
骨架 6 段 + 8 个 slot 注入
LLM 生成
qwen3-235b
chatReply / generateColdOpener
净化 + 安检
sanitizeReply(协议字节扫)
+ post ban check · v16
入队送出
message_queue: pending_approval
→ 运营审批 → ADB / WDA → 抖音
反评公开通道 · 反向评论模块
④'
挑候选
pickCandidates · peer-filter + off-topic 正则
reverse_comment_queue
⑤'
Python agent 生成
local_reverse_comment_agent.py
Langfuse 拉 comment.reverse-comment-system-py-single
⑥'
骨架自检
<<unhookable>> 一票否决
+ <<retry>> 重写
⑦'
WDA 留评
iPhone WebDriverAgent 同行视频下留评
→ 回写 reverse_comment_queue.status
slot 横向注入第 ④ 步(DM 装配)和第 ⑤' 步(反评装配)— 两条通道共享一份事实手册
事实手册 · brand_profile + memory(所有 slot 的单一来源)
{{persona}} {{brandConfig}} {{pricingTable}} {{trustClaims}} · v26 {{showroomHooks}} · v26 {{customerMemory}} {{videoContext}} {{conversationHistory}}
来源 = brand_profile(PMM 维护,价格 / 品牌 / 政策 / 钩子)+ src/lib/memory.ts(跨会话客户画像,shallow-merge 成自然语言短句)+ 当前评论 / 视频 / 会话上下文。
PMM 改一次手册,所有 stage 的生成瞬间生效,不动代码。

双通道 7 跳架构 · 上半 = 破冰模块 DM 主通道 / 下半 = 反向评论模块公开通道 · 共用 ② 三路分析(意向模块)+ ③ 公告板 + ★ 事实手册
详见 src/lib/prompts.ts + src/lib/memory.ts + src/lib/reverseComment.ts + worker/scripts/local_reverse_comment_agent.py

② 三模块各自的内部架构

把 Panel ① 全景图里"分析层之后的部分"放大,三个模块并列展示各自从上游输入到出口落地的运行链。颜色与 Section 0 模块卡对齐:蓝=破冰 / 紫=反评 / 绿=意向。

破冰 · DM 主通道
① 触发意向分 ≥ 阈值 → 进入 stage 路由conversations.stage
② 取 promptLangfuse 拉 dm.ice_break.system / nurture / decision production label
③ 装配 slotpersona + brand_profile + memory + video / conversation 共 8 个 slot
④ LLM 生成qwen3-235b · chatReply / generateColdOpener
⑤ 净化 + 安检sanitizeReply(协议字节)+ post ban check v16(绝对化 / 陌生品牌)
⑥ 入队送出message_queue · pending_approval → 运营审批 → ADB / WDA → 抖音 DM
骨架颗粒度:高自由度(6 段 + slot),LLM 负责风格与应变
反评 · 公开通道
① 候选挑选pickCandidates 用 peer-filter + off-topic 正则过滤同行视频评论池
② 入 30d cooldown 队列reverse_comment_queue,每 sec_uid 30 天去重
③ Python agent 拉 promptlocal_reverse_comment_agent.py · Langfuse get_prompt comment.reverse-comment-system-py-single
④ skeleton 注入 + LLM注入 5 个 slot(skeleton / source_comment / video_title / nickname / no_title)→ LLM 生成 4 步话术
⑤ 双类自检<<unhookable>> 一票否决 / <<retry>> 错称呼即重写
⑥ WDA 留评 + 回写iPhone WebDriverAgent 串行在同行视频下留评 → reverse_comment_queue.status = posted
骨架颗粒度:低自由度(skeleton + 4 步),LLM 必须按骨架走
意向 · 分流闸门
① 拉评论池Cron 抓 douyin comments 最近一批,按 batchSize 分块
② 正则预筛(省 token)peer-filter(同行画像)+ off-topic(家电 / 促销 / AI 指令)正则先过
③ 取 promptLangfuse 拉 analyze.comments.system production label
④ LLM 四轴打分deepseek-v4-flash · 输出 type / specificity / freshness / category 四轴 JSON
⑤ deriveIntent 合成前 3 轴按公式合 score;category=off_topic short-circuit 到 label='无关'
⑥ 三向分流高意向 → DM 候选池 / 中意向 → 反评候选池 / 无关 → 丢回评论池
骨架颗粒度:结构化输出(4 轴 JSON),下游公式合成分数

每列 6 步同形结构(触发 → 取 prompt → 装配 → LLM → 自检 → 出口),但实现栈各自一套——同形不同实现是这套架构能各自演进又不互相牵扯的关键。

③ 一条破冰穿过对话策略链路的 7 步

1

触发

Vercel Cron 拉一批新评论,按账号分批入队。

/api/cron/analyze
2

意图打分

analyzeComments 调 analyze.intent.system 给买家意图打分。

deepseek-v4-flash
3

路由

命中高意向阈值 → 进 generateColdOpener;否则丢回评论池。

stage 判定
4

取模板

Langfuse 拉 dm.ice_break.system 的 production label。

prompt @v30
5

装 slot

persona + brand_profile + 客户 memory + 视频上下文注入。

slot inject
6

生成

chatReply 按"对话路"调风格化模型出文案。

qwen3-235b
7

净化 + 安检

sanitizeReply + 后置 ban check,命中即拦下不发;过关写 message_queue。

post-process
关键点(破冰):分析 prompt(第 2 步)和对话 prompt(第 6 步)在同一条链路上接力。打分先用便宜的 deepseek 把池子过滤掉 80% 不值得发的;只有命中阈值的,才把贵的 qwen3-235b 拉进来。

反评模块 · 7 步类比

1

候选挑选

pickCandidates 在同行视频评论池里过滤同行 / 家电 / 硬装。

pickCandidates
2

cooldown

每 sec_uid 30 天去重,写 reverse_comment_queue

30d cooldown
3

装 skeleton

Python agent 拉 Langfuse,注入 skeleton + source_comment + video_title + nickname。

py-single
4

LLM 生成

Python agent 调 LLM 出 4 步话术(1 段连贯、禁止换行)。

LLM (cfg)
5

骨架自检

命中 <<unhookable>> 拒;命中 <<retry>> 重写。

unhookable / retry
6

WDA 留评

iPhone WebDriverAgent 在同行视频下串行留评。

worker WDA
7

回写状态

reverse_comment_queue.status = posted,留评 URL 待对方私信回流。

queue 回写

意向模块 · 5 步类比

1

拉评论池

Cron 抓 douyin comments 最近一批,待打分。

comments fetch
2

正则预筛

peer-filter + off-topic 正则先过一遍,省 token。

peer-filter
3

LLM 打分

analyzeComments 调 analyze.comments.system。

deepseek-v4-flash
4

四轴合成

deriveIntent() 用 type+specificity+freshness 合 score;off_topic short-circuit 到"无关"。

deriveIntent
5

分流

高意向 → DM 候选池;中意向 → 反评候选池;无关 → 丢。

dispatch
关键点(三模块对照):三条 pipeline 都是"取上下文 → 拉 prompt → LLM 生成 → 自检 → 出口",但每一步的执行方完全不同:破冰是 TS / qwen 走 ban check;反评是 Python / 配置模型 走 unhookable+retry;意向是 TS / deepseek 走 deriveIntent。骨架同形,实现各自一套。

④ Prompt 内部解剖:6 段骨架 + 8 个 slot 注入 + 1 道外层安检

§(P) persona小艳的角色档案:名字 / 品牌 / 语气 / 被问"你是机器人吗"时怎么回。
§③ 业务边界全屋定制 = 柜体 + 硬装 + 软装 + 家电预留位;OFFTOPIC_RE 偏题收口。
§(H) 报价放行 · v22报价两条件:客户先问 + 数字来自 brand_profile,否则不报。
§(W) 联系方式强意向信号才允许说"加我微信";正常对话禁透微信号。
§(p) self_check · v14生成前自问三件事:陌生品牌?泄露后台指令?强行推销?
§softening · v23客户拒绝时从 fallback_lines 挑一句温柔挽回,只挽留一次
post ban check · v16外层最后一道:绝对化措辞、陌生品牌、协议字节,命中即拦。

装配时注入的 slot

{{persona}} — 当前账号绑定的销售身份卡
{{brandConfig}} — 板材 / 五金 / 品牌矩阵(PMM 维护)
{{pricingTable}} — 锚价 / 活动价 / 配置系数表
{{trustClaims}} · v26 — ENF / 假一赔三 / 品牌三选一
{{showroomHooks}} · v26 — 样板房 3 条钩子
{{customerMemory}} — 跨会话客户画像(自然语言短句)
{{videoContext}} — 这条视频的标题 / 评论原文
{{conversationHistory}} — 当前会话历史(按 stage 截断)
关键点(破冰):骨架 6 段全部归工程 review,PMM 不直接动;slot 8 个全部归 brand_profile / memory 这两层数据,PMM / 运营自己改 brand_profile 即时生效。骨架管"什么时候怎么说",slot 管"具体说什么"。

反评模块 · 4 步话术结构 + 2 类自检

① 称呼对方严格按【🔒 称呼锁】判定:身份词 / 男女后缀 / 典型男女字 / 性别不明裸名 / 英文 emoji 兜底"朋友"。错称呼即 <<retry>>
② 视频引用必须挂钩对方此条视频里 1 个柜体 / 装修具体点(型号 / 材料 / 收纳 / 数字)。视频无标题时跳过此步、压成 3 步。
③ 销售肯定销售视角给一句肯定回答 / 经验判断("能做" / "够" / "这一行经验上看…"),不许写"得看板材"等延展难点。
④ 反问 + 私信钩开放反问(户型 / 进度 / 痛点 / 场景 4 类之一)+ 一句含「私信」的钩子("私信发你看看" / "方便私信细聊")。
<<unhookable>>原评论涉及重级土建 / 家电品牌选购 / 物流维权 / 与全屋装修零交集 → 直接输出 unhookable 不生成。
<<retry>>错称呼 / 「家人们」/ 「友友」/ 凭空猜户型预算 / 编原评论不存在的关键词 → 重写一遍。

反评装配时注入的 slot

{{skeleton}} — 本次必须采用的话术骨架
{{source_comment}} — 对方此前的公开评论(理解意图)
{{video_title}} — 对方此条视频标题
{{author_nickname}} — 对方抖音昵称(推断称呼用)
{{no_title_clause}} — 标题缺失时的兜底子句

意向模块 · 四轴 anatomy + short-circuit

type评论意图大类:product(问产品 / 价格 / 配置)/ life(生活吐槽 / 感慨)/ off_topic(无关)。
specificity具体程度:specific(带户型 / 面积 / 预算等具体信息)/ general(仅泛问)。
freshness时效信号:fresh("正在装" / "刚交房")/ aged(已装好 / 已成交)/ unclear。
category细品类标签:cabinet / hardcoat / softcoat / appliance / off_topic 等。
off_topic short-circuitcategory=off_topic 在 deriveIntent() 里直接到 label='无关'——家电 / 数码 / 促销询券防漏网。
★ HIGH RISK改动会决定哪些客户进高意向队列、谁触发 DM 和反评。PM 改完务必 dry-run ≥15 条历史评论看分布;任一档 >80% = 定义有问题。

意向 prompt 的 slot 和输出

{{batchSize}} — 本批评论条数
{{commentList}} — 格式化后的评论列表(带 video 上下文)
输出 每条评论一个 JSON 对象 + type_reason / category_reason 推理字段
下游 deriveIntent() 用前 3 轴合成 score;公式留代码层,PM 改不到
共享 peer-filter.ts 给反评 + 破冰共用,避免重复维护
关键点(三模块对照):骨架的"颗粒度"对应模块自由度——破冰 6 段(高自由度,靠 slot 注入事实);反评 4 步(低自由度,靠 skeleton 锁定切入路径 + 双类自检);意向 4 轴(结构化输出,靠 deriveIntent 公式合成分数)。模块越公开、越无法人审,骨架颗粒度越细。

⑤ 模型路由:对话路与分析路各走各的

对话路 · qwen3-235b

风格化、有人设、贵但能聊。LLM_CHAT_MODEL 单独覆盖。
  • generateColdOpenerdm.ice_break.system
  • chatReply(stage=ice_break)dm.ice_break.system
  • chatReply(stage=nurture)dm.nurture.system
  • chatReply(stage=decision)dm.decision.system

分析路 · deepseek-v4-flash

便宜、稳定结构化 JSON 输出。LLM_ANALYSIS_MODEL 单独覆盖。
  • analyzeCommentsanalyze.intent.system
  • detectDecisionSignalsanalyze.signals.system
  • classifyDecorationStageanalyze.stage.system
关键点:聊天和分析是两件完全不同的事。聊天要风格化、贵也认;分析只要稳定结构化 JSON,便宜模型够用。两路独立路由的好处是——任一方换模型只动一边,不互相牵扯;全局 LLM_MODEL 仍可一键回滚到统一模型,作为兜底。

⑥ 三条不变的规则

3

演进路上踩过的坑 & 现在要管的风险

破冰模块从 v10 一路打补丁到 v30(当前生产),每出一类翻车就在 prompt 里加一段永久防护;反评模块从 v1 内容创作者视角换到 v4 销售路线后持续迭代到 v14;意向模块从 v1 单值 intent 拆轴到 v10 四轴。现在三个骨架都稳了,下面要管的不再是"AI 会不会说错话",而是数据治理、法务边界、灰度纪律——下面 6 个风险三个模块都受影响。

A · 三模块各自的特定风险

破冰风险

brand_profile 冷启动

v26 新增 4 段 slot、v30 又把价格口径切成每平方米 284 一平(依赖 budgetTable),但线上 brand_profile 字段仍偏空。PMM 没一次性填齐就 promote,破冰文案会大面积命中 fallback。

反评风险

skeleton 池窄 + 趋同

当前只有 1 套 skeleton(销售路线),所有视频品类共用。骨架太窄会导致留评趋同,被同行运营识破"批量发评论的脚本"。本周要扩到 8 套并按 video tag 路由。

意向风险

off_topic 词表盲点

"618 / 双 11 / 蹲一波 / 满减券 / 家电品牌 / 自建房" 词表是手写维护。新型促销 / 新品牌冒出来时漏过,下游 DM 和反评候选池会被噪音塞爆。

B · 三模块共通的全局风险

共通风险

换模型的协议字节

三模块都依赖 Langfuse + LLM。破冰下游有 sanitizeReply + ban check 兜底;反评 / 意向没有同等强度防护。任何换模型动作都要先做协议字节回归再放灰度。

共通风险

法务边界

"假一赔三"等承诺类、"全国唯一"等绝对化措辞,三模块的 prompt 都涉及。法务过一遍后统一进全局禁词表,比每个模块各自维护可靠。

共通风险

版本回滚 / label 漂移

三模块共用 Langfuse staging → production label。promote 前 audit-data 必须 pass;线上失控时回退 label 而不是改代码。改意向模块还要额外 dry-run 看分布。

给同事的讲法:骨架稳之后,三个模块要管的不再是"AI 会不会说错话",而是"PMM 数据齐不齐、法务过不过、灰度看哪个指标、回退按哪个键"——尤其意向分析改一次会同时影响破冰和反评的候选池,dry-run 历史分布是硬规定。
4

三模块下一步

三个模块全部在线上最新版(破冰 v30 / 反评 v14 / 意向 v10)。下一步是把刚 promote 的版本观察稳,再各自推下一轮——破冰跑 v30 价格口径灰度、反评扩 skeleton 池、意向上多模态。任一模块改动都先 staging → audit-data → 灰度。

破冰模块

v30 价格口径灰度 → v31

  • 已落地 · v26(2026-05-29 13:03 promote)后五天四轮迭代:v26 直辖市 IP 脱敏修正 → v27/v28 prompt-health 收 5 条告警 + 3 道 systemic 守卫 → v29 §(B) 面积+总价强制走预算三档 → v30 价格口径投影→每平方米 284 一平(全面禁 投影 / 568 旧价)。
  • 本周 · v30 vs v25 灰度对比:v25 末轮基线 95.6%(583/610),盯主指标加微率、次指标 DM 触线率 + 报价口径一致性(不再出现投影/568)。
  • 下周 · 数据稳的话全量稳定 v30;不稳则 label 回切上一版保业务,问题在 staging 上修。
  • 规模化 · 多品牌复用:只换 brand_profile,prompt 骨架不动;v31 准备把 nurture / decision 两段也按 v26 同款 slot 重构。
反评模块

v14 稳态 → 扩 skeleton 池

  • 今日 · v14 当前生产(最近一次 promote 2026-05-18):单 skeleton + 4 步话术 + <<unhookable>> / <<retry>> 自检全跑通;7d 273 次调用。
  • 本周 · skeleton 池扩到 8 套:按视频品类(柜体 / 硬装 / 软装 / 收纳 / 户型槽点 / …)各自一套切入路径,picker 按 video tag 路由。
  • 下周 · 留评回流率指标接 Langfuse trace:把"留评 → 对方私信回复"配对,看哪类 skeleton 钩对方私信效率最高。
  • 规模化 · 多账号 Python agent 并发跑,reverse_comment_queue 加 per-account 配额隔离。
意向分析模块

v10 稳态 → v11 多模态

  • 今日 · v10 当前生产(最近 promote 2026-05-28):type / specificity / freshness / category 四轴 + reasons;off_topic short-circuit 拦家电 / 数码 / 促销询券;7d 2,373 次调用(量最大)。
  • 本周 · off_topic 词表回归:补"家电 / 硬装 / 促销 / AI 指令"4 大类正则盲点(peer-filter 共享给反评 + 破冰)。
  • 下周 · v11 草案:加 product_category 字段(柜体 / 硬装 / 软装 / 家电预留 / 重级土建),让下游 pickCandidates 走分类 filter 而不是堆正则。
  • 规模化 · 多模态升级:把视频封面 / 视频标题一起喂给模型,处理短评论"价格?"这类无文本上下文的客户。
收尾建议:三个模块独立演进,但任一改动都先走 staging → audit-data → 灰度——尤其意向分析改动会同时影响破冰和反评的候选池,dry-run 历史分布是硬规定。下一阶段重点是把 PMM、法务、运营拉进事实手册(brand_profile)的维护链路,让骨架背后的事实层一直保持新鲜。
+

附录:如果同事追问细节

这部分可以不主动讲,但可以用来回答深一层的问题。

A · 三模块各自的版本演进

破冰追问

v10 → v30 版本演进

v10+ 智能称呼 3 层 · v14 §(p) self_check · v16 后置 ban check · v22+ §(H) 报价类放行 · v23 §softening · v25 末轮 95.6%(583/610)· v26 §(B) 预算 / §(T) 信任 / §(C) 收口三段 + 4 slot + 直辖市 IP 脱敏 · v27/28 prompt-health 收告警 + 3 道 systemic 守卫 · v29 §(B) 面积+总价强制走预算三档 · v30 价格口径投影→每平方米 284 一平(禁投影/568)。Langfuse 上累计 30 个版本。

反评追问

v1 → v14 视角换血 + 持续打磨

v1-v3 内容创作者视角(留评像水军、钩不到 DM)· v4 切销售视角(2026-05-13 与夏夏 Lark 对齐)· v5-v14 打磨称呼锁、unhookable 触发面、私信钩子句式 · TS multi-skeleton 路径下线,统一走 Python single-skeleton;fallback 字字对应 PYTHON_REVERSE_COMMENT_FALLBACK。Langfuse 上累计 14 个版本。

意向追问

v1 → v10 四轴稳定

v1 只输出 intent 单值,下游难以 short-circuit;v2 拆成 type / specificity / freshness / category 四轴 + keywords + reasons,v3-v10 持续在 off_topic 词表、reasons 句式、batchSize 上打磨。Langfuse 上累计 10 个版本。改动直接影响破冰和反评的候选池分布,risk HIGH。

B · 三模块共通的工程约定

两层 LLM 路由

chat / analysis / agent 三栈

破冰:chatReplyqwen3-235b;意向:analyzeCommentsdeepseek-v4-flash;反评:Python agent 单独配。全局 LLM_MODEL 仍可一键回滚到统一模型。

客户记忆

自然语言而非 KV

跨会话 memory 合成一句自然语言:"这位客户在杭州、110㎡、关心环保",写进破冰 system prompt。反评不读 memory(公开通道无配对客户);意向只看当条评论上下文。

紧急回退

label 切回上一版

Langfuse 把 production label 切回上一版即时回退,不走代码 revert——避免 prompt 与 fallback 文件不一致。三模块同一套规则。

C · 速记 6 条