6356ff9d85
Co-Authored-By: Claude Code <noreply@anthropic.com>
6.9 KiB
6.9 KiB
联系方式双要 + 国家代码完整化 — 设计文档
- 日期:2026-10-08
- 状态:已与需求方确认方向与漏洞修法
- 线上版本:服务运行于 chat2.agent.hnxinyouhe.com(部署手册 docs/deploy-production.md)
1. 背景与目标
当前 AI 客服索要联系方式是"WhatsApp 或邮箱二选一",且不引导国家代码。需求方要求:
- 双要:邮箱和 WhatsApp 都要(画像更全,客户经理多一条触达通道)
- 国家代码完整化:WhatsApp 号码必须含国家代码(如 +966 5x xxx xxxx), 否则客户经理无法回访海外客户
非目标:
- 不改变"任一 confirmed 即触发邮件"的线索及时性原则(双要是画像增强, 不是线索交付门槛)
- v1 不动前端(输入提示记 v2 备选)
2. 现状分析(实测,2026-10-08)
| 现状 | 位置 | 问题 |
|---|---|---|
| 引导话术二选一 | app/prompts/system.md 联系方式引导策略节("Drop your WhatsApp or email?") |
无双要引导、无国家代码引导 |
| 号码校验只查位数 | app/services/contact_pipeline.py split_validate(7-15 位即 confirmed) |
无国家代码的裸号照样确认并进入线索,客户经理无法回访 |
| 再索要墙一刀切 | app/services/conversation.py stream 循环(has_contact=True 丢一切索要句) |
客户留 WhatsApp 后 AI 补问邮箱会被墙静默丢句——不改墙双要做不成 |
| 无状态感知提醒 | app/services/conversation.py _build_context_reminder |
没有"有 WhatsApp 缺邮箱""号码无国家代码"的提醒注入 |
3. 方案选型
选定:方案 B(提示词 + 状态提醒 + 墙精确化,三层闭环)
已否决:
- 方案 A(只改提示词):新话术"补要邮箱"会被再索要墙丢句,行不通
- 方案 C(无国家代码降级 suspect、凑齐才发线索):延迟线索交付、纠缠客户, 转化率受损
4. 详细设计
4.1 话术升级(system.md「联系方式引导策略」节)
- WhatsApp 引导带国家代码(首轮索要即引导完整格式):
- 英文:"What's your WhatsApp number with the country code (like +966 5x xxx xxxx)? Our manager will reach out directly."
- 中文:"你WhatsApp多少?带上国家代码(比如+966…),客户经理直接加你。"
- 分步双要(一次只问一个,先 WhatsApp 后邮箱——用"正式报价单 PDF"做天然理由):
- WhatsApp 到手后轻补:"Got it! And an email address would help too — our manager will send the formal quotation PDF there."
- 中文:"收到!邮箱也留一个呗?客户经理把正式报价单 PDF 发你邮箱。"
- 只肯留一个时不坚持:拿到哪个都确认致谢,第二个渠道只顺带一提, 绝不纠缠(转化率优先)
- 国家代码追问话术(引导重发完整号,而非只补国家码——客户重发
完整号会走现有"改号覆盖"机制,管道零改动):
- "Just so our manager dials it right — could you send the full number with the country code, like +966 5x xxx xxxx?"
- 已有【好差示例】节补 2 组:①客户给裸号 → 差:直接"Got it"收下; 好:礼貌请其重发完整号(一次);②已有 WhatsApp → 差:再问 WhatsApp; 好:轻补邮箱一次
4.2 状态感知提醒(conversation.py _build_context_reminder)
复用现有注入机制,新增两个一次性提醒(互斥场景见 4.3 计数):
- 邮箱轻补提醒:条件 = confirmed 含 WhatsApp(或电话)、不含 email、
_email_asked未标记 → 注入逐字英文/中文模板句(含"轻描淡写、问过不追"指引) - 国家代码确认提醒:条件 = confirmed 号码均不以
+/00开头、_cc_asked未标记 → 注入 4.1-4 的追问模板句 + "仅此一次,客户拒绝即作罢"
4.3 一次性计数(防死缠/spam,防漏洞 1/3)
- raw_info 内部状态键(
_前缀,不进推送画像):_email_asked、_cc_asked - 注入提醒的同时落计数;条件判断先查计数——每个提醒每会话最多注入一次
- 计数由 reminder 注入路径写入(与现有
_前缀内部状态管理同构)
4.4 再索要墙精确化(boundary_filter.py asks_contact)
- 签名升级:
asks_contact(sentence, confirmed_channels: set | None = None)(None = 原行为全丢,兼容无参调用) - 渠道分辨:精确渠道词(whatsapp / e-mail / 邮箱 / 微信…)命中 → 仅当 该渠道已在 confirmed_channels 才丢;不在手则放行
- 泛渠道词(number / phone / contact / 联系方式 / 号码)保守处理: 客户已有任何号码渠道在手 → 照丢(宁丢勿放,防重复索要惹恼客户)
- 中文/英文模式同规则
- conversation.py 调用点传入 confirmed 渠道集合(该状态已在前移区算好)
4.5 预期行为明确(不是 bug)
- 邮箱后到会触发一封"更正/补充邮件"(客户经理先后收 WhatsApp 版、补邮箱版) —— 信息更全,属预期
- 客户拒绝补国家代码:号码按现状照常 confirmed,线索照发(软引导不设卡)
5. 不动清单
| 不动 | 理由 |
|---|---|
| split_validate 的 7-15 位 confirmed 标准 | 国家代码用软引导收敛,不降级延迟线索 |
| 邮件触发 D1(任一 confirmed 即发) | 线索及时性原则 |
| extractor.md 联系方式字段与指令 | 四层合并契约稳定,无需感知新策略 |
| 前端 | v2 备选:输入框 placeholder 提示国家代码 |
6. 测试策略
- 墙精确化单测(test_boundary_filter.py):有 WhatsApp+问 email → 放行; 有 WhatsApp+问 WhatsApp → 丢;有号码+问泛"number" → 丢;无参调用 → 原全丢行为
- 提醒注入单测(test_lead_email_trigger.py 风格):构造"有 WhatsApp 无邮箱"
画像 → reminder 含邮箱轻补句;标记
_email_asked后 → 不再含;裸号 → 含 国家代码追问句;_cc_asked后 → 不含 - prompt 静态断言:system.md 含 "with the country code" / 邮箱轻补模板句 / 好差示例新增组
- 全量 pytest 绿(现有再索要墙断言按新语义同步更新)
- 真实 LLM 验收(生产冒烟后补):①客户给裸号
0501234567→ AI 礼貌请其 重发完整号(仅一次);②客户留 WhatsApp → AI 轻补邮箱一次;③只留邮箱的 客户 → 不被纠缠要 WhatsApp(分步双要以 WhatsApp 起手,邮箱-only 客户 场景 AI 不硬要)
7. 风险登记
| 风险 | 等级 | 缓解 |
|---|---|---|
| 墙放行后 GLM 仍过度索要 | 低 | 4.3 一次性计数收口;真实验收观察 |
| 追问话术被翻译成小语种(REASK 墙认不出) | 低 | 模板句按语言规则保持英文/中文原版(现有规则覆盖) |
| 双要增加对话轮次导致流失 | 低 | 分步+一次性+不坚持三重克制;观察期画像完整率对比 |