用途
Podium Contact Dedup 用于在生产环境中对 Podium 联系人进行去重,并让去重流水线持续运行。它不是一个一次性清理脚本,而是集成持续运行的数据质量层,在消息、通话、网页聊天和评论不断变更联系人数据时保持联系人语料库的整洁。
该技能针对六类生产故障:
- 电话格式不一致:+61 412 345 678、0412 345 678、(04) 1234-5678、+61412345678 是同一号码却产生四个联系人。Podium 按精确字符串匹配去重,四种格式全部保留,下一个来电者又成为第五个。
- 合并 API 顺序导致字段丢失:Podium 合并端点接收一个主记录和一个重复记录,主记录保留自身字段,另一条字段被丢弃。若选错主记录(较新但更空),较旧但更丰富的记录的名称、标签和会话链接会静默消失。
- 合并时丢失退订标记:重复记录 marketing_opt_out=true,主记录 marketing_opt_out=false,朴素合并保留主记录标记,重新向已明确退订的人发送营销,构成合规事件(TCPA、GDPR 第 21 条、ACMA Spam Act)和信任事件。
- 软删除与硬删除语义混淆:Podium 的 DELETE /contacts/{uid} 是可逆的,记录被隐藏而非销毁。若当作终结操作,每次管理员通过 UI 恢复联系人都会产生“删除后联系人又出现”的支持工单。硬删除(清除)是独立、不可逆的端点,作用域不同。
- 跨门店重复检测遗漏:同一号码呼叫 Sydney 和 Burleigh Heads,按门店各创建一个联系人,按门店去重完全遗漏。跨门店去重需要以 phone_natural_key 为键、覆盖所有 location_uid 联系人并集的独立例程。
- 并发编辑的合并冲突:两个操作者(或一个操作者加一个自动任务)同时合并重叠集群,第二次合并的主记录可能已被合并到另一条记录,API 静默合并到已过时的目标,一方意图被丢弃且不暴露冲突。
主要能力
- E.164 规范化函数,输出自然键,由 phonenumbers 库校验。
- 基于 SQLite 的自然键索引,以 natural_key 和 (natural_key, location_uid) 为键。
- 重复检测,输出带置信度评分的集群(0.60 下限,0.80 自动合并阈值)。
- 合并编排器,采用确定性主记录选择(field_count > updated_at > uid)。
- 每次合并后通过并集再 PATCH 保留退订状态。
- 跨门店重复扫描器,生成人工审核队列。
- 幂等合并状态文件(崩溃后可恢复)。
- 每次合并前通过 updated_at_podium 复查进行冲突检测。
使用方式
前置条件:
- Python 3.10+ 及 phonenumbers 库(pip install phonenumbers)。
- 可用的 podium-auth 集成(本技能通过已认证客户端调用 Podium)。
- 读作用域 contacts.read,写作用域 contacts.write(仅当硬清除在范围内时才需 contacts.delete)。
- 用于自然键索引和合并状态文件的本地 SQLite 数据库(默认 ./podium-dedup.sqlite)。
- E.164 解析的默认区域(澳大利亚部署为 AU,美国为 US,按租户设置)。
构建顺序(每节消除一种生产故障模式):
- E.164 规范化与自然键生成:每个联系人电话由 phonenumbers 解析为 E.164,自然键即 E.164 字符串本身,直接用作 SQLite 主键。
- SQLite 自然键索引:建立 (natural_key → [contact_uid, ...]) 索引,重复检测从 O(N²) 降为 O(N)。field_count 在索引时预计算,供合并编排器选择更丰富的记录。
- 带置信度评分的重复检测:同一 natural_key 的联系人构成集群,每对评分:相同 E.164 得 0.60(必需下限),相同姓名 +0.20,相同邮箱 +0.15,标签重叠 +0.05。默认仅所有成对评分 >= 0.80 的集群自动合并,较低分集群提交人工审核。
- 带主记录选择的合并编排器:按顺序确定性选择主记录——字段最多(field_count 最高)、最近更新(updated_at_podium)、contact_uid 字典序最低。集群中其他联系人均合并入主记录。
- 退订状态并集保留:最强设置始终胜出。集群中任一记录 marketing_opt_out=true,合并后即为 true,sms_opt_out 和 email_opt_out 同理。合并前先计算退订并集,合并完成后立即通过 PATCH /contacts/{primary_uid} 强制覆盖。
- 软删除与硬删除处理:去重流水线从不硬删除,始终调用 POST /contacts/{primary_uid}/merge,Podium 软删除重复记录并将其会话历史链接到主记录,操作记入本地审计日志。硬删除保留给合规擦除请求,由不同技能处理。
- 跨门店去重:按门店去重完成后运行跨门店扫描,查找不同 location_uid 间共享 natural_key 的集群。跨门店合并默认不自动合并,提交人工审核并附两个门店名称。
- 幂等合并与状态文件:每次集群操作在 API 调用前记入 merge_state,调用后确认。状态转换:pending → merging → merged → patched,仅 patched 为终态成功。崩溃后下次运行从非终态恢复。
- 并发编辑冲突检测:每次合并 API 调用前重新获取每个重复记录,验证 updated_at_podium 与索引值一致。若已更新则中止该集群合并,记录 conflict_detected,标记集群需重新索引。
适用场景
- 生产环境中 Podium 联系人语料库持续被消息、通话、网页聊天和评论变更。
- 需要处理电话格式不一致、合并字段丢失、退订标记丢失、软硬删除混淆、跨门店重复和并发合并冲突等数据质量问题。
- 需要可恢复、可审计、幂等的去重流水线。
限制
- 需要 Python 3.10+、phonenumbers 库、已认证的 Podium 客户端及相应读写权限。
- 需要本地 SQLite 数据库存储自然键索引和合并状态。
- 需要按租户设置 E.164 解析默认区域。
- 跨门店合并默认不自动执行,需人工确认。
- 硬删除不在本技能范围内,由其他技能处理。
- 资料未提供具体收费、价格或平台支持信息。