Files
hms/docs/superpowers/specs/2026-05-11-copilot-gene-design.md
iven df1d85bfde docs: T40 UI 审计报告 + wiki 更新 + Docker 配置
- T40 UI 审计计划和结果文档(docs/qa/)
- wiki 更新:miniprogram 设计系统合规审计记录 + index 关键数字更新
- 审计 V2 完整报告(docs/audits/v2/)
- 讨论记录文档(docs/discussions/)
- 设计规格和实施计划(docs/superpowers/)
- 角色测试计划和结果(docs/qa/role-test-*)
- Docker 生产部署配置
2026-05-13 23:29:42 +08:00

927 lines
42 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HMS Copilot 基因化设计规格
> 日期: 2026-05-11 | 状态: Draft | 分支: feat/media-library-banner
> 讨论来源: 2026-05-11 发散式互动探讨
---
## §1 愿景与定位
### 1.1 问题陈述
当前 erp-ai 模块是一个独立的 AI 分析工具,覆盖 3 个场景(化验单解读、趋势分析、报告摘要),用户需要主动点击"AI 分析"按钮才能触发。AI 与系统的关系是"附加工具"——不用它,系统照常运转。
这带来三个问题:
1. **医护端:被动发现** — 医护需要主动查数据、看报告才能发现异常。高风险患者的风险信号淹没在数据海洋中,依赖医护的经验和注意力。
2. **患者端:沟通空白** — 血透机构无互联网医院资质,医生不能在线与患者对话产生诊断行为。患者离院后的疑问、不适、焦虑没有合规渠道可以解答。
3. **系统层面AI 价值未被释放** — AI 只在用户主动触发时才工作99% 的运行时间处于闲置状态,但它本可以持续观察数据、发现模式、生成洞察。
### 1.2 Copilot 定义
Copilot 将 AI 从"工具"转变为"基因"——一个始终在场、主动观察、适时建议的智能层。
它不是系统的一个器官,而是弥漫在每个交互点的基础能力。就像免疫系统不是一个独立的器官,而是无处不在的防御能力。
**Copilot 不是什么:**
- 不是自动决策系统——它不替医护做决定
- 不是诊断工具——它不做医疗诊断
- 不是聊天机器人——它有深度上下文感知能力
- 不是 erp-ai 的替代品——它是 erp-ai 的进化形态
**Copilot 是什么:**
- 一个"永远醒着的观察者"——持续监控数据变化
- 一个"适时开口的顾问"——在关键时刻主动提供建议
- 一个"合规的沟通桥梁"——在法律允许范围内连接医护和患者
- 一个"越用越了解你的助手"——基于患者数据提供个性化洞察
### 1.3 核心价值主张
**医护端:从"查数据发现问题"到"被推送需要关注的风险"**
| 现在 | Copilot 之后 |
|------|-------------|
| 医护每天花 30 分钟逐个查看患者数据 | Copilot 自动筛选高风险患者,推送到仪表盘 |
| 异常数据依赖医护经验发现 | 规则引擎 + LLM 自动检测异常并分级告警 |
| 随访计划从空白模板开始写 | Copilot 基于风险画像推荐个性化随访方案 |
| 咨询时需要手动翻看患者历史 | Copilot 侧边栏实时展示背景和追问建议 |
**患者端:合规替代医患在线沟通**
血透机构的核心痛点:想服务好患者、想提高随访率、想增加到院量,但没有互联网医院资质,医生不能在线"看病"。
Copilot 以"AI 健康管家"身份填补这一空白:
- 解答患者疑问(在合规边界内)
- 提供健康科普和个性化数据解读
- 引导需要关注的症状到院就医
- 驱动患者日常互动(每日问候、健康打卡、积分激励)
### 1.4 业务驱动力
**合规痛点是 Copilot 患者端存在的根本理由:**
血透机构没有互联网医院资质,意味着:
- 医生不能在线与患者进行问诊对话
- 不能在线给出诊断或治疗建议
- 不能在线开具处方
但患者离院后确有大量沟通需求:用药疑问、不适咨询、复查提醒、心理支持。这些需求目前没有合规渠道可以满足。
Copilot 作为 AI 客服/管家:
- 不做诊断、不开处方、不给治疗建议
- 在合规边界内解答患者疑问
- 智能识别需要就医的情况并引导到院
- 所有输出经过合规审查引擎自动检查
这不仅是功能创新,是解决了一个真实的合规痛点。
### 1.5 设计原则
1. **Copilot 不替人做决定** — 只建议,医护审批。患者端不诊断,只引导。
2. **规则保底LLM 拓展** — 规则引擎保证确定性和可解释性LLM 提供超越规则的洞察。规则是下限LLM 是上限。
3. **合规第一** — 患者端所有 AI 输出必须经过合规审查引擎。宁可过度保守,不可越界。
4. **渐进式渗透** — 从一个触点(风险画像)开始,逐步扩展到全系统。不追求一步到位。
---
## §2 架构总览
### 2.1 分层架构
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 前端呈现层 │
│ ├─ 医护端:<CopilotCard /> <CopilotBadge /> <CopilotAlert /> │
│ └─ 患者端:对话式 UI嵌入小程序消息体系
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Copilot API 层 │
│ ├─ GET /copilot/insights — 获取预计算洞察 │
│ ├─ POST /copilot/chat — 患者端对话(经合规审查) │
│ └─ GET /copilot/patients/{id}/risk — 获取风险评分 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Copilot 引擎层 │
│ ├─ 混合评分引擎(规则引擎 + LLM 补充) │
│ ├─ 意图识别引擎(患者端对话分类) │
│ ├─ 合规审查引擎(关键词 + 语义双层) │
│ └─ 洞察调度器(决定何时/如何生成洞察) │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 数据层 │
│ ├─ copilot_insights — 预计算洞察存储(带过期时间) │
│ ├─ copilot_risk_snapshots — 患者风险评分快照 │
│ ├─ copilot_chat_logs — 患者端对话审查日志(合规审计) │
│ └─ copilot_rules — 规则引擎配置(可动态调整) │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 触发层 │
│ ├─ 异步:事件总线订阅 → 后台预计算洞察 │
│ └─ 同步API 请求时 → 合并预计算结果 + 实时补充 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### 2.2 混合触发模型
洞察通过两种机制产生,互相补充:
**异步预计算(后台):**
事件总线上的健康数据变更事件触发 Copilot 后台引擎,异步生成洞察并写入存储。医护在打开页面前,相关洞察已经准备就绪。
| 触发源 | 时机 | 延迟 | 示例 |
|--------|------|------|------|
| 事件总线订阅 | 数据写入后秒级 | < 5s | 血压录入 → 后台更新风险评分 |
| 定时任务 | 每日凌晨 | 批量 | 重新计算所有在管患者风险评分 |
| 化验报告确认 | 报告确认后 | < 10s | 肌酐异常 → 生成告警洞察 |
**同步实时补充(前端请求时):**
医护或患者打开页面时,前端调用 Copilot API。API 先返回预计算的洞察,再根据当前上下文(如正在查看的页面、当前对话内容)实时补充额外建议。
| 触发源 | 时机 | 延迟 | 示例 |
|--------|------|------|------|
| 页面加载 | 用户请求时 | < 500ms | 打开患者档案 → 返回风险画像 |
| 对话消息 | 患者发消息时 | < 2s | 患者提问 → 意图识别 + 合规审查 + 回复 |
| 随访创建 | 医护操作时 | < 1s | 创建随访 → 返回推荐方案 |
**合并策略:** API 响应中同时包含 `precomputed`(预计算结果,即时返回)和 `realtime`(实时补充,可能稍慢)。前端先渲染预计算部分,实时部分流式追加。
### 2.3 与现有 erp-ai 的关系
Copilot 不替换 erp-ai而是在其上构建。现有 erp-ai 的 AI Provider 抽象OpenAI / Claude / Qwen / Ollama、Prompt 模板管理、SSE 流式输出能力完全保留。
```
erp-ai保持不变
├─ AI Provider 抽象4 个 Provider
├─ Prompt 模板管理Handlebars
└─ SSE 流式输出
Copilot 引擎层(新增,调用 erp-ai
├─ 规则引擎 — 纯 Rust 实现,不依赖 AI Provider
├─ LLM 补充分析 — 调用 erp-ai 的 Provider 能力
├─ 合规审查 — 调用 erp-ai 的 Provider 能力
└─ 意图识别 — 调用 erp-ai 的 Provider 能力
```
**分层依赖关系:**
- 规则引擎:完全离线可用,不依赖任何 AI Provider
- LLM 补充 / 合规审查 / 意图识别:依赖 erp-ai 的 Provider 抽象
- AI Provider 不可用时Copilot 降级为纯规则模式
### 2.4 降级策略
当 AI 服务不可用时Provider 宕机、配额用尽、网络故障Copilot 分层降级:
| 降级级别 | 触发条件 | 影响范围 | 表现 |
|----------|---------|---------|------|
| 正常 | 所有 Provider 可用 | 全部功能 | 规则 + LLM 混合模式 |
| 一级降级 | 主 Provider 不可用,备用可用 | LLM 延迟增加 | 自动切换到备用 Provider |
| 二级降级 | 所有 LLM Provider 不可用 | 医护端部分降级 | 规则评分正常,无 LLM 补充;患者端仅回答服务类问题,健康类问题使用安全兜底模板 |
| 三级降级 | Copilot 引擎整体不可用 | 全部 Copilot 功能 | 静默降级,系统回到无 Copilot 状态,不阻塞任何业务流程 |
**关键设计约束Copilot 的任何故障都不能阻塞 HMS 核心业务流程。** 患者管理、预约、随访、咨询等功能在 Copilot 完全不可用时必须正常运转。
---
## §3 医护端 Copilot
医护端 Copilot 不改变现有工作流,而是在每个关键节点"旁边"插入智能建议。医护照常操作Copilot 在适当的时候主动开口。
4 个触点形成闭环:风险画像(基础)→ 异常检测(感知)→ 随访推荐(决策)→ 咨询辅助(执行)→ 回到异常检测。
### 3.1 触点①:患者风险画像(基础层)
**触发时机:** 医护打开任意患者相关页面时(同步 API 调用 + 预计算数据)
**呈现方式:** 患者姓名旁的风险等级徽章 + 可展开的 Copilot 洞察卡片
**评分机制(混合):**
Layer 1 — 规则引擎(确定性):
- 医疗专家定义规则,存储在 `copilot_rules` 表中
- 每条规则包含:条件表达式、风险分值(+1~+5、严重度、建议文案
- 规则以 JSON 表达式存储,支持动态加载和机构自定义
- 基础风险分 = 所有匹配规则的分值之和
Layer 2 — LLM 补充分析(拓展性):
- 输入:患者近期数据 + 规则评分结果
- 输出:自然语言的补充风险描述、建议、相似病例参考
- 非阻塞LLM 失败时仅展示规则结果
内置规则覆盖 5 大类:
| 类别 | 示例规则 | 分值范围 |
|------|---------|---------|
| 体征异常 | 收缩压连续>140、体重周增幅>2kg | +1~3 |
| 化验异常 | eGFR<60、肌酐环比>20%、血钾>5.5 | +2~5 |
| 依从性 | 随访失约>2次、药物依从性<80% | +1~2 |
| 透析质量 | Kt/V<1.2、透析间期体重增长>5% | +2~4 |
| 综合风险 | 多指标同时异常叠加 | 叠加计算 |
风险等级映射0-2 低 | 3-5 中 | 6-8 高 | 9-10 危急
**规则条件表达式 SchemaJSONLogic 子集):**
采用 JSONLogic 风格的表达式格式,支持嵌套逻辑组合,存储在 `copilot_rules.condition_expr` 字段中。
```json
// 示例:收缩压连续 >140
{
"and": [
{ ">=": [{ "var": "vital_signs.systolic.latest" }, 140] },
{ ">=": [{ "var": "vital_signs.systolic.prev1" }, 140] },
{ ">=": [{ "var": "vital_signs.systolic.prev2" }, 140] }
]
}
// 示例eGFR < 60
{ "<": [{ "var": "lab_reports.egfr.latest" }, 60] }
// 示例:肌酐环比 > 20%
{
">": [
{ "var": "lab_reports.creatinine.change_pct" },
20
]
}
```
支持的数据引用路径:
- `vital_signs.{指标}.latest` / `.prev1` / `.prev2` — 最近 3 次体征值
- `lab_reports.{指标}.latest` / `.change_pct` — 最新化验值 / 环比变化百分比
- `follow_up.missed_count` — 随访失约次数
- `dialysis.ktv.latest` — 最新透析充分性指标
- `medication.adherence_rate` — 药物依从性百分比
支持的操作符:`>`, `>=`, `<`, `<=`, `==`, `!=`, `and`, `or`, `!`, `in`, `var`
规则引擎在 Rust 中实现为递归下降的 JSONLogic 解释器,不依赖外部 DSL。
### 3.2 触点②:健康数据异常检测(感知层)
**触发时机:** 新体征/化验数据入库时(异步事件驱动)
**呈现方式:**
- 实时:医护首页仪表盘的 Copilot 告警卡片
- 推送:浏览器通知(严重异常时)
**告警分级:**
| 级别 | 条件 | 示例 | 呈现 |
|------|------|------|------|
| 🔴 危急 | 危及生命或需立即干预 | 血钾>6.0、严重低血压 | 首页置顶 + 浏览器通知 |
| 🟡 警告 | 需要关注,非紧急 | 收缩压>160、肌酐环比>30% | 首页告警列表 |
| 🟢 提示 | 轻度异常或趋势变化 | 体重周增幅>1.5kg、血压趋势上升 | 患者档案内洞察卡片 |
**与现有告警系统的关系:**
当前 HMS 已有 `health.alerts` 模块。Copilot 异常检测不替代,而是增强:
- 现有告警:基于固定阈值的简单规则(血压>140
- Copilot 告警:基于趋势 + 上下文的智能判断血压从130快速升到150比稳定在145更值得关注
两者共存。固定阈值走现有系统,趋势/上下文异常走 Copilot。
### 3.3 触点③:随访计划智能推荐(决策层)
**触发时机:** 医护为患者创建或编辑随访计划时
**呈现方式:** 随访表单右侧的 Copilot 推荐面板
**生成逻辑:**
1. 规则引擎匹配患者疾病类型 → 基础随访模板(如 CKD 4 期标准随访方案)
2. 规则引擎叠加风险因素 → 调整频率和关注指标
3. LLM 补充 → 基于近期数据生成个性化问诊要点
**输出内容:**
- 推荐随访频率(如"每 2 周 1 次")及理由
- 关注指标列表(如"肾功能、电解质、甲状旁腺激素"
- 建议问诊要点(如"近期是否有恶心、食欲下降、尿量变化"
医护可选择"采纳全部"、"选择性采纳"或"不采纳"。
### 3.4 触点④:在线咨询实时辅助(执行层)
**触发时机:** 医护进入咨询对话时
**呈现方式:** 对话界面侧边栏的 Copilot 面板,不侵入对话区域
**生成逻辑:**
1. 加载患者风险画像(触点①的预计算结果)
2. 实时分析患者消息内容
3. LLM 生成:建议追问方向 + 注意事项提醒 + 过敏/禁忌提示
**输出内容:**
- 患者背景摘要(诊断、透析方案、上次关键指标)
- 建议追问方向(如"浮肿是双侧还是单侧?"
- 注意事项(如"该患者对 XX 药物过敏"
医护可选择"一键插入"追问问题到回复框。
### 3.5 数据流闭环
```
① 风险画像(基础层)
│ 输出:风险评分 + 规则匹配结果 + LLM 补充
② 异常检测(感知层)← 新数据入库事件触发
│ 输出:分级告警 + 异常指标
③ 随访推荐(决策层)← 风险评分 + 异常指标输入
│ 输出:随访方案建议 + 关注指标 + 问诊要点
④ 咨询辅助(执行层)← 患者档案 + 对话内容输入
│ 输出:追问建议 + 注意事项 + 过敏提醒
└─→ 产生新的健康数据/咨询记录 → 回到 ②
```
每个触点的输出是下一个触点的输入。数据在闭环中越转越丰富Copilot 的建议也越来越精准。
---
## §4 患者端 Copilot
### 4.1 角色定位与行为边界
患者端 Copilot 以"小H 健康管家"的身份存在,是血透机构无互联网医院资质下的合规医患沟通桥梁。
**角色:** AI 客服 + 健康管家,嵌入小程序消息体系
**行为边界:**
| 可以做 | 不可以做 |
|--------|---------|
| 解释化验单指标含义(科普) | 诊断疾病("你得了XX" |
| 生活方式建议(饮食、运动) | 开处方("吃XX药" |
| 预约引导、流程咨询 | 预测疗效("吃了会好" |
| 健康数据通俗解读 | 替代医生评估 |
| 紧急情况引导就医 | 推荐特定治疗方案 |
| 基于数据的关怀提醒 | 承诺治疗结果 |
### 4.2 产品形态:对话式嵌入消息体系
"小H"作为小程序内的一个"联系人"出现在消息列表中,患者可以像微信聊天一样互动。
**与 erp-message 模块的关系:**
小H 对话**不复用** erp-message 的消息系统。erp-message 管理的是医护之间的通知消息而小H 对话是 AI 驱动的实时交互两者的数据模型、推送机制、存储需求完全不同。小H 对话使用独立的 `copilot_chat_logs` 表存储。
**消息列表集成方式:**
- 小程序 TabBar 中的"咨询"标签(现有)中新增"小H 健康管家"入口卡片
- 点击进入独立的 Copilot 对话页面(新页面,不属于现有消息列表)
- 不修改现有消息 TabBar 的结构和功能
**微信服务号模板消息推送:**
透析日提醒、复查提醒等需要通过微信服务号模板消息推送。这需要:
- 机构在微信公众平台注册并认证服务号
- 申请模板消息权限并创建所需模板
- 后端集成微信模板消息 API
此功能作为 Phase 4 后期可选增强不影响核心对话功能。Phase 4 MVP 仅实现小程序内对话。
交互入口:
- "咨询"Tab 中的"小H 健康管家"卡片 → 对话窗口
- 首页 AI 问候卡片 → 点击进入对话
- 各健康数据页面的"问小H"按钮 → 带上下文进入对话
### 4.3 意图识别引擎
患者消息先过 LLM 意图分类再路由到不同处理逻辑。5 种意图类型,按优先级排序:
| 优先级 | 意图类型 | 示例 | 处理方式 | 合规要求 |
|--------|---------|------|---------|---------|
| 1 | 紧急情况 | "我胸痛"、"喘不上气"、"出血不止" | 优先响应 + 强制引导就医 + 通知医护 | 必须包含"请立即就医或拨打120" |
| 2 | 健康咨询 | "头晕是不是血压高了"、"这个指标什么意思" | 科普式回答 + 基于患者数据的个性化解读 | 禁止诊断性语言,必须附"建议到院评估" |
| 3 | 服务咨询 | "怎么预约"、"透析时间"、"收费多少" | 规则库直接匹配回答 | 无特殊合规要求 |
| 4 | 情感关怀 | "我不想透析了"、"好累啊"、"谢谢小H" | 共情回应 + 自然过渡到健康话题 | 不做健康承诺 |
| 5 | 闲聊 | "今天天气怎么样"、"你好" | 友好回应 + 巧妙关联健康 | 保持角色一致性 |
**分类策略:** 单次 LLM 调用完成分类(低 token 消耗的快速分类 prompt延迟 < 500ms。分类结果缓存到对话上下文中连续同类消息可跳过重复分类。
### 4.4 对话上下文管理
每次对话自动注入患者上下文,使"小H"真正"认识"患者:
```
上下文结构(后端自动组装,前端不可篡改):
{
"patient": {
"name": "张三",
"age": 62,
"diagnosis": "CKD 4期",
"dialysis_schedule": "每周二、四、六 下午",
"allergies": ["青霉素"],
"medications": ["硝苯地平", "碳酸氢钠"]
},
"recent_data": {
"last_bp": "135/85",
"last_weight": "68.5kg",
"last_dialysis": "2026-05-09",
"next_dialysis": "2026-05-13",
"next_checkup": "2026-05-15"
},
"risk_summary": {
"score": 7,
"level": "中高",
"top_risks": ["eGFR快速下降", "血压趋势上升"]
},
"conversation_summary": "最近5轮对话摘要..."
}
```
**设计约束:**
- 上下文由后端自动组装,前端不可篡改
- 对话历史保留最近 5 轮摘要(控制 token 消耗)
- 敏感字段(详细诊断、具体用药剂量)不注入患者端上下文,只在医护端可见
- 上下文随每次请求刷新,确保数据时效性
### 4.5 引导到院策略
"引导到院"不是生硬的"请去医院",而是基于上下文的自然引导。通过规则 + LLM 配合实现:
**规则驱动引导(确定性):**
- 患者提到任何身体不适 → 触发引导
- 患者问药物相关问题 → 触发引导
- 患者数据持续异常(后台检测)→ 主动推送提醒
- 患者表达消极情绪("不想来了")→ 共情 + 正面引导
**引导话术模板(可配置):**
- 症状类 → "XX可能有多种原因建议让医生当面评估。要不要帮您预约"
- 用药类 → "用药调整需要医生评估。我帮您看看最近有没有门诊?"
- 消极类 → "理解您可能有些疲惫。规律透析很重要,要不看看有没有更方便的时间段?"
---
## §5 合规审查引擎
### 5.1 双层审查架构
患者端 Copilot 的每一条 AI 输出都必须经过合规审查。审查不通过则自动修正,不阻断对话流程。
**Layer 1 — 关键词过滤(规则层,< 5ms**
使用 Aho-Corasick 多模式字符串匹配精确子串匹配扫描预定义的违规词表。不使用正则表达式——Aho-Corasick 只做子串匹配,不支持模式,因此违规词表需列举具体词组而非模式。
| 扫描维度 | 违规关键词(示例,非穷举) | 严重度 |
|---------|---------|--------|
| 诊断类 | "确诊为"、"诊断为"、"你得了"、"诊断结果是" | CRITICAL |
| 处方类 | "建议你吃"、"开点"、"处方"、"调整药量" | CRITICAL |
| 疗效类 | "吃了会好"、"可以治愈"、"保证能好" | HIGH |
| 评估类 | "我判断"、"我认定" | HIGH |
| 承诺类 | "肯定没问题"、"绝对不会出问题" | MEDIUM |
| 误导安慰类 | "完全不用担心"、"绝对没事" | MEDIUM |
命中违规 → 标记违规片段 → 进入修正流程。
未命中 → 进入 Layer 2。
**Layer 2 — 语义审查LLM 层,< 200ms**
通过低 token 消耗的快速分类 prompt 进行语义级审查,捕捉绕过关键词的隐性违规:
```
Prompt: "以下AI回复是否存在医疗合规问题
A.无问题 B.含诊断 C.含处方建议 D.含疗效承诺 E.其他违规
只输出字母。"
实现:调用 erp-ai Provider优先本地 Ollama 降成本)
```
返回 A → 放行。返回 B/C/D/E → 标记违规类型 → 进入修正流程。
### 5.2 审查规则配置
合规过滤规则与风险评分规则§3.1 的 `copilot_rules` 表)是不同的数据结构,使用独立的内存加载方式:
- **风险评分规则** → 存储 `copilot_rules` 表(含 condition_expr、score通过事件驱动执行
- **合规过滤规则** → 使用 Rust 代码内嵌的静态词表 + 可选的 `copilot_compliance_rules` 表(机构自定义扩展词)
机构自定义合规词表在 Phase 4 MVP 中不实现。MVP 使用代码内嵌的固定词表,覆盖 §5.1 中列出的标准违规关键词。后续版本可通过管理后台动态管理词表。
```json
{
"rule_id": "no_diagnosis",
"category": "diagnosis",
"severity": "critical",
"keywords": ["确诊为", "诊断为", "你得了", "诊断结果是", "可以确诊"],
"replacement_template": "这个情况建议让医生当面评估一下",
"auto_fix": true
}
```
内置规则分类CRITICAL诊断/处方)→ 自动修正不可跳过HIGH疗效/评估)→ 自动修正MEDIUM绝对化/误导)→ LLM 重写。
### 5.3 修正策略
三级修正,逐级升格:
**策略 1 — 模板替换(关键词违规,确定性高):**
- 直接用预设安全模板替换违规片段
- 例:"可能是高血压引起的头晕" → "头晕可能有多种原因,建议到院让医生评估"
**策略 2 — LLM 重写(语义违规,需理解上下文):**
- Prompt"将以下回复改写为合规版本,移除诊断/处方语言,改为引导到院,保持关怀语气"
- 重写后再次过 Layer 1 审查
**策略 3 — 兜底降级(两次修正仍不通过):**
- 使用预设安全模板:
- "感谢您的提问,这个问题建议您下次来的时候直接跟医生聊聊。要不要我帮您预约?"
### 5.4 降级策略AI 不可用时)
当 LLM 服务不可用时合规审查降级为纯规则模式Layer 1 only
- 仅回答服务咨询类问题(预约、流程、地址等)
- 健康类问题统一使用安全兜底模板
- 不尝试生成个性化健康解读
- 对话 UI 显示"小H 暂时只能回答预约和流程类问题,健康问题建议直接咨询医生"
### 5.5 审计追踪
每条患者端对话的审查记录持久化存储到 `copilot_chat_logs` 表:
| 字段 | 说明 |
|------|------|
| user_message | 患者原文 |
| intent_classification | 意图分类结果 |
| ai_raw_response | AI 原始输出(修正前) |
| layer1_result | 关键词审查结果 |
| layer2_result | 语义审查结果 |
| violations_found | 违规项列表 |
| fix_strategy | 修正策略类型 |
| final_response | 最终发给患者的文本 |
**数据保留策略:**
- 审查日志保留 3 年(医疗数据合规要求)
- 原始输出与最终输出的对比可用于持续评估审查准确性
- 机构可定期审查 AI 对话是否有违规漏过
---
## §6 技术设计
### 6.1 Crate 架构
扩展现有 erp-ai crate在其内部新增 `copilot/` 子模块。不新建独立 crate。
理由Copilot 的 AI 调用复用 erp-ai 的 Provider 抽象层,无需重复实现。规则引擎虽不依赖 AI但作为子模块放在 erp-ai 内部更内聚。如未来 Copilot 发展到需要独立部署,再拆分为微服务。
```
crates/erp-ai/src/
├── copilot/ (新增)
│ ├── mod.rs — 模块入口
│ ├── engine.rs — 洞察调度器
│ ├── rules.rs — 规则引擎(条件解析 + 评分)
│ ├── scoring.rs — 混合评分(规则分 + LLM 补充)
│ ├── intent.rs — 患者端意图识别
│ ├── compliance.rs — 合规审查引擎
│ └── context.rs — 对话上下文组装
├── handler/ (新增)
│ ├── insight_handler.rs — 洞察查询 API
│ ├── chat_handler.rs — 患者对话 API
│ └── risk_handler.rs — 风险评分 API
├── entity/ (新增)
│ ├── copilot_insights.rs
│ ├── copilot_risk_snapshots.rs
│ ├── copilot_chat_logs.rs
│ └── copilot_rules.rs
├── service/ (新增)
│ ├── insight_service.rs
│ ├── risk_service.rs
│ ├── chat_service.rs
│ └── compliance_service.rs
└── event/ (新增)
└── copilot_consumer.rs — 订阅 health 模块事件
```
### 6.2 数据库设计
4 张新表均包含标准字段id, tenant_id, created_at, updated_at, created_by, updated_by, deleted_at, version
**跨 crate 外键策略:** copilot_insights 和 copilot_risk_snapshots 中的 `patient_id` 使用逻辑关联(无外键约束),不直接引用 erp-health 的 `patients` 表。理由:根据架构铁律"模块间只通过事件总线和 trait 通信"erp-ai 不应直接依赖 erp-health 的表结构。数据一致性通过事件驱动保证——patient.created 事件触发初始化patient 数据变更通过事件通知。
**copilot_rules — 规则配置**
```sql
CREATE TABLE copilot_rules (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
name VARCHAR(200) NOT NULL,
category VARCHAR(50) NOT NULL, -- vital_signs/lab/adherence/dialysis/composite
condition_expr JSONB NOT NULL, -- 规则条件表达式
score SMALLINT NOT NULL, -- +1 ~ +5
severity VARCHAR(20) NOT NULL, -- info/warning/critical
suggestion TEXT,
enabled BOOLEAN DEFAULT true,
sort_order INT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
created_by UUID, updated_by UUID,
deleted_at TIMESTAMPTZ, version INT DEFAULT 1
);
```
**copilot_insights — 洞察存储**
```sql
CREATE TABLE copilot_insights (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL, -- 逻辑关联 patients 表,无外键约束(跨 crate
insight_type VARCHAR(50) NOT NULL, -- risk_score/anomaly/follow_up_hint/consult_hint
source VARCHAR(20) NOT NULL, -- rule/llm/hybrid
severity VARCHAR(20),
title VARCHAR(500) NOT NULL,
content JSONB NOT NULL,
rule_matches JSONB,
llm_supplement TEXT,
expires_at TIMESTAMPTZ NOT NULL,
is_read BOOLEAN DEFAULT false,
is_dismissed BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
created_by UUID, updated_by UUID,
deleted_at TIMESTAMPTZ, version INT DEFAULT 1
);
```
**copilot_risk_snapshots — 风险评分快照**
```sql
CREATE TABLE copilot_risk_snapshots (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL, -- 逻辑关联 patients 表,无外键约束(跨 crate
risk_score SMALLINT NOT NULL, -- 0-10
risk_level VARCHAR(20) NOT NULL, -- low/medium/high/critical
rule_details JSONB NOT NULL,
llm_summary TEXT,
computed_at TIMESTAMPTZ NOT NULL,
data_freshness JSONB,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
created_by UUID, updated_by UUID,
deleted_at TIMESTAMPTZ, version INT DEFAULT 1
);
```
**copilot_chat_logs — 对话审查日志**
```sql
CREATE TABLE copilot_chat_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
patient_id UUID NOT NULL,
session_id UUID NOT NULL,
user_message TEXT NOT NULL,
intent_classification VARCHAR(30),
ai_raw_response TEXT,
layer1_result JSONB,
layer2_result JSONB,
violations_found JSONB,
fix_strategy VARCHAR(30),
final_response TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
created_by UUID, updated_by UUID,
deleted_at TIMESTAMPTZ, version INT DEFAULT 1
);
```
### 6.3 API 设计
**医护端 API需 JWT 认证 + 权限码):**
| 方法 | 路径 | 权限码 | 说明 |
|------|------|--------|------|
| GET | `/api/v1/copilot/insights` | copilot.insights.list | 查询洞察列表(支持按患者/类型/严重度过滤) |
| GET | `/api/v1/copilot/insights/{id}` | copilot.insights.list | 获取单条洞察详情 |
| POST | `/api/v1/copilot/insights/{id}/dismiss` | copilot.insights.manage | 标记洞察已处理/忽略 |
| GET | `/api/v1/copilot/patients/{id}/risk` | copilot.risk.view | 获取患者风险画像 |
| GET | `/api/v1/copilot/patients/{id}/followup-hint` | copilot.risk.view | 获取随访推荐建议 |
| GET | `/api/v1/copilot/patients/{id}/consult-hint` | copilot.risk.view | 获取咨询辅助建议 |
| GET | `/api/v1/copilot/rules` | copilot.rules.list | 列出规则 |
| POST | `/api/v1/copilot/rules` | copilot.rules.manage | 创建规则 |
| PUT | `/api/v1/copilot/rules/{id}` | copilot.rules.manage | 更新规则 |
**患者端 API需患者 JWT**
患者端与医护端共享同一套 JWT 认证体系erp-auth。小程序通过微信登录获取 token`apps/miniprogram/src/services/` 的现有 auth 流程),该 token 包含 `user_id``tenant_id`。Copilot API 通过 `user_id` 关联 `patients` 表确定患者身份。
`copilot.chat.patient` 权限码在角色初始化时自动赋予"患者"角色(非管理后台角色),无需手动分配。
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/v1/copilot/chat` | 发送消息,返回合规审查后的回复 |
| GET | `/api/v1/copilot/chat/history` | 获取对话历史(分页) |
| GET | `/api/v1/copilot/chat/daily-greeting` | 获取今日个性化问候 |
**权限码汇总:**
```
copilot.insights.list — 查看洞察列表
copilot.insights.manage — 处理/忽略洞察
copilot.risk.view — 查看风险画像
copilot.rules.list — 查看规则
copilot.rules.manage — 管理规则
copilot.chat.patient — 患者端对话(患者角色自带)
```
### 6.4 事件订阅
Copilot 引擎订阅以下 erp-health 模块事件。事件名称已对齐 `crates/erp-health/src/event/mod.rs` 中的实际常量:
**已有事件(可直接订阅):**
| 事件常量 | 触发动作 |
|---------|---------|
| `daily_monitoring.created` | 体征数据录入 → 异常检测 + 风险评分刷新 |
| `lab_report.reviewed` | 化验报告审核 → 化验异常检测 + 风险评分刷新 |
| `follow_up.completed` | 随访完成 → 更新随访依从性 |
| `follow_up.overdue` | 随访失约 → 风险评分 +1 + 生成告警 |
| `patient.created` | 患者建档 → 初始化风险基线 |
**需新增事件(在 erp-health 中添加发布点):**
| 事件常量 | 发布时机 | 触发动作 |
|---------|---------|---------|
| `appointment.completed` | 预约状态变为已完成 | 更新依从性数据 + 风险评分刷新 |
事件消费流程EventBus 收到事件 → copilot_consumer 匹配事件类型 → 调用规则引擎评估 → 生成/更新洞察 → 写入 copilot_insights → 如有异常告警则通知医护端。
### 6.5 前端组件设计
**医护端 React 组件apps/web/src/components/Copilot/**
```
├── CopilotBadge.tsx — 风险等级徽章(嵌入患者列表/详情页)
├── CopilotCard.tsx — 洞察卡片(风险画像/异常告警)
├── CopilotAlert.tsx — 告警通知(仪表盘/首页)
├── CopilotPanel.tsx — 侧边栏面板(随访推荐/咨询辅助)
├── CopilotInsightList.tsx — 洞察列表页
└── hooks/
├── useCopilotInsights.ts — 洞察数据 hook
└── useCopilotRisk.ts — 风险评分 hook
```
**患者端小程序组件apps/miniprogram/src/pages/copilot/**
```
├── index.tsx — 对话主页
└── components/
├── ChatBubble.tsx — 消息气泡
├── QuickActions.tsx — 快捷入口
└── InputBar.tsx — 输入框
```
---
## §7 实施阶段
总体策略:自下而上,每个阶段交付可验证的价值。
### Phase 0基础设施地基
**目标:** 搭建 Copilot 引擎骨架,让它能"跑起来"
| 任务 | 产出 | 依赖 |
|------|------|------|
| 数据库迁移 | 4 个迁移文件copilot_rules, copilot_insights, copilot_risk_snapshots, copilot_chat_logs | 无 |
| 规则引擎核心 | `copilot/rules.rs` — 条件解析 + 评分计算 | 无 |
| 洞察存储 CRUD | `insight_service.rs` — 写入/查询/过期清理 | 迁移文件 |
| 风险评分基础框架 | `scoring.rs` — 规则评分逻辑(纯规则,无 LLM | 规则引擎 |
| Copilot API 骨架 | 3 个 handler + 路由注册 | 洞察存储 |
| 预置规则种子数据 | 10-15 条内置规则(体征/化验/依从性) | 迁移文件 |
**验收标准:**
- `cargo check` 通过
- 内置规则对患者数据跑通评分逻辑
- API 可查询风险评分和洞察列表
### Phase 1医护端风险画像第一个可见价值
**目标:** 医护打开患者档案时,能看到 Copilot 风险徽章和洞察卡片
| 任务 | 产出 | 依赖 |
|------|------|------|
| 事件消费者 | `copilot_consumer.rs` — 订阅体征/化验事件 | Phase 0 |
| 风险评分刷新(异步) | 事件触发 → 规则评估 → 写入风险快照 | 事件消费者 |
| LLM 补充分析集成 | 规则评分结果 → 调用 erp-ai → LLM 补充洞察 | erp-ai Provider |
| 前端 CopilotBadge | 患者列表/详情页风险徽章 | API |
| 前端 CopilotCard | 可展开的洞察卡片 | API |
| 每日风险快照批量刷新 | 定时任务:凌晨重算所有在管患者 | 评分逻辑 |
**验收标准:**
- 录入新体征数据后,风险评分自动更新
- 医护端患者详情页显示风险徽章和洞察卡片
- LLM 补充分析正常返回(非阻塞,失败降级为纯规则)
### Phase 2异常检测 + 告警推送
**目标:** 健康数据入库时自动检测异常,推送告警给医护
| 任务 | 产出 | 依赖 |
|------|------|------|
| 异常检测规则扩展 | 新增趋势类/复合类规则 | Phase 1 |
| 告警洞察生成 | 异常 → 生成洞察 → 推送通知 | 事件消费者 |
| 前端 CopilotAlert | 仪表盘告警卡片 + 浏览器通知 | API |
| 告警处理工作流 | 标记已处理 / 忽略 / 升级 | API |
**验收标准:**
- 危急值(如血钾 >6.0)入库后秒级生成告警
- 医护仪表盘显示分级告警列表
- 告警可标记处理状态
### Phase 3随访推荐 + 咨询辅助
**目标:** Copilot 在医护创建随访/咨询时提供智能建议
| 任务 | 产出 | 依赖 |
|------|------|------|
| 随访推荐逻辑 | 基于风险画像 + 疾病模板 → 推荐随访方案 | Phase 1 风险数据 |
| 咨询辅助逻辑 | 患者档案 + 对话内容 → 追问建议 | Phase 1 + 对话上下文 |
| 前端 CopilotPanel | 随访/咨询页面侧边栏 | API |
| 一键采纳/插入 | 医护可将建议直接填入表单 | 前端组件 |
**验收标准:**
- 创建随访计划时 Copilot 面板显示个性化建议
- 咨询对话时侧边栏显示患者背景和追问建议
- 建议可一键插入到表单/回复框
### Phase 4患者端 CopilotAI 客服/管家)
**目标:** 患者小程序内可与小H对话合规解答、引导到院
| 任务 | 产出 | 依赖 |
|------|------|------|
| 意图识别引擎 | `intent.rs` — 5 类意图分类 | erp-ai Provider |
| 合规审查引擎 | `compliance.rs` — 双层审查 + 自动修正 | 意图识别 |
| 对话上下文组装 | `context.rs` — 患者数据 + 对话历史自动注入 | 风险画像数据 |
| 对话 API | `chat_handler.rs` — 消息收发 + 审查 | 合规引擎 |
| 小程序对话页面 | 聊天 UI + 快捷入口 | API |
| 每日问候生成 | 基于患者数据的个性化推送 | 风险画像 + 定时任务 |
| 审计日志 | 对话审查记录持久化 | 合规引擎 |
**验收标准:**
- 患者可发送消息,获得合规审查后的回复
- 诊断性/处方性提问被自动修正为引导到院
- 对话记录完整可审计
- 每日个性化问候正常推送
### Phase 5日活引擎小程序游戏化
**目标:** 积分体系 + AI 问候驱动患者日常互动
| 任务 | 产出 | 依赖 |
|------|------|------|
| 每日任务系统 | 打卡/录入/阅读任务定义 + 积分规则 | Phase 4 |
| 积分经济扩展 | 分层兑换:服务特权 + 实物商品 | 现有积分模块 |
| 连续打卡 + 勋章 | streak 追踪 + 成就系统 | 任务系统 |
| AI 问候与任务联动 | 问候消息嵌入任务入口 | Phase 4 + 任务系统 |
| 小程序首页改版 | 任务入口 + 积分展示 + AI 问候卡片 | 前端 |
**验收标准:**
- 患者每日可完成健康任务获得积分
- 积分可兑换服务特权/实物商品
- 连续打卡有加成奖励
- AI 问候与当日任务关联
### 阶段依赖总览
```
Phase 0基础设施
Phase 1风险画像← 第一个可见价值
├─────────────────┐
▼ ▼
Phase 2异常检测 Phase 3随访/咨询辅助)
│ │
└────────┬────────┘
Phase 4患者端 Copilot← 合规 AI 客服
Phase 5日活引擎← 游戏化闭环
```
### 预估工作量
| 阶段 | 后端 | 前端 | 数据库 | 核心挑战 |
|------|------|------|--------|---------|
| Phase 0 | 5-7 天 | — | 2 天 | 规则引擎的条件表达式设计 |
| Phase 1 | 5-7 天 | 3-5 天 | — | LLM 集成的稳定性与降级 |
| Phase 2 | 3-5 天 | 2-3 天 | — | 告警分级与推送策略 |
| Phase 3 | 5-7 天 | 3-5 天 | — | 随访模板与疾病类型的映射 |
| Phase 4 | 7-10 天 | 5-7 天 | 1 天 | 合规审查的准确性与延迟 |
| Phase 5 | 5-7 天 | 5-7 天 | 1 天 | 积分经济平衡 |