---
title: 算法 · 通俗版
description: 用大白话讲清楚 PAC 的召回 / 画像 / 优先级 / 话术四个算法在算什么、为什么这么算。
icon: Sparkles
---

> **谁该读**:产品 / 运营 / 诊所管理者 / 客服主管 —— 不需要懂技术。
> **读法**:正文是大白话;每个关键论断下带一个 `📐 证据` 块(简短公式 / 取值 / 真理源),专业读者可核对,非技术读者可跳过。完整实现见 [召回](/docs/algorithms/recall) · [画像](/docs/algorithms/persona) · [话术](/docs/algorithms/script-generation)。

## 〇、PAC 是干什么的

一句话:**PAC 帮诊所找出"该回来但还没回来"的患者,告诉客服先打给谁、怎么打。**

诊所每天产生大量就诊记录,里面藏着"漏掉的机会":医生说过"这颗牙该补",患者却一直没来补。PAC 把算法连成一条流水线,客服拿到的是排好序、带背景、带话术的电话清单:

```
   全院患者                                            客服每天的电话
      │                                                      ▲
      │ ① 召回         ② 画像        ③ 优先级      ④ 话术     │
      └「谁该回来?」→「他是谁?」→「先打给谁?」→「怎么打?」─┘
        (筛候选)        (贴标签)       (排顺序)      (定制脚本)
```

> ⚙️ **关于数值**:本文列的**权重 / 分档 / 阈值都是"出厂默认",可按宿主或集团策略调**。**算法的"形状"(公式 / 流程)稳定,"数值"可调**;真理源永远在代码 / 配置,改参后同步更新本文。

---

## 一、召回算法 —— "谁该被请回来?"

**核心判断只有一句**:

> 医生发现 / 建议了某个治疗,但患者一直没去做 —— 这个人就该被召回。

> 📐 **触发条件**(两个信号源,任一命中):有一条 active 的「诊断记录」或「医生建议」(`diagnosis_record` / `recommendation_record`),其 `code` ∈ 本子场景的码集,且**不存在**诊断之后启动的同类治疗(见第 3 道过滤网)。诊断 `confidence=1.0`;医生建议 `0.8`;影像 AI `0.5`(影响优先级)。

### 覆盖哪些情况(11 个子场景)

按牙科疾病大类(ICD-10 K00–K09)覆盖 **10 种"发现了没去做"的病** + 1 个跨病种的**「建议拔除」**。每种病有**诊断码**(如 `K08`)或**建议码**(如 `IMPLANT_RECOMMENDED`)两个触发源,任一命中即召。

| 诊断码 | 建议码 | 情况(大白话) | 起步分 | 冷静期 | 黄金窗末 | 紧迫临界 |
|---|---|---|---|---|---|---|
| K08 | `IMPLANT_RECOMMENDED` | 缺失牙未修复(没去种 / 镶) | **60** | 30 | 180 | 120 |
| K07 | `ORTHO_CONSULT_RECOMMENDED` | 错颌畸形未正畸 | 55 | 30 | 365 | 180 |
| K04 | `RCT_RECOMMENDED` | 牙髓炎未做根管 | 52 | 14 | 60 | 45 |
| K05 | `SRP_RECOMMENDED` | 牙周炎未做基础治疗 | 50 | 30 | 120 | 90 |
| K09 | `JAW_CYST_REMOVAL_RECOMMENDED` | 颌骨囊肿未处理 | 50 | 14 | 90 | 60 |
| K02 | `FILLING_RECOMMENDED` | 龋齿未充填(蛀牙没补) | 45 | 14 | 90 | 60 |
| K03 | `HARD_TISSUE_REPAIR_RECOMMENDED` / `CROWN_RECOMMENDED` | 牙体损伤未修复 | 35 | 14 | 90 | 60 |
| K06 | `GUM_TREATMENT_RECOMMENDED` | 牙龈牙槽问题未处置 | 35 | 14 | 120 | 60 |
| K01 | (只认诊断,无建议码) | 阻生牙未拔除 | 30 | 14 | 180 | 90 |
| K00 | `ERUPTION_INTERVENTION_RECOMMENDED` | 牙发育 / 萌出异常未处置 | 25 | 30 | 365 | 180 |
| (跨病种) | `EXTRACTION_RECOMMENDED` | **建议拔除未拔**(残根 / 松动牙等;同牙已有病种诊断则让位) | 30 | 14 | 90 | 60 |

> 📐 **真理源**:起步分在 `SUB_SCENARIOS[*].base`;冷静期 / 黄金窗 / 紧迫临界在 `DiagnosisTreatmentMap`(`canonical-codes.ts`)。上表是**默认值,可按宿主 / 集团调**。**不漏码**:host 出现的码都进池,起步分低的靠综合分自然沉底。

### 三道"过滤网"(避免打错电话)

**第 1 道 · 合规红线**(一票否决):已故 / 标了"勿打扰" → 不打。没电话的提示客服补(数据问题 ≠ 不让打)。

> 📐 `p.active=true AND pp.do_not_contact=false AND pp.deceased=false`(任一不满足直接踢)。

**第 2 道 · 时间窗**(不能太早,但不嫌晚):刚诊断完(冷静期内)不打,患者还在考虑;**越晚越该打**,缺牙拖一年比拖三个月更该召。

> 📐 只设下界 `诊断日 <= now − cooldownDays`,**不设上界**(超窗不踢,交优先级的新鲜度因子软衰减)。

**第 3 道 · 已经处理过就别打**(关键,精确到牙位):

- 已做对应治疗 / 已拔该牙 → 不召;**精确到牙位**(36 补了不挡 46 还没补)
- 已约未来的号 / 近期(14 天内)刚到过诊 → 不打扰(人在来的路上 / 刚见过面)

> 📐 `NOT EXISTS(诊断之后启动的同类 actual 治疗)`,按牙位集合交集判定(双方有牙位→牙位 overlap;信号全口→按类别;治疗全口→覆盖该类全牙位)。**逐牙算"剩余未治牙位"**,还含固定桥盲点 / 间隙关闭 / 患者拒绝 / 最新诊断为准等细化(见 [召回算法](/docs/algorithms/recall))。

### 一个聪明的合并

同患者多颗牙多个问题会**智能合并**:同病种、相邻 / 重叠牙位 → 合成一条(如"18;28;38;48 四颗智齿"一件事);不同问题分开列。客服看到的是整理好的几件事。

> 📐 按牙位重叠做并查集(union-find),每组一条理由,标识 = `病种@牙位`(`caries_no_filling@36` / `impacted_tooth@18;28;38;48` / `perio_no_srp@whole`);组内取最早诊断日。

> **本质**:召回不"猜",只认医生白纸黑字写下的诊断和建议。

---

## 二、画像算法 —— "这个患者是谁?"

筛出候选后,客服打电话前想知道:这人值不值得花时间?会不会不想来了?能不能打?画像给每个患者贴**16 个可解释标签**。

> 📌 16 标签:`rfm`(价值分群)/ `lifecycle_stage`(生命周期)/ `age_bracket` / `gender` / `acquisition_channel`(获客)/ `family_structure` / `referral_champion`(转介绍达人)/ `entitlement_status`(权益)/ `treatment_history`(治疗史)/ `potential_treatment`(潜在治疗)/ `urgency_level`(急迫等级)/ `contraindication`(禁忌)/ `time_preference`(时间偏好)/ `discount_anchor`(折扣锚点)/ `special_attention`(特别关注)/ `treatment_sensitivity`(治疗敏感)。完整见 [画像算法](/docs/algorithms/persona)。

几个客服最常看的(通俗示例):

- **价值分群(RFM)**:按最近就诊(R)+ 频次(F)+ 累计消费(M)分 8 档(重要价值 / 重要保持 / … / 低活跃)。M 按**租户内分位**,不是绝对金额。喂优先级的"意愿度"。
- **潜在治疗**:这人有哪些"诊断了还没做"的项目(种植 / 正畸 / 补牙…)—— **和召回挖的是同一个 gap**,口径一致。
- **急迫等级**:这病多快要处理(紧急 / 高 / 中 / 低),由潜在治疗 × 末诊推出,喂优先级的"急迫性"。
- **特别关注**:屡次爽约 / 经常迟到 / 免打扰 / 不可等候 —— 提醒客服沟通方式。

> 📐 **两个特点**:① **全确定性,不靠 AI 猜**(16 个里 15 个规则 + RFM 是统计分位),每个标签算法写死、带证据可追溯;② **自动更新**:患者有新动作就自动重算。真理源 `persona-feature-specs.ts`。

> **本质**:画像把散乱就诊记录,浓缩成客服一眼读懂的几个标签。

---

## 三、召回优先级 —— "先打给谁?"

客服时间有限。同样"该召回",给每个人打一个 **0–100 分**,分越高越优先。

### 分数怎么来(三维 × 两因子)

```
综合(0-10) = 急迫性 × 0.4 + 价值性 × 0.3 + 意愿度 × 0.3
最终分(0-100) = clamp( 综合 × 新鲜度 × 置信度 × 10 , 0, 100 )
```

| 维度 | 通俗解释 | 怎么算(默认值可配) |
|---|---|---|
| **急迫性** ×0.4 | 这病多快要处理(纯客观) | 急迫等级:紧急 10 / 高 7 / 中 4 / 低 1 |
| **价值性** ×0.3 | 这单成交值多少钱(纯客观,按**治疗单价**不是患者身价) | 种植 单颗 8 / 多颗 9 / 半口+ 10 · 正畸 7 · 根管 6 · 牙体 5 · 牙周 5 · 拔 3 · 补 2 |
| **意愿度** ×0.3 | 客户接受这治疗的依从性 | RFM 依从 ×0.375 + 主诉行为 ×0.375 + 信任基础 ×0.25 |

**意愿度三件套**:RFM 分群(重要价值 10 … 低活跃 2)+ 主诉行为(咨询过该治疗 8 / 仅被动诊断 2)+ 信任基础(生命周期 成熟 9…流失 0,再 + 同类治疗史 / 转介达人 / 近 1 年履约良好 各 +1,封顶 10)。

**两个打折因子**(乘在最后):

- **新鲜度**(0.4–1.0):黄金窗内 1.0,过窗线性衰减,到 2× 窗触底 0.4(老诊断压低,止损)。
- **置信度**(0.5–1.0):医生诊断 **×1.0** / 医生建议 **×0.8** / 影像 AI **×0.5**(防影像 AI 误判冲高分)。

> 📐 **真理源** `priority-scorer.ts`。每个分数附带完整 `breakdown`(三维 + 各子项 + 新鲜度 / 置信度)落 `plan_reasons.breakdown`,客服详情页逐项可见 —— **可解释 = 可信任**。

> 例:缺失 4 颗牙(潜在多颗种植)+ 咨询过种植 + RFM 重要价值 + 成熟客有种植史 + 黄金窗内 → (急迫 10×.4 + 价值 9×.3 + 意愿 9×.3) × 1.0 × 1.0 × 10 = **85 分**。

> ⚠️ **已知局限**:意愿度 ≈ 倾向性(propensity),偏好"本来就会来的人";做对"该不该打"需测增益(uplift)= 试点随机对照组。见 [召回验证](/docs/algorithms/verification)。

---

## 四、AI 话术生成 —— "电话该怎么打?"

排好打给谁,客服还需要"开口说什么"。话术按**这个患者的具体情况**生成定制脚本(开场 / 切入 / 异议应对 / 结束 4 件事),分**三档投入**(稳健 / 标准 / 深度),客服可在"重新生成"处选档 + 选模型。

### 不是套模板,是"按患者拼装"

```
按患者特征挑「话术块」:召回病种(K00–K09 各有专属)+ 人群(儿童对家长 / 老人慢)+ 新老客
  + 安全规则 → 拼成给大模型的指令 → 大模型生成话术
档位差别:稳健 = 4 段模板填空;标准 = 4 段自由编排;深度 = 多段 + 自检修订
```

举例:**70 岁老人 + 缺牙**召回 → 自动拼"种植话术 + 老人沟通 + 老客"块,出来的话术语速提示慢、主动提家属商量、不催。

### 三道安全护栏(不让 AI 乱说)

| 护栏 | 防什么 |
|---|---|
| **只认提纲事实** | 只能用系统给的诊断 / 医生 / 时间,**不许编**;只喂结构化切片,不喂病历全文 |
| **禁词 + 不承诺** | 不许"保证治好" / 报价 / 写死时间(诊所没排班接口,时间只能给"示例") |
| **失败降级** | 大模型出错或违规 → 退回安全模板,客服永远有东西可用 |

> 📐 **真理源**:提示词组装 `skill-composer.ts` + `skills/*/SKILL.md`(按 frontmatter 声明式匹配);安全规则**单一源** `safety-rules.ts`(机器闸 + prompt 同引,输出后扫禁词 / 加粗时间 / 临床码,命中即兜底);模型默认 `deepseek-v4-flash`;每次落 `agent_invocations`(档位 / 模型 / token / cost / 用了哪些块)。话术块是 MD 文件,**运营可改文案不动代码**。

> **本质**:话术不是"一个大模板",而是按患者特征拼装 + 大模型润色 + 安全兜底。

---

## 五、四者怎么配合(端到端)

以一个高价值老客走一遍:

```
① 召回:扫全院 → 发现他 128 天前诊断"46 缺失",至今没种、没拔、没约
        → 过合规红线 → 进候选池,理由="缺失牙未启动修复 · 牙位 46"
② 画像:贴标签 —— RFM=重要价值客户 / 生命周期=成熟活跃 / 可联系 / 潜在治疗含"种植"
        → 客服打电话前就知道"高价值活跃客户,值得好好聊"
③ 优先级:三维 × 新鲜度 × 置信度 → 高分排进今天清单最前,且看得到"为什么这个分"
④ 话术:点"生成" → 按"种植(K08)+ 老客 + 成人"拼装 + 大模型 → 贴合他的开场 / 异议 / 结束
        (不编事实、不报价、不写死时间)
```

> **一句话总括**:**召回**筛出"该回来的人",**画像**告诉客服"他是谁",**优先级**排好"先打谁",**话术**定制"怎么打" —— 四个算法串成一条流水线,把散乱就诊数据变成客服每天一份**排好序、带背景、可解释、带脚本**的电话清单。

---

## 附:常见疑问

**Q:会不会乱召回、打扰患者?** A:三道过滤网(合规红线 + 时间冷静期 + 已处理就不打)层层把关;且只认医生写下的诊断,不自己编理由。

**Q:为什么有的患者分高有的分低?** A:三维(急迫 / 价值 / 意愿)加权 × 新鲜度 × 置信度,每个患者的明细(breakdown)详情页都能看到,完全透明。

**Q:画像标签准吗?会不会 AI 算错?** A:16 个标签目前全是确定性算的(规则 + 统计分位,不是 AI 猜),比如"消费分位"都是写死口径,可解释可追溯。

**Q:换一家诊所 / 集团,算法还能用吗?** A:能。算法逻辑跟具体诊所无关,新诊所把数据按格式对接进来即可复用。

**Q:AI 话术会不会瞎编、乱承诺?** A:三道护栏 —— ① 只能用系统给的事实;② 禁词 + 不报价 + 不写死时间;③ 出错 / 违规自动退回安全模板。且按患者真实情况(病种 / 年龄 / 新老客)定制。
