Akke · 企微好友单聊
7 天召回 · 部署与验证指南
给企微好友里加了资料就沉默的客户做召回:结合抖音+企微对话和画像,从甲方话术库里挑 7 个可能戳中他的话题,每天发一条、连推 7 天,把人唤回、最终邀约到店。这一页写给帮忙部署验证的同事——照着走即可。
01它是怎么跑起来的
一条流水线,两半:服务端「大脑」选人选话术,云电脑「手」去发。
027 天召回的逻辑
这套系统怎么决定「发给谁 · 发什么 · 发几次 · 什么时候停」——设置召回前先看懂这四件事。
① 谁会被召回:入池 4 个条件,全满足才进
handed_off 自动豁免,不打扰)这四条每天扫一遍自动判定。他一旦回复,「最后一条」就变成他发的 → 第 2 条自动不成立 → 当天起不再召回(自清场,不用人管)。
② 发什么:7 个话题怎么挑、怎么排
客户首次进池那一刻,系统让 AI 看他的抖音+企微对话和画像,从下面这个话题库(甲方话术 9 类 + 4 个画像钩子,共 13 项)里挑出 7 个最可能戳中他的、排好顺序、一次冻结(后面 6 天都照这份走,不天天重挑)。
AI 选中话题的 3 条标准:
- 贴他的实际诉求和画像——他最初求什么、聊到过什么(户型 / 面积 / 城市 / 风格 / 预算 / 顾虑),就优先选相关话题。
- 画像钩子只在画像真有对应信息时才选——比如没读到城市/户型就不选「同小区实拍」,防止 AI 脑补穿帮。
- 由浅入深排序——先勾兴趣、再谈价值、后推行动,不会第 1 天就硬推报价或催名额。
9 类 · 主动可抛
| 话题 | 聊什么 | 什么样的客户会被选中(标准) |
|---|---|---|
| 产品核心配置 | ENF 环保兜底 · 三大品牌板材任选 · 悍高五金 · PUR封边 · 六面防伪 | 还没确认过配置/价格,或最初就是冲板材 / 性价比 / 环保来的 |
| 正品与品质保障 | 环保补充协议 + 假一赔三,白纸黑字盖公章、有法律效力 | 可能担心品质 / 真假,性格谨慎,或问过品牌真伪 |
| 标准化服务流程 | 设计→生产→安装→售后全流程 SOP,总部系统全程兜底 | 担心售后 / 交付掉链子,或第一次装修没经验 |
| 样板房活动稀缺性 | 568 补贴的由来,名额按套限量、抢完即止 | 有一定意向但在犹豫 / 拖延,需要一个行动理由 |
| 样板房专属权益 | 每平直降 300 + 品质工艺加码 + 顶配设计师和安装班组 | 在意性价比 / 预算,或想要更好的设计与落地效果 |
| 报价与预算 | 按面积给个总价区间的钩子(细清单留到到店算) | 问过价格 / 预算,或画像里有面积但没报过总价 ⚑ 需画像有:面积 / 户型 |
| 板材防伪与选材 | 六面防伪 vs 5 个防伪等级,选板材看等级+基材才不踩坑 | 在多家比价,或很在意板材真假 / 等级 |
| 售后方案 | 免费基础(保修1年+终身保养)/ 升级 5 年超长保修,二选一 | 担心后期维修找不到人,或问过质保 |
| 品牌与口碑答疑 | 客观看待网上评价(有评价=正规品牌),绝不主动评竞品 | 提过对品牌的疑虑,看过负面评价,或问过认不认识某品牌 |
4 个 · 画像里有对应信息才选
| 话题 | 聊什么 | 什么样的客户会被选中(标准) |
|---|---|---|
| 同小区/同户型实拍 | 拿他所在城市/小区或同户型的真实落地案例勾(「你们那边刚做完一套同户型」) | 用地域/户型相关性制造「这跟我有关」的信任 ⚑ 需画像有:城市 / 小区 / 户型 / 面积 |
| 免费效果图钩子 | 针对他户型/风格,提「可以先给你出个参考效果图看看」 | 表达过要效果图/看设计,或画像有明确风格/户型 ⚑ 需画像有:风格 / 户型 / 面积 |
| 风格灵感/搭配建议 | 顺着他偏好的装修风格(法式/极简/现代…)聊落地要点或搭配 | 画像里有明确装修风格偏好 ⚑ 需画像有:装修风格 |
| 新样板房名额 | 同步「本片区新放出样板房名额」的限时钩子,给一个再聊的由头 | 之前有意向但沉默,需要一个不突兀的重启话题(无画像门槛,可兜底) |
选好后,每天取当天那个话题,结合他的画像写成一条自然的、主动勾回的话,不是干巴巴甩海报——实测里客户就是被「重复自我介绍 + 重问已知信息」这种话问沉默的。
③ 发几次、隔多久:节奏时间线
前 3 次每天一条;连推 3 次他都没回应 = 暂时不想聊,系统自动放慢到隔天一条,把剩下 4 次摊开——既保持节奏、又压低骚扰/拉黑/封号风险。7 个话题走完约 1.5 周。(这就是你定的「连推 7 天、遇信号退避」。)
④ 随时可能提前出库:三个停止条件
03两块拼图
Block A 是服务端「大脑」(已上线),Block B 是云电脑「手」(本次要部署验证的部分)。
Block A服务端大脑
已合并部署、迁移已 apply。全程 dry-run,什么都不发。
- 新建召回队列表 + 节奏状态表 + 派单/回执/选题 RPC
- 候选筛选 + LLM 选 7 话题 + 按画像写当天话术
- cron 派单 + 端点
claim_recall/complete_recall供云电脑拉/回执
Block B云电脑主动发起腿
代码已在 main。云电脑现在只会被动回未读,这条腿补上主动找人发——按阶段 B 更新上去。
- 经端点领当天召回话术 → 点搜索框搜客户名
- 身份门:读会话标题匹配才发(无 DOM 下防发错人的唯一防线)
- 复用现有发送 + 落库 + 计数;发后 VL 探红点感叹号判是否被删
04部署流程 · 加到云电脑现有的企微自动回复上
召回腿和被动代回是同一个 loop——部署 = 更新那个文件 + 加几个 env + 量一个坐标 + 重启。分四个阶段:先配后台,再更新云电脑,空跑验证,最后灰度真发。
C:\akke-wecom\wecom_reply_loop.py 那个常驻脚本,现在多了一条召回腿(代码已在 main)。它跟原来的被动代回串在同一个 loop 里、不抢窗口,且默认关。所以不用新装东西,只是把这个文件更新到新版 + 配置 + 逐步打开。全程被动回复照常工作。
在此之前云电脑腿一直开着、cron 每 2h 也在跑,但服务端那道真发闸从没打开 → 只算候选不写队列 → 一条召回都没真发过(队列 7/18 之后零新行、wecom_recall_state 全是 touch_count=0)。现在闸开了,首次真派单 = 07-21 16:00。
开的方式是翻代码里的默认值,不是设 Vercel 环境变量 —— akke 项目挂在 Gus 的 team 下,其他人改不到线上 env。所以下面凡是写「去 Vercel 设 WECOM_RECALL_AUTOSEND_ENABLED=true」的地方都已作废,见阶段 D。
服务端配置
后台一次性,新人接入才需要动-
✅ 建企微销售号的账号行 —— 已由我建好(每个操作员一行)
召回按各自账号走、按人设隔离(只发自己的客户)。已建好这两行,阶段 B 填你自己那行的 id:
操作员 persona AKKE_ACCOUNT_ID(阶段 B 用) 野荞(小文) xiaowen 0242b7ff-e003-44df-b929-ce71722e6853 饭粒(小范) xiaofan a78b96e9-5acb-4946-ae5a-f365e0854acb 夏夏(小夏) xiaoxia e494e462-21dd-445b-b1b5-1327861c12ed Gus(小武) xiaowu 297b50a4-6ade-4070-b934-18d456ba0941 子扬(小杨)新 xiaoyang 89aff532-3657-4f7a-a2f3-149f4182d2fb 加新人要做两件事,别只做一件:
① 建账号行:channel_pref='wecom'+wecom_persona=<key>,零代码。
② 确认这个 persona key 在代码里存在(SALES_PERSONAS,src/lib/llm.ts)。这步不是零代码 —— key 不在注册表里不会报错,而是静默回退成小艳(抖音 DM 的默认人设),企微那套价格口径、风格块、召回专属块全都不生效,人却照发。小杨(xiaoyang)是 2026-07-21 新加的第 5 个壳,已在代码里。 -
✅ persona 已随账号设好 —— 不用再动 Vercel
人设现在设在账号行上(
accounts.wecom_persona=xiaowen),已建好。每个操作员的账号带各自人设、只发各自客户,互不串。全局WECOM_RECALL_PERSONA只在账号没填时兜底 —— 各操作员不用设。
真发总开关已于 2026-07-21 打开(改的是代码默认值,Vercel 那边不用设也设不了),细节见阶段 D。
更新云电脑上的自动回复
操作员(野荞 / 饭粒 / 夏夏 / Gus / 子扬)在自己的云电脑 PowerShell 里按顺序跑,每步看一眼输出;被动回复不受影响AKKE_WECOM_CROP_RATIO=0.18 会把客户气泡 + 会话标题整个裁掉 → 机器人把自己发的话当成客户消息回复、自问自答,还会真发出垃圾(饭粒那台回过「哈哈您抢我词儿啦」)。日志里出现 客户[小范](自己人设名)或 客户[系统横幅碎片] 就是中招了。先查:
Select-String -Path C:\akke-wecom\.env -Pattern "AKKE_WECOM_CROP_RATIO"是
0.10x 就没事;是 0.18 或日志有自问自答 → 别抄别人的值(跟屏幕分辨率/会话列表宽度绑死),截张企微全屏图发 Claude,它给你算。改完重启生效。
-
停当前正在跑的 loop
ni C:\akke-wecom\wecom_reply_STOP Get-CimInstance Win32_Process | ? {$_.CommandLine -like '*wecom_reply_loop*'} | % { Stop-Process -Id $_.ProcessId -Force } -
把两个脚本更新到新版(wecom_reply_loop.py + measure_wecom_coords.py)🟢 2026-07-21 起:所有机器统一走这一条,不用管有没有 git 仓库
upio.ai上那份分发脚本以前一直没人维护、冻在v2026-07-02.11,现在已同步到最新并会持续更新,直接拉就行:cd C:\akke-wecom copy wecom_reply_loop.py wecom_reply_loop.py.bak-$(Get-Date -f yyyyMMdd) # 先备份,回滚用 iwr https://upio.ai/akke/wecom-chat/wecom_reply_loop.py -OutFile wecom_reply_loop.py核对版本号,必须是
v2026-07-20.redblue-test-22或更新:Select-String -Path wecom_reply_loop.py -Pattern '^VERSION'
⛔ 别从 jsDelivr 镜像拉 —— 那个冻在
v2026-07-02.11(旧版、没召回)。
有 git 仓库的机器(C:\Users下能搜到.git)也可以照旧git pull后 copy,两种都行;measure_wecom_coords.py(量坐标用,只有初次部署/换分辨率才需要)仍走 git 或人工传。 -
.env 加召回 4 变量(RECALL 先关,AKKE_ACCOUNT_ID 填你自己那行)
把
<你的账号id>换成阶段 A 表里你自己那行(野荞0242b7ff…/ 饭粒a78b96e9…/ 夏夏e494e462…/ Gus297b50a4…):Add-Content C:\akke-wecom\.env "`nAKKE_WECOM_RECALL_ENABLED=0`nAKKE_ACCOUNT_ID=<你的账号id>`nAKKE_WECOM_C_SEARCH=`nAKKE_WECOM_RECALL_CLAIM_LIMIT=2"
-
量搜索框坐标 → 填进 .env
cd C:\akke-wecom python measure_wecom_coords.py
鼠标悬停在企微左上角搜索框上,它打印
AKKE_WECOM_C_SEARCH=x,y;把这行填进.env的AKKE_WECOM_C_SEARCH=(纯读坐标,不点击不发消息)。 -
删 STOP + 重启,确认没搞坏现有功能
del C:\akke-wecom\wecom_reply_STOP cd C:\akke-wecom .\start-wecom-reply.bat
黑窗第一行的版本号带
recall-b3(或更新的recall-bN)就对 —— 说明拉到的是含召回的新版;要是还是旧的没 recall 字样的版本,说明git pull/copy没成功,回上一步重来。此时召回还关着,原来的被动自动回复应照常工作。
空跑验证
不发任何消息,验通了再开真发-
✅ 本机 dry-run —— dev 机器(有 repo)上跑,已由我跑过
这步在有代码仓库的电脑上跑、不是云电脑,同事不用管。已跑过,结果:选出 5 个候选、话题/话术正常。需要重跑时:
# 务必带 eval key,不烧生产额度 AKKE_USE_EVAL_KEY=1 AKKE_ORG_ID=00000000-0000-0000-0000-000000000001 \ pnpm tsx scripts/_wecom-recall-dryrun.ts --max=10
⚠️ 候选里可能混着测试/误加的联系人(实测见到
fanny、某工程师号)。真上线前扫一眼那几个候选是不是真客户,不是的把会话标handed_off排除。 -
云电脑 DRY_RUN:空跑验召回腿(野荞做)
用记事本打开
C:\akke-wecom\.env,把这两行改成:AKKE_WECOM_RECALL_ENABLED=1 # 打开召回腿 AKKE_WECOM_DRY_RUN=1 # 只空跑不真发
存盘后重启(建
wecom_reply_STOP→ 删 → 跑start-wecom-reply.bat)。看黑窗日志走完一整条但不真发:[recall] claim 到 N 条待召回 → 搜人 → 身份门读标题 → 点开 → [DRY_RUN] 不真发
重点验三件事点得准:搜到人 · 身份门读对标题 · 点开对话,顺便看红点探测。坐标偏就回上一步重量搜索框。
⚠ DRY_RUN=1 是全局的这期间被动自动回复也会暂时只空跑不真发(同一个开关管整个 loop)。所以别在 DRY_RUN=1 状态停太久;验完召回腿点得准,就进阶段 D 把DRY_RUN改回0,被动回复 + 召回一起真发。
真发(已开)
服务端闸 2026-07-21 打开,日限 5 起服务端现在会派单了。不过队列行只有云电脑侧也开了召回腿的号才会被取走 —— 你那台没开 AKKE_WECOM_RECALL_ENABLED=1,派给你的单就一直 pending 堆着(每号 backlog 门自会短路,不会无限涨),不会往外发。所以「服务端开了」不等于「你被迫上线」,节奏还在你手里。
开关是翻在代码默认值里的(src/app/api/cron/wecom-recall-dispatch/route.ts),不是 Vercel 环境变量 —— akke 挂在 Gus 的 team 下,别人改不到线上 env。所以别再去 Vercel 找 WECOM_RECALL_AUTOSEND_ENABLED 了,那儿没有。
-
云电脑侧开腿,日限压到 5
确认阶段 C 都点得准后,在自己那台的
.env里:# 云电脑 .env AKKE_WECOM_RECALL_ENABLED = 1 # 云电脑 .env AKKE_WECOM_DRY_RUN = 0 # 云电脑 .env AKKE_ACCOUNT_ID = <阶段 A 表里你那行>
重启,盯账号状态没异常再慢慢往上爬。任何异常先建 wecom_reply_STOP 急停(见下方急停回滚)。
服务端日限默认
WECOM_RECALL_DAILY_CAP=5(每号每天最多 5 条),云电脑侧还有一层独立日限AKKE_WECOM_RECALL_DAILY_LIMIT=5,两层都在,取严的那层。 -
第一批盯什么
队列里出现 pending 新行 + 云电脑日志出现
[recall] claim 到 N 条待召回= 通了。然后看三件事:① 发出去的话像不像你本人说的(人设对不对);② 有没有
身份门不匹配的日志(搜到人但开错会话,不发是对的,多了就要查名字);③ 发完有没有红色感叹号(被删 → 那人自动出库)。
05配置清单
两处:Vercel 后台(服务端)+ 云电脑 .env(发送端)。带 开关 的默认关。
Vercel 环境变量(服务端大脑)
| 变量 | 作用 | 建议值 |
|---|---|---|
| WECOM_RECALL_AUTOSEND_ENABLED | 总真发开关。2026-07-21 起默认就是开(代码里翻的默认值),设 false 才回到 dry-run。线上 Vercel 没有这个变量、也改不了(项目在 Gus 的 team 下) | 不用设;要关走急停三档 |
| WECOM_RECALL_PERSONA | 全局兜底人设(现在 persona 存在账号行 wecom_persona,此项仅账号没填时用) | 可不设 |
| WECOM_RECALL_DAILY_CAP | 单号召回日上限 | 起步 5 |
| WECOM_RECALL_MIN_HOURS | 最后一条我方消息隔多久没回才进队 | 24 |
| WECOM_RECALL_COMBINED_HOURLY_CAP | DM+召回合并 1h 活跃门 | 3 |
| WECOM_RECALL_CHANNEL_PREF | 企微号在 accounts 的通道值 | wecom |
云电脑 .env(发送端,C:\akke-wecom\.env)
| 变量 | 作用 | 值 |
|---|---|---|
| AKKE_WECOM_RECALL_ENABLED | 云电脑侧召回腿开关 开关 | 灰度前 0;上线 1 |
| AKKE_ACCOUNT_ID | 企微销售号 accounts.id(已建好的 wecom 账号) | 0242b7ff-…-ce71722e6853 |
| AKKE_WECOM_C_SEARCH | 顶部搜索框坐标(measure 量出) | 如 60,30 |
| AKKE_WECOM_DRY_RUN | 只读空跑(验腿用)/ 真发 | 验证 1 → 上线 0 |
| AKKE_WECOM_RECALL_CLAIM_LIMIT | 每轮最多领几条召回 | 2 |
wecom_persona 决定该操作员召回用谁的口吻 + 只发谁的客户(按 persona:% 隔离,不串号)。野荞账号已设 xiaowen。以后加夏夏/饭粒/Gus,各自账号填各自 persona(xiaoxia / xiaofan / xiaowu)。全局 WECOM_RECALL_PERSONA 仅兜底。
06防翻车护栏
好友单聊主动推,封号风险最高。护栏都在代码里,这里是心里有数。
发之前
- 进队门槛:≥24h 没回才进,不会刚发完就当沉默
- 排除人工在聊:把有潜力、人工在深聊的客户标
handed_off,自动豁免、不打扰 - 身份门:搜到的人标题对不上就不发,防重名发错人
发之后 / 节奏
- 红点感叹号=被删 → 只白发 1 条、永久出库
- 满 7 次出库;连推没回应 → 每天改隔天退避
- 封号护栏:日限 5 起步 + DM/召回合并 1h 门 + 工作时间 9–21,灰度从低起、盯账号随时停
对齐企微平台规则 · 调研 2026-07-16
企微给客户发消息分三条通道、规则各不同——我们的召回只走第三条「好友单聊」,运营听到的「只能连续发 7 天」是另一条通道(群发)的事,不约束我们。
| 发送通道 | 平台规则 / 硬性上限 | 用不用 |
|---|---|---|
| 群发助手 | 硬额度:每天 1 条 / 每周 7 条 / 每月当月天数。运营听到的「只能连续发 7 天」= 这里的每周 7 条群发 | 不走 |
| 微信客服 kf | 客户发消息后 48h 内最多回 5 条(会话窗口) | 不走 |
| 好友单聊 1:1 成员 GUI 手打 | 无「发 X 条 / 连续 X 天」的硬 API 上限,只受风控约束 | ✓ 走这条 |
好友单聊没有硬性条数上限,真正的约束是风控(触发 → 限流停 24h 甚至封号)。上面那两块护栏,正是对着风控每条红线做的:
| 风控红线 | 我们对应的护栏 |
|---|---|
| 官方建议 ≤ 1 条/天 | 每天最多 1 条;连推没回应自动退避到隔天 |
| 消息相似度 > 70% | 7 条话术防复读、不复用句式 |
| 客户回复率骤降 > 40% / 骚扰投诉 | 一回复 / 被删 / 满 7 次立即出库 |
| 好友请求成功率 < 85% | 只召回已加成功的好友,不新增加人请求 |
07急停 & 回滚
出任何异常,先停再查。三条独立开关,任一即停。
# 1. 自己那台停消费 .env 设 AKKE_WECOM_RECALL_ENABLED=0 ← 最快,派了也没人取 # 2. 全局停派单 有 Vercel 权限的人设 WECOM_RECALL_AUTOSEND_ENABLED=false,或 revert 5aa5e294 # 3. 云电脑一键急停 在 C:\akke-wecom\ 建空文件 wecom_reply_STOP
数据库要回退整套表:跑 supabase/migrations-rollback/20260716120432_wecom_recall_rollback.sql(drop 新表/RPC,无数据依赖)。