# PAC 实时坐席辅助(Real-time Agent Assist)设计方案

> 客服打电话回访患者时,AI 实时旁听通话 → 在 PAC 屏幕上推"下一步该说什么 / 别忘了提的点 / 异议怎么接",
> 是 Cresta Agent Assist 那类"实时坐席辅助"在 PAC 场景的落地。
> **状态**:设计草案(讨论用,未排期)

---

## 一、目标与边界

**做什么(v1)**:
- 客服与患者通话时,AI 静默旁听,**只在屏幕给文字提示**(不出声、不替客服说话)。
- 提示结合 **该患者的 PAC 上下文**(画像 / 治疗链 / 已生成话术 / 召回理由)—— 这是 PAC 区别于通用 Agent Assist 的核心优势。
- 通话结束:转写 → 自动起草 `plan_execution`(执行结果 / 备注 / 下次跟进),省客服手填。

**明确不做(v1)**:
- ❌ AI 直接和患者对话 / 替客服打电话(那是"AI 外呼",Phase 3 另议,用豆包/Qwen-Omni 端到端语音)。
- ❌ 通话质检 / 情绪分析大盘(Phase 2+)。
- ❌ 多语种(先普通话 + 粤语)。

---

## 二、架构选型:级联(ASR→DeepSeek)优先,实时端到端备选

两条路,v1 选**级联**:

| 维度 | **A. 级联:国内流式 ASR → DeepSeek 教练**(v1 选) | B. 实时端到端:Qwen-Omni-Realtime(文字输出) |
|---|---|---|
| 延迟 | ASR ~0.3s + LLM 首 token ~0.5-1s ≈ **1-2s** | 模型侧 ~234ms,但需全程国内部署 |
| 可控性 | ⭐⭐⭐ 文字转写 → 注入完整 PAC 上下文 → 结构化提示 | ⭐⭐ 上下文塞 systemInstruction,输出结构弱 |
| 复用 PAC | ⭐⭐⭐ 直接走现有 AiCall harness + skills + agent_invocations | 需新链路 |
| 中文电话准确率 | ⭐⭐⭐ 阿里/腾讯/讯飞专用 8k 电话 ASR | ⭐⭐ |
| 成本 | 低(ASR 按分钟 + LLM 小 token) | 高(音频按分钟) |
| 风险 | 低(都是成熟件) | 中(较新) |

**结论**:v1 走 **级联**——最可控、复用 PAC 最多、中文最稳、最便宜。Qwen-Omni-Realtime 留作 Phase 2 对照(各跑真实通话 benchmark 再定)。豆包定位"AI 开口跟患者聊",归 Phase 3 外呼。

---

## 三、端到端数据流(级联)

```
客服浏览器(PAC 详情页)
  │  ① getUserMedia 抓麦克风(+ 患者远端流,见 §4)→ PCM 16k 帧
  ▼  WebSocket(/pac/v1/realtime/coach,JWT 鉴权)
┌─────────────────────────── 实时教练服务(国内区,见 §7 部署)───────────────────────────┐
│  ② 音频帧 → 国内流式 ASR(WebSocket)→ 滚动转写(分客服/患者两轨)                        │
│  ③ 触发器:患者说完一句(VAD 静音)/ 每 ~6s 新内容 → 攒一批                              │
│  ④ realtime_coach AiCall(走 AiCall harness):                                          │
│       system = PAC 上下文(画像 + 治疗链 + 已生成话术 + 召回理由 + skills)               │
│       user   = 最近滚动转写                                                              │
│       → DeepSeek 流式出【结构化提示】→ 落 agent_invocations                              │
│  ⑤ 提示经 WS 推回浏览器                                                                  │
└──────────────────────────────────────────────────────────────────────────────────────┘
  │  ⑥ PAC 详情页"实时教练"面板:按 urgency 染色滚动显示
  ▼
通话结束 → ⑦ 整段转写 → summarize AiCall → 自动起草 plan_execution(outcome/notes/next)
```

---

## 四、音频接入 —— 决定性问题(必须先定)

**浏览器抓麦克风零 telephony 集成**,但"听谁"取决于电话怎么打:

| 客服打电话方式 | 能拿到的音频 | 评价 |
|---|---|---|
| **电脑网页软电话(WebRTC 拨号)** | 客服 + 患者**双轨,原生干净** | ⭐⭐⭐ 最佳。需接语音 CPaaS(阿里云语音/腾讯云)做 WebRTC↔PSTN 桥 |
| 座机 + 耳麦 | **只有客服**(患者声进耳机不进麦) | ⭐ 患者半段丢失,价值大减 |
| 座机 + 免提外放 | 麦克风录双方(有回声/质量差) | ⭐⭐ 凑合 |
| 电脑 + `getDisplayMedia` 抓系统声 | 患者半段(系统声)+ 客服(麦) | ⭐⭐ 要手动授权共享音频,糙 |

**强烈建议走软电话**(电话从 PAC/电脑里打)—— 双轨干净是实时教练质量的前提。
**→ 待确认:你们客服现在电话从哪打?有没有可对接的呼叫中心/CPaaS?** 这条不定,实时路无从落地。

---

## 五、教练 LLM 设计(PAC 的护城河在这)

**开场注入上下文**(通话开始拉一次,塞进 system):
- persona features(价值 / 召回风险 / 沟通偏好)
- 治疗链(该患者诊断了什么、链卡在哪一阶段)
- 已生成的 plan_script(开场/跟进/异议/结束四段)
- plan_reasons(召回理由 + 子场景 + 证据)
- 复用现有 **draft-plan-script 的 skills 体系**(K00-K09 诊断 SKILL + 人群 + 异议库 + 安全规则)

**输出结构(流式)**:
```jsonc
{
  "hints": [
    { "type": "say_next",          // 建议下一句说什么
      "text": "提一下种植 3 个月骨结合期,先约个免费 CT 评估",
      "urgency": "high" },
    { "type": "objection_rebuttal", // 患者刚说"太贵" → 接法
      "text": "强调分期 + 缺牙不补的邻牙倾斜风险" },
    { "type": "remember",           // 别忘了
      "text": "该患者是 VIP(累计 5.7w),态度要更尊重" },
    { "type": "compliance",         // 合规红线
      "text": "未确诊别承诺疗效" }
  ],
  "detected": { "patientConcern": "价格", "stage": "犹豫" }
}
```

**触发节奏**(控成本 + 防闪烁):患者 turn-end(ASR 静音事件)或每 ~6s 新转写,debounce,无新内容不调。

**走 AiCall harness**:`kind:'realtime_coach'`、新 callKey、流式、落 `agent_invocations`(token/cost/审计),safety gate 复用 `playbook-safety-self-check`。

---

## 六、需要新增的部件

**后端(实时教练服务)**:
- `RealtimeCoachModule` + WebSocket Gateway `/pac/v1/realtime/coach`(JWT)
- 会话生命周期:start(拉 PAC 上下文)→ 流式音频 → ASR → 攒转写 → 触发 coach AiCall → 推提示 → end
- **ASR 适配层**(服务端代理音频到阿里/腾讯 ASR,密钥不下发浏览器)
- `RealtimeCoachCall`(AiCall):复用 DeepSeek + skills composer
- 数据落库:`call_sessions`(会话)+ `call_transcripts`(转写,PII)+ `call_suggestions`(提示,审计/复盘)

**前端**:
- 麦克风采集(getUserMedia → PCM 帧)+ WS 客户端
- 详情页"实时教练"面板(话术区旁):流式提示、urgency 染色、一键"已说"
- 通话控制(开始/结束辅助)

**数据模型**(新表,延续 PAC 版本流 + 审计账本风格):
```
call_sessions:    id, plan_id, patient_id, operator_user_id, started_at, ended_at, status
call_transcripts: id, session_id, speaker(agent/patient), text, ts, asr_confidence  (PII,留存策略管控)
call_suggestions: id, session_id, agent_invocation_id, hints(jsonb), shown_at        (审计/效果复盘)
通话结束 → 复用 plan_executions(transcript 起草 outcome/notes)
```

---

## 七、部署:实时链路必须在国内区(关键!)

⚠️ **现 PAC 服务器在美国(加州)** —— 但客服和患者在国内。实时音频若走 客服(国内)→ 美国 PAC → 国内 ASR,跨太平洋来回延迟会毁掉体验。

**所以实时教练服务应独立部署在国内区**(阿里云/腾讯云华东),就近接 ASR + DeepSeek:
```
客服(国内)──低延迟──▶ 实时教练服务(国内区)──▶ 国内 ASR + DeepSeek
                                  │
                                  └──拉患者上下文──▶ PAC API(美国,非实时,可缓存)
```
PAC 主体(美国)只在**开场**提供一次患者上下文(可缓存),不在实时音频回路上。这是个**边缘/相邻服务**,通过 PAC API 取数,不耦合主库。

---

## 八、延迟 / 成本 / 合规

- **延迟预算**(级联,国内):患者说完 → 提示出现 ~**1-2s**。教练提示场景可接受(不是抢话)。
- **成本**(粗估):ASR ~¥0.4-0.6/分钟 + DeepSeek 提示(每分钟几次小调用)~¥0.05/分钟 → 10 分钟通话 ~¥5-7。需实测核。
- **合规(重)**:录患者通话需**告知同意**;转写是高敏 PII → 加密 + 访问控制 + 留存清理(对齐 `agent_invocations.input_snapshot` 的 N 天清理);需集团法务过一遍。

---

## 九、分期路线

| 阶段 | 内容 | 价值 | 风险 |
|---|---|---|---|
| **Phase 0 · POC**(数天) | 麦克风 → 国内 ASR → DeepSeek 教练 → 简单面板,1 个诊所,验延迟/质量 | 验证可行性 | 低 |
| **Phase 1 · 通话后异步** | 录音 → ASR → summarize → **自动填 plan_execution** | 立竿见影 + 补 PAC"手填 outcome"缺口 + 跑通 ASR 管道 | 低(无实时压力) |
| **Phase 2 · 实时教练** | 流式 ASR + 上下文注入 + 实时面板 + harness + 落库 | 核心功能 | 中 |
| **Phase 3 · AI 外呼(可选)** | Qwen-Omni-Realtime / 豆包端到端语音,AI 直接跟患者讲 | 全自动召回 | 高 |

**建议先做 Phase 1**:不依赖软电话/实时,只要能拿到通话录音文件就能做,价值直接(自动填执行结果),还顺手把 ASR 选型/管道验了,为 Phase 2 铺路。

---

## 十、待确认(决定能不能往下走)

1. **客服电话从哪打?**(座机 / 电脑软电话 / 微信语音)→ 决定能否拿干净双轨音频 —— **最关键**。
2. 有无可对接的呼叫中心 / 语音 CPaaS?(决定软电话路 + 录音获取)
3. 录音合规:患者告知同意流程、留存策略,集团法务口径。
4. ASR 选型:阿里 fun-asr / 腾讯 / 讯飞,拿真实诊所通话各测一轮中文准确率。
5. 是否接受新增国内区边缘服务(实时链路不能走美国主机)。

---

## ▎一句话归纳

> **级联(国内流式 ASR → DeepSeek 教练,走 PAC AiCall harness)+ 注入该患者画像/治疗链/话术作上下文 + 实时面板出结构化提示**;音频靠浏览器麦克风(最好电话从电脑软电话打拿双轨);实时链路独立部署国内区,PAC 主体只供一次上下文。**先做 Phase 1(通话后自动填执行结果)**——零实时依赖、价值直接、顺带验 ASR 管道。最大未决项是"客服电话从哪打"。
