起因是一份「客户问什么就自动发对应资料」的方案,里面有 6 个地方拿不准要人拍板。这一页把真实数据翻出来,把这两件事定下来。
他想做一条全自动的流水线,让机器人代替人做这几步:
你们已经攒好了 314 份文档、11071 张效果图、27 条话术。方案说:内容都齐了,就差把它自动跑起来。
第 2 步「机器人怎么听出他要什么」,方案的做法是列一张关键词表——客户说到"避坑""防水""合同""报价"这些词,就对上号发对应的资料。这张关键词表,是整个方案的心脏。
我拿你们真实的客户私信跑了一遍,发现:① 方案的核心零件(靠关键词认出客户要什么)在真实客户面前基本失灵;② 它要优化的那一步,几乎没有客户走到;③ 真正卡住我们的,是客户开口要资料时我们的反应——而这个不用建知识库就能改。
我把你们 657 条真实客户私信翻出来看(剔掉了 71 条测试用的假数据)。真实客户是这么说话的——
| 用什么方式认客户 | 认出来几条 | 其中真该发资料的 |
|---|---|---|
| 方案的关键词表(话题词 × 索取词) | 5 | 0 |
| 系统里已经有的一段判断逻辑 | 4 | 4 |
| 新表比现有的多认出来的 | 5 | 0 |
那 5 次触发,逐条看是什么人:1 个同行("我是做水电安装的,谢谢你"→ 系统看到"水电"就想发水电攻略);1 个明确说不装了的("暂时还没有改的计划"→ 系统看到"报价"两个字就想发报价表);2 条是脏数据(我们自己的话术被错存成了客户消息,系统认了自己);1 个真有需求的,但他要的是找人来修漏水,不是要一份防水 PDF。
我按真实私信记录,把整条路重新数了一遍:
| 客户表现 | 人数 | 最后真给了微信/电话 | 转化率 |
|---|---|---|---|
| 开口要过资料的 | 20 | 3 | 15% |
| 没开口要的 | 120 | 6 | 5% |
原因一:5 个我们压根没回。客户问「不是送资料吗?」「现在不能发我看看吗?不是说留言就发吗?」——我们沉默。
原因二:剩下 12 个,我们回了、也说了理由,人还是走了。
注意——现在的话术已经在说「抖音发不了/图会糊」这个理由了:
照样失败。所以"把理由说清楚"不是缺的那一环——我们已经在说了。
成功的(客户下一句就给号):
→ 客户回:「好的!联系方式 13438622988」
失败的:
| 做法 | 话术长什么样 | 结果 |
|---|---|---|
| ✗ 现在这样 反问 + 要微信 |
「抖音图压糊,你家几室几厅?给个 v 我发你」 | 已实测失败 客户要的是现在,你却又给他派了个活 |
| ✗ 也别这样 把整份清单文字全发过去 |
「好的,避坑清单第一条…第八条…」 | 丢筹码 他拿完就走,没理由给微信了 |
| ✓ 这样 已完成态 + 一小块真货 + 要微信 |
「你家 113 平三室对吧——同户型那份我已经拉出来了,光柜体投影就 78㎡,最容易多花钱的是吊柜层板和五金这两项。整份是带图的表格,抖音发不了文件、发图也会压糊,加个 v 我直接发你。」 | 待验证 成功的 3 个案例都是这个形状 |
| 形式 | 能不能用 | 说明 |
|---|---|---|
| 发链接 | ✓ 白捡,直接用 | 314 份文档里 311 份已经有公网链接了,文字里塞个网址就行。还能看到谁点了 |
| 发图片 | ✓ 能力已有 —— 但你们没用 | 企微早就能发图了。而你们手上有 11071 张效果图 + 120 组知识图集——客户要的"参考图""清单图"本来就是图。只差把图传上公网(现在只传了文档)。 |
| 发 PDF 文件 | ✗ 别做 | 要从零建能力 + 改出口白名单。而链接能达到一样的效果,客户在手机上点开还更顺手 |
25cd140,五端已对齐核实)。以下改动现在就在跑。
| 什么情况 | 以前 | 现在 |
|---|---|---|
| 客户说"要资料" | 甩我们的号 | 不甩 → 走承接话术 |
| 客户怼"这是 AI" | 甩我们的号 | 不甩 → 要他的号 |
| 客户问"能不能上门" | 甩我们的号 | 不甩 → 要他的号 |
| 客户明说"加个微信/怎么加你" | 甩号 | ✓ 保留,照样甩 |
| 聊到第 5 条还没换到联系方式 | 无条件甩号 | ✓ 保留,照样甩(长尾收口) |
| 客户主动给了自己的号 | "我们添加您啦…" | ✓ 一字未动 |
留了开关 AKKE_HARD_GATE_WECHAT=off,以后想回测「不主动甩号是不是转化更高」,一行就能关。
客户开口要资料时,必须按这四步回,禁止反问「你家几室几厅」:
关键是没只写 prompt。光求 LLM"别反问"压不住——因为它是真不知道客户家几室几厅(那 20 个人里 0 个说过)。所以加了一道代码硬闸:
撞车:4 轮兜底是绕开 LLM 直接甩号的。客户要是聊到第 5 轮才开口要资料,原本会收到一个光秃秃的号、他要的东西一个字不提——正是我们刚测出来会赶走人的那句。
现在这种情况发的是合并话术:号照样甩(收口没丢),但资料给到位。实际长这样——
给了双向出口——他懒得加就报个号,我们去加他。客户没在要资料时(问板材、问价格),还是走原来那条纯甩号模板,一个字没动。
转人工的量可能会上来。如果 LLM 还是老想反问户型,那些草稿会全部被闸拦下、堆到人工那儿。
这是故意的——宁可让人接手,也别发一句已被实测证明会赶走客户的话。但要盯 needs_human 的量:堆太多说明 prompt 没压住,得再收。
回测口径:657 条真实入站私信 = messages 表 role='customer' 全量 728 条,剔除 71 条无 messaging_account_id 绑定的 seed 数据。词典照抄 spec 3.1 原文,索取意图词表按页面「推演 2」的对策实现。
问题 2 插桩点:应挂 src/lib/dm-reply/run.ts 的 processAwaitingRow——已有 4 条同形确定性旁路(run.ts:99/172/217/257),能拿到 stage / 完整历史 / 原评论 / 跨会话我方消息。不要挂 poll agent:DOM 捕获只读会话列表预览(约 60 字截断),请求体只有 conversation_id。会打架的是 src/lib/dm-reply/wechat-push.ts 的 _WANT_MATERIAL_RE(已在识别"客户要资料",动作是推号)。新旁路不能抢在"客户主动给号"承接之前。
问题 4 硬闸:罐头必须过 gate.ts 的 MAX_LEN=200(超了转人工,不是截断)+ guardrails.ts 的 mergeToSingleParagraph(换行会被云电脑打成 Enter,一条草稿拆成两个气泡,回执验证必假阴)。零间隔连发在 douyin_dm_autoreply.py:219-243。
事实错误对应:① 「每类限 1 条」删于 PR #843 / 225e2e22(2026-07-10),现为相关度排序 llm.ts:345-375。② 主动发号的 3 处:llm.ts:742/744/745(兜底话术)、llm.ts:2362(4 轮硬门)、wechat-push.ts:111(意向推微信);opener 侧的代码级兜底在 llm.ts:3500。③ role 污染样本:会话 5ac33f5a 连续两条 customer,第二条为我方话术。
问题 6 补充:语义重排实现在 src/lib/llm/embed.ts(bge-m3 + 内存 cosine + 进程级 LRU),默认开启(fail-open,LLM_SEMANTIC_RERANK=off 才关),门控 llm.ts:1223 只放行企微 persona / channel==="weixin",抖音 DM 明确不进。DB 侧 pgvector 从未 enable,008_knowledge_base.sql:27,55 的 embedding vector(1536) 是注释。
已落地(PR #865 · commit 25cd140):① wechat-push.ts hasWechatPushIntent 拆为 hasExplicitAddIntent / hasMaterialRequest,shouldIntentPushWechat 只认前者。② llm.ts hardGateWechatEnabled() 默认 true,AKKE_HARD_GATE_WECHAT=off 可关。③ llm.ts 新增 buildHardGateMaterialHandoffText(176 字 < gate MAX_LEN=200,有单测锁);硬门分支按 isDmMaterialRequest(latestUserMessage) 分流,provenance promptName 区分 hard_gate_r5_material_handoff / _wechat_push。④ gate.ts 新增 asksLayoutBack 硬闸。⑤ isDmMaterialRequest 下沉 llm/signals.ts(llm → dm-reply 是反向依赖,wechat-push 改为转发,避免两处 regex 漂移)。⑥ 顺带修 latestUserMessage TDZ(原定义在硬门之后,硬门分支引用会运行时崩)。tsc 通过,全量 522 测试全绿。
问题 5 补充:企微发文件 0 代码(GUI 侧只有剪贴板发图,kf API 只有 msgtype:"text",且 wecom-proxy 白名单未开 media/upload)。DM 抓到的微信号只写 dm_notify_state + 推 Lark,无任何代码写入加好友队列;活的待加队列只有 enterprise_leads(吃 B 端 xlsx 线索,customer_leads 已退役)。我方承诺话术写死在 wechat-push.ts:128。