doc_id: ODS-202606-001 feature_id: FEAT-202605-001-ai-future-hospital-platform type: outline-design title: 医梦 AI 未来医院中台二期技术方案与三期商业闭环设计 status: approved owner: 医梦研发团队 created_at: 2026-06-03 updated_at: 2026-06-03 reviewers: [] related_docs:
| 项目 | 内容 |
|---|---|
| 文档定位 | 生产级技术方案设计文档 |
| 适用范围 | 医梦 AI 开放平台、Dify 医疗智能体、统一入口客户端、设备注册与适配、卡片交互、MCP/HIS 集成、三期商业闭环 |
| 二期主题 | OpenPlatform + Dify Workflow + MCP Server + Card Runtime + Terminal Runtime + Device Registry/Adapter |
| 三期主题 | 能力值预付账户、设备授权、设备维度计量、额度、账单、统计、运营、审计 |
| 计费主粒度 | 项目 / 医院客户;科室、智能体、用户、设备、场景作为分摊与统计维度 |
| 版本 | v6.3 |
| 更新时间 | 2026-06-03 |
二期方案的核心方向仍然合理,但需要按照医院最新确认的“AI 未来医院软硬件一体化建设方案”升级边界:开放平台负责统一入口、租户权限、项目授权、用量记录和卡片运行时;Dify 负责智能体编排、会话推理和流程画布;MCP Server 负责把 HIS / EMR / LIS / PACS / 支付 / 叫号 / 床位 / 护理等院内系统封装成标准工具;统一入口客户端负责把导诊屏、自助机、机器人、叫号屏、诊室屏、医生站插件等门诊终端接入同一套中台,住院护理白板和床头屏只通过迪耐克/鸿蒙病房生态做 AI 嵌入。
需要修正的是职责边界:开放平台不能退化成“只渲染 UI”。在生产环境中,开放平台必须掌握合同、额度、计量、账单、审计、风控、卡片实例状态、租户权限和系统可观测性。Dify 可以做流程总控,但不能成为商业账本和医疗安全责任的唯一来源。
医院确认版方案带来的新增结论是:门诊侧由医梦主导整体入口总包,重点不是医梦生产所有硬件,而是控制门诊软硬件入口标准、统一客户端、设备准入、联调验收和持续运营;住院侧不做硬件总包,应收敛为“AI 大脑层”,与迪耐克 / 鸿蒙病房体系互通,医梦负责智能体、IoMT 预警解释、护理任务、病历质控、出院随访等 AI 闭环。
空海医院最新会议进一步把方案主轴从“多设备统一入口”提升为“动线 + 感知”:感知负责识别患者身份、空间位置、业务状态、设备能力和风险约束;动线负责判断患者当前处于就医流程的哪个阶段、下一步该做什么;AI 中台负责把感知结果转成可确认、可审计、可计量的智能体服务;统一入口客户端负责在机器人、自助机、导诊屏、诊室屏等设备前外显这些服务。该主轴不改变“医梦不做全院物联网硬件平台”的边界,反而要求第一期更克制:先做低门槛、可验收的动线节点感知和服务找人闭环。
三期应优先建设商业闭环,而不是继续堆业务场景。原因是公司商业口径已经明确为“能力值包 + 项目实施费 + 综合运营服务费 / 合理不限量服务包”,且新方案增加了设备集成服务费、统一入口客户端授权费、设备运维服务费、鸿蒙服务找人 POC、机器人场景服务费等收费项。当前工程只有 token 级调用日志,尚不能支撑真实合同、设备维度授权、设备用量统计、预扣款、超量控制、分摊对账和运营报告。
关键架构决策速查:
| 决策 | 本方案口径 | MVP 落地方式 |
|---|---|---|
| OpenPlatform 控事实,Dify 控编排 | 权限、卡片状态、审计、计量、账本都归 OpenPlatform;Dify 只做 Workflow 编排 | 不改造 Dify 内核,只做 DifyAgentEngine、输出校验和版本映射 |
| 门诊统一入口优先 | 门诊导诊屏、自助机、机器人、叫号屏、诊室屏进入医梦统一入口 | 先接 P0 设备,P1/P2 只进准入清单 |
| 住院 AI 大脑层 | 医梦不接管床头屏、护理白板和 IoMT 硬件,只接收迪耐克/鸿蒙病房体系标准事件 | 先做护理预警解释和任务闭环,不做病房硬件运维 |
| 设备授权和能力值分流 | 设备授权费覆盖入口运行,高级 AI 能力按合同进入能力值或服务包 | 通过 charge_policy 避免重复收费 |
| 事件可靠性优先 | 业务成功不能丢审计、不能漏计量、不能重复扣费 | Outbox + 幂等键 + 账本不可变流水 |
| 服务找人最小化 | 主动签到只处理诊室门口到达事件,不保存连续轨迹 | BLE/NFC/二维码兜底,患者确认后才签到 |
| 动线驱动服务 | 同一设备面向不同用户、不同动线阶段,展示不同智能体、卡片和工具权限 | MVP 不新增复杂规则引擎,先用 VisitTimeline + TaskState + DeviceContext + DeviceEvent 推导 journeyState |
| 感知分级落地 | 身份、空间、业务、设备、风险五类感知分层接入 | P0 用扫码/NFC/刷卡/人工确认,P1 才做 BLE 区域感知,P2 才评估星闪/UWB/鸿蒙高精度 |
本方案只引用能在公开资料中找到对应实践的设计,且默认按创业公司资源做裁剪。大厂方案可以证明方向,但不能照搬其平台规模。
| 参考对象 | 公开资料可验证能力 | 对本方案的启发 | 医梦采用方式 | 明确不照搬 |
|---|---|---|---|---|
| 卫宁 WiNEX | 公开资料提出“1 个中台 + X 场景化解决方案”,并以业务中台、数据中台、技术中台支撑智慧医院场景 | 中台应沉淀共性能力,再支撑场景扩展 | OpenPlatform、Card、MCP、计量账本作为最小共性底座 | 不建设完整医院核心业务中台,不替代 HIS/EMR |
| 科大讯飞智医助理 | 公开资料强调在不改变基层医生现有诊疗过程的基础上提供辅助诊断建议 | AI 医疗应嵌入医生工作流,医生保留最终决策权 | 诊间病历、CDSS、质控、四诊结果均需医生确认 | 不承诺 AI 自动诊断、自动处方 |
| 医惠智慧病房 | 公开资料显示智慧病房以物联网共性开放平台为基础,统一感知、管控和管理病房数据与设备 | 住院物联网应由病房/物联平台统一接入,AI 厂商接标准事件 | 医梦只接收迪耐克/鸿蒙病房网关或医院物联平台标准事件 | 不直连住院 IoMT 原始设备,不接管病房硬件运维 |
| 华为智慧病房/医疗物联网 | 公开资料强调物联网平台自动采集和处理海量物联数据,支撑病房上层应用 | 网络、设备接入、协议适配是重资产能力 | 只把 IoMT 作为事件输入和 AI 解释对象 | 不自建医疗物联网络和设备接入平台 |
| Dify Workflow | 官方文档已有 Chatflow/Workflow 版本控制、发布、历史版本和恢复能力 | 编排平台已有能力应复用,不重复造轮子 | 医梦只做 Dify 版本映射、输出校验、配置灰度和回滚指针 | 不自研完整 Workflow 发布系统 |
| 中医四诊仪公开产品 | 公开产品通常包含舌诊、面诊、脉诊、问诊和多模态采集/AI 分析 | 四诊仪不是普通屏幕,必须依赖厂商 SDK/API 或专精模型 | 首期只做舌/面采集、分析结果卡片和医生确认 | 不自研四诊硬件,不训练全量四诊模型 |
| 《个人信息保护法》 | 医疗健康、行踪轨迹属于敏感个人信息,处理需特定目的、必要性和严格保护措施 | 服务找人和医疗数据链路必须最小化 | 主动签到只保留诊室门口到达事件,支持拒绝授权后降级 | 不保存患者连续轨迹,不做无感自动签到 |
| 空海医院会议反馈 | 信息科主任认可“系统知道患者是谁、设备是谁、当前位置和下一步业务,主动把签到/结算/导航服务外显出来”的价值,同时强调门槛低、先做一个场景、不能假设全院蓝牙/星闪 | 动线和感知是本项目差异化表达,但必须按低门槛方案起步 | 第一阶段只做关键节点感知和服务卡片推送,优先老人、特殊人群、诊区签到、缴费/检查提醒 | 不把电梯控制、全院无感定位、腕带体系作为 P0 |
参考来源:
| 资料 | 链接 | 本文使用方式 |
|---|---|---|
| 卫宁 WiNEX 发布报道 | CHIMA:卫宁健康正式发布新一代医疗健康科技产品 WiNEX | 支撑“中台 + 场景化解决方案”的方向,但不照搬三中台规模 |
| 科大讯飞智慧医疗 | 科大讯飞智慧医疗官网 | 支撑“AI 辅助医生、不改变医生流程”的原则 |
| 东软 5G 智慧医院信息平台 | 东软5G智慧医院信息平台系统 | 支撑“统一信息平台集成各子系统”的方向,但医梦只做 AI 入口层 |
| 医惠智慧病房 | 医惠科技智慧病房 | 支撑病房物联网由专业平台统一感知、管控、管理的边界 |
| 华为智慧病房 | 华为智慧病房解决方案 | 支撑病房物联网络和平台是重资产能力,医梦不自建 |
| Dify 版本控制 | Dify Version Control | 支撑复用 Dify 自带发布、历史版本、恢复能力 |
| 个人信息保护法 | 中央网信办:中华人民共和国个人信息保护法 | 支撑医疗健康、行踪轨迹敏感信息和最小化处理要求 |
| 四诊仪公开产品资料 | 本足智能中医四诊仪、高校装备展四诊仪资料 | 支撑四诊仪多模态采集和厂商 SDK/API 优先策略 |
以下分级用于约束研发排期。没有进入 MVP 的能力,不允许在第一期以“顺手做一下”的名义扩张。
| 能力 | 难度 | 核心难点 | MVP 做法 | 延后条件 |
|---|---|---|---|---|
| AgentEngine + DifyAdapter | 中 | 旧引擎迁移、SSE 解析、输出不稳定 | 复用现有 DifyApiClient,先支持文本 + 单卡片 | 多模型路由、复杂降级后置 |
| Card Runtime | 中 | 状态机、幂等、卡片快照、动作回传 | 只做内置医疗卡片,不开放第三方卡片生态 | 沙箱、插件市场后置 |
| MCP/HIS Adapter | 高 | 医院接口差异、写操作幂等、网络和厂商联调 | 先做科室/医生/排班查询 + 锁号/挂号 Mock,再接真实写操作 | 多医院通用 Adapter 后置 |
| Device Registry | 中 | 设备身份、心跳、位置、版本、准入 | 只管门诊 P0 设备;住院只记映射 | P1/P2 设备批量接入后置 |
| Terminal Runtime | 高 | 多端兼容、扫码/读卡/打印/语音 Bridge、现场升级 | 首期 Web/H5 + Android WebView 壳,优先导诊屏/自助机/诊室屏 | Electron/Harmony 原生能力后置 |
| Scene Orchestrator | 中 | 场景规则容易复杂化 | 先做设备到默认场景、默认智能体、UI 模板的静态绑定 | 动态位置/时间/用户状态规则后置 |
| Journey Context | 中 | 业务状态来自 HIS/叫号/卡片动作/设备事件,容易变成复杂状态机 | P0 不独立建服务,先在 OpenPlatform 里用任务状态和设备事件生成 journeyState |
全院患者动线引擎、复杂路径优化后置 |
| Perception Event | 中高 | 身份绑定、近场准确率、授权、误触发、安全合规 | P0 只接扫码/NFC/刷卡/人工确认和诊室门口事件 | 连续轨迹、全院定位、自动化触发后置 |
| 服务找人 POC | 高 | 近场准确率、授权、误触发、叫号/HIS 联动 | 诊室门口小屏 + BLE/NFC/二维码兜底,只做主动签到 | 全院定位、路线推送后置 |
| IoMT Event Hub | 高 | 病房设备边界、事件标准化、护理闭环 | 只接迪耐克/鸿蒙病房网关标准预警事件 | 原始体征流、复杂风险模型后置 |
| 四诊仪 | 高 | 专用硬件、图像质量、厂商算法、医生采纳 | 舌/面图片采集 + 结果卡片 + 医生确认 | 脉诊、多厂商统一后置 |
| 三期计量账本 | 中高 | 事件归并、幂等、账本一致性、合同规则 | ai_meter_event + ai_credit_ledger,先项目主账户 |
科室硬预算、区域分账后置 |
| 运营看板 | 中 | 指标口径、数据质量、设备/业务归因 | 先做项目、设备、智能体、场景的基础统计 | 区域驾驶舱、毛利模型后置 |
本节采纳 docs/initiatives/FEAT-202606-001-unified-entry-client/详细设计.md 的边界,但按创业公司 MVP 做收敛:统一入口客户端后端能力进入 AI 中台统一工程,前端和移动端另起 emoon-terminal-client 工程,不新增一套 Demo 后端。
| 结论 | 正式方案口径 | MVP 落地 |
|---|---|---|
| 后端归属 | Device Registry、Scene Profile、AgentRouter、TaskStateService、Card Runtime、File Service、HisMockAdapter、TongueDiagnosisAdapter 都归 AI 中台模块 | 复用 OpenPlatform 对外入口和 Maven 多模块工程,不新建独立终端后端 |
| 前端归属 | 机器人、自助机、导诊屏三端进入独立 emoon-terminal-client 工程 |
后端只提供 OpenAPI、场景配置、卡片 schema 和设备命令协议 |
| P0 业务链路 | 机器人导诊导航、自助机建档/分诊/挂号 Mock/舌诊、导诊屏 FAQ/科室介绍/路线/轻分诊 | 每条链路必须能回放 conversationId、taskId、cardInstanceId、traceId |
| TaskStateService | 任务状态是 AI 中台内部状态,不作为第一期公共 /tasks API 暴露 |
任务状态通过 /agent/chat/stream、/conversations/* 和 /cards/* 返回给终端 |
| AgentRouter | 先按设备能力、场景、任务状态和少量规则路由,再少量使用 LLM 意图分类兜底 | 不在第一期建设复杂规则引擎和在线学习系统 |
| 舌诊接入 | 前端只上传文件和执行卡片动作,后端通过 TongueDiagnosisAdapter 调专精能力 |
不允许前端直连舌诊底层接口,不把 base64 图片塞进 Dify |
| HIS 接入 | 无真实 HIS 前必须显式使用 HisMockAdapter |
Mock 数据只用于 POC,不得冒充真实支付、真实挂号或真实医保 |
| 终端接口白名单 | 终端只调用设备、SSE 对话、文件、卡片、事件、命令轮询等 P0 接口 | 终端不得直连 Dify、HIS Tool、计量写接口和舌诊底层接口 |
该取舍与行业实践一致:东软类智慧医院平台强调统一信息平台集成各子系统,华为/医惠类病房方案强调物联平台统一接入设备,Dify 官方已提供 Workflow 版本能力。医梦作为创业团队,应只做 AI 入口层、卡片闭环、设备场景治理和必要适配,不复制大厂完整医院平台和物联网底座。
空海会议中甲方真正感兴趣的不是“多接几个设备”,而是设备能理解患者当前处于哪条就医动线、应该外显哪个服务。产品表达应统一为:
医梦 AI 未来医院不是简单接入智能设备,而是通过统一入口客户端和 AI 中台,把患者身份、当前位置、业务状态和设备能力统一感知起来,再基于患者全流程动线主动推送下一步服务,实现“患者少找路、少找窗口、少找设备,医院服务主动找人”。
感知模型分为五类,P0 只做能低成本验证的部分:
| 感知类型 | 含义 | P0 落地 | 不做 |
|---|---|---|---|
| 身份感知 | 知道当前服务对象是谁 | 扫码、刷卡、NFC、患者确认后绑定 patientId/visitId/deviceId/terminalSessionId |
无授权人脸识别、长期腕带绑定 |
| 空间感知 | 知道患者在哪个服务区域 | 设备位置 + 诊室门口扫码/NFC/BLE 区域事件 | 全院连续轨迹、高精度室内定位 |
| 业务状态感知 | 知道患者就医流程状态 | HIS/叫号/卡片动作返回:已挂号、待签到、候诊、待缴费、待检查、报告已出 | 跨系统大数据画像 |
| 设备状态感知 | 知道当前设备能提供什么服务 | Device Registry 返回设备能力、场景、允许卡片和允许智能体 | 未准入设备进入核心业务 |
| 风险感知 | 知道哪些动作必须确认或人工接管 | 高风险卡片 confirm=true,特殊人群优先提示,失败转人工 |
自动签到、自动缴费、自动诊断 |
动线模型不是大型流程引擎,MVP 只做可解释的状态推导:
VisitTimeline + TaskState + DeviceContext + DeviceEvent + CardAction
→ JourneyContext
→ Scene Orchestrator / AgentRouter
→ 智能体、卡片、设备命令
→ 用户确认
→ 状态回写
第一期只实现 4 个可验收动线节点:
| 动线节点 | 触发条件 | 外显服务 | 验收方式 |
|---|---|---|---|
| 到院/到诊区 | 患者扫码/NFC/刷卡或诊区近场事件 | 建档、签到、候诊提醒 | 能产生 journeyState=WAITING_CHECKIN/WAITING_CALL |
| 就诊后待缴费 | HIS 或 Mock 返回缴费/处置单状态 | 缴费提醒、窗口/自助机引导 | 前端展示待办卡片,用户确认后跳转或转人工 |
| 待检查/检验 | 医嘱/检查单状态 + 设备位置 | 检查导航、注意事项 | 机器人/屏幕能生成导航命令或路线卡 |
| 报告已出/诊后 | 报告状态或就诊结束状态 | 报告解读卡、诊后小结/随访提醒 | 只展示辅助解释,不自动给诊断结论 |
同一台设备必须按用户和动线阶段动态裁剪能力。例如诊室门口屏对普通患者只展示签到、候诊、缴费提醒;对医护人员可展示队列管理和人工接管;对未授权访客只展示公共导诊和科室介绍。这个差异通过 sceneProfile + userContext + 服务端 journeyState + allowedAgents/allowedCards 决定,前端不得自行放开能力。
SceneOrchestrator 和 AgentRouter 都使用上下文,但职责不同,不能混成一个“大路由器”。
| 组件 | 决策层级 | 输入 | 输出 | 调用时机 |
|---|---|---|---|---|
| SceneOrchestrator | 设备/场景级 | deviceId/deviceType、设备状态、用户身份、服务端 journeyState、项目配置 |
homeTemplate、allowedAgents、allowedCards、blockedIntents、perceptionCapabilities、journeyPolicy |
GET /devices/{deviceId}/scene;每次 /agent/chat/stream 前复核 |
| AgentRouter | 对话/任务级 | 用户输入、TaskState、等待卡片、服务端 journeyState、allowedAgents/blockedIntents |
具体 agentId、任务类型、是否创建卡片或设备命令 |
每次 /agent/chat/stream 内部执行 |
调用顺序固定为:
Device Registry / SceneOrchestrator
→ 服务端 JourneyContext 推导
→ AgentRouter 在 allowedAgents 范围内路由
→ Dify / Direct / Mock
→ Card Runtime / Device Command
禁止反向依赖:AgentRouter 不得绕过 SceneOrchestrator 放开设备不允许的智能体;前端不得用本地配置覆盖 allowedAgents/allowedCards。
perceptionCapabilities 和 journeyPolicy 不是终端自声明字段。MVP 阶段配置来源如下:
| 配置 | 来源 | 维护人 | P0 实现 |
|---|---|---|---|
perceptionCapabilities |
Device Registry 设备能力配置 | 医梦运维 / 项目交付 | 管理后台或 SQL 种子配置,终端只读取 |
journeyPolicy |
设备场景绑定配置 | 医梦运维 / 项目交付 | MVP_STATIC,控制是否展示动线区和服务找人入口 |
allowedAgents/allowedCards |
设备场景白名单 | 医梦运维 / 项目交付 | 后端强制校验,前端只渲染 |
| 身份绑定策略 | 项目授权和患者确认策略 | 医院信息科 / 医梦交付 | 绑定、解绑、过期、拒绝授权降级 |
感知事件安全链路:
| 风险 | P0 防护 |
|---|---|
| 伪造设备事件 | 只有已注册、已激活、归属当前项目的设备可调用事件接口;请求必须通过 HMAC/Bearer 鉴权 |
| 重放事件 | eventId + deviceId + projectId 幂等,服务端校验时间窗口和 nonce/signature |
| 伪造动线阶段 | 客户端请求不得传 journeyState;即使通过扩展字段伪造,服务端也完全忽略 |
| 近场误触发 | NEARBY_DETECTED 只作为感知事实,必须结合身份授权、HIS/叫号状态和患者确认后才生成卡片 |
| 安全校验失败 | 降级为 L0 扫码、NFC、人工确认,不自动执行业务动作 |
P0 验收采用 Given-When-Then,避免“到诊区”“服务找人”等概念不可测试。
| 场景 | Given | When | Then |
|---|---|---|---|
| 到诊区主动签到 | 患者已挂号,设备已激活并绑定诊区,患者已授权身份绑定 | 患者在诊室门口屏刷卡/NFC 或扫描签到二维码 | SSE 返回 journey_updated.stageCode=WAITING_CHECKIN;创建主动签到卡;用户确认后才调用签到工具 |
| 候诊提醒 | 患者已签到,叫号系统返回候诊状态 | 患者靠近候诊屏或自助机,或主动询问“还要等多久” | 返回 journeyState.stageCode=WAITING_CALL;展示候诊提醒卡,不暴露他人队列隐私 |
| 就诊后缴费引导 | HIS/Mock 返回待缴费或处置状态 | 患者靠近自助机/导诊屏或发起缴费咨询 | 返回 journeyState.stageCode=WAITING_PAYMENT;展示缴费引导卡;P0 不做真实支付 |
| 待检查导航 | HIS/Mock 返回待检查/检验状态,设备具备路线或导航能力 | 患者在机器人/导诊屏请求检查路线 | 返回 journeyState.stageCode=WAITING_EXAM;生成路线卡或机器人导航命令 |
| 报告已出解释入口 | 报告状态已出,患者身份授权有效 | 患者在受控终端请求解读报告 | 返回报告解读入口卡;文件和报告内容走 File Service;不自动给正式诊断 |
医护电梯场景拆分处理:普通患者电梯控制不进入 P0/P1;医护授权电梯可作为 P1 可选试点,前提是医院已有电梯控制 API 或物联平台能力。医梦只通过 MCP/Adapter 调用,不改造电梯系统,不把医护电梯作为门诊 MVP 交付前置条件。
为支撑交付,管理后台至少需要形成以下配置能力。MVP 可以先用种子数据或内部配置页实现,但必须有明确归属。
| 配置页面 | 关键字段 | MVP 要求 |
|---|---|---|
| 设备准入审核 | deviceId、设备类型、院区/楼层/区域、activateStatus、准入等级 |
P0 必须能激活/拒绝设备 |
| 设备能力配置 | capabilities、perceptionCapabilities、Bridge 能力、厂商信息 |
P0 可配置扫码/NFC/刷卡/摄像头/导航 |
| 场景绑定配置 | homeTemplate、allowedAgents、allowedCards、blockedIntents、journeyPolicy |
P0 必须支持按设备切换场景 |
| 身份绑定策略 | 授权方式、绑定有效期、解绑规则、拒绝授权降级 | P0 可用固定项目配置 |
| 动线规则配置 | stageCode、触发事件、依赖 HIS/Mock 状态、推荐卡片 |
P0 可硬编码 + 文档化,P1 再后台化 |
| 感知事件审计 | eventId、设备、区域、事件类型、处理结果、traceId |
P0 必须可查询和回放 |
当前仓库基于 RuoYi-Vue-Plus 改造,核心模块如下:
| 模块 | 当前职责 |
|---|---|
emoon-admin |
管理后台启动模块,承载系统管理接口 |
emoon-openplatform |
对外开放平台入口,包含签名鉴权、模型调用、Dify API 客户端、二期对话入口 |
emoon-infra/emoon-modules-api/emoon-system-api |
系统领域 API、DO、Mapper、Service 接口,已加入部分 AI 元数据表 |
emoon-infra/emoon-modules-api/emoon-mcp-api |
二期新增 MCP/卡片/会话相关 API,已包含 AgentEngine 抽象与 Mock 引擎 |
emoon-infra/emoon-modules/emoon-system |
管理后台业务实现,已有引擎配置 CRUD |
emoon-infra/emoon-modules/emoon-mcp |
MCP 业务模块雏形,目前仍偏 CRUD 模板 |
emoon-infra/emoon-modules-api/emoon-knowledge-api |
既有知识库、模型、智能体、质控等能力 |
| 能力 | 当前状态 | 说明 |
|---|---|---|
AgentEngine 抽象 |
已有 | 统一 chat / chatStream,支持按 engineType 路由 |
| Mock 引擎 | 已有 | 可返回模拟科室卡片,用于开发联调 |
| OpenPlatform 对话入口 | 已有 | /api/v1/agent/chat 支持同步和 SSE |
| 项目签名鉴权 | 已有 | 基于 X-Emoon-* 请求头和项目公私钥 |
| 会话记录 | 已有 | ai_conversation 记录开放平台会话与外部会话映射 |
| 用量日志 | 初步已有 | ai_usage_log 记录 token 与费用字段,但尚不是计费账本 |
| 卡片定义 / 实例表 | 初步已有 | 已有 DO/Mapper,缺少完整卡片运行时和动作闭环 |
| 引擎配置管理 | 初步已有 | 管理后台支持引擎配置 CRUD |
| 缺口 | 影响 |
|---|---|
DifyAgentEngine 未进入统一 AgentEngine 主链路 |
二期文档描述的 Dify 统一编排尚未真正闭环 |
| MCP Server 工具协议未形成生产工具集 | Dify 调 HIS 的工具层仍需实现和治理 |
| 卡片动作回传与状态机不足 | 用户点击卡片后的业务动作、幂等、审计、结果回传无法生产化 |
ai_usage_log 不能直接计费 |
token 日志缺少合同、套餐、能力值、冻结、扣减、冲正、对账语义 |
| 项目租户边界不完整 | 当前 OpenPlatform 鉴权中 tenantId 使用默认值,需要与项目/医院绑定 |
| 风控、限额、预警、账单缺失 | 无法支撑能力值包、合理不限量、区域能力池和运营服务 |
当前代码中存在几类历史包袱。它们不一定马上删除,但必须在二期设计中明确归属,否则初级工程师会把新旧链路混在一起。
| 体系 | 位置 | 当前用途 | 处理策略 |
|---|---|---|---|
新体系 AgentEngine |
emoon-mcp-api/src/main/java/com/emoon/mcp/engine |
/api/v1/agent/chat 主链路正在使用 |
作为二期唯一主链路 |
旧体系 AIEngine/EngineAdapter/ChatFactory |
emoon-openplatform/src/main/java/com/emoon/openplatform/engine |
DifyAdapterClient 仍接在旧体系上 |
标记为 legacy,迁移可复用转换逻辑 |
| Dify HTTP 客户端 | emoon-openplatform/dify/DifyApiClient |
已封装 Dify REST/SSE 调用 | 保留复用,接入新 DifyAgentEngine |
决策:二期主链路只认 AgentEngine。DifyAgentEngine 应复用现有 DifyApiClient 的协议能力,但不要继续把业务入口接在旧 EngineAdapter 体系上。
初级工程师重点:为什么不能同时维护两套引擎入口?
两套入口会导致权限、日志、卡片、计量都走不同路径。线上排障时会出现“同样是 Dify 调用,有的写会话,有的不写;有的计费,有的不计费”。所以必须确定唯一主链路。
/chat/apisse 巨石控制器迁移ApiSseController 是遗留入口,包含模型路由、RAG、旧 MCP 概念、SSE、音频、提示词占位符等逻辑。它与 /api/v1/agent/chat 新链路并存时,会产生鉴权、日志、计量和卡片体系不一致。
迁移策略:
| 遗留能力 | 迁移目标 |
|---|---|
| 直连模型调用 | DirectLLMAgentEngine |
| RAG 检索 | Dify 知识库节点或独立 RAG Service |
| 音频模型 | AudioService,再作为 Agent 能力或 MCP 工具 |
| 提示词占位符 | PromptTemplateService |
| 旧 SSE 输出 | 统一到 /api/v1/agent/chat 的 SSE 协议 |
| 旧 MCP 流式代理 | 与 Model Context Protocol 区分,逐步废弃 |
兼容期内可保留 /chat/apisse,但必须在网关或文档中标记为 legacy,不再新增能力。
AiAgent 与 AiAgentApp 的关系当前存在两个智能体实体:
| 实体 | 所在模块 | 定位 |
|---|---|---|
AiAgent |
emoon-knowledge-api |
产品/知识侧的复杂智能体定义,包含目标、场景、步骤、输入输出、集成、KPI |
AiAgentApp |
emoon-system-api |
开放平台对外运行视图,绑定项目、引擎配置、状态和对外 agentId |
建议关系:AiAgent 是“设计态 / 产品态”,AiAgentApp 是“运行态 / 开放平台态”。二期主链路读取 AiAgentApp;需要展示业务目标、流程步骤、KPI 时可关联 AiAgent。
可选关联字段:
| 字段 | 说明 |
|---|---|
ai_agent_app.agent_ref_id |
关联 ai_agent.id |
ai_agent_app.agent_ref_version |
关联设计态智能体版本 |
ai_agent_app.scenario_code |
运行态计量和报表使用的场景编码 |
卡片相关表分散在 system-api 和 mcp-api,需要明确服务边界:
| 服务 | 建议位置 | 说明 |
|---|---|---|
CardDefinitionService |
emoon-system |
管理卡片定义、版本、灰度、启停 |
CardInstanceService |
emoon-mcp-api 接口,emoon-openplatform 或 emoon-mcp 实现 |
创建实例、保存快照、查询状态 |
CardActionService |
emoon-ai-card 实现,动作编排由 emoon-ai-agent 承接 |
校验动作、幂等、保存快照、更新状态;不得直接绕过 Agent 调 MCP |
CardRenderConfigService |
前端配合,后端提供定义查询 | 前端按 UI 配置渲染 |
二期对话链路中,AgentChatServiceImpl 在收到 cardKey/cardData 后必须触发 CardInstanceService.createFromAgentResponse() 这类能力,不能只把卡片数据透传给前端。
文档中的 MCP 指 Model Context Protocol 工具协议。当前代码中 emoon-mcp 同时承载 AgentEngine、会话、卡片实例等能力,历史 ApiSseController 里的 “MCP” 又像是外部 LLM 代理。为避免混淆,设计上采用以下命名:
| 名称 | 含义 |
|---|---|
| Agent Core | AgentEngine、会话、卡片实例等智能体核心能力 |
| MCP Tool Server | 真正对 Dify 暴露的工具协议服务 |
| Legacy MCP Proxy | 旧 /chat/apisse 中的外部代理逻辑,迁移后废弃 |
物理模块可分阶段调整:短期先在文档和包名中区分概念;中期再考虑把真正 MCP 工具拆到 emoon-mcp-server 或等价模块。
Dify 是二期流程编排核心,需要独立健康检查和降级策略。
| 能力 | 说明 |
|---|---|
| 健康检查 | 管理后台展示 Dify baseUrl、应用密钥是否可用、最近调用成功率 |
| 超时配置 | 每个智能体配置 Dify 连接超时、读取超时、SSE 最大空闲时间 |
| 熔断策略 | 连续失败后短时间熔断,避免拖垮 OpenPlatform |
| 降级策略 | 按智能体配置:返回预设答复、降级 DirectLLM、只展示人工入口或直接失败 |
| 告警 | Dify 错误率、P99 延迟、SSE 断连率超过阈值时告警 |
二期的目标不是一次性建完整 AI 医院,而是建立可复用的医疗智能体与多终端入口底座:
医院确认版方案下,二期必须明确门诊和住院边界:
| 区域 | 二期定位 | 医梦主责 | 不应承担 |
|---|---|---|---|
| 门诊 | 医梦主导整体入口总包 | 门诊 P0 设备统一入口、设备准入、统一客户端、Agent 绑定、HIS/支付/叫号/EMR 对接、业务闭环验收 | 自研所有硬件、替代医院采购流程 |
| 住院 | 医梦 AI 大脑层协同 | 住院智能体、IoMT 预警解释、护理任务、病历质控、出院随访、与迪耐克/鸿蒙病房互通 | 接管床头屏/护理白板/病房硬件总包 |
| 鸿蒙协同 | 标杆 POC 与国产化亮点 | 主动签到、候诊状态同步、检查路线提醒等“服务找人”小闭环 | 全院所有设备鸿蒙化、无授权自动识别 |
二期不应承担以下事项:
| 不建议二期承担 | 原因 |
|---|---|
| 完整计费结算系统 | 应纳入三期商业闭环统一设计 |
| 第三方卡片开放生态 | 安全、审核、沙箱成本高,优先级低于内置医疗卡片 |
| 复杂模型训练平台 | 与二期 Dify + MCP 主链路不是同一交付焦点 |
| 大而全 HIS 数据中台 | 二期只需要按场景封装必要工具,避免前期失控 |
| 住院硬件总包 | 与迪耐克/既有病房体系边界冲突,医梦应做 AI 层互通 |
| 全院鸿蒙化 | 技术和设备生态不确定,第一期只做可演示、可验收的 POC |
flowchart TD
Client["门诊统一入口客户端<br/>患者端 / 医生站 / 机器人 / 自助机 / 大屏"]
WardEmbed["住院 AI 嵌入端<br/>护理白板 / 床头屏<br/>通过迪耐克/鸿蒙生态接入"]
Device["Device Registry / Adapter<br/>设备身份 / 能力 / 心跳 / 厂商 SDK"]
Scene["Scene Orchestrator<br/>设备-位置-场景-智能体绑定"]
Journey["Journey Context<br/>动线阶段 / 下一步任务 / 服务找人"]
Perception["Perception Event<br/>身份 / 空间 / 业务 / 设备 / 风险感知"]
WardGateway["迪耐克/鸿蒙病房网关<br/>床头屏 / 护理白板 / IoMT 标准事件"]
OpenAPI["OpenPlatform API<br/>签名鉴权 / 租户项目授权 / 限流 / 审计"]
Engine["AgentEngine 路由层<br/>Dify / Direct / Mock"]
Dify["Dify Workflow<br/>意图识别 / 分支 / RAG / 工具调用 / 响应组装"]
MCP["emoon-mcp<br/>MCP Tool Server / HIS Adapter / 幂等 / 熔断"]
HIS["HIS / EMR / LIS / PACS / 排班 / 支付 / 叫号 / 床位 / 护理 / 随访"]
Card["Card Runtime<br/>卡片定义 / 实例 / 动作 / 状态"]
Event["IoMT Event Hub<br/>设备事件 / 护理预警 / 服务找人"]
Data["AI Metadata<br/>智能体 / 会话 / 用量 / 卡片 / 审计"]
Meter["三期计量账本<br/>能力值 / 额度 / 账单"]
Client --> Device
Device --> Scene
Device --> Perception
Perception --> Journey
Scene --> Journey
Journey --> OpenAPI
Client --> OpenAPI
WardEmbed --> WardGateway
WardGateway --> Event
WardGateway --> OpenAPI
OpenAPI --> Engine
Engine --> Dify
Dify --> MCP
MCP --> HIS
Device --> Event
Event --> Perception
Event --> OpenAPI
Dify --> OpenAPI
OpenAPI --> Card
OpenAPI --> Data
OpenAPI -.调用事件.-> Meter
MCP -.工具事件.-> Meter
Card -.动作事件.-> Meter
Device -.设备维度事件.-> Meter
Event -.业务闭环事件.-> Meter
Journey -.动线服务事件.-> Meter
| 组件 | 核心职责 | 不负责 |
|---|---|---|
| OpenPlatform | 对外入口、项目授权、租户隔离、调用编排、卡片运行时、审计、三期计量入口 | 复杂业务流程画布 |
| Terminal Runtime | 门诊多设备统一入口客户端、UI 模板、虚拟形象、语音/触控/扫码/打印 Bridge、远程升级和异常上报;住院侧只做嵌入或协议适配 | 医疗业务规则、合同账本;不承担住院床头屏/护理白板硬件责任 |
| Device Registry | 设备身份、型号、位置、能力、状态、版本、智能体绑定、SLA 等级 | 直接调用 HIS 写业务 |
| Device Adapter | 厂商 SDK/API、屏幕、机器人、自助机、四诊仪;住院侧仅适配迪耐克/鸿蒙病房标准接口 | 决定临床结果、财务扣费;不直接接管病房硬件设备 |
| Scene Orchestrator | 根据设备、位置、时间、用户和业务状态选择 UI、智能体、工具权限 | 替代 Dify Workflow 的多轮医学编排 |
| Perception Event | 接收和归一身份、空间、业务、设备、风险事件,形成可审计的感知事实 | 采集全院连续轨迹、替代医院物联平台 |
| Journey Context | 根据 VisitTimeline/TaskState/DeviceContext/DeviceEvent/CardAction 推导患者当前动线阶段、下一步服务和允许动作 |
建设复杂路径优化引擎、自动完成高风险业务 |
| Dify Workflow | 多轮对话、意图识别、条件分支、RAG、工具编排、自然语言回复 | 合同账本、额度扣减、财务结算 |
| MCP Server | 院内系统工具封装、协议适配、幂等、熔断、降级、工具审计 | UI 渲染、合同管理 |
| Card Runtime | 卡片定义、卡片实例、动作状态机、交互结果回传 | 直接绕过 MCP 操作 HIS |
| HIS Adapter | 对接医院厂商接口、响应格式标准化、错误码映射 | 业务定价与计费策略 |
| IoMT Event Hub | 接收迪耐克/鸿蒙病房网关或医院物联平台输出的标准事件,做事件归一、护理预警、服务找人事件入口 | 直接认证和采集住院 IoMT 原始设备数据;把设备心跳直接作为客户扣费事实 |
| Metering/Billing | 三期能力值计量、预扣、账单、分摊、报表 | 直接参与医疗诊断决策 |
二期/三期融合后,最容易出错的是调用方向。生产方案采用“OpenPlatform 掌控入口和事实记录,Dify 掌控流程编排,MCP 掌控院内工具”的模式。
flowchart LR
Client["客户端 / 终端<br/>患者端 / 医护端 / 机器人 / 自助机 / 屏幕"]
Device["Device Context<br/>设备身份 / 场景 / 能力"]
Open["OpenPlatform<br/>鉴权 / 会话 / 卡片 / 计量入口"]
Engine["AgentEngine<br/>Dify / Direct / Mock"]
Dify["Dify Workflow<br/>流程编排"]
MCP["MCP Tool Server<br/>院内工具网关"]
HIS["医院系统<br/>HIS / EMR / LIS / PACS"]
Meter["Metering/Billing<br/>三期账本"]
Client -->|"1. heartbeat / scene resolve"| Device
Device -->|"2. device profile / scene profile"| Open
Client -->|"3. chat / card action"| Open
Open -->|"4. route by engineType"| Engine
Engine -->|"5. Dify API"| Dify
Dify -->|"6. tool call"| MCP
MCP -->|"7. adapter call"| HIS
HIS -->|"8. standardized result"| MCP
MCP -->|"9. tool result"| Dify
Dify -->|"10. answer / card output"| Engine
Engine -->|"11. unified response"| Open
Open -->|"12. response / SSE / card"| Client
Open -. "business event" .-> Meter
MCP -. "tool event" .-> Meter
Device -. "device event" .-> Meter
| 调用段 | 发起方 | 接收方 | 是否可信 | 关键控制 |
|---|---|---|---|---|
| 客户端到 OpenPlatform | 外部端 | OpenPlatform | 不可信 | 签名、时间戳、项目授权、幂等键、限流 |
| 终端到 Device Registry | 医梦客户端 / 第三方设备 | OpenPlatform / Device Registry | 不可信 | 设备证书、设备密钥、医院/科室绑定、心跳、版本校验 |
| OpenPlatform 到 Dify | 平台内服务 | Dify | 半可信 | Dify App 授权、超时、熔断、输出校验 |
| Dify 到 MCP | Dify | MCP Tool Server | 半可信 | 工具白名单、项目工具授权、患者授权、幂等 |
| MCP 到 HIS | MCP Adapter | 医院系统 | 受控内网 | 厂商鉴权、短超时、结果确认、审计 |
| OpenPlatform 到 Metering | 平台内服务 | 计量账本 | 可信但必须可重放 | Outbox、幂等、状态机 |
初级工程师重点:为什么 Dify 不是“可信后端”?
Dify 是流程编排平台,流程画布可能被运营人员调整,输出结构也可能变化。它可以决定下一步问什么、调用什么工具,但不能直接决定扣费、越权访问、写 HIS 或绕过卡片确认。所有安全和账务判断都必须回到 OpenPlatform/MCP 的强校验链路。
MCP Tool Server 可以先嵌入现有工程,也可以独立部署。选择依据不是“哪个更高级”,而是医院网络、交付阶段和治理要求。
| 部署形态 | 适用阶段 | 优点 | 风险 | 必须满足 |
|---|---|---|---|---|
嵌入 emoon-openplatform |
二期早期联调、小型试点 | 少一个服务,开发和部署简单 | 与对外 API 耦合,内外网边界不清 | 工具包名和服务边界必须独立,后续可拆 |
嵌入 emoon-mcp 模块同进程 |
二期正式试点 | 保留模块边界,部署复杂度适中 | 仍与主应用共享资源 | 独立线程池、超时、熔断、工具审计 |
| 独立 MCP 服务 | L3 项目交付、院内私有化、区域平台 | 网络隔离清晰,便于院内部署和扩容 | 部署、监控、版本治理成本更高 | 服务鉴权、工具注册、健康检查、灰度 |
推荐路线:二期先允许同进程落地,但接口和数据模型按独立服务设计;进入 L3 项目建设版后,把 MCP Tool Server 独立部署到医院内网或专属区。
初级工程师重点:同进程不等于可以省略 Outbox。
只要业务成功和计费/审计事件不是同一张表,就存在“业务写成功但事件丢失”的风险。即使 MCP 和 OpenPlatform 在同一个 JVM,仍要用 Outbox 保证业务事实能被后续可靠处理。
这张图用于回答“医梦 AI 中台在医院项目中和谁交互”。初级工程师先看这张图,明确系统边界,不要把外部系统职责写进中台。
C4Context
title System Context - 医梦 AI 中台
Person(patient, "患者", "通过小程序、APP、自助机或机器人使用 AI 服务")
Person(doctor, "医生 / 护士", "在医生站、护士站使用 AI 辅助功能")
Person(operator, "医院管理员 / 医梦运营", "配置项目、查看用量、处理账单和运营报告")
System(emoon, "医梦 AI 中台", "统一智能体入口、多终端入口、Dify 编排、MCP 工具、卡片交互、设备治理、计量账本")
System_Ext(dify, "Dify 平台", "Workflow、LLM 节点、RAG、工具调用")
System_Ext(his, "医院业务系统", "HIS、EMR、LIS、PACS、排班、支付、叫号、床位、护理、随访")
System_Ext(device, "门诊终端与设备", "导诊屏、自助机、机器人、叫号屏、诊室屏、四诊仪")
System_Ext(harmony, "鸿蒙 / 迪耐克病房体系", "近场感知、床头屏、护理白板、IoMT、病房设备")
System_Ext(model, "模型与语音图像服务", "大模型、ASR、TTS、舌诊/面诊模型")
Rel(patient, emoon, "发起咨询、问诊、挂号、随访")
Rel(doctor, emoon, "使用病历、质控、CDSS、报告解读")
Rel(operator, emoon, "配置、监控、对账、运营")
Rel(device, emoon, "注册、心跳、场景加载、设备事件")
Rel(harmony, emoon, "服务找人、病房事件、住院 AI 互通")
Rel(emoon, dify, "调用 Workflow", "HTTPS/SSE")
Rel(dify, emoon, "调用 MCP 工具", "MCP/HTTP")
Rel(emoon, his, "读取/写入业务数据", "MCP Adapter")
Rel(emoon, model, "调用模型能力", "OpenAI-compatible/API")
这张图用于回答“代码应该放在哪个工程模块”。实现时优先遵守这个边界,避免把计费逻辑写进 Dify Adapter,或者把 HIS 调用写进前端卡片。
C4Container
title Container Diagram - 医梦 AI 中台
Person(user, "患者 / 医护 / 管理员", "系统使用者")
System_Boundary(emoon, "医梦 AI 中台") {
Container(admin, "emoon-admin", "Spring Boot", "管理后台入口,加载 system/mcp 等模块")
Container(open, "emoon-openplatform", "Spring Boot", "对外 API、签名鉴权、Agent 调用、Dify 客户端")
Container(systemApi, "emoon-system-api", "Java API", "系统域 DO、Mapper、Service 接口")
Container(system, "emoon-system", "Java Module", "系统管理、引擎配置、后续合同账单管理")
Container(mcpApi, "emoon-mcp-api", "Java API", "AgentEngine、会话、卡片实例、MCP 域接口")
Container(mcp, "emoon-mcp", "Java Module", "MCP 工具、HIS Adapter、工具审计")
Container(deviceCore, "Device Core", "Java Module", "设备注册、设备能力、场景绑定、设备事件接入")
Container(terminal, "Terminal Runtime", "Web / Android / Harmony / Electron", "多终端统一入口客户端、UI 模板、设备 Bridge")
Container(knowledge, "emoon-knowledge-api", "Java API", "知识库、提示词、质控、既有 AI 资产")
ContainerDb(mysql, "MySQL", "Relational DB", "元数据、会话、卡片、账本、账单")
ContainerDb(redis, "Redis", "Cache", "限流、幂等、热点配置、短锁")
}
System_Ext(dify, "Dify Platform", "Workflow")
System_Ext(his, "Hospital Systems", "HIS/EMR/LIS/PACS")
System_Ext(devices, "Outpatient Devices", "门诊屏幕 / 自助机 / 机器人 / 四诊仪")
Rel(user, terminal, "使用统一入口客户端", "Touch/Voice/Web")
Rel(terminal, open, "调用智能体、卡片和场景 API", "HTTPS/SSE/WebSocket")
Rel(devices, deviceCore, "注册、心跳、设备事件", "HTTPS/MQ/SDK")
Rel(user, admin, "使用管理后台", "HTTPS")
Rel(open, mcpApi, "使用 AgentEngine / 会话 / 卡片接口")
Rel(open, systemApi, "查询项目、智能体、引擎配置")
Rel(open, deviceCore, "解析设备上下文和场景绑定")
Rel(open, dify, "调用 Dify 应用", "HTTPS/SSE")
Rel(dify, mcp, "调用 MCP 工具", "HTTP/MCP")
Rel(mcp, his, "适配院内系统接口", "HTTP/DB/Vendor API")
Rel(system, systemApi, "实现管理域服务")
Rel(mcp, mcpApi, "实现 MCP 域服务")
Rel(system, mysql, "读写合同、配置、账单")
Rel(open, mysql, "读写会话、日志、卡片实例")
Rel(mcp, redis, "幂等、短锁、熔断状态")
| 实现单元 | 建议位置 | 输入 | 输出 | 关键注意事项 |
|---|---|---|---|---|
| 对外智能体 Controller | emoon-openplatform |
签名请求、agentId、用户消息 |
统一响应 / SSE | 只做参数、鉴权、响应封装,不写复杂业务 |
| 项目鉴权服务 | emoon-openplatform 或 system API |
publicKey、签名、payload |
projectId、tenantId、授权范围 |
签名、时间戳、项目智能体授权必须统一封装 |
| 统一入口客户端 | 独立前端 / Android / Harmony / Electron | deviceId、场景配置、UI 模板 |
多终端页面、语音/触控/扫码/打印能力 | 先保证 P0 设备可运行,硬件能力通过 Bridge 标准化 |
| 设备注册服务 | system/mcp API 或新 Device Core | 设备注册、心跳、位置、能力 | DeviceProfile、在线状态、版本、智能体绑定 |
设备必须绑定医院/科室/位置,不能匿名接入核心闭环 |
| 设备适配服务 | Device Core + 厂商 Adapter | SDK/API/驱动事件 | 标准设备能力协议 | 第三方设备只能通过适配层进入中台 |
| 场景编排服务 | Device Core / OpenPlatform | 设备、位置、时间、用户、业务状态 | sceneProfile、UI 模板、Agent 绑定、工具权限 |
解决“同一设备不同场景加载什么” |
| 动线上下文服务 | emoon-openplatform 内部服务,P1 可下沉到 Agent Core |
TaskState、HIS/叫号状态、设备事件、卡片动作 |
journeyState、下一步服务、推荐卡片 |
MVP 不独立建微服务,不做全院路径优化 |
| 感知事件接入 | Device Core / OpenPlatform | 扫码、NFC、刷卡、近场、业务状态回调 | 标准 perceptionEvent、审计记录 |
只存业务必要事件,不保存连续轨迹 |
| Agent 编排服务 | emoon-openplatform |
对话请求、项目上下文 | AgentResponse |
查智能体、查引擎配置、路由引擎、写会话 |
| Dify 引擎适配器 | emoon-openplatform 或 emoon-mcp-api 实现类 |
AgentRequest |
AgentResponse |
只负责协议转换,不负责计费、不直接调 HIS |
| 卡片运行时服务 | emoon-mcp-api + 实现模块 |
cardKey、卡片数据、动作请求 |
卡片实例、动作结果 | 创建快照、校验状态、动作幂等 |
| MCP 工具服务 | emoon-mcp |
Dify 工具请求 / 卡片动作请求 | 标准工具结果 | 院内系统访问统一从这里走 |
| HIS Adapter | emoon-mcp |
标准工具参数 | HIS 响应标准对象 | 每家医院可配置不同 Adapter |
| IoMT 事件接入 | Device Core / emoon-mcp |
设备事件、病房事件、护理事件 | 标准事件、护理工单、Outbox 事件 | 只把业务闭环事件计入客户侧,心跳进入内部监控 |
| 调用日志服务 | system/mcp API | 调用上下文和结果 | ai_usage_log |
用于排障,不作为财务账本 |
| 计量入口 | 三期新增 system/mcp 能力 | 标准调用事件 | ai_meter_event |
二期可预留接口,三期完整实现 |
二期不要从“做全链路”开始。建议按以下顺序逐步打通:
/api/v1/agent/chat 能根据 agentId 查配置、路由 Mock 引擎、写会话、返回卡片。cardKey/cardData 并创建卡片实例。每完成一步都应保留可回放样例:请求参数、响应结果、数据库关键记录、日志 traceId。
X-Emoon-* 请求头调用 /api/v1/agent/chat。publicKey 查询项目,校验签名、时间戳和智能体授权。ai_agent_app 和 ai_agent_engine_config。AgentEngineFactory 按 engineType 路由到 Dify / Direct / Mock。卡片不是简单 UI 组件,而是确定性医疗业务操作的承载单元。
| 阶段 | 说明 |
|---|---|
| 卡片生成 | Dify 返回 cardKey、cardData 和业务上下文 |
| 实例创建 | OpenPlatform 根据 cardKey 查卡片定义并创建 ai_card_instance |
| 前端渲染 | 前端根据卡片定义渲染科室、医生、时间、确认、建档等卡片 |
| 用户操作 | 用户点击、选择、确认后调用卡片动作接口 |
| 动作执行 | OpenPlatform 校验实例状态、幂等键、权限、有效期 |
| 工具调用 | 需要操作 HIS 时,通过 MCP Server 调用,不建议前端或卡片绕过 MCP |
| 状态回写 | 更新卡片实例、会话上下文、动作日志,并把结果作为下一轮对话输入 |
MCP Server 是医院系统的唯一工具出口,所有对 HIS / EMR / LIS / PACS 的确定性调用都应经过它。
这里的 MCP 是医梦内部“AI 工具网关”设计,不把它包装成医院行业已经成熟的通用标准。公开行业方案更常见的是信息平台、集成平台、物联网平台对异构系统做统一接入;医梦采用 MCP 思路,是为了让 Dify 工具调用、卡片动作和 HIS Adapter 都进入同一个可授权、可审计、可幂等的工具出口。MVP 阶段可先用 HTTP/JSON Tool Service 实现,不要求一次性实现完整 Model Context Protocol 生态。
| 工具域 | 示例工具 | 生产要求 |
|---|---|---|
| 基础数据 | 科室、医生、院区、病区、床位 | 本地缓存、版本同步、数据来源标识 |
| 排班号源 | 医生排班、号源详情、锁号、释放号源 | 幂等、短锁、超时释放、并发控制 |
| 患者档案 | 查询患者、建档、更新档案 | 患者授权、敏感字段脱敏、审计 |
| 挂号预约 | 创建预约、取消预约、状态同步 | 订单幂等、支付状态一致性 |
| 住院管理 | 入院评估、床位预约、护理任务、出院小结 | 人工确认、高风险拦截 |
| 随访管理 | 随访计划、随访记录、风险分层 | 触达记录、升级人工 |
| 知识检索 | 指南检索、制度检索、院内 FAQ | 引用来源、版本号、召回质量记录 |
sequenceDiagram
autonumber
participant C as 客户端
participant API as OpenPlatform API
participant Auth as 项目鉴权
participant Agent as Agent 编排服务
participant Engine as AgentEngineFactory
participant Dify as Dify Workflow
participant Card as Card Runtime
participant DB as MySQL
C->>API: POST /api/v1/agent/chat
API->>Auth: 校验 publicKey、签名、时间戳、agent 权限
Auth-->>API: projectId、tenantId、授权范围
API->>Agent: chat(request, projectContext)
Agent->>DB: 查询 ai_agent_app、ai_agent_engine_config
Agent->>Engine: getEngine(engineType)
Engine-->>Agent: DifyEngine / MockEngine
Agent->>Dify: 发送消息、inputs、conversationId
Dify-->>Agent: reply、usage、cardKey、cardData
Agent->>DB: 创建/更新 ai_conversation、ai_usage_log
alt 返回卡片
Agent->>Card: 创建卡片实例和快照
Card->>DB: 写 ai_card_instance
end
Agent-->>API: AgentChatResponse
API-->>C: 文本 + 卡片数据 + conversationId
sequenceDiagram
autonumber
participant C as 前端卡片
participant API as Card Action API
participant Card as Card Runtime
participant MCP as MCP Tool Server
participant HIS as HIS / EMR
participant DB as MySQL
participant Dify as Dify Workflow
C->>API: POST /api/v1/card/{instanceId}/actions/{action}
API->>Card: 校验实例、状态、过期时间、幂等键
Card->>DB: 写 ai_card_action_log(pending)
alt 只更新卡片状态
Card->>DB: 更新 ai_card_instance.state_json
else 需要业务写操作
Card->>MCP: 调用标准工具,如 his_lock_schedule
MCP->>HIS: 调用医院接口
HIS-->>MCP: 返回业务结果
MCP-->>Card: 标准工具结果
Card->>DB: 更新实例状态、动作结果
end
Card->>Dify: 可选:把动作结果作为下一轮上下文
API-->>C: actionResult、nextCard 或 nextMessage
stateDiagram-v2
[*] --> active: 创建实例
active --> submitted: 用户提交动作
submitted --> processing: 后端执行动作
processing --> completed: 执行成功
processing --> failed: 执行失败
failed --> active: 可重试
active --> expired: 超时未操作
active --> cancelled: 用户取消/流程终止
completed --> [*]
expired --> [*]
cancelled --> [*]
状态机实现要求:
| 状态 | 允许操作 | 说明 |
|---|---|---|
active |
submit、cancel、refresh | 卡片可交互 |
submitted |
none | 防止重复点击,等待后端处理 |
processing |
query | 正在调用 MCP/HIS |
completed |
query | 业务已完成,只能查看 |
failed |
retry、cancel | 失败可重试,但必须复用幂等上下文 |
expired |
none | 超时失效,前端应提示重新发起 |
cancelled |
none | 用户或系统终止 |
每个 MCP 工具都按同一套模式实现,避免不同工具风格混乱。
| 步骤 | 实现说明 |
|---|---|
| 定义工具契约 | 明确工具名、输入字段、输出字段、错误码、是否写操作 |
| 参数校验 | 校验必填、格式、项目权限、患者授权 |
| 幂等处理 | 写操作必须接收业务幂等键,如 projectId + instanceId + actionName |
| HIS 调用 | 通过医院 Adapter 调厂商接口,不在工具里写死某家医院 URL |
| 结果标准化 | 把厂商响应转换为统一结构,屏蔽厂商差异 |
| 审计记录 | 记录工具名、耗时、状态、错误、输入输出摘要 |
| 熔断降级 | HIS 超时或异常时返回可解释错误,必要时走人工 |
Dify 接入不是简单 HTTP 转发。OpenPlatform 必须把 Dify 的不稳定输出转换成平台稳定响应,并在转换失败时给出可观测错误。
ai_agent_engine_config.config_json 建议按以下逻辑字段管理,敏感字段加密存储,展示时脱敏:
| 字段 | 说明 |
|---|---|
baseUrl |
Dify 服务地址 |
appId |
Dify App 标识 |
apiKeyRef |
密钥引用,不直接明文保存 |
responseMode |
blocking 或 streaming |
conversationMode |
是否复用 Dify conversation |
inputMapping |
平台上下文字段到 Dify inputs 的映射 |
outputSchemaVersion |
约定的输出结构版本 |
timeout |
连接、读取、SSE 空闲超时 |
fallbackPolicy |
失败时返回预设答复、DirectLLM 或人工入口 |
同步和流式最终都要归一成平台响应。Dify Workflow 的最终输出建议固定包含以下逻辑字段:
| 字段 | 来源 | 说明 |
|---|---|---|
answer |
Dify 文本节点 | 给用户展示的自然语言答复 |
cards |
Dify 结构化输出节点 | 可选,数组;每张卡包含 cardKey、cardData、businessContext |
riskLevel |
Dify 分支或平台后处理 | 医疗安全等级 |
scenarioCode |
智能体配置或 Dify 输出 | 三期计量和报表使用 |
workflowRunId |
Dify 返回 | 排障、审计、版本追踪 |
usage |
Dify 返回 | 原始 token/模型消耗,仅作成本和排障参考 |
卡片输出必须满足:
| 要求 | 说明 |
|---|---|
cardKey 必须存在 |
用于匹配平台卡片定义 |
cardData 必须通过 schema 校验 |
不通过时不能创建卡片实例 |
businessContext 只保存必要上下文 |
不把完整病历、身份证号等敏感信息塞进卡片 |
actionHints 只能作为建议 |
后端实际动作仍以卡片定义和项目授权为准 |
卡片数据的敏感字段边界:
| 字段类型 | 是否允许由 Dify 输出到 cardData |
说明 |
|---|---|---|
| 卡片结构字段 | 允许 | 如字段类型、选项布局、按钮动作名 |
| 业务标识 | 允许 | 如 deptId、doctorId、slotId、appointmentTime |
| 患者 PII 预填 | 禁止 | 如姓名、身份证号、手机号、住址 |
| 医疗原文 | 禁止 | 如完整病历、检查报告原文、诊断原文 |
| 图像原始引用 | 禁止 | 舌诊/面诊原图 fileId 不进入 Dify 卡片输出 |
患者 PII 只能通过“前端卡片动作 -> AgentActionOrchestrator -> CardActionService -> MCP Tool Service”的加密后端链路提交,不能进入 Dify 的输入、输出或 Workflow 变量。
DifyOutputNormalizer 作为 DifyAgentEngine 的内部输出后处理步骤实现,不新增独立 Maven 模块,也不放在 emoon-openplatform。建议落在 emoon-ai-agent 的 adapter/application 边界内,职责包括:
| 职责 | 处理规则 |
|---|---|
| JSON 合法性校验 | 不合法时降级为普通文本并记录 Dify 输出告警 |
cardKey 校验 |
不存在或未注册时拒绝创建卡片 |
cardData schema 校验 |
不通过时拒绝创建卡片,并返回可观测错误 |
| 风险等级归一 | 将 Dify 输出映射为平台医疗安全等级 |
| 敏感字段拦截 | 阻止 PII、完整病历原文、舌象原图引用进入卡片输出 |
| SSE 事件归一 | 将 Dify 流式事件转换为平台 message_delta、card_created、usage_reported 等稳定事件 |
Normalizer 不执行卡片动作、不调用 HIS、不扣能力值。它只负责把 Dify 的不稳定输出转换成平台可审计、可校验、可降级的稳定事件,避免开发人员把校验逻辑散落到 openplatform、Card Runtime 或前端。
SSE 模式下,Dify 可能先输出文本,再在最终节点输出卡片。平台 SSE 协议应区分事件类型:
| 事件 | 说明 |
|---|---|
message_delta |
文本增量 |
message_completed |
文本输出结束,包含 Dify message/workflow 标识 |
card_created |
平台已创建卡片实例,前端可渲染 |
usage_reported |
原始 usage 已记录 |
error |
可恢复或不可恢复错误 |
实现规则:
card_created。conversationId 查询最终消息和卡片状态。卡片动作执行后,Dify 需要知道用户选择了什么。这里不采用“卡片动作直接回调 Dify 内部状态”的假设,因为 Dify Chat API 主要是消息驱动。
默认方案:
ai_card_action_log 和会话上下文。inputs。inputs.cardActionResult 继续流程。需要立即续跑时:
synthetic=true,并携带 cardActionResult、cardInstanceId、actionId。synthetic message 必须有边界:
| 控制项 | 规则 |
|---|---|
| 最大深度 | 单次用户动作触发的 synthetic 链路默认最多 3 轮,超过后必须返回卡片或提示,等待用户下一次主动操作 |
| 并发控制 | 同一个 conversationId 同一时间只能有一个 synthetic 链路运行,防止消息乱序 |
| 计量控制 | 每轮 synthetic message 都是一次平台调用,必须产生独立调用日志、计量事件和额度校验 |
| 风险控制 | L3+ 写操作不能被 synthetic 链路自动连续执行,必须有用户或医护确认动作 |
| 上下文裁剪 | Dify inputs 只携带最近 3 轮卡片动作结果和当前业务摘要,历史动作通过 conversationId 查询 |
synthetic message 的场景和计费归属:
scenarioCode、billingEpisodeId 和合同上下文。scenarioCode,但平台必须校验该场景在合同范围和智能体授权范围内。billingEpisodeId,由计量中心按业务 episode 统一定价。parent_event_id 关联原 episode。初级工程师重点:为什么不让前端直接把动作结果发给 Dify?
前端不可信,且无法保证动作结果已经通过 HIS/MCP 落库。必须以后端动作日志为准,再把“已确认事实”传给 Dify,否则会出现前端伪造挂号成功、Dify 继续错误流程的问题。
| 失败点 | 处理 |
|---|---|
| Dify 请求超时 | 记录失败 usage log,释放预冻结额度,按 fallback 策略返回 |
| Workflow 运行失败 | 记录 workflowRunId 和错误摘要,返回平台统一错误码 |
| Dify 输出结构错误 | 不创建卡片,保留原始输出摘要,触发 Workflow 输出告警 |
| Dify 已输出文本但后续失败 | SSE 标记 partial,按 partial 计量策略处理 |
| Dify 调 MCP 失败 | 由 MCP 返回标准错误,Dify 可继续降级解释,但写操作不得自动重试 |
AgentEngine 需要同时支持 Dify、DirectLLM、Mock,但三者定位不同。
| 引擎 | 用途 | 生产要求 |
|---|---|---|
DifyAgentEngine |
主流程编排,承载问诊、导诊、住院等多步骤流程 | 优先实现,支持同步、SSE、usage、卡片输出 |
DirectLLMAgentEngine |
L1 标准能力主引擎、简单问答、提示词模板、Dify 降级、旧 /chat/apisse 能力迁移 |
必须走同一鉴权、会话、计量、日志链路 |
MockAgentEngine |
本地开发、前端联调、自动化测试 | 不允许生产项目误用,生产环境默认禁用 |
L1 客户可以使用 DirectLLM 作为主引擎,不强依赖 Dify。L2/L3 的复杂场景优先由 Dify Workflow 编排,DirectLLM 作为简单能力、降级能力或专用模型调用能力存在。无论哪种模式,DirectLLM 都不能绕过平台治理;即使只是直连模型,也要写入 ai_conversation、ai_usage_log,并按三期计量规则生成事件。
以“智能分诊后挂号”为例,工程实现可以拆成以下业务步骤:
| 步骤 | 主责模块 | 说明 |
|---|---|---|
| 用户描述症状 | OpenPlatform | 接收消息,写入会话上下文 |
| 症状追问与分诊 | Dify Workflow | LLM 节点和知识检索生成候选科室 |
| 获取科室和医生 | MCP Server | 调 HIS 查询科室、医生、号源 |
| 展示科室/医生卡片 | Card Runtime + 前端 | 创建卡片实例,前端渲染 |
| 用户选择医生时间 | AgentActionOrchestrator + Card Runtime | Agent 编排承接动作,Card Runtime 校验状态并写动作日志 |
| 锁定号源 | MCP Server | 写操作,必须幂等和短锁 |
| 确认挂号 | AgentActionOrchestrator + Card Runtime + MCP | 用户确认后由 Agent 编排推进预约或订单创建 |
| 返回结果 | OpenPlatform | 更新会话和卡片状态,返回成功卡片 |
| 产生计量事件 | 三期计量中心 | 按“智能分诊 / 挂号服务”计量 |
卡片动作调用 MCP 的路径统一为:
flowchart LR
Front["前端卡片"]
API["OpenPlatform Card Action API"]
Agent["AgentActionOrchestrator"]
Card["CardActionService"]
Tool["MCP Tool Service"]
Adapter["HospitalAdapter"]
HIS["HIS / EMR / LIS / PACS"]
Front --> API
API --> Agent
Agent --> Card
Agent --> Tool
Tool --> Adapter
Adapter --> HIS
实现时,AgentActionOrchestrator -> MCP Tool Service 在同进程部署时可以是模块内 Service 调用;MCP 独立部署后改为内部 HTTP/RPC。无论哪种部署,前端和 Dify 都不能绕过 OpenPlatform、Agent 编排和 Card Runtime 直接执行卡片动作。
统一入口客户端是医院最新方案中的战略控制点。它不是普通网页,而是优先部署在门诊导诊屏、自助机、机器人、叫号屏、诊室屏、医生站插件等终端上的多设备 AI 场景运行时。
住院侧要单独说明:护理白板、床头屏属于迪耐克/鸿蒙病房生态的终端,医梦只通过 Web/H5 嵌入、SDK/API 或标准事件协议提供 AI 能力,不承担住院屏幕硬件、基础呼叫、病房网关和 IoMT 原始采集的主责。
sequenceDiagram
participant T as Terminal Runtime
participant D as Device Registry
participant S as Scene Orchestrator
participant O as OpenPlatform
participant A as Agent Center
T->>D: 设备启动,提交 deviceId、版本、能力、位置
D->>D: 校验设备密钥、医院/科室绑定、准入等级
D->>S: 请求当前设备的场景配置
S->>A: 查询可用智能体、工具权限、UI 模板
A-->>S: 返回 agentBindings、cardTemplates、toolScopes
S-->>T: 返回 sceneProfile、首页模板、默认智能体
T->>O: 携带 deviceContext 发起对话或卡片动作
设备上下文必须进入每一次调用:
| 字段 | 用途 |
|---|---|
deviceId |
设备唯一身份,关联授权、心跳、故障定位 |
deviceType |
区分导诊屏、自助机、机器人、叫号屏、诊室屏等入口 |
hospitalId / departmentId |
设备所属医院和科室,用于权限和统计 |
location |
楼栋、楼层、区域、诊室、床位,用于服务找人和场景编排 |
capabilities |
触控、语音、扫码、读卡、打印、摄像头、导航等能力 |
sceneProfile |
当前加载的业务场景,例如 outpatient_registration |
agentBindings |
当前设备允许调用的智能体集合 |
clientVersion |
统一入口客户端版本,用于灰度和排障 |
初级工程师重点:为什么不能让每个设备直接写自己的页面? 医院现场设备多、厂商多、版本多。如果没有统一入口客户端和 Device Registry,后续每个屏幕都会变成项目定制,Agent 绑定、权限、日志、计量和升级都无法统一治理。
设备适配层要把第三方 SDK、机器人驱动、自助机读卡打印、四诊仪采集、迪耐克病房接口等差异收敛成医梦标准能力。
| 能力 | 标准动作 | 典型设备 |
|---|---|---|
| 屏幕显示 | renderCard、showPage、showAlert |
大屏、叫号屏、诊室屏;床头屏仅通过迪耐克生态嵌入 |
| 语音采集 | startRecord、stopRecord、sendAudio |
机器人、诊室麦克风;床头屏语音由病房生态能力决定 |
| 语音播放 | playTTS、stopTTS |
机器人、自助机、导诊屏 |
| 摄像头 | captureImage、scanFace、scanQRCode |
自助机、机器人、四诊仪 |
| 打印 | printReceipt、printWristband、printReport |
自助机、护士站 |
| 读卡 | readIdCard、readMedicalCard |
自助机、诊区终端 |
| 导航 | startNavigation、stopNavigation、getLocation |
机器人、室内导航 |
| IoMT | receiveWardEvent、ackAlert、closeTask |
迪耐克/鸿蒙病房网关或医院物联平台输出的标准事件 |
设备准入按 A/B/C/D 分级治理:
| 等级 | 标准 | 能否进入核心闭环 |
|---|---|---|
| A 级 | 支持医梦统一客户端,开放 API/SDK,支持远程运维和日志 | 可以进入核心闭环 |
| B 级 | 支持 Web/H5 嵌入或标准接口,能完成基础业务 | 可进入部分闭环 |
| C 级 | 只能播放内容或展示页面,不开放接口 | 不进入核心闭环,只做展示 |
| D 级 | 无接口、无系统、无法远程管理、稳定性差 | 不建议采购或接入 |
中医四诊仪适配采用更保守的 MVP 路径。行业公开产品通常把舌诊、面诊、脉诊、问诊作为多模态采集和辅助分析能力,涉及专用相机、脉象传感器、厂商算法或云端 API,不能按普通屏幕设备处理。
| 阶段 | 范围 | 技术路径 | 不做 |
|---|---|---|---|
| MVP | 舌诊 / 面诊图片采集与结果卡片 | 复用厂商 SDK 或文件上传接口,OpenPlatform 保存 fileId,调用专精模型或厂商 API,返回舌诊/面诊结果卡片 |
不自研采集硬件,不训练新模型 |
| P1 | 问诊结构化 + 舌面结果合并 | Dify 问诊流程 + 四诊结果卡片,医生确认后进入 EMR 摘要 | 不自动生成诊断和处方 |
| P2 | 脉诊 / 多设备联动 | 仅在厂商提供稳定 SDK、数据格式和验收样例后接入 | 不承诺首期接入所有四诊能力 |
四诊仪链路:
flowchart LR
Device["四诊仪<br/>舌象/面象/脉象/问诊采集"]
Adapter["FourDiagnosisAdapter<br/>厂商 SDK / 文件上传 / API"]
File["File Service<br/>fileId / 加密 / 审计"]
Model["专精模型或厂商分析 API"]
Card["四诊结果卡片<br/>辅助解释 / 风险提示"]
Doctor["医生确认"]
EMR["EMR 摘要写回"]
Device --> Adapter --> File --> Model --> Card --> Doctor --> EMR
验收以“采集成功、图片质量可判定、结果卡片可解释、医生确认可追溯”为准。第一期不得承诺四诊结论自动诊断、自动处方或跨厂商通用算法。
鸿蒙协同不应写成全院设备自动互联,而应落到“服务找人”的小闭环。第一期推荐主动签到 POC。空海会议后,本节的正式口径应从“某个近场设备触发签到”升级为“感知到患者动线阶段后,把下一步服务外显到当前设备”,但 P0 仍只做诊区/诊室门口的低门槛场景。
sequenceDiagram
participant P as 患者手机 / 小程序
participant N as 近场设备 / 诊室门口屏
participant D as Device Event Hub
participant O as OpenPlatform
participant Q as 叫号系统
participant H as HIS / 签到系统
P->>N: 到达诊室门口区域
N->>D: 上报患者靠近事件
D->>O: 归一为 service_find_patient 事件
O->>Q: 查询当前队列与患者状态
O->>H: 查询是否允许签到
O-->>P: 推送签到服务卡片
P->>O: 用户确认签到
O->>H: 调用签到接口
O->>Q: 同步叫号状态
O-->>P: 返回候诊提醒
兜底路径必须同时存在:鸿蒙生态设备发现、星闪/近场通信、BLE Beacon、Wi-Fi/院内定位、二维码/NFC、小程序位置授权。签到、支付、挂号等动作都必须由患者确认,不能因为“服务找人”而自动完成高风险操作。
感知能力分级:
| 级别 | 能力 | 适用阶段 | 医梦职责 |
|---|---|---|---|
| L0 | 二维码、人工确认、终端点选 | 所有医院可用,P0 必备 | 提供卡片、接口和审计 |
| L1 | NFC 碰一碰、刷卡、手机/手表确认 | P0 推荐 | 提供绑定和解绑流程,不保存长期轨迹 |
| L2 | BLE Beacon / Wi-Fi 区域判断 | P1 试点 | 只判断是否进入服务区域,事件需患者确认后生效 |
| L3 | 星闪 / 鸿蒙近场 / UWB 高精度 | 标杆 POC | 只在医院和设备方已有能力时接入,不作为首期交付前置条件 |
服务找人触发表:
| 动线状态 | 感知事实 | 推荐服务卡片 | 必须确认 |
|---|---|---|---|
| 已挂号未签到 | 患者到达诊区或诊室门口 | 主动签到卡、候诊队列提醒 | 是 |
| 已就诊待缴费 | HIS/Mock 产生缴费或处置状态,患者靠近自助机/屏幕 | 缴费引导卡、窗口/自助机导航 | 是 |
| 已缴费待检查 | 检查/检验状态存在,患者靠近机器人/导诊屏 | 检查导航卡、注意事项卡 | 否,导航可直接展示 |
| 报告已出 | 报告状态更新,患者再次到院或打开终端 | 报告解读入口卡 | 是,涉及个人报告 |
| 特殊人群 | 老人、孕产妇、轮椅、急诊等标签或人工标记 | 人工协助、优先引导、无障碍路线 | 是或人工确认 |
近场设备硬件策略:
| 方案 | 定位 | 适用条件 | 医梦责任 |
|---|---|---|---|
| 推荐 MVP:诊室门口小屏 + BLE Beacon / NFC / 二维码 | 最小可落地方案 | 医院暂不具备成熟鸿蒙近场生态时 | 医梦提供设备准入、客户端、场景配置和联调;硬件采购按项目合同确认 |
| 标杆 POC:鸿蒙生态近场设备 / 星闪能力 | 展示“服务找人”亮点 | 医院和设备方具备鸿蒙生态设备与接口 | 医梦负责事件接入、卡片推送、签到闭环;不承诺全院覆盖 |
| 兜底方案:小程序定位授权 + 二维码签到 | 低成本兜底 | 近场设备部署受阻或权限不足时 | 医梦负责软件流程,体验弱于主动触达 |
第一期不建议采购复杂定位基站或做全院级精准定位。主动签到只要求判断“患者是否到达诊室门口服务区域”,不需要保存患者全院移动轨迹。
隐私合规规则:
patientId_hash / visitId / deviceId / eventTime / actionResult,不保存可复原的移动路线。本节用端到端流程检查方案能否闭环。所有流程都遵守同一原则:OpenPlatform 掌握入口、身份、会话、卡片和计量事实;Dify 负责流程编排;MCP 负责院内系统工具;计量中心按业务事实和合同规则结算。
flowchart TD
U["用户描述症状"]
API["OpenPlatform<br/>鉴权 / 幂等 / 额度检查"]
Dify["Dify Workflow<br/>意图识别 / 分诊 / RAG"]
DeptTool["MCP: 查询科室/医生/号源"]
DeptCard["科室/医生/时间卡片"]
Action["AgentActionOrchestrator + CardActionService<br/>用户选择"]
Confirm["确认挂号卡片<br/>L3 二次确认"]
WriteTool["MCP: 锁号 + 创建预约"]
HIS["HIS"]
Meter["计量中心<br/>billingEpisode 统一计费"]
U --> API --> Dify --> DeptTool --> HIS
HIS --> DeptTool --> Dify --> DeptCard --> Action
Action --> Dify
Dify --> Confirm --> WriteTool --> HIS
API -.原始调用.-> Meter
Action -.卡片动作.-> Meter
WriteTool -.内部工具成本.-> Meter
计费规则:一次用户主动分诊请求和其 synthetic 链路归入同一 billingEpisodeId,按“智能分诊/导诊一次”计费;挂号确认是新的业务事实,按“挂号服务”计费。MCP_TOOL_WRITE 只进入内部成本,除非合同明确把某类写操作单独对客户计费。
flowchart TD
U["用户发起建档"]
API["OpenPlatform<br/>鉴权 / 患者授权"]
Dify["Dify Workflow<br/>返回建档卡片结构"]
Form["前端建档卡片<br/>用户填写 PII"]
CardAPI["AgentActionOrchestrator + CardActionService<br/>字段校验 / 加密 / 审计"]
MCP["MCP: his_create_patient"]
HIS["HIS 患者主索引"]
Meter["计量中心<br/>建档业务事件"]
Audit["敏感操作审计"]
U --> API --> Dify --> Form
Form --> CardAPI --> MCP --> HIS
CardAPI --> Audit
MCP --> Audit
CardAPI -.CARD_ACTION_CONFIRMED.-> Meter
MCP -.MCP_TOOL_WRITE 内部成本.-> Meter
安全规则:Dify 只输出建档卡片结构,不预填姓名、身份证、手机号等 PII。PII 从前端提交后,经 Agent 编排、CardActionService 状态校验和后端加密链路进入 MCP/HIS;日志、Outbox、计量事件只保存摘要、字段完整度、HIS patientId 和 traceId。
flowchart TD
Upload["上传舌象图片"]
FileAPI["FileAPI<br/>鉴权 / 类型 / 大小 / 安全扫描"]
OSS["对象存储<br/>加密保存"]
Chat["OpenPlatform Chat<br/>携带 fileId"]
Engine["AgentEngine<br/>Dify 或 DirectLLM"]
Model["视觉模型 / 舌诊模型"]
Result["舌诊结果卡片"]
Meter["计量中心<br/>IMAGE_ANALYSIS"]
Audit["文件与分析审计"]
Upload --> FileAPI --> OSS
Chat --> Engine --> Model --> Result
FileAPI --> Audit
Engine --> Audit
Chat -.文件类型识别.-> Meter
Result -.分析完成.-> Meter
计量规则:IMAGE_ANALYSIS 由 OpenPlatform 统一产生。OpenPlatform 在构造 AgentRequest 时识别 files 中的图片数量和类型,在模型调用完成后按文件类型、图片数量和场景生成计量事件。Dify/DirectLLM 只提供 usage 和模型成本信息,不决定客户侧计量项。
flowchart TD
Upload["上传面部图片"]
FileAPI["FileAPI<br/>人脸敏感数据标记"]
OSS["对象存储<br/>加密 + 访问审计"]
Chat["OpenPlatform Chat"]
Model["视觉模型 / 面诊模型"]
Post["平台后处理<br/>敏感特征裁剪"]
Card["面诊结果卡片"]
Meter["计量中心<br/>IMAGE_ANALYSIS"]
Audit["敏感数据审计"]
Upload --> FileAPI --> OSS
Chat --> Model --> Post --> Card
FileAPI --> Audit
Post --> Audit
Chat -.图片计量上下文.-> Meter
Card -.完成事件.-> Meter
合规规则:面部图片和特征属于个人敏感数据。卡片快照只保存医学解释结论、风险提示、建议动作和必要 traceId,不保存原图引用、面部特征向量或可复原的结构化人脸特征。
flowchart TD
Patient["患者端<br/>文本 / 语音 / 点选"]
API["OpenPlatform<br/>身份 / 授权 / episode"]
Dify["Dify Workflow<br/>多轮追问 / 问题树"]
Knowledge["平台 RAG/MCP Tool<br/>问诊模板 / 诊疗规则"]
Draft["结构化预问诊报告<br/>主诉 / 现病史 / 既往史"]
Doctor["医生站<br/>医生确认 / 修改"]
EMR["EMR<br/>写入病历草案"]
Meter["计量中心<br/>previsit_episode"]
Audit["审计<br/>AI 输出 + 医生修改"]
Patient --> API --> Dify --> Knowledge
Knowledge --> Dify --> Draft --> Doctor --> EMR
Draft -.预问诊完成.-> Meter
Doctor --> Audit
EMR --> Audit
规则:预问诊输出只能作为病历草案,不能直接形成正式病历。写入 EMR 前必须有医生确认或医院明确授权的流程节点。计费按“完整预问诊单”或“预问诊 episode”计算,多轮追问和 synthetic 调用归并到同一 episode。
flowchart TD
Audio["诊间音频"]
ASR["ASR<br/>说话人分离 / 实时转写"]
NLP["结构化抽取<br/>症状 / 体征 / 诊断 / 药品"]
Draft["SOAP / 病历草案"]
QC["质控服务<br/>完整性 / 逻辑 / 时限"]
CDSS["CDSS<br/>鉴别诊断 / 用药风险"]
Doctor["医生确认"]
EMR["EMR 正式保存"]
Meter["计量中心<br/>ASR_MINUTE / EMR_DRAFT / QC"]
Audit["审计<br/>AI 建议 + 医生采纳"]
Audio --> ASR --> NLP --> Draft --> Doctor --> EMR
Draft --> QC --> Doctor
Draft --> CDSS --> Doctor
ASR -.分钟成本.-> Meter
Draft -.病历生成.-> Meter
QC -.质控事件.-> Meter
Doctor --> Audit
规则:诊间病历、CDSS、用药安全都属于医生主导场景。AI 可生成草案、提示风险、推荐方案,但正式诊断、处方、医嘱必须由医生确认和签名。计量上,ASR 分钟、病历生成、质控/CDSS 可以形成同一个诊中 episode 下的多个业务事件,账单按合同约定展示为单项或组合服务。
flowchart TD
Patient["患者 / 医护发起入院评估"]
API["OpenPlatform<br/>住院 episode"]
Dify["Dify Workflow<br/>预评估 / 护理等级建议"]
BedTool["MCP: 床位 / 手术 / 检查资源"]
Ward["病区护士站 / 床位中心"]
Confirm["医护确认"]
HIS["HIS / 住院系统"]
IoMT["IoMT<br/>体征 / 跌倒 / 输液"]
Alert["护理风险预警 / 任务派发"]
Meter["计量中心<br/>inpatient_assessment / IoMT事件"]
Patient --> API --> Dify --> BedTool --> HIS
BedTool --> Ward --> Confirm --> HIS
IoMT --> Alert --> Ward
Dify -.评估完成.-> Meter
IoMT -.监测/预警事件.-> Meter
规则:床位、护理等级、出入院安排都属于高影响业务,AI 只能给建议或草案,医护确认后才能写入住院系统。IoMT 预警默认按事件或服务包计量,不能把每一次设备心跳都作为客户侧扣费事件。
flowchart TD
Discharge["医生触发出院意向"]
Data["病历 / 检查 / 医嘱 / 手术记录"]
Agent["出院小结 Agent"]
Summary["出院小结草案 / 康复计划"]
Doctor["医生审核确认"]
FollowPlan["随访计划"]
FollowAgent["AI 随访<br/>电话 / 微信 / 问卷"]
Risk["风险分层<br/>稳定 / 需关注 / 高危"]
Workbench["护士 / 医生工作台"]
Meter["计量中心<br/>文书 / 随访分钟 / 随访次"]
Discharge --> Data --> Agent --> Summary --> Doctor
Doctor --> FollowPlan --> FollowAgent --> Risk
Risk --> Workbench
Summary -.文书生成.-> Meter
FollowAgent -.随访计量.-> Meter
规则:出院小结属于正式医疗文书,AI 只能生成草案。随访中识别为高危的患者必须升级人工,不允许 AI 独立完成医疗处置。计费可按出院小结份数、随访分钟、随访次数或合理不限量服务包归集。
不是所有 AI 医院场景都适合走 /api/v1/agent/chat。诊间语音、IoMT 护理预警、AI 外呼随访属于流式、事件驱动或任务调度型能力,需要进入同一个审计和计量体系,但入口形态不同。
flowchart LR
Mic["诊室麦克风 / 医生站"]
WS["OpenPlatform Audio Gateway<br/>WebSocket / 音频片段"]
ASR["ASR Service<br/>转写 / 说话人分离"]
NLP["结构化服务<br/>医学实体 / SOAP"]
Agent["AgentEngine<br/>Dify 或 DirectLLM"]
QC["质控 / CDSS"]
Doctor["医生确认"]
EMR["EMR"]
Meter["计量中心<br/>ASR_MINUTE / EMR_DRAFT / QC"]
Mic --> WS --> ASR --> NLP --> Agent --> QC --> Doctor --> EMR
WS -.音频时长.-> Meter
Agent -.文书事件.-> Meter
QC -.质控事件.-> Meter
实现规则:
traceId/sessionId/durationSeconds。billingEpisodeId。住院 IoMT 的责任边界必须前置说明:医梦不直接接管床垫、雷达、输液泵、生命体征设备等病房硬件的接入、认证和原始数据采集。住院侧优先由迪耐克/鸿蒙病房体系或医院既有物联平台完成设备接入和数据归一,医梦 IoMT Event Hub 只接收已标准化的业务事件、预警事件或护理任务事件,并在此基础上做 AI 解释、风险分级和闭环审计。
flowchart LR
Device["IoMT 设备<br/>床垫 / 雷达 / 输液泵 / 生命体征"]
WardGateway["迪耐克/鸿蒙病房网关<br/>设备认证 / 原始数据归一"]
Hub["医梦 IoMT Event Hub<br/>标准事件接收 / 患者床位映射 / traceId"]
Rule["规则与 AI 预警<br/>跌倒 / 离床 / 输液 / 体征"]
Task["护理建议 / 预警工单"]
Nurse["护士站 / PDA"]
Outbox["Outbox / Event Ingestion"]
Meter["计量中心<br/>IOMT_ALERT / NURSING_TASK"]
Audit["护理闭环审计"]
Device --> WardGateway --> Hub --> Rule --> Task --> Nurse
Task --> Outbox --> Meter
Task --> Audit
实现规则:
flowchart LR
Plan["随访计划"]
Job["SnailJob<br/>任务调度"]
Gateway["语音网关<br/>外呼 / 状态回调"]
ASR["ASR / 对话理解"]
Agent["随访 Agent<br/>Dify 或 DirectLLM"]
Risk["风险分层"]
Human["人工升级<br/>护士 / 医生"]
Meter["计量中心<br/>FOLLOWUP_CALL_MINUTE / FOLLOWUP_COMPLETED"]
Audit["随访审计"]
Plan --> Job --> Gateway --> ASR --> Agent --> Risk
Risk --> Human
Gateway -.通话分钟.-> Meter
Risk -.随访结果.-> Meter
Agent --> Audit
实现规则:
| 场景 | 主要入口 | 核心业务事实 | 客户侧计费单元 | 必须人工确认 | 关键验收指标 |
|---|---|---|---|---|---|
| 导诊问答 | 导诊大屏 / 患者端 / 机器人 | 完成一次导诊答复 | 次 / episode / 设备服务包 | 否 | 答复准确率、转人工率、设备在线率 |
| 智能分诊挂号 | 导诊屏 / 患者端 / 自助机 | 分诊完成、挂号确认 | 分诊次 + 挂号服务 | L3 挂号确认 | 分诊命中率、挂号成功率 |
| 患者建档 | 患者端卡片 | HIS 创建 patientId | 建档成功次 | 是 | 建档成功率、PII 脱敏合规 |
| 舌诊 / 面诊 | 文件上传 + 对话 | 图像分析完成 | 图片分析次 | 医疗建议需医生确认 | 图片质量通过率、分析完成率 |
| 预问诊 | 患者端 | 结构化问诊单完成 | 问诊单 / episode | 正式病历需医生确认 | 问诊完整度、医生采纳率 |
| 到院签到 / 叫号 | 诊室门口屏 / 自助机 / 小程序 | 签到成功、叫号状态同步 | 签到服务次 / 入口服务包 | 是 | 签到成功率、误触发率、叫号同步延迟 |
| 诊间病历 | 诊室桌面屏 / 医生站插件 | 病历草案生成并确认 | 份 / ASR分钟 | 是 | 病历书写节省时间、修改率 |
| CDSS / 用药审核 | 医生站 | 风险提示或建议生成 | 次 / 事件 | 是 | 预警采纳率、误报率 |
| 住院评估 | 患者端 / 护士站 | 入院评估报告 | 次 / episode | 是 | 评估完整度、床位匹配成功率 |
| 护理预警 | IoMT / 护理白板 / PDA | 高风险预警事件 | 事件 / 服务包 | 高危必须人工处理 | 预警及时率、闭环处理率 |
| 出院小结 | 医生站 | 文书草案生成并确认 | 份 | 是 | 文书生成时间、质控通过率 |
| 随访 | 电话 / 微信 / APP | 随访完成或风险升级 | 分钟 / 次 | 高危必须人工处理 | 随访完成率、高危触达率 |
| 设备运行 | 门诊统一入口客户端 / Device Registry | 设备在线、版本、异常、场景加载 | 设备授权 / 运维服务 | 否 | 在线率、故障恢复时间、远程升级成功率 |
验收时不能只看“接口调用成功”或“设备通电能打开”。每个场景至少要验证:业务事实是否落库、是否可追溯到 traceId、是否携带 deviceId、是否生成正确计量事件、是否按合同计费、是否有人工确认或升级路径、是否进入运营指标。
二期只保留必要的元数据模型,完整 SQL 不放在方案正文,应放在迁移脚本或实施文档中。
| 表 | 角色 | 关键字段 |
|---|---|---|
ai_agent_app |
智能体元数据 | agent_id、project_id、engine_config_id、agent_type、status |
ai_agent_engine_config |
引擎连接配置 | engine_type、config_json、project_id、status |
ai_conversation |
开放平台会话 | conversation_id、external_conversation_id、agent_id、user_id |
ai_task_instance |
多轮业务任务状态 | task_id、conversation_id、task_type、status、current_step、agent_code、context_json、device_id、trace_id |
ai_usage_log |
原始调用日志 | prompt_tokens、completion_tokens、workflow_run_id、latency_ms |
ai_card_definition |
卡片定义 | card_key、version、schema_json、ui_config_json、actions_json |
ai_card_instance |
卡片实例 | instance_id、conversation_id、message_id、state_json、status |
ai_card_action_log |
卡片动作日志 | instance_id、action_name、action_payload、status |
ai_device_registry |
设备注册中心 | 门诊设备:device_id、hospital_id、department_id、device_type、vendor、model、location_json、capabilities_json、status、client_version、last_heartbeat;住院嵌入端:仅记录 external_system、external_terminal_id、ward_id/bed_id、interop_status、last_event_time |
ai_device_scene_binding |
设备场景绑定 | device_id、scene_code、ui_template、agent_bindings_json、tool_scopes_json、effective_time |
ai_device_event |
设备事件日志 | device_id、event_type、event_payload、trace_id、occurred_at、status |
ai_iomt_event |
IoMT/病房事件 | event_id、device_id、patient_id_hash、bed_id、event_type、risk_level、business_status |
ai_usage_log 是事实日志,不是财务账本。三期要新增不可变计量账本,避免日志补写、失败重试、异步丢失导致账单不可信。ai_conversation.agent_id 使用 ai_agent_app.id,对外 API 使用 agent_id 字符串,Service 层完成映射。ai_card_instance 必须保存 UI 和动作快照,避免卡片定义升级影响历史会话。ai_agent_engine_config.config_json 可继续存 Dify / Direct / Mock 差异配置,但生产环境应加密敏感字段,不能明文暴露密钥。project_id 要成为权限、额度、账单的核心维度;tenant_id 不能长期使用默认值,应由项目绑定医院/租户。ai_device_registry 是门诊总包的基础表。门诊侧导诊屏、自助机、机器人、叫号屏、诊室屏、四诊仪必须有医梦管理的设备身份、位置、能力、状态和心跳监控。住院侧护理白板、床头屏由迪耐克/鸿蒙病房体系管理设备身份和硬件状态,医梦只记录必要映射标识、互通状态和最后事件时间,不承担住院设备心跳监控和硬件管理责任。ai_device_scene_binding 不能写死在前端。设备在哪个位置、加载哪个 UI 模板、绑定哪些智能体、允许哪些工具,要能由后台配置和灰度。ai_device_event 与 ai_iomt_event 默认是业务和运维事实,不等于财务账本。只有形成可解释业务事实,例如签到成功、护理预警闭环、设备授权周期,才进入计量中心。| 接口 | 用途 | 备注 |
|---|---|---|
POST /api/v1/agent/chat |
智能体对话,支持同步和 SSE | 二期主入口 |
POST /api/v1/device/register |
设备注册或重新激活 | 统一入口客户端启动时调用 |
POST /api/v1/device/heartbeat |
设备心跳、版本、状态上报 | 支持故障定位和在线率统计 |
GET /api/v1/device/{deviceId}/scene |
获取设备当前场景配置 | 返回 UI 模板、默认智能体、工具权限 |
POST /api/v1/device/{deviceId}/events |
上报设备事件 | 近场、扫码、打印、异常、IoMT 入口 |
POST /api/v1/conversation/create |
创建会话 | 可选,chat 无会话时也可自动创建 |
GET /api/v1/conversation/list |
查询会话列表 | 按项目、智能体、用户隔离 |
GET /api/v1/conversation/{conversationId} |
查询会话详情 | 需校验项目归属 |
POST /api/v1/card/{instanceId}/actions/{action} |
卡片动作执行 | 建议二期补齐 |
GET /api/v1/card/{instanceId} |
查询卡片实例状态 | 支持前端恢复、超时、刷新 |
| 能力 | 用途 |
|---|---|
| 智能体管理 | 配置智能体、绑定项目、选择引擎配置 |
| 引擎配置管理 | 管理 Dify / Direct / Mock 配置 |
| 卡片定义管理 | 管理内置卡片、版本、状态、灰度 |
| MCP 工具管理 | 管理 HIS 工具、厂商配置、超时、熔断 |
| 设备注册管理 | 管理设备身份、位置、能力、状态、版本、SLA |
| 场景绑定管理 | 管理设备、场景、智能体、UI 模板、工具权限 |
| 设备准入管理 | 管理 A/B/C/D 准入等级、厂商测试、联调验收 |
| 调用日志查询 | 排查对话、Dify、MCP、卡片动作链路 |
初级工程师实现接口时应遵守这些规则:
projectId。deviceId 字符串接入,必须校验证书/密钥、医院、科室和准入状态。config_json、state_json、capabilities_json、agent_bindings_json 可以存 JSON,但 Service 层要有明确解析对象和校验规则。所有会产生业务事实的接口都必须支持 X-Emoon-Idempotency-Key。幂等键由调用方生成,平台按项目隔离保存,避免不同医院或不同项目之间误判重复。
| 接口类型 | 幂等键建议 | 重复请求返回 |
|---|---|---|
| 对话请求 | projectId + resolvedAgentId/routeKey + clientMessageId |
返回第一次会话消息结果;统一入口客户端未传 agentId 时由后端路由结果补齐 |
| 设备事件 | projectId + deviceId + eventType + clientEventId |
返回第一次事件接收结果 |
| 卡片动作 | projectId + cardInstanceId + actionName + clientActionId |
返回第一次动作结果 |
| MCP 写工具 | projectId + toolName + businessKey |
返回第一次工具调用结果或最终查询结果 |
| 能力值冻结 | accountId + sourceEventId + freezePurpose |
返回第一次 freezeId |
| 能力值结算 | accountId + meterEventId |
返回第一次结算流水 |
幂等记录需要保存:
| 字段 | 说明 |
|---|---|
idempotency_key |
外部幂等键,项目内唯一 |
request_hash |
请求摘要,用于识别同键不同请求 |
status |
processing / succeeded / failed / expired |
response_snapshot |
首次成功响应摘要 |
trace_id |
首次处理 traceId |
expire_at |
幂等记录保留到期时间 |
合并规则:
API 幂等与计量幂等的关系:
trace_id/source_id 用于定位第一次请求生成的计量事件。traceId + sourceId 建立关联。初级工程师重点:幂等不是“加 Redis 锁”。
Redis 锁只能减少并发进入,不能证明业务是否已经成功。真正的幂等要有数据库记录和唯一约束,能在服务重启、Redis 丢失、网络超时后仍然判断“这件事是否做过”。
| 设计 | 评价 |
|---|---|
| Dify Workflow 承载流程编排 | 合理。适合频繁调整的问诊、导诊、咨询流程 |
| MCP Server 统一对接 HIS | 合理。可以降低多厂商 HIS 的适配复杂度 |
AgentEngine 抽象 |
合理。Dify、直连模型、Mock 可以共存 |
| 卡片承载确定性操作 | 合理。医疗流程不能完全依赖自然语言 |
| 卡片实例快照 | 必须保留。否则历史卡片会受模板升级影响 |
| 统一入口客户端 | 必须新增。医院最新方案要求所有门诊带屏设备和机器人都能进入医梦统一入口 |
| Device Registry / Adapter | 必须新增。设备数量、厂商和能力差异会成为门诊总包交付的主要风险 |
| Scene Orchestrator | 必须新增。同一设备在不同位置、时间、患者状态下加载不同智能体和 UI |
| 住院 AI 大脑层 | 合理。与迪耐克/鸿蒙病房体系互通,避免医梦背负住院硬件总包责任 |
| 风险 | 修正方案 |
|---|---|
| Dify 过度承担业务和账本 | Dify 做编排,OpenPlatform 做权限、审计、计量、账本 |
| 卡片动作绕过 MCP 直连 HIS | 统一经过 MCP Server,保证工具治理和审计 |
| 用 token 日志直接生成账单 | 新增计量账本和能力值扣减流水 |
| 每个细节都做第三方插件化 | 三期前以内置医疗卡片为主,第三方生态后置 |
| HIS 工具无幂等和熔断 | 所有写操作必须有业务幂等键、超时、补偿和人工兜底 |
| 医疗建议不可追溯 | 记录 Dify workflow run、知识引用、工具输入输出摘要、医生确认动作 |
| 设备各自为政 | 所有 P0 设备必须接入统一入口客户端或标准协议,不能项目现场临时页面堆叠 |
| 设备准入失控 | 建立 A/B/C/D 准入和联合验收,接口不开放的设备不进入核心闭环 |
| 住院边界扩散 | 医梦只负责 AI 服务、事件解释和业务闭环,不承担床头屏/护理白板硬件故障主责 |
| 鸿蒙过度承诺 | 第一阶段只承诺主动签到等 POC,保留 BLE/NFC/二维码/小程序位置授权兜底 |
三期目标是把 AI 中台从“可调用”升级为“可收费、可控额、可结算、可运营、可审计”的生产平台。
| 项 | 设计结论 |
|---|---|
| 合同主粒度 | 项目 / 医院客户 |
| 额度来源 | 合同签署时购买能力值包,形成预付账户 |
| 分摊维度 | 科室、智能体、用户、设备、终端类型、场景 |
| 扣费方式 | 调用前校验,高成本任务先冻结,完成后按实际能力值结算 |
| 余额不足 | 软拦截优先,按合同边界、能力风险和审批策略处理 |
| 医疗关键链路 | 不因计费简单中断,但必须记账、预警、审批或事后结算 |
| 合理不限量 | 仍需内部计量,用于风控、成本核算和边界判定 |
| 设备授权 | 统一入口客户端可按设备、场景、年度授权计费 |
| 设备集成 | 设备接入、适配、测试、验收进入项目实施费扩展项 |
| 设备运维 | 设备巡检、远程配置、版本升级、异常告警进入综合运营服务费 |
业务文档中的 L1/L2/L3 不是销售标签,它们决定工程交付深度、部署形态、计量方式和运营责任。
| 合作模式 | 客户购买的核心价值 | 工程最小能力 | 计费与运营要求 |
|---|---|---|---|
| L1 标准能力接入版 | 买单点 AI 能力 | API 鉴权、AgentEngine、标准能力接口、用量日志、基础计量 | 接入开通费 + 能力值包;按能力值扣费,基础用量报表 |
| L2 院级场景建设版 | 买场景交付结果;门诊总包是 L2 的增强子类型,不单独新增中间编号 | Dify Workflow、卡片运行时、MCP/HIS 集成、医生确认、场景验收、运营看板;门诊总包子类型增加统一入口客户端、Device Registry、Device Adapter、设备准入、供应商联调 | 项目实施费 + 综合运营服务费 + 能力值包或合理不限量;门诊总包子类型增加设备集成服务费、入口客户端授权、运维服务费 |
| L3 区域平台运营版 | 买多院平台运营能力 | 区域项目、医院子池、多院权限、多院审计、区域驾驶舱、统一计量与分账、设备运营看板 | 区域项目实施费 + 区域运营服务费 + 区域能力池 + 设备授权 |
| 私有平台共创版 | 买自主建设能力,作为内部扩展形态,不进入对外 L1/L2/L3 编号体系 | 平台授权、Builder、Workflow 编排、多模型/知识库/MCP 扩展、域空间隔离 | 平台授权费 + 运维服务 + 联合运营或分成 |
工程实现要避免“所有客户都上一套最重方案”。L1 只要求标准能力稳定接入;L2 才需要深度 HIS/EMR/LIS/PACS 集成和场景验收,其中门诊总包只是 L2 的增强子类型;L3 才引入区域能力池、多院监管和统一运营;私有平台共创版作为专项合同处理,不改变 L1/L2/L3 对外口径。
| 收费项 | 系统如何支撑 | 不应混淆的点 |
|---|---|---|
| 接入开通费 | 项目、公私钥、智能体授权、联调环境、基础验收 | 不是能力值,不进入用量账本 |
| 项目实施费 | 场景配置、卡片、MCP Adapter、HIS 联调、培训验收、项目里程碑 | 是交付收入,不随调用量扣减 |
| 综合运营服务费 | 巡检、工单、版本升级、安全审计、运营报告、培训记录 | 不是简单服务器运维费 |
| 能力值包 | ai_credit_account + ai_credit_ledger |
面向按量服务,支撑超量计费 |
| 合理不限量服务包 | ai_quota_policy + ai_cost_record + ai_operation_report |
客户余额不扣,但内部成本和异常必须计量 |
| 设备集成服务费 | 设备清单、准入测试、Adapter 联调、联合验收、现场培训 | 是项目交付收入,不按每次调用扣减 |
| 统一入口客户端授权费 | ai_device_registry + license_policy 支撑按设备/场景/年度授权 |
不是 AI 能力值,设备离线也可能占用授权 |
| 设备运维服务费 | 心跳监控、远程配置、版本升级、设备异常工单、SLA 报告 | 不是硬件维修费,硬件故障主责仍按合同归属设备方 |
| 鸿蒙服务找人 POC | 主动签到、候诊状态同步、近场能力联调、演示验收 | 不承诺全院鸿蒙化,属于标杆亮点专项 |
| 机器人场景服务费 | 机器人导诊、带路、语音交互、场景配置和运维 | 硬件采购、AI 能力、运行服务要分开报价 |
初级工程师重点:为什么实施费不能进能力值账本?
能力值账本记录“客户买了多少服务额度、用了多少”。项目实施费和运营服务费是交付和服务收入,和调用消耗不是同一类财务事实。如果混在一起,账单会无法解释,也无法对齐合同。
flowchart LR
Contract["合同与套餐中心"]
Account["能力值账户中心"]
Meter["计量中心"]
Rating["定价与折算中心"]
Billing["账单与结算中心"]
Allocation["额度分摊中心"]
DeviceLicense["设备授权与运维计费"]
Risk["风控与审批中心"]
Analytics["统计与运营中心"]
Audit["审计与合规中心"]
Contract --> Account
Contract --> Rating
Contract --> DeviceLicense
Meter --> Rating
Rating --> Account
Account --> Billing
Account --> Allocation
Account --> Risk
DeviceLicense --> Billing
DeviceLicense --> Analytics
Meter --> Analytics
Billing --> Analytics
Meter --> Audit
Risk --> Audit
三期计费不是“每次模型调用都扣费”,而是“把多来源调用事实归并成可解释的业务计费单元”。一个业务计费单元称为 billingEpisode。
flowchart LR
Call["用户主动调用<br/>chat / card action / file analysis"]
Context["计量上下文<br/>project / contract / scenario / episode"]
Events["标准计量事件<br/>CHAT / CARD / MCP / IMAGE"]
Merge["事件归并<br/>billingEpisode / parent_event"]
Pricing["定价折算<br/>合同快照 / 规则快照"]
Ledger["能力值账本<br/>freeze / settle / release"]
Bill["月账单<br/>项目 / 科室 / 智能体分摊"]
Report["运营报告<br/>成本 / 质量 / 风险"]
Call --> Context --> Events --> Merge --> Pricing --> Ledger --> Bill --> Report
计费闭环规则:
billingEpisodeId,除非它明确属于已有业务链路。billingEpisode 和业务事件为主,内部成本以 token、图片、分钟、工具调用等 detail 记录。settled 且未出账的账本流水;账单修正通过 reverse/adjust/correction,不改原流水。billingEpisode 状态机:
stateDiagram-v2
[*] --> open: 创建 episode
open --> completed: 达到业务完成点
open --> expired: 超时/用户中断
completed --> settling: 进入定价和账本处理
settling --> settled: 结算完成
settling --> failed: 处理失败
failed --> settling: 重试/重放
settled --> billed: 进入账单
expired --> closed: partial 处理完成
billed --> closed: 归档
episode 边界规则:
| 场景 | episode 处理 |
|---|---|
| 用户主动发起新 chat | 默认创建新 episode |
| synthetic message | 归入当前 episode |
| 同一 conversation 内短时间卡片动作 | 默认归入当前 episode,除非动作本身定义为新的业务能力 |
| 业务完成点,如挂号确认、建档成功、图像分析完成 | 当前 episode 进入 completed 或创建子业务 episode |
| 医生站独立触发质控、病历生成、CDSS | 创建新 episode |
| IoMT 预警和外呼随访任务 | 由事件或任务创建 episode,不依赖 chat |
| episode 长时间未完成 | 进入 expired,按 partial 策略结算或不扣客户余额 |
管理客户购买了什么、能用什么、在哪些边界内使用。
| 功能 | 说明 |
|---|---|
| 合同档案 | 客户、项目、医院、院区、合同周期、合作层级 L1/L2/L3 |
| 能力值包 | 试点包、标准包、深度包、旗舰包、区域包 |
| 服务包 | 合理不限量服务包、综合运营服务费、项目实施费 |
| 合同范围 | 医院、院区、科室、场景、智能体、模型、终端、并发 |
| 价格策略 | 标准价、折扣、超量价、阶梯价、赠送额度 |
| 状态管理 | 草稿、生效、暂停、过期、终止、续签 |
合同中心不直接扣费,只定义规则和边界。
每个项目默认一个主账户,可按科室或区域拆分子账户。
| 账户类型 | 用途 |
|---|---|
| 项目主账户 | 合同购买能力值进入主账户 |
| 科室预算账户 | 从主账户分配预算,不作为财务合同主体 |
| 智能体预算 | 控制单个智能体使用上限 |
| 区域总账户 | L3 区域项目的总池 |
| 医院子账户 | 区域总池下的医院分配池 |
账户核心字段包括:
| 字段 | 说明 |
|---|---|
available_credits |
可用能力值 |
frozen_credits |
已冻结未结算能力值 |
used_credits |
已使用能力值 |
granted_credits |
合同授予能力值 |
valid_from / valid_to |
有效期 |
overdraft_policy |
超额策略 |
计量中心采集标准事件,生成不可变流水。它是三期的核心。
| 来源 | 事件 |
|---|---|
| OpenPlatform | 对话请求、流式完成、异常结束 |
| DifyAdapter | Dify message、workflow run、usage |
| MCP Server | 工具调用、HIS 写操作、失败重试 |
| Card Runtime | 卡片展示、卡片确认、卡片动作执行 |
| 语音服务 | ASR、TTS、随访电话分钟数 |
| 图像服务 | 舌诊、面诊、影像类模型分析 |
| 文书服务 | 病历生成、质控、出院小结、报告解读 |
| 字段 | 说明 |
|---|---|
event_id |
全局唯一事件 ID |
idempotency_key |
幂等键,避免重复扣费 |
billing_episode_id |
业务计费单元 ID,用于归并 synthetic、MCP、Card 等子事件 |
parent_event_id |
父事件 ID,用于表达一次业务链路内的事件层级 |
project_id |
计费主对象 |
dept_id |
分摊维度 |
agent_id |
智能体维度 |
device_id |
设备维度,门诊总包和统一入口客户端授权使用 |
terminal_type |
终端类型,如 kiosk、robot、doctor_desktop、waiting_screen |
scenario_code |
场景,如 triage、previsit、emr_write |
meter_item |
计量项,如 token、call、minute、image、document |
raw_quantity |
原始数量 |
credits |
折算能力值 |
source_type |
openplatform / dify / mcp / card |
source_id |
messageId / workflowRunId / toolCallId / instanceId |
charge_policy |
customer_charge / license_covered / bundle_included / internal_cost / no_charge |
contract_snapshot |
合同关键快照,包含适用范围、折扣、套餐、超量规则 |
status |
pending / settled / reversed / failed |
charge_policy 默认规则:
| 策略 | 含义 | 适用场景 |
|---|---|---|
customer_charge |
从客户能力值账户扣减 | 高级 AI 能力、按次服务、超出套餐范围的调用 |
license_covered |
已被设备授权费或场景服务费覆盖,不再扣能力值 | 设备首页、基础导览、基础 FAQ、设备运行服务 |
bundle_included |
已被合理不限量或运营服务包覆盖,客户侧不扣余额 | 合同明确包含的场景包 |
internal_cost |
只记内部成本,不对客户单独展示 | RAG、MCP 查询、synthetic 调用、模型 token 明细 |
no_charge |
不计费,仅留审计 | 失败、取消、测试、人工豁免 |
事件归并规则:
| 组合 | 客户侧计费 | 内部成本 |
|---|---|---|
用户主动 CHAT_COMPLETED + synthetic CHAT_COMPLETED |
按同一 billingEpisodeId 计一次业务能力 |
synthetic token 进入 detail |
CARD_ACTION_CONFIRMED + MCP_TOOL_WRITE |
只对卡片确认业务事件定价 | MCP 写操作进入工具成本 |
IMAGE_ANALYSIS + 模型 usage |
对图像分析业务事件定价 | token、图片张数、模型成本进入 detail |
MCP_TOOL_READ 支撑卡片展示 |
默认不对客户单独扣费 | 记录工具查询成本 |
| 设备授权 + 基础交互 | 设备年费/月费覆盖,不重复扣能力值 | 记录设备活跃、并发和基础 token 成本 |
| 设备授权 + 高级 AI 能力 | 设备授权覆盖入口运行,高级能力按合同继续扣能力值 | 分别记录设备成本和能力成本 |
| 机器人场景服务费 + 导诊问答 | 场景服务费覆盖机器人运行服务,导诊/分诊能力按合同扣或包内 | 记录机器人在线、语音分钟、模型成本 |
| 失败或取消事件 | 默认不扣客户余额 | 可记录内部失败成本 |
把不同底层成本折算为能力值。
| 能力类型 | 建议计量方式 |
|---|---|
| 导诊问答 | 次 + token 阈值修正 |
| 智能分诊 | 次 |
| 预问诊 | 次 / 完整问诊单 |
| 报告解读 | 份 |
| 舌诊 / 面诊 | 次 |
| 语音随访 | 分钟 |
| 病历生成 | 份 |
| 病历质控 | 份 |
| CDSS | 次 |
| MCP 写操作 | 次,通常并入业务能力,不单独对客户展示 |
| RAG 检索 | 内部成本项,通常并入业务能力 |
| 设备授权 | 台 / 年或台 / 月,覆盖统一入口客户端基础运行 |
| 设备运维 | 台 / 月或项目 / 月,覆盖巡检、升级、告警、SLA |
| 机器人运行服务 | 台 / 月或场景 / 年,覆盖机器人场景配置、语音交互运行、导航联调和运维 |
| 机器人 AI 能力 | 次 / 分钟 / episode,按导诊、分诊、问答、带路等能力进入能力值或服务包 |
定价规则应支持:
不同任务采用不同扣费策略。
| 任务类型 | 策略 |
|---|---|
| 普通问答 | 完成后扣费 |
| 高成本生成 | 调用前冻结预估额度,完成后结算 |
| 语音电话 | 分段冻结,按实际分钟结算 |
| 图像分析 | 调用前冻结单次额度,失败自动释放 |
| HIS 写操作 | 业务成功后结算,失败不扣或按合同定义扣基础成本 |
| 合理不限量 | 不扣客户余额,但仍写内部计量与成本流水 |
扣费流水必须支持:
| 操作 | 说明 |
|---|---|
freeze |
冻结能力值 |
settle |
结算扣减 |
release |
释放未使用冻结额度 |
reverse |
冲正 |
adjust |
人工调整 |
grant |
合同授予或续包 |
账单按项目生成,支持多维分摊。
| 账单类型 | 用途 |
|---|---|
| 月度账单 | 客户对账 |
| 超量账单 | 能力值耗尽后的补费 |
| 科室分摊账单 | 医院内部核算 |
| 智能体用量账单 | 产品运营分析 |
| 区域结算账单 | L3 区域能力池分配 |
| 内部成本账单 | 模型、语音、图像、硬件成本核算 |
账单生成后应支持状态流转:
draft -> confirmed -> invoiced -> paid -> archived
统计不是简单图表,而是支撑综合运营服务费的交付物。
| 看板 | 指标 |
|---|---|
| 项目总览 | 总用量、余额、预计耗尽日期、活跃智能体、异常调用 |
| 能力值消耗 | 日/月趋势、科室分摊、智能体分摊、场景排行 |
| 成本分析 | 模型成本、语音成本、图像成本、毛利估算 |
| 医疗场景效果 | 分诊命中率、预问诊完整度、病历节省时间、质控问题闭环率 |
| 运营服务 | 工单响应、巡检记录、升级记录、客户培训、版本发布 |
| 风险审计 | 超量、越权、异常峰值、高风险医疗建议、人工确认率 |
综合运营服务费必须有可交付物,否则客户会把它理解为普通运维费。运营中心需要把“系统是否持续产生价值”变成可查询、可导出、可复盘的数据。
flowchart LR
Usage["用量与成本"]
Quality["医疗质量指标"]
Ops["运营服务记录"]
Risk["风险与审计"]
Report["月度/季度运营报告"]
Action["运营动作<br/>培训 / 优化 / 续包 / 扩科"]
Usage --> Report
Quality --> Report
Ops --> Report
Risk --> Report
Report --> Action
Action --> Usage
| 运营对象 | 必须沉淀的数据 | 对应交付物 |
|---|---|---|
| L1 客户 | API 调用量、能力值余额、错误率、超量预警 | 月度用量简报、续包提醒 |
| L2 单院 | 场景用量、科室分摊、分诊/预问诊/病历/质控效果、工单记录 | 月度运营报告、阶段复盘、培训记录 |
| L3 区域 | 多院用量、医院排行、区域能力池、异常医院、统一审计 | 区域驾驶舱、监管报表、多院运营报告 |
| 合理不限量客户 | 内部成本、峰值、场景占比、合同边界命中 | 异常复核报告、边界调整建议 |
业务附件中提到的门诊、住院建设目标需要落成可统计指标。以下指标不是全部上线第一天都要具备,但 L2/L3 项目验收必须至少选定一组。
| 场景 | 建议指标 |
|---|---|
| AI 门诊 | 患者平均在院时间、分诊命中率、挂号成功率、预问诊完整度、患者满意度 |
| 诊间病历 | 病历生成耗时、医生修改率、病历甲级率、质控问题闭环率 |
| CDSS / 用药安全 | 预警覆盖率、医生采纳率、误报率、高风险问题拦截数 |
| 舌诊 / 面诊 | 图片质量通过率、分析完成率、医生确认率、复测一致性 |
| AI 住院 | 病历书写时间、平均住院日、床位使用率、护理风险闭环率 |
| IoMT / 护理预警 | 预警及时率、误报率、护士处理时长、不良事件趋势 |
| 出院随访 | 随访完成率、高危识别率、人工升级闭环率、复诊推荐转化率 |
风控策略按合同、能力、余额、风险等级综合判断。
| 场景 | 默认策略 |
|---|---|
| 余额低于 20% | 预警客户管理员、运营负责人 |
| 余额低于 5% | 强预警,可触发续包流程 |
| 余额为 0 | 非关键能力审批或停用,关键医疗链路软放行并记超量 |
| 超出合同场景 | 阻断或审批 |
| 异常高频调用 | 限流、冻结、人工复核 |
| 高成本模型调用 | 先冻结额度 |
| 合理不限量异常峰值 | 标记异常,不直接扣客户余额,但进入运营复核 |
三期不要把“计量、扣费、账单”写成一个大 Service。建议按以下服务拆分,职责清楚后初级工程师更容易实现和测试。
| 服务 | 职责 | 依赖 | 不能做什么 |
|---|---|---|---|
| ContractService | 查询合同、合同范围、合同状态 | 合同表、套餐表 | 不直接扣费 |
| PricingService | 根据规则计算能力值 | 定价计划、定价规则 | 不修改账户余额 |
| CreditAccountService | 管理账户余额、冻结、释放、结算 | 账户表、账本表 | 不理解业务场景含义 |
| MeterEventService | 接收标准计量事件,保证幂等 | 计量事件表 | 不生成最终账单 |
| BillingService | 汇总账本生成账单 | 账本、账单表 | 不直接调用 Dify/MCP |
| QuotaPolicyService | 判断预警、封顶、审批、停用 | 合同范围、账户、策略表 | 不做实际扣费 |
| CostService | 记录内部模型和资源成本 | 成本表、模型价格 | 不影响客户余额 |
| OperationReportService | 生成运营报告 | 账单、计量、业务指标 | 不修改原始流水 |
sequenceDiagram
autonumber
participant API as OpenPlatform
participant Quota as QuotaPolicyService
participant Contract as ContractService
participant Credit as CreditAccountService
participant Agent as Agent/Dify/MCP
participant Meter as MeterEventService
participant Pricing as PricingService
participant Ledger as CreditLedger
API->>Contract: 查询项目合同和能力范围
Contract-->>API: 合同有效、覆盖当前智能体/场景
API->>Quota: 判断是否需要预扣或审批
alt 高成本或固定价能力
Quota->>Credit: freeze(预估能力值, idempotencyKey)
Credit->>Ledger: 写 freeze 流水
end
API->>Agent: 执行 AI / Dify / MCP 调用
Agent-->>API: 返回结果、usage、工具调用信息
API->>Meter: 记录标准计量事件
Meter->>Pricing: 根据事件和合同规则折算能力值
Pricing-->>Meter: credits
alt 已冻结
Meter->>Credit: settle(freezeId, actualCredits)
Credit->>Ledger: 写 settle / release 流水
else 未冻结
Meter->>Credit: settle(actualCredits, idempotencyKey)
Credit->>Ledger: 写 settle 流水
end
stateDiagram-v2
[*] --> granted: 合同生效/续包
granted --> available: 额度入账
available --> frozen: 高成本任务预扣
frozen --> settled: 任务成功结算
frozen --> released: 任务失败/未用完释放
available --> settled: 普通任务完成后扣减
settled --> reversed: 冲正
available --> adjusted: 人工调账
reversed --> [*]
settled --> [*]
released --> available
账本实现要求:
| 流水类型 | 余额影响 | 场景 |
|---|---|---|
grant |
增加可用余额 | 合同生效、续包、赠送额度 |
freeze |
可用余额减少,冻结余额增加 | 高成本任务开始前 |
settle |
冻结或可用余额转为已使用 | 调用完成 |
release |
冻结余额回到可用余额 | 任务失败、取消、实际消耗低于预估 |
reverse |
生成反向流水 | 错扣、退款、人工复核 |
adjust |
人工增加或减少 | 合同外调整、历史修正 |
erDiagram
AI_CONTRACT ||--o{ AI_CONTRACT_SCOPE : defines
AI_CONTRACT ||--o{ AI_CREDIT_ACCOUNT : grants
AI_PRICING_PLAN ||--o{ AI_PRICING_RULE : contains
AI_CONTRACT }o--|| AI_PRICING_PLAN : uses
AI_CREDIT_ACCOUNT ||--o{ AI_CREDIT_LEDGER : records
AI_METER_EVENT ||--o{ AI_METER_EVENT_DETAIL : has
AI_METER_EVENT ||--o{ AI_CREDIT_LEDGER : charges
AI_BILLING_STATEMENT ||--o{ AI_BILLING_STATEMENT_ITEM : includes
AI_CREDIT_LEDGER }o--o{ AI_BILLING_STATEMENT_ITEM : summarized_by
AI_CONTRACT {
bigint id
bigint project_id
string contract_no
string cooperation_level
string status
}
AI_CREDIT_ACCOUNT {
bigint id
bigint project_id
bigint parent_account_id
decimal available_credits
decimal frozen_credits
decimal used_credits
}
AI_METER_EVENT {
string event_id
bigint project_id
bigint agent_id
string scenario_code
string idempotency_key
string status
}
AI_CREDIT_LEDGER {
string ledger_id
bigint account_id
string event_id
string ledger_type
decimal credits
string direction
}
| 阶段 | 触发点 | 主责服务 | 落库对象 |
|---|---|---|---|
| 合同签署 | 商务录入或项目初始化 | ContractService | ai_contract、ai_contract_scope |
| 能力值入账 | 合同生效 | CreditAccountService | ai_credit_account、ai_credit_ledger(grant) |
| 调用前校验 | 用户调用智能体 | QuotaPolicyService | 可选 freeze 流水 |
| 调用执行 | Dify/MCP/Card 完成业务 | OpenPlatform / MCP | ai_usage_log、ai_card_action_log |
| 计量事件 | 调用完成或失败 | MeterEventService | ai_meter_event、ai_meter_event_detail |
| 价格折算 | 事件入库后 | PricingService | 事件 credits 字段或明细 |
| 额度扣减 | 价格计算后 | CreditAccountService | ai_credit_ledger(settle/release) |
| 月度汇总 | 定时任务 | BillingService | ai_billing_statement、明细 |
| 运营报告 | 月度或季度 | OperationReportService | ai_operation_report |
idempotency_key 重复上报时返回已有处理结果。能力值是对外报价和内部计量的统一额度。建议对外口径保持“1 能力值约等于 1 元人民币”的理解,但实际合同可按折扣、赠送额度、套餐价进行换算。
示例:L2 标准能力值包。
| 项 | 示例值 |
|---|---|
| 套餐名称 | 标准包 |
| 合同价格 | 200,000 元 / 年 |
| 授予能力值 | 200,000 credits |
| 有效期 | 合同生效日起 12 个月 |
| 超量单价 | 1 元 / credit,或按合同阶梯价 |
| 适用范围 | 单院项目,覆盖已授权智能体和科室 |
能力折算示例:
| 能力 | 计量单位 | 标准 credits | 说明 |
|---|---|---|---|
| 导诊问答 | 次 | 1-3 | 高频轻量能力,可含 token 上限 |
| 智能分诊 | 次 | 3-8 | 含症状采集、科室推荐、紧急度提示 |
| 预问诊 | 完整问诊单 | 5-15 | 多轮追问并输出结构化病史 |
| 报告解读 | 份 | 5-20 | 按报告类型和长度分档 |
| 舌诊 / 面诊 | 次 | 5-15 | 图像专精模型 |
| 病历生成 | 份 | 10-30 | 门诊病历、SOAP 等 |
| 病历质控 | 份 | 8-30 | 规则 + LLM 质控 |
| 语音随访 | 分钟 | 1-3 | 按实际通话分钟结算 |
| CDSS | 次 | 10-30 | 必须医生主导 |
| 机器人导诊问答 | 次 / episode | 1-3 | 若合同已买机器人基础服务,可按 license_covered 处理基础 FAQ |
| 机器人分诊 / 挂号引导 | 次 / episode | 3-8 | 属于高级 AI 能力,默认进入能力值或合理不限量服务包 |
| 机器人语音带路 | 次 / 分钟 | 2-10 | 机器人运行服务覆盖设备运维,AI 语音和导航按合同定义是否另计 |
初级工程师重点:credits 不是 token。
token 是底层模型消耗,credits 是商业计量单位。一次“报告解读”可能包含 token、RAG、格式化和审计多个成本项,但对客户只展示为“1 份报告解读消耗 X 能力值”。
定价规则必须支持版本化,避免规则变更后历史账单被重新解释。
| 字段 | 说明 |
|---|---|
pricing_rule_id |
规则 ID |
version |
规则版本 |
effective_from |
生效开始时间 |
effective_to |
生效结束时间 |
meter_item |
计量项 |
scenario_code |
场景编码 |
calculation_mode |
fixed / tiered / token_based / minute_based |
rule_snapshot_json |
规则快照 |
计量事件生成时必须记录:
pricing_rule_id。pricing_rule_version。账单汇总时优先使用事件内的规则快照,不实时读取最新规则。
同一个计量事件可能同时命中平台默认价、项目合同价、套餐折扣和人工优惠。生产系统必须有唯一优先级,否则同一事件在不同任务里会算出不同金额。
定价优先级从高到低:
| 优先级 | 规则来源 | 示例 | 说明 |
|---|---|---|---|
| 1 | 合同明细覆盖价 | 某医院报告解读固定 3 credits/份 | 最优先,商务合同已明确 |
| 2 | 合同套餐折扣 | 购买 50 万能力值包享 8 折 | 作用于合同范围内的计量项 |
| 3 | 项目专属定价规则 | 区域医联体统一定价 | 用于多项目统一政策 |
| 4 | 平台版本化定价规则 | 默认报告解读 5 credits/份 | 全局默认 |
| 5 | 人工审批调整 | 运营减免或补扣 | 必须形成调整流水,不改原事件 |
实现要求:
PricingService 每次计算都输出 pricing_source、pricing_rule_id、pricing_rule_version 和规则快照。reverse + adjust,不能直接改原流水。contract_id 和合同关键快照,至少包含适用范围、折扣、套餐类型、超量规则和合理不限量边界。计量事件不是一生成就扣费。它要经过定价、账户处理和账本落地。
stateDiagram-v2
[*] --> received: 接收事件
received --> duplicated: 幂等命中
received --> pricing_completed: 定价完成
pricing_completed --> frozen: 需要预冻结
pricing_completed --> settled: 不需冻结直接结算
frozen --> settled: 实际结算
frozen --> released: 失败或取消释放
pricing_completed --> failed: 定价失败
settled --> billed: 出账
failed --> dead_letter: 超过重试
released --> [*]
billed --> [*]
duplicated --> [*]
| 状态 | 是否可重试 | 是否影响余额 | 说明 |
|---|---|---|---|
received |
是 | 否 | 已接收但未定价 |
pricing_completed |
是 | 否 | 已确定 credits 和规则快照 |
frozen |
是 | 冻结余额 | 预估额度已占用 |
settled |
否 | 扣减余额 | 已形成正式扣减流水 |
released |
否 | 释放冻结 | 业务失败、取消或超时 |
failed |
是 | 否 | 可重试技术失败 |
dead_letter |
人工处理 | 视情况 | 自动处理失败,需要运营/财务介入 |
billed |
否 | 否 | 已进入账单周期 |
一致性规则:
ai_meter_event 负责“事件处理状态”,ai_credit_ledger 负责“账户资金事实”。meter_event_id 最多只能有一条正式 settle 流水。settled 且未出账流水,不能读取 received/pricing_completed/frozen。billed 的事件不回退状态;账单错误通过 reverse/adjust/correction 生成新流水和补差账单,保留原账单审计链。本期计费主粒度已确认是项目 / 医院客户。账户层级建议只做两层,避免早期账务复杂度失控。
| 账户层级 | 用途 | 是否真实扣费 |
|---|---|---|
| 项目主账户 | 合同能力值池、真实余额、真实冻结和扣减 | 是 |
| 分摊维度账户 | 科室、智能体、医生、渠道的用量统计和预算提醒 | 否,默认只做分摊 |
不建议三期初版做多级资金账户递归扣减。科室预算可以先做软控制:统计、预警、审批,不直接把资金拆成多套真实余额。
账户并发规则:
ai_credit_account 增加 version 字段,扣减时用乐观锁更新余额。100ms * 2^retryCount + random(0, 50ms),最多重试 3 次。初级工程师重点:为什么账户余额不能直接
balance = balance - x?
多个请求同时扣同一个账户时,直接更新会丢失扣减。必须用版本号或条件更新确保“读到的余额就是当前余额”。如果更新失败,说明别人已经改过余额,需要重新读取再计算。
这里不写 Java 代码,只定义服务输入输出。编码前应先把这些契约固化成接口。
| 服务 | 输入 | 输出 |
|---|---|---|
| ContractService | projectId、agentId、scenarioCode、时间 |
合同状态、合同范围、定价计划 |
| QuotaPolicyService | 项目、账户、场景、预估 credits | allow / freeze_required / approval_required / reject |
| PricingService | 计量事件、合同、规则版本 | credits、规则版本、规则快照 |
| MeterEventService | 标准计量事件、幂等键 | accepted / duplicated / failed |
| CreditAccountService.freeze | 账户、预估 credits、幂等键 | freezeId、冻结结果 |
| CreditAccountService.settle | 事件、实际 credits、freezeId 可选 | 结算流水 |
| CreditAccountService.release | freezeId、原因 | 释放流水 |
| BillingService | 项目、账期、账单类型 | 账单主表和明细 |
| ApprovalService | 审批类型、申请对象、原因 | 审批单和状态 |
风控策略依赖审批,审批必须成为显式模块。
stateDiagram-v2
[*] --> pending: 触发审批
pending --> approved: 审批通过
pending --> rejected: 审批拒绝
pending --> expired: 超时未处理
approved --> effective: 生效
effective --> invalid: 到期/撤销
rejected --> [*]
expired --> [*]
invalid --> [*]
| 审批类型 | 审批人 | 生效范围 |
|---|---|---|
| 余额不足放行 | 医梦运营 / 医院管理员 | 项目、智能体、时间窗口 |
| 超合同范围调用 | 项目负责人 / 医梦运营 | 指定场景或能力 |
| 高成本模型调用 | 医梦运营 | 单次或批量任务 |
| 合理不限量异常峰值 | 医梦运营 / 商务 | 复核后继续或限制 |
| 账本人工调整 | 财务 / 管理员 | 指定账户和流水 |
审批记录至少包含:申请人、审批人、审批类型、关联对象、原因、结果、有效期、审批意见、审计 traceId。
余额不足不是简单停用,按合同和风险处理。
| 场景 | 策略 |
|---|---|
| 余额低但未为 0 | 继续使用,触发预警 |
| 余额为 0 且合同允许超量 | 继续使用,写超量流水,生成超量账单 |
| 余额为 0 且合同不允许超量 | 非关键能力阻断,高风险医疗关键链路走审批 |
| 合理不限量超出边界 | 不扣客户余额,标记异常并进入运营复核 |
| 现场补购 | 合同续包后 grant 新能力值,再抵扣后续使用 |
超量账单触发方式:
| 事件类型 | 默认计量策略 |
|---|---|
CHAT_COMPLETED |
普通对话完成,按智能体或 token 折算 |
CHAT_STREAM_PARTIAL |
流式中断,按 partial 策略 |
CHAT_FAILED |
失败事件,默认不扣客户余额 |
CARD_DISPLAYED |
默认不扣费,仅用于漏斗分析 |
CARD_ACTION_CONFIRMED |
用户确认动作,可触发业务计量 |
MCP_TOOL_READ |
内部计量,通常不对客户单独展示 |
MCP_TOOL_WRITE |
并入业务能力,写操作必须幂等 |
ASR_MINUTE |
按分钟 |
TTS_MINUTE |
按分钟或字符 |
IMAGE_ANALYSIS |
按次或图片张数 |
DOCUMENT_GENERATED |
按份 |
REPORT_INTERPRETED |
按份 |
FOLLOWUP_CALL_MINUTE |
按分钟 |
MANUAL_ADJUSTMENT |
人工调整,必须审批 |
项目月度运营报告建议包含以下字段:
| 区块 | 字段 |
|---|---|
| 项目概览 | 项目、医院、账期、合同状态、合作层级 |
| 用量概览 | 总调用次数、总能力值、剩余额度、预计耗尽日期 |
| 场景分析 | 导诊、预问诊、报告解读、病历、质控、随访等用量 |
| 科室分摊 | 科室用量、科室占比、异常增长 |
| 智能体排行 | 调用量、消耗、成功率、失败率 |
| 成本分析 | 模型成本、语音成本、图像成本、毛利估算 |
| 质量指标 | 分诊命中率、预问诊完整度、质控闭环率 |
| 风险审计 | 越权、超量、审批、敏感访问、高风险操作 |
| 运营动作 | 巡检、培训、版本升级、问题处理 |
| 下月建议 | 续包建议、能力优化、科室推广建议 |
合同状态机:
stateDiagram-v2
[*] --> draft: 创建合同
draft --> active: 审核并生效
active --> suspended: 暂停
suspended --> active: 恢复
active --> expired: 到期
active --> terminated: 提前终止
expired --> renewed: 续签
renewed --> active: 新合同生效
账单触发规则:
| 账单类型 | 触发方式 | 说明 |
|---|---|---|
| 月度账单 | 每月 1 日由 SnailJob 生成上月账单 | 支持人工重算 |
| 超量账单 | 月末汇总,或合同要求时实时提醒 | 来自超量流水 |
| 科室分摊账单 | 月度账单生成后同步生成 | 医院内部管理使用 |
| 区域账单 | 按区域项目账期生成 | 包含医院子池分摊 |
| 人工调整账单 | 审批通过后生成 | 对应 adjust/reverse 流水 |
区域能力池初版规则:
transfer 流水。| 场景 | 处理策略 | 账本动作 |
|---|---|---|
| 用户取消 | 业务未完成则释放冻结;已完成则按合同规则结算或冲正 | release 或 reverse |
| SSE 中断 | 根据 Dify 最终状态判断是否完成;无法确认则标记 partial | settle_partial 或 release |
| Dify 部分失败 | 已产生成本但未形成客户价值时,可内部记成本、不扣客户余额 | 成本事件 + 客户 release |
| MCP 写操作超时 | 先查 HIS 最终状态;成功则结算,失败则释放 | settle 或 release |
| 冻结超时 | 定时任务释放超过 TTL 的冻结记录 | release_timeout |
| 能力值到期 | 合同到期或套餐过期后未使用余额按合同处理 | expire |
| 人工减免 | 审批后生成减免流水,不改原始扣费 | adjust_credit |
| 人工补扣 | 审批后生成补扣流水 | adjust_debit |
能力值到期需要特别谨慎:如果合同约定可结转,则不能执行 expire;如果合同约定到期作废,expire 也必须生成账本流水,不能直接把余额清零。
批量账务修正用于处理规则配置错误、批量误扣、合同折扣漏配等运营事故。流程必须是:选择事件范围和修正原因,预览受影响事件、账户和账单,通过财务/运营审批后批量生成 correction 流水;已出账账单要触发重算或补差账单,不能直接改历史流水。
以下为设计级模型,不替代最终迁移 SQL。
| 表 | 说明 |
|---|---|
ai_contract |
合同主表,记录客户项目、合作层级、周期、状态 |
ai_contract_scope |
合同范围:医院、科室、场景、智能体、模型、终端、并发 |
ai_pricing_plan |
套餐和定价计划,如能力值包、合理不限量包 |
ai_pricing_rule |
计量项到能力值的折算规则,支持版本化 |
ai_credit_account |
能力值账户,项目主账户和子账户 |
ai_credit_ledger |
能力值账本,记录 grant/freeze/settle/release/reverse |
ai_meter_event |
标准计量事件,来自 OpenPlatform/Dify/MCP/Card |
ai_meter_event_detail |
token、分钟、图片、文书等明细 |
ai_quota_policy |
额度、封顶、预警、审批策略 |
ai_billing_statement |
月账单 / 超量账单 / 区域账单 |
ai_billing_statement_item |
账单明细,支持科室和智能体分摊 |
ai_operation_report |
运营报告快照 |
ai_cost_record |
内部成本记录,模型、语音、图像、硬件、人工服务 |
能力值账本必须满足:
idempotency_key。ai_usage_log 只作为排障和统计辅助。ai_meter_event_detail 的规模会随调用量快速增长。初版如果明细只用于排障和少量统计,可以先作为 ai_meter_event.detail_json 保存;如果需要按 token、分钟、图片等维度高频查询,则独立建表并按月分区,至少保留 project_id + event_time 索引。
在 /api/v1/agent/chat 进入主链路时增加:
project_id + agent_id + scenario 查询合同范围。traceId 和计量上下文。files 类型,调用完成后由 OpenPlatform 统一生成 IMAGE_ANALYSIS、DOCUMENT_ANALYSIS、ASR_MINUTE 等文件/多模态计量事件。billingEpisodeId;synthetic message、MCP 工具调用和卡片动作沿用或关联该 episode。Dify 返回 usage、messageId、conversationId、workflowRunId 时:
ai_meter_event。每个 MCP 工具调用生成工具事件:
| 工具类型 | 是否对客户展示扣费 | 是否内部计量 |
|---|---|---|
| 查询类 | 通常不单独展示 | 是 |
| 写操作 | 通常并入业务能力 | 是 |
| 高成本第三方接口 | 可单独配置 | 是 |
| 失败重试 | 不重复扣客户费 | 是,记录成本 |
MCP 工具事件必须携带 billingEpisodeId、parentEventId 和可选 cardActionId。当它由卡片动作触发时,计量中心以 CARD_ACTION_CONFIRMED 作为客户侧定价事件,MCP_TOOL_WRITE 只进入内部成本,避免重复扣费。
卡片动作应接入计量上下文:
二期主链路应尽早携带计量上下文,即使三期账本还没有完全实现。这样后续接入计费时不需要重构所有接口。
| 字段 | 来源 | 用途 |
|---|---|---|
traceId |
OpenPlatform 生成 | 串联日志、调用、MCP、账本 |
projectId |
项目鉴权 | 合同和额度主对象 |
tenantId |
项目绑定租户 | 多租户隔离 |
agentId |
请求参数映射 | 智能体维度 |
deptId |
智能体、用户或业务上下文 | 科室分摊 |
userId |
请求参数 | 用户维度 |
scenarioCode |
智能体配置或 Dify 输出 | 定价规则匹配 |
contractId |
ContractService 查询 | 合同追溯 |
idempotencyKey |
请求 / 卡片动作 / 工具调用生成 | 防重复扣费 |
sourceType |
openplatform / dify / mcp / card | 事件来源 |
| 异常 | 二期处理 | 三期处理 |
|---|---|---|
| Dify 超时 | 返回可解释错误,记录调用失败 | 若已冻结额度则释放 |
| SSE 中断 | 标记会话未完整完成 | 按 partial 策略计量或不计量 |
| MCP 查询失败 | 卡片展示失败或降级为空状态 | 记录工具失败成本,不扣客户业务费 |
| MCP 写操作超时 | 查询 HIS 最终状态,避免重复写 | 冻结保持 pending,人工复核后 settle/release |
| HIS 返回业务失败 | 展示失败原因,可重试 | 不扣或按合同基础成本扣 |
| 重复点击卡片 | 幂等返回第一次结果 | 不重复生成计量事件 |
| 余额不足 | 二期只记录 | 三期按软拦截/审批/超量策略 |
本章补齐线上医疗项目必须具备的架构能力。它们不是“后续优化”,而是决定系统能否在医院真实运行、能否被审计、能否结算、能否排障的基础能力。
主数据边界决定权限、计费、统计和审计能不能对齐。当前设计中 project_id 是合同和额度主粒度,但生产环境还需要把客户主体、医院、院区、科室、智能体之间的关系固定下来。
flowchart TD
Customer["客户主体<br/>医院 / 医疗集团 / 卫健委"]
Contract["合同<br/>L1 / L2 / L3 / 合理不限量"]
Project["项目 project_id<br/>计费、授权、账单主对象"]
RegionPool["区域能力池<br/>L3 可选"]
Hospital["医院"]
Campus["院区"]
Dept["科室 / 病区"]
Agent["智能体 / AI 能力"]
User["用户 / 医护 / 患者"]
Customer --> Contract
Contract --> Project
Project --> RegionPool
Project --> Hospital
RegionPool --> Hospital
Hospital --> Campus
Campus --> Dept
Project --> Agent
Dept --> Agent
User --> Project
| 模块 | 作用 | 与现有设计的关系 |
|---|---|---|
| 客户主体管理 | 记录签约主体,可能是单院、集团或卫健委 | 合同中心的上游 |
| 项目管理 | 绑定客户、合同、医院范围,是授权和计费主对象 | 复用当前 sys_project,补充医院/租户绑定 |
| 医院组织映射 | 维护医院、院区、科室、病区 | 支撑科室分摊、权限和 HIS Adapter |
| 智能体授权 | 控制项目可使用哪些智能体和场景 | 当前 project.agentIds 应升级为关系表 |
| 科室预算分摊 | 将项目能力值分配到科室或智能体 | 三期额度分摊中心使用 |
projectId,并尽量补齐 hospitalId/campusId/deptId/agentId。初级工程师重点:为什么不能只用 tenantId?
tenantId解决的是数据隔离,不等于合同主体。一个租户可能有多个项目,一个区域项目可能覆盖多家医院。计费、账单和审计必须挂在projectId上,否则后续无法解释“这笔能力值是谁用的、属于哪份合同、哪个医院或科室消耗”。
| 功能 | 说明 |
|---|---|
| 项目-医院绑定 | 一个项目可绑定一家或多家医院 |
| 项目-智能体授权 | 控制项目可调用的智能体清单 |
| 项目-工具授权 | 控制项目可调用的 MCP 工具范围 |
| 科室预算配置 | 主账户额度分配到科室或智能体 |
| 组织映射同步 | 从 HIS 或手工维护院区/科室 |
| 账单分摊规则 | 按科室、智能体、场景或用户分摊 |
三期计量依赖 OpenPlatform、Dify、MCP、Card 多来源事件。如果只用异步线程写账本,线上会出现“业务成功但没扣费”“重复重试导致重复扣费”“SSE 中断后状态不一致”等问题。
flowchart LR
Biz["业务事务<br/>会话 / 卡片 / MCP"]
Outbox["本地事件表 Outbox<br/>同事务落库"]
Dispatcher["事件投递任务<br/>SnailJob / 定时扫描"]
Meter["计量事件处理器"]
Ledger["能力值账本"]
Retry["失败重试 / 死信"]
Biz --> Outbox
Outbox --> Dispatcher
Dispatcher --> Meter
Meter --> Ledger
Dispatcher --> Retry
Retry --> Dispatcher
| 模块 | 作用 |
|---|---|
| OutboxEventService | 在业务事务内写入待处理事件 |
| EventDispatcherJob | 使用 SnailJob 扫描待处理事件,投递给计量、审计、报表处理器 |
| MeterEventHandler | 将业务事件转换为标准计量事件 |
| DeadLetterService | 记录多次失败事件,支持人工重放 |
| EventReplayService | 按 traceId 或 eventId 重放事件 |
pending 事件。idempotency_key 去重。processed。初级工程师重点:为什么要 Outbox?
因为“业务数据”和“计费事件”必须一致。比如挂号成功了,但计费事件因为网络问题没写到账本,账单就漏了。Outbox 的做法是先把事件和业务结果放在同一个本地事务里,保证至少不会丢,再由后台任务慢慢处理。
| 功能 | 说明 |
|---|---|
| 事件本地落库 | 所有计量、审计、报表事件先写 Outbox |
| 幂等处理 | eventType + idempotencyKey 唯一 |
| 自动重试 | 支持指数退避或固定间隔 |
| 死信队列 | 多次失败后人工处理 |
| 事件重放 | 排障后可重新执行计量 |
| 事件查询 | 按 traceId 查看事件处理状态 |
| 字段 | 说明 |
|---|---|
event_id |
全局唯一事件 ID |
event_type |
事件类型,如 CHAT_COMPLETED、MCP_TOOL_WRITE |
source_type |
openplatform / dify / mcp / card |
source_id |
源业务 ID |
trace_id |
调用链 ID |
project_id |
项目 ID |
idempotency_key |
幂等键 |
payload_json |
事件负载 |
status |
pending / processing / processed / dead |
retry_count |
重试次数 |
next_retry_at |
下次重试时间 |
last_error |
最近失败原因 |
create_time |
创建时间 |
update_time |
更新时间 |
payload_json 不能作为任意自由 JSON 使用。编码前必须定义 OutboxPayload 基类,并按 event_type + source_type 选择具体 payload schema。
| source_type | payload schema | 必填字段 |
|---|---|---|
openplatform |
OpenPlatformCallPayload |
conversationId、messageId、agentId、requestSummary、responseSummary |
dify |
DifyRunPayload |
workflowRunId、difyMessageId、usage、modelName、outputSchemaVersion |
mcp |
McpToolPayload |
toolName、hospitalId、operationType、latencyMs、resultStatus |
card |
CardActionPayload |
instanceId、actionName、cardKey、actionResult |
billing |
BillingPayload |
accountId、ledgerId、amountCredits、ledgerType |
解析规则:
event_type 决定业务语义,source_type 决定 payload 类型。payload_schema_version 应进入 payload_json 或单独字段,后续 schema 变更必须兼容旧事件。MeterEventHandler 只处理已注册 schema,未知事件进入死信,不做静默忽略。恢复机制:
pending 状态。processing,防止多节点重复处理。pending 并设置 next_retry_at。dead,由人工处理台重放。Dify Workflow 是二期流程编排核心,但生产环境不能让任何人随意改画布后立即影响线上。Workflow 版本会影响业务流程、卡片结构、MCP 工具、计费场景和审计证据。
这里采用轻量治理,不重新实现一套 Dify 发布引擎。Dify 自身负责 Workflow 的草稿、发布版本、历史版本和恢复;医梦平台只维护“平台智能体版本 -> Dify App/Workflow 已发布版本”的映射、发布前探测和配置灰度。这样既能控制线上风险,又不会把小团队拖进重型 DevOps 平台建设。
flowchart TD
Agent["ai_agent_app<br/>智能体"]
Version["ai_workflow_version<br/>平台版本映射"]
DifyApp["Dify App / Workflow"]
Release["轻量发布记录<br/>映射 / 探测 / 配置灰度"]
CardSchema["卡片 Schema 版本"]
ToolSet["MCP 工具版本"]
Pricing["计费规则版本"]
Agent --> Version
Version --> DifyApp
Version --> CardSchema
Version --> ToolSet
Version --> Pricing
Release --> Version
| 模块 | 作用 |
|---|---|
| WorkflowVersionMappingService | 维护平台智能体与 Dify 应用发布版本的映射 |
| WorkflowProbeService | 发布前探测 Dify 可用性、输出结构和关键工具是否存在 |
| WorkflowSnapshotService | 保存平台侧关键快照:Dify App ID、发布版本、卡片 schema、工具集、计费规则版本 |
| AgentConfigGrayService | 通过切换 ai_agent_app.engine_config_id 或版本映射实现按项目/科室灰度 |
| WorkflowDiffNote | 只记录人工填写的变更说明和影响范围,不做复杂自动 diff |
ai_agent_app.engine_config_id 或版本映射,灰度到指定项目、科室或设备。初级工程师重点:为什么 Dify 也要版本管理?
Dify 画布虽然不是 Java 代码,但它就是线上业务逻辑。改错一个条件分支,可能会把“咨询”走成“挂号写操作”;改错输出字段,前端卡片就渲染失败;改错工具名,HIS 调用就失败。所以 Dify 版本必须像代码一样发布、灰度、回滚。
| 功能 | 说明 |
|---|---|
| Workflow 版本映射 | agentId -> difyAppId -> difyPublishedVersion |
| 轻量审批 | 医梦技术负责人或项目负责人确认映射变更 |
| 输出结构校验 | 校验 reply/cardKey/cardData/usage |
| 工具依赖校验 | 校验 Workflow 用到的 MCP 工具是否授权 |
| 配置灰度 | 按项目、科室、设备或智能体配置灰度,不自研完整发布引擎 |
| 快速回滚 | 切回上一稳定 Dify 发布版本映射 |
| 发布审计 | 记录谁切换了映射、切换到哪个 Dify 版本、影响范围 |
医疗系统中的“用户”不等于“患者”。一个登录用户可能给自己、孩子、老人操作;医生操作患者数据也需要明确就诊上下文。
| 标识 | 含义 | 示例 |
|---|---|---|
platformUserId |
平台登录用户 | 小程序用户、医生账号 |
patientId |
医院患者主索引 | HIS 患者 ID / MPI ID |
visitId |
一次门诊或住院就诊 | 门诊流水号、住院号 |
encounterId |
诊疗接触,可兼容门诊/住院/随访 | 一次诊疗上下文 |
operatorId |
实际操作者 | 医生、护士、患者本人、家属 |
relationship |
操作者与患者关系 | 本人、父母、子女、医生、护士 |
authorizationId |
授权记录 | 患者授权或代办授权 |
flowchart TD
User["platformUserId<br/>登录用户"]
Auth["授权记录"]
Patient["patientId<br/>患者主索引"]
Visit["visitId / encounterId<br/>就诊上下文"]
AgentCall["AI 调用"]
Audit["审计记录"]
User --> Auth
Auth --> Patient
Patient --> Visit
Visit --> AgentCall
AgentCall --> Audit
Auth --> Audit
platformUserId + patientId + visitId + operatorId + authorizationId。初级工程师重点:为什么 userId 不够?
因为userId=10001只能说明是谁登录了系统,不能说明他正在为哪个患者操作、有没有授权、属于哪次就诊。医疗数据访问必须回答“谁在什么场景下,为哪个患者,基于什么授权,做了什么操作”。
| 功能 | 说明 |
|---|---|
| 就诊人选择 | 患者端调用前选择患者 |
| 代办授权 | 家属为患者操作时记录关系和授权 |
| 医护诊疗关系校验 | 医生/护士只能访问职责范围内患者 |
| 授权快照 | AI 调用时保存授权状态 |
| 最小化传参 | Dify/MCP 只接收必要患者摘要 |
| 敏感操作二次确认 | 建档、挂号、支付、写病历前确认 |
不同 AI 能力的风险不同,不能使用同一套自动化策略。风险分级决定是否允许自动回复、是否必须患者确认、是否必须医生确认、是否允许写入 HIS。
| 等级 | 示例 | 默认策略 |
|---|---|---|
| L0 信息查询 | 院内 FAQ、科室介绍、流程咨询 | 可自动回复,记录日志 |
| L1 低风险建议 | 导诊建议、报告通俗解释、就诊准备 | 自动回复,但要有来源和免责声明 |
| L2 中风险辅助 | 分诊、预问诊、病历质控建议 | 需要用户确认或医护确认 |
| L3 高风险操作 | 挂号写入、患者建档、用药风险提示、CDSS | 必须明确确认,写操作走 MCP 幂等 |
| L4 严肃医疗决策 | 处方、医嘱、诊断结论、危急值处置 | AI 只辅助,必须人工决策和签名 |
| 模块 | 如何使用风险等级 |
|---|---|
| Dify Workflow | 根据场景输出 riskLevel 和建议动作 |
| OpenPlatform | 根据风险等级决定是否允许自动返回、是否创建确认卡片 |
| Card Runtime | L2 及以上场景通过卡片确认,L3 及以上记录明确确认动作 |
| MCP Server | L3+ 写操作必须校验确认结果和幂等键 |
| 计量中心 | 高风险能力可使用不同计量项 |
| 审计中心 | L2 及以上必须保留输入摘要、输出摘要、确认人和时间 |
flowchart TD
AI["AI 生成建议或操作意图"]
Risk["风险等级判断"]
Low["L0/L1<br/>自动回复"]
Confirm["L2/L3<br/>卡片确认"]
Human["L4<br/>人工决策"]
MCP["MCP 写操作"]
Audit["审计记录"]
AI --> Risk
Risk --> Low
Risk --> Confirm
Risk --> Human
Confirm --> MCP
Low --> Audit
Confirm --> Audit
Human --> Audit
MCP --> Audit
初级工程师重点:为什么不能让 AI 自动完成所有事?
医疗系统里,AI 输出可能影响患者就医路径、用药安全和医疗责任。系统可以让 AI 提建议,但高风险动作必须有人确认,尤其是写入 HIS、影响病历、医嘱、处方、危急值处理的动作。
HIS 厂商差异是 L2/L3 最大交付风险。MCP 工具必须稳定,但每家医院的接口字段、鉴权、错误码、网络环境都可能不同。
flowchart TD
Tool["标准 MCP Tool<br/>his_create_appointment"]
Service["标准业务服务<br/>AppointmentService"]
Adapter["HospitalAdapter 接口"]
A["医院 A Adapter"]
B["医院 B Adapter"]
C["医院 C Adapter"]
Map["字段映射 / 字典映射"]
Mock["联调 Mock Server"]
Tool --> Service
Service --> Adapter
Adapter --> A
Adapter --> B
Adapter --> C
A --> Map
B --> Map
C --> Map
Service --> Mock
| 模块 | 作用 |
|---|---|
| StandardToolContract | 平台标准工具契约 |
| HospitalAdapter | 医院适配器接口 |
| HospitalAdapterConfig | 每家医院的 URL、鉴权、超时、字段映射 |
| DictionaryMappingService | 科室、医生、号别、支付状态等字典映射 |
| HisMockServer | 没有真实 HIS 时用于联调 |
| HisCapabilityRegistry | 记录某家医院支持哪些接口 |
his_get_departments、his_lock_schedule。projectId/hospitalId 选择 Adapter。初级工程师重点:为什么不能在 MCP 工具里直接写医院接口 URL?
因为一个工具会服务很多医院。直接写死 URL 会导致每接一家医院都改主流程代码。正确做法是工具保持标准,医院差异放到 Adapter 和配置里。
| 功能 | 说明 |
|---|---|
| 医院接口配置 | URL、鉴权、超时、重试、启停 |
| 字段映射 | 厂商字段和平台标准字段互转 |
| 字典映射 | 科室、号别、医生职称、支付状态 |
| 能力探测 | 判断医院是否支持锁号、建档、取消预约等 |
| Mock 联调 | 未接真实 HIS 前可模拟返回 |
| 验收用例 | 每个工具有标准输入输出和异常场景 |
线上医疗项目必须支持快速排障。用户只会说“挂号失败了”,工程上要能定位是签名、Dify、MCP、HIS、卡片、计费还是前端问题。
flowchart LR
Trace["traceId"]
Request["API 请求"]
Dify["Dify message/workflowRun"]
Card["Card instance/action"]
Tool["MCP toolCall"]
HIS["HIS request"]
Meter["Meter event"]
Ledger["Credit ledger"]
Log["应用日志"]
Trace --> Request
Trace --> Dify
Trace --> Card
Trace --> Tool
Trace --> HIS
Trace --> Meter
Trace --> Ledger
Trace --> Log
| 模块 | 作用 |
|---|---|
| TraceContext | 在 API、Dify、MCP、Card、Meter 之间传递 traceId |
| CallChainQuery | 按 traceId 查询完整调用链 |
| FailureWorkbench | 展示失败事件、死信、可重试操作 |
| ReplayService | 支持重放计量事件或重新查询 HIS 最终状态 |
| AlertService | 对超时、错误率、余额、异常峰值告警 |
初级工程师重点:为什么写操作不能随便重试?
查询失败可以重试,但写操作可能已经在 HIS 成功了,只是响应超时。如果直接重试,可能重复挂号、重复建档、重复扣费。所以写操作失败后,要先用幂等键或订单号查询最终状态。
| 功能 | 说明 |
|---|---|
| 调用链查询 | 一个 traceId 展示 API、Dify、MCP、HIS、账本 |
| 失败原因分类 | 网络、鉴权、参数、HIS 业务失败、超时、计费失败 |
| 可重试标记 | 明确哪些失败可以自动重试 |
| 人工处理台 | 死信、账本异常、HIS pending 状态处理 |
| 告警规则 | 错误率、延迟、余额、异常调用峰值 |
医疗数据要默认按敏感数据处理。日志、Dify 输入、计量事件、运营报表都不能无节制保存原文。
| 等级 | 数据 | 策略 |
|---|---|---|
| P0 公开数据 | 科室介绍、就诊流程 | 可正常记录 |
| P1 内部数据 | 系统配置、智能体配置、运营指标 | 权限控制 |
| P2 个人敏感 | 姓名、手机号、身份证、住址 | 脱敏展示、加密存储 |
| P3 医疗敏感 | 病历、诊断、检验、影像、用药 | 最小化传输、严格审计 |
| P4 高敏业务 | 支付、医保、处方、危急值 | 加密、强审计、人工确认 |
| 模块 | 合规要求 |
|---|---|
| OpenPlatform | 请求日志脱敏,不记录完整身份证、手机号、病历全文 |
| DifyAdapter | 只传必要患者摘要,避免整份病历无控制进入 Dify |
| MCP Server | 工具输入输出记录摘要,不默认保存完整 HIS 响应 |
| Card Runtime | 卡片展示按权限脱敏,历史快照避免保存过多敏感字段;建档卡片不保存 PII 预填,舌诊/面诊卡片不保存原图引用和可复原特征 |
| Metering | 计量事件只保存计费用字段,不保存完整医疗内容 |
| Billing | 账单展示能力值和场景,不展示患者隐私 |
| OperationReport | 运营报告使用聚合数据,不展示个人明细 |
projectId/agentId/scenario/quantity/credits/sourceId 等账务字段。初级工程师重点:为什么不能把完整请求和响应都打日志?
医疗请求里可能有身份证、手机号、病历、诊断、检查结果。完整日志一旦泄漏就是严重合规事故。排障需要的是 traceId、错误码、摘要和必要上下文,不是所有原始隐私数据。
| 功能 | 说明 |
|---|---|
| 日志脱敏工具 | 手机号、身份证、姓名、地址、病历字段脱敏 |
| 字段级加密 | 密钥、患者身份、支付信息加密 |
| Dify 输入裁剪 | 将完整病历变成任务所需摘要 |
| 审计留痕 | 谁查看了敏感数据、为什么查看 |
| 数据出域开关 | 院内部署项目可限制 Dify/模型调用边界 |
| 报表聚合 | 运营报告默认不展示患者级明细 |
当前工程已有 emoon-knowledge-api,Dify 也有知识库节点。两者不能互相替代,需要明确边界。
| 能力 | emoon-knowledge |
Dify 知识库 / Workflow |
|---|---|---|
| 知识资产管理 | 主责,管理文档、标签、适用医院、版本、审核状态 | 引用已发布知识 |
| 提示词模板 | 主责,沉淀医疗场景 prompt、变量、版本 | Workflow 节点使用 |
| RAG 检索 | 可作为平台统一 RAG Service | 可使用 Dify 内置节点快速编排 |
| 质控后处理 | 主责,如病历质控、报告结构化校验 | 调用平台质控服务或接收结果 |
| 工作流编排 | 不负责 | 主责 |
| 审计和发布治理 | 主责,知识版本、引用来源、审核人 | 保存 workflow 运行引用 |
推荐设计:
emoon-knowledge,包括院内制度、指南、FAQ、报告模板、质控规则。knowledgeVersion 和引用来源的结果。PromptTemplateService 管理提示词变量和版本,Dify 发布时记录使用的模板版本。报告解读、病历生成、质控建议等输出,必须经过平台后处理校验,不只依赖 Dify 文本。
flowchart LR
Knowledge["emoon-knowledge<br/>知识资产 / Prompt / 质控"]
Publish["知识发布版本<br/>审核 / 生效 / 回滚"]
DifyKB["Dify Knowledge<br/>流程内检索"]
DifyWF["Dify Workflow"]
RAGTool["平台 RAG Tool<br/>带引用和版本"]
Quality["质控后处理"]
Open["OpenPlatform"]
Knowledge --> Publish
Publish --> DifyKB
Publish --> RAGTool
DifyKB --> DifyWF
DifyWF --> RAGTool
DifyWF --> Open
Open --> Quality
初级工程师重点:为什么知识库不能只放 Dify?
医疗知识需要审核、版本、适用医院和引用追溯。Dify 适合编排和快速检索,但合同审计、医疗责任和知识发布治理必须由平台掌握,否则无法回答“这次建议引用的是哪版指南,谁审核过,是否适用于这家医院”。
SSE 是二期主入口的重要形态,但它不是普通 HTTP 短请求。必须设计连接生命周期、心跳、断线恢复和资源清理。
| 阶段 | 平台动作 | 失败处理 |
|---|---|---|
| 建连 | 校验签名、项目权限、并发额度,创建 traceId | 失败直接返回错误,不创建会话 |
| 发送请求到 Dify | 记录外部 message/workflow 标识 | 超时触发 fallback |
| 流式转发 | 解析 Dify event,转换为平台 SSE event | 非法事件忽略并记录摘要 |
| 心跳 | 平台定期发送 heartbeat,避免网关空闲断开 | 客户端超时后可查询会话 |
| 完成 | 写会话、usage、卡片、Outbox 事件 | 卡片失败不影响文本保存 |
| 断开 | 标记连接关闭,清理内存对象 | 根据 Dify 最终状态决定 partial |
SSE 实现规则:
conversationId/messageId/traceId 映射,客户端断线后可以查询最终结果。client_cancelled,Dify 是否可取消按引擎能力处理。SseEmitter,需要维护活跃连接注册表,定时发送 heartbeat,并在 onCompletion/onTimeout/onError 清理连接。缓存只服务性能和降级,不能作为资金、授权、幂等的唯一依据。
| 缓存对象 | 建议 TTL | 失效策略 | 注意事项 |
|---|---|---|---|
| 项目公钥和状态 | 5-10 分钟 | 管理后台变更后主动失效 | 签名失败时可回源确认 |
| 智能体运行配置 | 1-5 分钟 | 发布后主动失效 | Dify 密钥不明文放 Redis |
| 卡片定义 | 5-30 分钟 | 卡片发布后失效 | 卡片实例使用快照,不受缓存影响 |
| 基础科室/医生 | 10 分钟到 1 天 | HIS 同步任务刷新 | 展示可降级,写操作不可只信缓存 |
| 定价规则 | 5-10 分钟 | 规则发布后失效 | 事件内必须保存规则快照 |
| 额度概览 | 30-60 秒 | 账本变更后刷新 | 仅展示,不作为扣费依据 |
合理不限量必须参数化,不能只靠人工感觉判断。建议在 ai_quota_policy 中配置以下监控项:
| 参数 | 示例默认值 | 作用 |
|---|---|---|
daily_usage_multiplier |
合同隐含日均量的 2 倍 | 标记异常峰值 |
single_call_cost_limit |
单次内部成本超过指定金额 | 标记高成本调用 |
scenario_share_limit |
单场景占比超过 60% | 识别异常集中使用 |
monthly_cost_limit |
月内部成本上限 | 触发运营复核 |
approval_required_after_alert |
true | 告警后继续超阈值需审批 |
Redis 不可用时:
门诊/住院场景会涉及报告、图片、语音和附件。文件链路必须独立于对话文本治理。
flowchart LR
Client["客户端上传"]
FileAPI["文件服务<br/>鉴权 / 类型 / 大小"]
Object["对象存储<br/>加密保存"]
Scan["安全扫描 / 病毒扫描"]
Extract["解析服务<br/>OCR / ASR / PDF"]
Agent["Agent 调用<br/>只传 fileRef/摘要"]
Audit["文件访问审计"]
Client --> FileAPI
FileAPI --> Object
FileAPI --> Scan
Object --> Extract
Extract --> Agent
Object --> Audit
实现规则:
fileId/fileRef。| 增强方向 | 影响二期 | 影响三期 |
|---|---|---|
| 主数据边界 | API 鉴权、智能体授权、HIS Adapter 选择 | 合同、额度、账单主粒度 |
| 事件可靠性 | 会话、卡片、MCP 事件不丢 | 计量和账本可靠 |
| Dify 版本治理 | Workflow 发布可控 | 计费规则和场景版本可追溯 |
| 患者身份授权 | 卡片动作、MCP 工具合法 | 审计和风控有依据 |
| 医疗安全分级 | 确定哪些动作需确认 | 高风险能力定价和审批 |
| 多医院 Adapter | MCP 工具可复用 | L2/L3 多院落地 |
| 可观测性 | 线上问题可定位 | 账本和事件可重放 |
| 数据合规 | 日志、Dify、MCP 不越界 | 账单和报表不泄露隐私 |
| 知识治理 | Dify 输出可追溯 | 高价值能力可定价和审计 |
| SSE 与文件治理 | 流式和多模态可上线 | partial 计量和文件类计量可信 |
| 设备治理 | 统一入口客户端、设备事件、设备场景可控 | 设备授权、运维服务和设备维度分摊 |
医院确认版方案把门诊设备入口提升为战略控制点。生产级增强必须补齐设备治理,否则门诊总包会退化成现场定制项目。
| 能力 | 生产要求 | 验收口径 |
|---|---|---|
| 设备身份 | 每台设备有全局唯一 deviceId、设备密钥、医院/科室/位置绑定 |
未注册设备不能进入核心业务闭环 |
| 远程配置 | UI 模板、默认智能体、工具权限、版本灰度由后台下发 | 现场切换场景不需要重新发版 |
| 心跳监控 | 设备在线、离线、异常、维护状态可查询和告警 | P0 设备在线率进入运营报告 |
| 版本治理 | 统一入口客户端有版本、灰度、回滚和升级记录 | 线上问题能定位到客户端版本 |
| 厂商责任 | A/B/C/D 准入等级、接口清单、联调记录、验收记录留痕 | C/D 设备不承诺核心业务闭环 |
| 设备计量 | 设备授权、设备运维、设备事件和业务调用分开计量 | 设备费不混入能力值扣减流水 |
设备运行状态不等于业务成功。导诊屏在线、机器人在线、自助机在线只能说明入口可用;分诊完成、挂号成功、签到确认、支付完成、病历确认、护理任务关闭才是可计量、可验收的业务事实。
本章覆盖测试、部署、迁移、安全、监控和灾备。它们不直接产生业务功能,但决定系统能不能稳定上线。
| 测试层级 | 重点 | Mock 方式 |
|---|---|---|
| 单元测试 | Pricing、Quota、Credit、状态机、脱敏工具 | 纯内存对象 |
| Service 集成测试 | 账本事务、Outbox、卡片动作、MCP Adapter | H2/Testcontainers 或测试库 |
| Dify 集成测试 | Dify 请求转换、SSE 解析、usage 解析 | Dify Mock Server |
| HIS 集成测试 | 科室、医生、锁号、挂号、建档 | HIS Mock Server |
| 设备集成测试 | 设备注册、心跳、场景下发、SDK 错误映射 | Device Mock / SDK Mock |
| 端侧兼容测试 | 导诊屏、自助机、机器人、诊室屏、医生站插件 | 浏览器矩阵 + Android/Harmony/Electron Mock |
| 端到端测试 | 对话 → 卡片 → MCP → 计量 → 账本 | 测试项目 + Mock Dify/HIS |
| 账务回归测试 | 冻结、结算、释放、冲正、超量 | 固定账本用例 |
关键测试场景:
二三期会新增大量表,不能依赖手工 SQL 随意执行。
建议策略:
| 项 | 设计 |
|---|---|
| 迁移工具 | 优先 Flyway 或 Liquibase;若暂不引入,也要统一脚本编号 |
| 脚本命名 | V20260523_001__create_ai_meter_tables.sql |
| 可重复脚本 | 字典、默认配置、测试种子数据独立 |
| 回滚策略 | 生产不依赖自动 drop,使用补偿迁移 |
| 审核 | 所有表结构变更先评审索引、字段类型、数据量 |
迁移顺序:
flowchart TD
LB["Nginx / 网关"]
Admin["emoon-admin<br/>管理后台"]
Open["emoon-openplatform<br/>对外 API / SSE"]
MCP["MCP Tool Server<br/>可先同进程,后独立"]
Dify["Dify Platform"]
MySQL["MySQL 主库/从库"]
Redis["Redis / Redisson"]
Snail["SnailJob Server"]
HIS["医院内网 HIS/EMR/LIS/PACS"]
LB --> Admin
LB --> Open
Open --> Dify
Dify --> MCP
Open --> MCP
MCP --> HIS
Admin --> MySQL
Open --> MySQL
MCP --> MySQL
Open --> Redis
MCP --> Redis
Snail --> MySQL
部署决策:
| 组件 | MVP | 规模化 |
|---|---|---|
| MCP Tool Server | 可嵌入 emoon-openplatform 或 emoon-mcp |
独立服务,便于内网部署和隔离 |
| Dify | 院内或专属云 | 按医院安全要求部署 |
| MySQL | 单主 + 备份 | 主从 / 高可用 |
| Redis | 单实例或哨兵 | 集群或哨兵 |
| SnailJob | 已有基础设施 | 用于 Outbox、账单、巡检、报表任务 |
当前存在旧 /chat/apisse 和新 /api/v1/agent/chat。
| 路径 | 状态 | 策略 |
|---|---|---|
/chat/apisse |
legacy | 只维护兼容,不新增能力 |
/api/v1/agent/chat |
主链路 | 所有新能力进入 v1 |
/api/v1/card/** |
新增 | 卡片动作和状态查询 |
/api/v1/billing/** |
三期新增 | 余额、账单、流水查询 |
兼容迁移:
/api/v1。/chat/apisse 增加访问统计,确认是否仍有调用。当前 MD5 签名可先兼容,但应进入升级计划。
| 能力 | 设计 |
|---|---|
| 请求签名 | 新接口使用 HMAC-SHA256;旧 MD5 兼容期保留 |
| 密钥存储 | API Key、Dify Secret、HIS Secret 加密存储 |
| 加密算法 | 对称加密建议 AES-256-GCM 或国密 SM4-GCM |
| 密钥轮换 | 项目支持多密钥并行,便于无停机轮换 |
| 传输安全 | 生产强制 HTTPS / 内网专线 |
| 日志安全 | 不打印密钥、签名原文、完整敏感 payload |
初级工程师重点:为什么 MD5 要升级?
MD5 已不适合做安全签名。即使短期为了兼容保留,也不能作为新接口长期方案。HMAC-SHA256 能证明请求确实由持有密钥的一方发出,并减少伪造风险。
| 数据 | 建议保留 | 说明 |
|---|---|---|
| 计费账本 | 按财务合规长期保留 | 只追加,支持审计 |
| 账单 | 长期保留 | 合同和对账依据 |
| 原始调用日志 | 6-12 个月热数据,之后归档 | 排障使用 |
| 会话内容 | 按合同和医院要求 | 默认脱敏和最小化 |
| 卡片实例 | 保留业务结果和必要快照 | 避免保存过多医疗明细 |
| 敏感数据访问审计 | 长期保留 | 满足等保和个人信息保护要求 |
删除和归档必须走任务,不允许人工直接删生产表。
挂号、锁号、支付、床位预约都是高并发写操作。
| 场景 | 锁粒度 | 说明 |
|---|---|---|
| 锁号 | hospitalId + scheduleId + slotId |
防止同一号源重复锁定 |
| 床位预约 | hospitalId + bedId |
防止重复占床 |
| 支付回写 | orderId |
防止重复回写 |
| 卡片动作 | instanceId + actionName |
防止重复点击 |
| 账本扣费 | accountId + idempotencyKey |
防止重复扣费 |
锁使用 Redis/Redisson,写操作还必须有数据库唯一约束或幂等记录兜底。
Redis 锁失败或 Redis 不可用时的降级策略:
| 场景 | 降级策略 |
|---|---|
| 查询类工具 | 允许继续访问 HIS 或本地缓存,但记录缓存降级告警 |
| 卡片重复点击 | 依赖数据库幂等表拦截,返回处理中或首次结果 |
| 锁号 / 建档 / 挂号 | 若无法确认互斥条件,优先拒绝或进入人工确认 |
| 账本扣费 | 继续使用数据库事务、唯一约束和乐观锁,不依赖 Redis |
| 限流 | 降级为本机限流并告警,必要时按项目临时关闭高成本能力 |
初级工程师重点:Redis 是加速器,不是最终事实。
医疗写操作和账本扣费必须以数据库事务、唯一索引、乐观锁为最终保障。Redis 丢数据、重启、网络分区时,系统仍要能防止重复挂号和重复扣费。
初始上线建议定义最低基准,后续按项目规模调整。
| 指标 | MVP 建议 |
|---|---|
| 普通 API P95 | < 500ms,不含 Dify/HIS 外部耗时 |
| Dify 对话首 token | < 3s,按模型和网络调整 |
| SSE 并发 | 按医院试点规模压测 |
| MCP 查询类工具 P95 | < 1s,HIS 慢接口需缓存 |
| MCP 写操作超时 | 3-10s,按厂商接口确定 |
| 计量事件处理延迟 | < 1 分钟 |
| 月账单生成 | 可离线任务,允许分钟级 |
| 对象 | 策略 |
|---|---|
| MySQL | 每日全量 + 增量 binlog,定期恢复演练 |
| Redis | 开启持久化,关键幂等状态仍以数据库为准 |
| Dify 配置 | 定期导出 Workflow 配置和版本映射 |
| 账本数据 | 重点备份,不允许物理删除 |
| 对象存储 | 医疗附件按医院要求备份和加密 |
| 维度 | 指标 |
|---|---|
| API | QPS、错误率、P95/P99、签名失败率 |
| SSE | 当前连接数、断连率、平均持续时长 |
| Dify | 成功率、超时率、P99、workflowRun 失败率 |
| MCP | 工具调用量、成功率、P99、HIS 错误码分布 |
| 卡片 | 展示量、点击量、动作成功率、过期率 |
| 计量 | Outbox backlog、处理延迟、死信数量 |
| 账本 | 扣费失败、冲正次数、账户余额异常 |
| 安全 | 敏感访问、越权、异常调用峰值 |
工程路线要服务 L2/L3 项目交付。业务文档中的 AI 门诊、AI 住院都建议按“试点 -> 扩展 -> 闭环 -> 运营”推进,技术上对应以下里程碑。
| 业务阶段 | 门诊交付重点 | 住院交付重点 | 中台必须具备 |
|---|---|---|---|
| 阶段 0:两周边界锁定 | 存量设备盘点、P0/P1/P2 设备清单、设备准入标准 | 迪耐克/鸿蒙病房接口摸底、责任边界确认 | 统一入口客户端 PRD、DeviceProfile、设备准入分级、主动签到 POC 方案 |
| 阶段 1:1-2 个月门诊 MVP | 导诊屏、自助机、机器人、叫号屏、诊室屏接入;导诊/分诊/挂号/签到基础闭环 | 住院接口只做摸底和最小互通准备 | AgentEngine、Dify、基础 MCP、Card Runtime、Device Registry、Scene Orchestrator、基础计量 |
| 阶段 2:2-4 个月打穿闭环 | 预问诊、科室推荐、号源推荐、签到叫号、诊间语音病历、四诊仪、诊后小结/随访 | 通过迪耐克/鸿蒙病房体系接收护理白板、床头屏的标准业务事件和 IoMT 标准化数据,形成护理任务 AI 闭环 | MCP 写操作、设备事件、医生/护士确认、IoMT Event Hub、Outbox、设备维度计量 |
| 阶段 3:4-6 个月标杆运营 | 门诊 P0/P1 设备统一运营、鸿蒙主动签到上线、运营看板、供应商生态 | 住院 AI 大脑层稳定互通,IoMT 预警解释与护理闭环 | 设备授权、合理不限量、运营报告、设备 SLA、区域/多院扩展准备 |
因此三期工程不能只做账本。它必须同时为项目验收提供证据:功能是否上线、场景是否跑通、医护是否确认、运营指标是否改善、合同范围内的用量和成本是否可解释。
目标:先让每次调用、每个设备入口和每个核心业务事件可计量、可追溯、可避免重复扣费。
交付:
ai_meter_event、ai_credit_account、ai_credit_ledger 基础表。目标:让能力值包可生产使用。
交付:
目标:支撑客户对账和医院内部科室分摊。
交付:
目标:支撑综合运营服务费和 L2/L3 长期运营。
交付:
以下拆分适合初级工程师领取,每个任务都有清晰边界。
| 任务 | 依赖 | 目标 | 验收标准 |
|---|---|---|---|
| 项目鉴权上下文改造 | 无 | 请求后能拿到 projectId/tenantId/agentId |
所有对话接口日志包含 traceId 和 projectId |
| Dify 引擎适配器 | 项目鉴权上下文 | Dify 接入 AgentEngine |
同步和流式对话能返回统一 AgentResponse |
| 卡片实例创建 | Dify 引擎适配器返回 cardKey/cardData |
Dify 返回卡片时落库 | ai_card_instance 有输入数据和快照 |
| 卡片动作接口 | 卡片实例创建 | 前端点击后状态流转 | 能从 active 变为 completed/failed |
| DeviceRegistry MVP | 项目鉴权上下文 | 注册导诊屏、自助机、机器人、诊室屏 | 设备有 hospitalId、location、capabilities、heartbeat |
| SceneOrchestrator MVP | DeviceRegistry MVP、智能体配置 | 按设备返回 UI 模板和 Agent 绑定 | 同一设备切换场景无需改前端代码 |
| TerminalRuntime MVP | DeviceRegistry MVP、SceneOrchestrator MVP | P0 设备统一加载入口 | 导诊屏/自助机/机器人/诊室屏至少跑通一条业务链路 |
| DeviceAdapter 基础协议 | TerminalRuntime MVP | 标准化语音、扫码、打印、导航;住院侧只接收 IoMT 标准事件 | 设备 SDK 错误和病房标准事件错误能映射为平台错误码 |
| MCP 查询工具 | 项目鉴权上下文 | 科室、医生、排班查询 | 返回统一结构,失败有错误码 |
| MCP 写工具 | 卡片动作接口、MCP 查询工具 | 锁号、建档、挂号 | 写操作具备幂等键和动作日志 |
| Outbox 事件表 | 项目鉴权上下文 | 业务事务内写事件 | 业务成功后一定有 pending 事件 |
| BillingEpisodeService | Outbox 事件表、计量上下文 | 管理 episode 状态和事件归并 | synthetic、MCP、Card 子事件不会重复扣客户余额 |
| 计量事件表 | Outbox 事件表 | 调用完成后写事件 | 重复 idempotencyKey 不重复入库 |
| 能力值账户 | 计量事件表 | 支持 grant、settle | 账户余额和账本流水一致 |
| 冻结结算 | 能力值账户 | 支持 freeze/release/settle | 高成本任务失败能释放额度 |
| 月账单汇总 | 能力值账户、冻结结算 | 按项目生成账单 | 账单金额等于账本汇总 |
| 运营看板接口 | 计量事件表、月账单汇总 | 输出项目用量和余额 | 支持按项目、科室、智能体筛选 |
| AudioStreamGateway | 项目鉴权上下文、ASR 服务 | 接入诊间音频流 | 能按 traceId 输出转写文本和 ASR 分钟事件 |
| IoMTEventIngestion | 项目/病区/床位映射 | 接收护理和 IoMT 标准预警事件 | 标准事件可进入 Outbox 和护理闭环 |
| ServiceFindPatient POC | DeviceEventIngestion、叫号/签到工具 | 主动签到服务找人闭环 | 患者确认后签到,叫号屏/小程序/医生站状态同步 |
| OutboundFollowupService | 随访计划、语音网关 | 调度 AI 外呼随访 | 通话状态、分钟数、风险分层和人工升级可追踪 |
可行。现有工程已有多租户、项目、公私钥鉴权、MyBatis-Plus、Redis、定时任务、审计日志、AI 调用入口和用量日志,三期可以在现有基础上增量建设。医院确认版新增的统一入口客户端、Device Registry、Device Adapter、Scene Orchestrator 属于新增产品能力,但可以先按门诊 P0 设备做最小闭环,不需要第一期覆盖所有终端。
关键工程难点不是 CRUD,而是账本一致性、幂等、异步事件可靠性、Dify/MCP/Card/Device 多来源事件归一化,以及设备厂商 SDK 差异、现场网络和版本治理。
可行。公司附件中的商业模式已经明确能力值包、合理不限量服务包、项目实施费和综合运营服务费。医院确认版进一步增加设备集成、统一入口客户端授权、设备运维、鸿蒙 POC、机器人场景服务等收费项,三期设计与该商业口径一致,能支撑 L1/L2/L3,其中门诊总包作为 L2 增强子类型落地。
| 风险 | 控制 |
|---|---|
| 计量规则频繁变化 | 规则版本化,账单按事件发生时规则计算 |
| Dify usage 不稳定或缺失 | 以平台事件为主,Dify usage 为补充 |
| 流式响应中断 | 记录 partial / failed,按策略释放或部分结算 |
| 重试重复扣费 | 全链路 idempotency key |
| 合理不限量成本失控 | 内部计量、峰值预警、合同边界和运营复核 |
| 医疗关键链路被计费中断 | 软拦截、审批、事后结算,不做简单硬停 |
| 科室分摊争议 | 保留原始事件、卡片动作、智能体、用户和时间维度 |
| 设备范围爆炸 | 第一阶段只做门诊 P0 设备,P1/P2 进入准入清单但不承诺闭环 |
| 厂商接口不开放 | 按 A/B/C/D 准入分级,不开放接口的设备只做展示或不进入核心闭环 |
| 住院硬件责任被转嫁 | 合同和方案中明确医梦做 AI 大脑层,床头屏/护理白板硬件由设备方负责 |
| 鸿蒙能力不成熟 | 主动签到 POC 保留 BLE、NFC、二维码、小程序位置授权兜底 |
原文中的大段 Java Controller、Service、SQL、Docker 示例不适合放在主技术方案中。后续建议拆为:
| 文档 | 内容 |
|---|---|
| 本文档 | 架构、职责、链路、数据模型、三期方案 |
docs/ai-platform-implementation-guide.md |
已实现内容和联调方式 |
docs/ai-platform-api-contract.md |
对外接口契约 |
docs/ai-platform-billing-design.md |
三期计费账本详细设计,如后续需要可单独拆出 |
docs/ai-terminal-runtime-design.md |
统一入口客户端、设备能力协议、UI 模板和端侧 Bridge |
docs/ai-device-registry-design.md |
设备注册、准入分级、场景绑定、心跳和远程运维 |
| SQL 迁移脚本 | 最终表结构和初始化数据 |
二期 MVP 最小可行路径:
| 项目 | 最小要求 |
|---|---|
| 主入口 | /api/v1/agent/chat 完成项目鉴权、traceId、会话写入 |
| 引擎 | DifyAgentEngine 接入统一 AgentEngine,支持 blocking 和 SSE |
| 设备 | ai_device_registry 支持 P0 设备注册、心跳、场景绑定 |
| 统一入口 | 门诊导诊屏、自助机、机器人、诊室屏可通过同一协议加载场景 |
| 卡片 | Dify 返回 cardKey/cardData 后创建 ai_card_instance |
| 卡片动作 | CardActionService 完成状态机、幂等、动作日志 |
| MCP | 至少打通科室、医生、排班查询和锁号/挂号 Mock 写工具 |
| 计量基础 | Outbox + ai_meter_event 写入,重复幂等键不重复计量 |
| 验收链路 | 对话 -> Dify -> 卡片 -> 卡片动作 -> MCP Mock -> Outbox -> 计量事件 |
| 门诊 P0 链路 | 设备启动 -> 场景加载 -> 导诊/挂号/签到 -> 卡片确认 -> HIS Mock -> 计量事件 |
| 术语 | 含义 |
|---|---|
| OpenPlatform | 医梦 AI 对外开放平台,统一鉴权、会话、卡片、审计和计量入口 |
| Dify Workflow | Dify 中配置的智能体流程画布,负责对话和流程编排 |
| MCP Tool Server | 对 Dify 和平台暴露的院内工具服务,封装 HIS/EMR/LIS/PACS |
| Terminal Runtime | 统一入口客户端,优先部署在门诊屏幕、自助机、机器人、医生站插件等终端上;住院侧只做 AI 嵌入 |
| Device Registry | 设备注册中心,管理设备身份、位置、能力、状态、版本和智能体绑定 |
| Device Adapter | 设备适配层,把厂商 SDK/API 收敛为医梦标准设备能力协议 |
| Scene Orchestrator | 场景编排器,根据设备、位置、用户和业务状态加载 UI、智能体和工具权限 |
| IoMT Event Hub | 设备事件中心,接收迪耐克/鸿蒙病房网关标准事件、护理预警和服务找人事件 |
| HIS Adapter | 每家医院系统的接口适配层,负责厂商字段、鉴权、错误码转换 |
| Card Runtime | 卡片定义、实例、动作、状态机和动作日志的后端运行时 |
| AgentEngine | 平台统一智能体引擎接口,支持 Dify、DirectLLM、Mock |
AiAgent |
设计态/产品态智能体,偏知识、目标、流程和 KPI |
AiAgentApp |
运行态智能体,对外暴露 agentId,绑定项目和引擎配置 |
| 能力值 credits | 面向客户的商业计量单位,不等同于 token |
| 计量事件 | 从调用、卡片、MCP、文件、语音等来源产生的标准用量事实 |
| 能力值账本 | 项目账户的 grant/freeze/settle/release/reverse/expire 资金事实 |
| Outbox | 与业务事务同库落地的待处理事件表,用于可靠异步处理 |
| 幂等键 | 防止重复提交、重复写 HIS、重复扣费的业务唯一键 |
| partial | 流式调用或流程中断后的部分完成状态 |
| 合理不限量 | 客户侧不按量扣余额,但平台仍做内部计量、成本和异常复核 |
| 服务找人 | 根据患者身份、位置、预约、叫号等上下文,主动推送签到、提醒、路线等服务 |
以下决策建议后续拆成独立 ADR,便于团队评审和长期维护。
| ADR | 决策 | 建议路径 | 状态 |
|---|---|---|---|
| ADR-001 | 二期主链路统一使用 AgentEngine,旧 EngineAdapter 标记 legacy |
docs/adr/ADR-001-agent-engine-unification.md |
建议采纳 |
| ADR-002 | OpenPlatform 掌握账本、审计、卡片状态,Dify 只做流程编排 | docs/adr/ADR-002-openplatform-owns-facts.md |
建议采纳 |
| ADR-003 | MCP Tool Server 作为 HIS/EMR/LIS/PACS 唯一工具出口 | docs/adr/ADR-003-mcp-tool-server-boundary.md |
建议采纳 |
| ADR-004 | 卡片动作结果默认写入平台上下文,下一轮通过 Dify inputs 传回 |
docs/adr/ADR-004-card-action-result-to-dify.md |
建议采纳 |
| ADR-005 | 三期计费主粒度为项目/医院客户,科室和用户只做分摊统计 | docs/adr/ADR-005-project-level-billing-grain.md |
已确认 |
| ADR-006 | 合同签署时预付能力值包,余额不足采用软拦截和审批策略 | docs/adr/ADR-006-prepaid-credit-package.md |
已确认 |
| ADR-007 | ai_usage_log 不作为财务账本,新增 ai_meter_event + ai_credit_ledger |
docs/adr/ADR-007-meter-event-credit-ledger.md |
建议采纳 |
| ADR-008 | 业务事件通过 Outbox 进入计量处理,避免业务成功但漏计费 | docs/adr/ADR-008-outbox-for-metering.md |
建议采纳 |
| ADR-009 | 医疗知识权威来源放在 emoon-knowledge,Dify 引用发布版本 |
docs/adr/ADR-009-knowledge-governance-boundary.md |
建议采纳 |
| ADR-010 | 账户初版只做项目主账户真实扣费,科室预算为软分摊 | docs/adr/ADR-010-credit-account-hierarchy.md |
建议采纳 |
| ADR-011 | 门诊 P0 设备必须接入统一入口客户端或标准设备协议 | docs/adr/ADR-011-terminal-runtime-device-entry.md |
建议采纳 |
| ADR-012 | 住院侧采用 AI 大脑层互通,不做硬件总包 | docs/adr/ADR-012-inpatient-ai-brain-boundary.md |
建议采纳 |
| ADR-013 | 鸿蒙协同先做主动签到 POC,并保留多技术兜底 | docs/adr/ADR-013-harmony-service-find-patient-poc.md |
建议采纳 |
ai_usage_log 保留为原始日志,新增 ai_meter_event + ai_credit_ledger 做商业账本。本章用于公司内部技术培训和初级工程师快速理解。阅读顺序建议:先看全局分层,再看主调用链,再看卡片、MCP、计量、Outbox、数据安全和交付路线。
读图要点:
读图要点:
traceId,否则线上排障会断链。读图要点:
CardActionService 状态校验。读图要点:
读图要点:
billingEpisode 是把原始调用、synthetic message、卡片动作、MCP 成本归并成业务计费单元的关键。ai_credit_ledger 汇总,不能从 ai_usage_log 汇总。读图要点:
读图要点:
读图要点: