AI中台工程约束.md 49 KB


doc_id: STD-202605-001 feature_id: type: standard title: 医梦 AI 中台工程约束 status: approved owner: 医梦研发团队 created_at: 2026-05-31 updated_at: 2026-05-31 reviewers: [] related_docs:

  • ODS-202606-001 related_modules:
  • emoon-openplatform
  • emoon-ai-agent
  • emoon-ai-card
  • emoon-ai-mcp
  • emoon-ai-device tags:
  • 工程约束
  • 模块边界
  • 架构红线 ---

医梦 AI 中台工程约束

项目 内容
文档定位 工程结构、模块边界、依赖规则、接口归属、调用方向约束
当前章节 Maven 工程依赖 + Controller/Service 调用方向 + 接口→模块映射
适用范围 现有后端工程、二期 AI Agent / Card / MCP / Device / File、三期计量 / 账务 / 运营
约束目标 高内聚、低耦合、可演进、可测试、可独立部署
版本 v2.1
更新时间 2026-05-31
变更说明 补充统一入口客户端落位:后端能力仍归 AI 中台模块,前端/移动端另起 emoon-terminal-client;明确 AgentRouter、TaskStateService、TongueDiagnosisAdapter、HisMockAdapter 的模块归属;修正 Card 动作不能直连 MCP 的调用方向

1. Maven 工程依赖规范约束

1.1 结论

当前阶段不建议优先微服务化。医梦 AI 中台仍处于能力快速建设期,团队规模约 3 名后端开发,直接拆微服务会过早引入服务治理、部署、链路追踪、分布式事务、接口版本管理和运维成本。

更合理的方向是:

先做模块化单体,再保留未来微服务拆分边界。

也就是说,短期仍然保持一个 Maven 多模块工程和少量启动应用,但必须先把 API 契约、领域实现、入口适配、基础设施、第三方系统适配分开。后续如果某个模块需要独立部署,只需要把已经稳定的 Maven 模块搬成服务,而不是重新拆业务逻辑。

本章的核心约束是:

入口层只负责编排入口,不沉淀业务状态。
API 模块只定义契约,不包含实现和重依赖。
领域实现模块只处理自己的业务闭环,不跨模块操作数据表。
计量、账务、合同、运营统计独立成模块,不混入 Agent 调用链。
MCP 只负责工具协议和治理,不承载所有院内系统适配细节。

本规约的工程取舍基于公开可验证案例做裁剪:东软类智慧医院平台证明“统一入口集成子系统”方向可行,但医梦只做 AI 入口层;华为/医惠类智慧病房证明病房物联网接入是重资产平台能力,因此住院设备只做事件映射;Dify 官方已有 Workflow 版本能力,因此后端只做版本映射和输出治理;科大讯飞类医疗 AI 产品强调嵌入医生流程,因此高风险动作必须通过卡片、工具审计和人工确认。以上案例用于约束边界,不作为照搬大厂平台规模的理由。

1.2 当前工程基线

现有工程大体可以分为以下几层:

层级 当前模块 当前职责 状态
启动入口 emoon-admin 管理后台启动模块 ✅ 合理
开放入口 emoon-openplatform 开放平台接口、签名鉴权、SSE ✅ 已重构:8 个 Mapper 清零,全改用 API Service;旧 ApiSseController 已降级
基础设施 emoon-infra/emoon-common-* Web、MyBatis、Redis、OSS 等公共能力 ✅ 稳定
API 契约 emoon-infra/emoon-modules-api/* 系统、知识库、AI Agent 等 API 契约 ⚠️ DO 类仍在 API 模块(47 条,RuoYi 框架基因),Mapper/ServiceImpl/EngineImpl 已全部迁出
领域实现 emoon-infra/emoon-modules/* 系统、知识库、聊天、AI 等业务实现 ✅ Mapper+ServiceImpl 已全部在实现模块,领域边界逐渐清晰
扩展服务 emoon-extend/* 监控、迁移、文件下载、舌诊等 ✅ 未变

当前最需要收口的不是模块数量,而是依赖方向。

现状风险:

风险 典型表现 后果
API 模块过重 *-api 中出现 Mapper、ServiceImpl、EngineImpl、第三方 SDK 调用方为了一个 DTO 被迫引入实现依赖
入口层过重 openplatform 直接调用 Mapper、EngineFactory、业务表 鉴权、会话、计量、账务散落在入口层
AI 领域过度集中 emoon-mcp-api 同时包含 Agent、Card、MCP、会话、活动等概念 后续二期/三期继续堆功能会形成新巨石
计费逻辑未独立 用量、能力值、合同、账单没有独立模块 无法支撑真实合同和线上对账
院内适配边界不清 MCP 工具和 HIS/EMR/LIS/PACS 适配容易混在一起 工具治理、院内系统集成和业务编排互相污染

1.3 目标模块分层

推荐采用以下 Maven 分层。该结构不要求一次性全部改完,但新功能必须按这个方向落位。

emoon-backend
├── emoon-admin                         # 管理后台启动入口
├── emoon-openplatform                  # 开放平台入口适配
├── emoon-infra
│   ├── emoon-common                    # 通用基础设施
│   ├── emoon-modules-api               # 领域 API 契约
│   │   ├── emoon-system-api
│   │   ├── emoon-chat-api
│   │   ├── emoon-knowledge-api
│   │   └── emoon-ai-api                # 建议新增 AI API 聚合父模块
│   │       ├── emoon-ai-agent-api
│   │       ├── emoon-ai-card-api
│   │       ├── emoon-ai-mcp-api
│   │       ├── emoon-ai-device-api      # 🆕 设备注册中心 API
│   │       ├── emoon-ai-file-api        # 🆕 文件服务 API
│   │       ├── emoon-ai-meter-api
│   │       ├── emoon-ai-billing-api
│   │       ├── emoon-ai-contract-api
│   │       └── emoon-ai-operation-api
│   └── emoon-modules                   # 领域实现
│       ├── emoon-system
│       ├── emoon-chat
│       ├── emoon-knowledge
│       └── emoon-ai                    # 建议新增 AI 实现聚合父模块
│           ├── emoon-ai-agent
│           ├── emoon-ai-card
│           ├── emoon-ai-mcp
│           ├── emoon-ai-device          # 🆕 设备注册中心实现
│           ├── emoon-ai-file            # 🆕 文件服务实现
│           ├── emoon-ai-meter
│           ├── emoon-ai-billing
│           ├── emoon-ai-contract
│           └── emoon-ai-operation
└── emoon-extend                         # 外围扩展、任务、迁移、专病能力

1.3.1 目标依赖方向

flowchart TB
    Admin["emoon-admin"]
    Open["emoon-openplatform"]
    Extend["emoon-extend"]

    SystemApi["emoon-system-api"]
    KnowledgeApi["emoon-knowledge-api"]
    ChatApi["emoon-chat-api"]

    AgentApi["emoon-ai-agent-api"]
    CardApi["emoon-ai-card-api"]
    McpApi["emoon-ai-mcp-api"]
    DeviceApi["emoon-ai-device-api"]
    FileApi["emoon-ai-file-api"]
    MeterApi["emoon-ai-meter-api"]
    BillingApi["emoon-ai-billing-api"]
    ContractApi["emoon-ai-contract-api"]
    OperationApi["emoon-ai-operation-api"]

    Agent["emoon-ai-agent"]
    Card["emoon-ai-card"]
    Mcp["emoon-ai-mcp"]
    Device["emoon-ai-device"]
    File["emoon-ai-file"]
    Meter["emoon-ai-meter"]
    Billing["emoon-ai-billing"]
    Contract["emoon-ai-contract"]
    Operation["emoon-ai-operation"]

    Common["emoon-common-*"]
    External["Dify / LLM / HIS / EMR / LIS / PACS"]

    Admin --> SystemApi
    Admin --> AgentApi
    Admin --> CardApi
    Admin --> DeviceApi
    Admin --> FileApi
    Admin --> BillingApi
    Admin --> ContractApi
    Admin --> OperationApi

    Open --> SystemApi
    Open --> AgentApi
    Open --> CardApi
    Open --> DeviceApi
    Open --> FileApi
    Open --> MeterApi

    Extend --> AgentApi
    Extend --> McpApi
    Extend --> MeterApi

    Agent --> AgentApi
    Agent --> CardApi
    Agent --> McpApi
    Agent --> DeviceApi
    Agent --> FileApi
    Agent --> MeterApi
    Agent --> ContractApi
    Agent --> Common
    Agent --> External

    Card --> CardApi
    Card --> AgentApi
    Card --> Common

    Mcp --> McpApi
    Mcp --> SystemApi
    Mcp --> FileApi
    Mcp --> Common
    Mcp --> External

    Device --> DeviceApi
    Device --> SystemApi
    Device --> Common

    File --> FileApi
    File --> SystemApi
    File --> Common

    Meter --> MeterApi
    Meter --> ContractApi
    Meter --> Common

    Billing --> BillingApi
    Billing --> MeterApi
    Billing --> ContractApi
    Billing --> Common

    Contract --> ContractApi
    Contract --> SystemApi
    Contract --> Common

    Operation --> OperationApi
    Operation --> MeterApi
    Operation --> BillingApi
    Operation --> ContractApi
    Operation --> Common

    KnowledgeApi --> Common
    ChatApi --> Common
    SystemApi --> Common

图中的箭头表示允许依赖方向。没有画出的方向默认不允许。

1.4 模块职责定义

1.4.1 入口模块

模块 允许职责 禁止职责
emoon-admin 管理后台入口、菜单权限、运营配置页面、调用领域 API 直接操作 AI 业务表、直接调用 Dify/LLM、直接扣减能力值
emoon-openplatform 对外 API、签名鉴权、租户识别、参数校验、SSE 输出、入口限流 保存 AI 会话核心状态、直接查写 Mapper、直接选择引擎实现、直接计费
emoon-extend 文件处理、迁移、外围任务、专病扩展、非主链路能力 承载 Agent 主链路、承载账务核心状态、绕过领域 API 改业务数据

入口模块的原则:

入口模块可以知道“谁来调用、是否有权限、把请求交给谁”,
但不应该知道“AI 会话怎么编排、卡片状态怎么流转、能力值怎么扣”。

1.4.2 API 契约模块

*-api 是工程边界的核心。它必须保持轻量,避免把实现细节传染给上游。

允许放入:

类型 示例
DTO / Command / Query AgentChatCommandCreateCardInstanceCommand
VO / Response AgentChatResponseCardRenderPayload
Enum / Constant EngineTypeMeterEventStatus
Facade Interface AgentChatFacadeBillingAccountFacade
Event Contract UsageMeteredEventCardActionSubmittedEvent
SPI Interface AgentEngineMcpToolInvoker

禁止放入:

禁止内容 原因
Mapper API 调用方不应该拿到数据访问能力
ServiceImpl API 模块不承载实现
Controller API 模块不暴露 Web 入口
EngineImpl Dify、DirectLLM、Mock 等实现必须放到实现模块
第三方 SDK 客户端 会把重依赖传染给所有调用方
MyBatis XML / SQL 破坏 API 与实现隔离
Web/SSE/WebSocket 具体实现 入口协议属于应用层或实现层

1.4.3 AI Agent 模块

模块 规划职责
emoon-ai-agent-api 定义 AI 调用、会话、流式事件、引擎抽象、编排命令、终端任务状态只读 DTO
emoon-ai-agent 实现 Agent 主链路、AgentRouter、ConversationService、TaskStateService、DifyAgentEngine、DifyOutputNormalizer、DirectLLM 引擎、Mock 引擎、SSE 事件转换、降级、幂等、Outbox

emoon-ai-agent 是 AI 中台二期的主链路模块,但不能变成所有 AI 功能的大杂烩。

允许依赖:

emoon-ai-agent-api
emoon-ai-card-api
emoon-ai-mcp-api
emoon-ai-device-api
emoon-ai-file-api
emoon-ai-meter-api
emoon-ai-contract-api
emoon-system-api
emoon-knowledge-api
必要的 emoon-common-*

禁止依赖:

emoon-ai-billing 实现模块
emoon-ai-operation 实现模块
openplatform
admin
任意 Controller 层

关键约束:

emoon-ai-agent 可以产生计量事件,但不能直接扣款。
emoon-ai-agent 可以读取合同授权快照,但不能维护合同。
emoon-ai-agent 可以调用 MCP 工具 API,但不能绕过 MCP 治理直连 HIS。
AgentRouter 和 TaskStateService 是 Agent 主链路内部能力,第一期不新增公共 /tasks API。
TaskStateService 必须持久化到 `ai_task_instance`,不能只放 Redis 或 `ai_conversation.ext_json`;Redis 只能作为短期缓存。
DifyOutputNormalizer 是 `DifyAgentEngine` 的内部组件,负责输出结构校验、卡片 schema 校验、风险等级归一和 SSE 事件归一,不新增独立模块。
卡片动作涉及 HIS 写操作时,由 Agent 编排链路调用 Card 做状态校验,再调用 MCP 工具,不允许 Card 自己直连 MCP。

1.4.4 AI Card 模块

模块 规划职责
emoon-ai-card-api 定义卡片模板、卡片实例、卡片动作、渲染数据、状态事件
emoon-ai-card 实现卡片状态机、动作幂等、卡片版本、卡片事件、渲染数据聚合

关键约束:

emoon-ai-card 只负责“确定性交互状态”,不负责模型推理。
emoon-ai-card 不能直接调用 MCP 工具。
emoon-ai-card 需要调用工具时,必须通过 emoon-ai-agent 编排。

原因:

如果卡片可以直接调用 MCP,系统会出现两条工具调用链:

Agent -> MCP
Card  -> MCP

这样会导致权限、审计、计量、失败补偿出现双标准。生产环境中必须保持一条主链路。

1.4.5 AI MCP 模块

模块 规划职责
emoon-ai-mcp-api 定义工具注册、工具调用、工具权限、工具审计、工具结果契约
emoon-ai-mcp 实现工具注册表、工具路由、权限校验、限流熔断、工具调用审计、HisMockAdapter、RealHisAdapter、TongueDiagnosisAdapter

emoon-ai-mcp 不等于所有院内系统适配。它负责工具协议治理,具体 HIS / EMR / LIS / PACS 的适配可以继续放在当前合适模块中,或后续独立为 hospital-integration / emoon-hospital-adapter

关键约束:

MCP 管工具治理,不管业务编排。
HIS 适配管系统协议,不管 Agent 对话。
Agent 管流程编排,不管 HIS 细节。
TongueDiagnosisAdapter 在 MVP 阶段作为 MCP 受控工具适配器处理,后续形成独立专精产品线时再拆模块。
HisMockAdapter 必须显式命名和配置,不能把 Mock 结果包装成真实医院交易。

1.4.6 计量模块

模块 规划职责
emoon-ai-meter-api 定义计量事件、计量状态、幂等键、用量查询接口
emoon-ai-meter 实现 Token/次数/分钟/项目/年费等用量归集、状态机、重放、去重

计量模块是三期商业闭环的第一层,不是账务模块。

关键约束:

业务模块只提交 usage event。
emoon-ai-meter 负责判断这个 event 是否可信、是否重复、是否可计量。
emoon-ai-billing 再根据计量结果做扣款或结算。

禁止:

emoon-ai-agent 直接写账务流水。
emoon-ai-card 直接扣能力值。
openplatform 直接计算费用。

1.4.7 账务模块

模块 规划职责
emoon-ai-billing-api 定义账户余额、冻结、扣减、退款、冲正、账单查询契约
emoon-ai-billing 实现能力值包预扣款、账务流水、账单、对账、调账、价格快照

账务模块必须独立,原因是账务有强一致性要求,而 Agent 调用链有高并发和失败降级要求。两者耦合会导致调用失败、重复扣款、漏扣款和对账困难。

关键约束:

扣款必须基于 pricing snapshot。
账务流水必须可追溯、可冲正、不可物理删除。
同一 meter event 只能入账一次。

1.4.8 合同模块

模块 规划职责
emoon-ai-contract-api 定义客户合同、能力值包、价格策略、授权范围、有效期
emoon-ai-contract 实现合同状态机、套餐绑定、能力包启停、区域能力池规则

合同模块不应该放在 system 里。system 可以提供租户、用户、组织、权限,但合同、套餐、能力值包属于 AI 商业闭环。

1.4.9 运营统计模块

模块 规划职责
emoon-ai-operation-api 定义统计查询、运营报表、客户看板、异常分析契约
emoon-ai-operation 实现统计宽表、报表聚合、医院/科室/医生/智能体维度分析

运营统计不能直接拖核心业务表做复杂联表,否则后续会拖慢主链路。

推荐方式:

emoon-ai-meter / emoon-ai-billing / emoon-ai-agent 产生事件
Outbox 或定时任务汇总到 operation 宽表
emoon-ai-operation 面向后台和客户报表查询

1.4.10 Device 设备注册模块

模块 规划职责
emoon-ai-device-api 定义设备注册、心跳、场景配置、事件上报、命令下发、设备查询契约
emoon-ai-device 实现 Device Registry、设备身份管理、准入等级校验(A/B/C/D)、心跳监控、Scene Orchestrator、命令轮询与回执、设备事件接入

关键约束:

门诊设备(导诊屏、自助机、机器人、诊室屏等)由医梦 Device Registry 管理,包含注册、心跳、场景和基础状态。
住院侧设备类型(nurse_pda / nursing_whiteboard / bedside_screen / ward_robot)
  默认 managementMode = mapped_external,由迪耐克/鸿蒙病房体系管理硬件生命周期,
  医梦只记录映射关系和 AI 事件互通,不承担住院硬件注册、心跳升级和故障主责。
设备事件只上报业务摘要,不保存患者连续轨迹。

设备管理模式枚举:

managementMode 说明 典型设备
emoon_managed 医梦统一入口客户端和 Device Registry 管理 导诊屏、自助机、门诊机器人、诊室屏
partner_managed 合作厂商管理硬件,医梦通过标准接口接入 第三方机器人、四诊仪
mapped_external 外部体系管理,医梦只做映射和事件互通 迪耐克床头屏、护理白板、护士 PDA

允许依赖:

emoon-ai-device-api
emoon-system-api(查询医院/科室绑定)
必要的 emoon-common-*

禁止依赖:

emoon-ai-agent(设备不编排 AI 流程)
emoon-ai-card(设备不管理卡片状态)
emoon-ai-billing(设备不计费)
emoon-openplatform(设备不反向依赖入口层)

1.4.11 File 文件服务模块

模块 规划职责
emoon-ai-file-api 定义文件上传、元数据查询、删除、安全扫描状态契约
emoon-ai-file 实现文件接收、对象存储适配、安全扫描对接、retentionPolicy 管理、幂等去重

关键约束:

文件必须先上传获得 fileId,后续 Agent/Card 调用只传 fileId。
不默认返回可公开访问 URL。
舌诊/面诊图片、报告原文按敏感医疗数据治理。
retentionPolicy 不传时,按 purpose 推断默认值:
  tongue_diagnosis / face_diagnosis → episode
  report_interpretation → episode
  medical_record → medical_record
  audio_transcription → transient
  other → transient
DELETE 必须支持幂等,同一文件重复删除返回首次结果或当前已删除状态。
文件上传幂等键建议:projectId + partnerId + clientFileId。

允许依赖:

emoon-ai-file-api
emoon-system-api
emoon-common-oss
必要的 emoon-common-*

禁止依赖:

emoon-ai-agent
emoon-ai-card
emoon-ai-mcp
emoon-openplatform

1.4.12 统一入口客户端工程归属

统一入口客户端不是一个新的后端系统。所有后端能力必须落在 AI 中台现有目标模块中:

能力 归属模块 说明
设备注册、心跳、场景配置、设备事件、命令轮询 emoon-ai-device 支撑机器人、自助机、导诊屏、诊室屏启动和运维
AgentRouter、ConversationService、TaskStateService、DifyAgentEngine、DifyOutputNormalizer emoon-ai-agent 统一入口客户端只调用 Agent API,不感知内部路由和输出归一
卡片定义、实例、动作幂等、快照 emoon-ai-card 卡片动作的业务编排由 Agent 主链路承接
文件上传、元数据、删除、访问审计 emoon-ai-file 舌象、身份证、报告、音频都先拿 fileId
HisMockAdapter、RealHisAdapter、TongueDiagnosisAdapter emoon-ai-mcp 作为受控工具适配器,不让终端直连
审计、计量、Outbox emoon-ai-meter / emoon-system 记录事实,不参与前端渲染

前端和移动端独立为 emoon-terminal-client 工程:

emoon-terminal-client
├── apps/robot-client
├── apps/kiosk-client
├── apps/guide-screen-client
└── packages/api-client / medical-cards / terminal-bridge / terminal-theme / terminal-core

后端仓库只维护 OpenAPI、DTO、业务模块和 Mock/Adapter。不得在 emoon-backend 内新增长期维护的终端 Demo 后端、前端页面构建或设备 SDK UI 代码。临时 Demo 只能作为联调样例,且必须通过 OpenPlatform API 调用正式后端能力。

1.5 依赖白名单

1.5.1 API 模块依赖白名单

API 模块允许依赖:

依赖 用途
emoon-common-core 基础实体、通用返回、工具类型
jakarta.validation 参数校验注解
jackson JSON 序列化注解
lombok 简化 DTO
mapstruct 注解 DTO 转换契约,需谨慎使用

API 模块禁止依赖:

emoon-common-web
emoon-common-mybatis
emoon-common-sse
emoon-common-websocket
emoon-common-oss
emoon-common-doc
emoon-common-excel
langchain4j
pdfbox
tika
okhttp
spring-boot-starter-web
mybatis-plus
任何具体数据库驱动

例外必须写 ADR,并说明为什么该依赖必须进入 API 层。

1.5.2 实现模块依赖白名单

实现模块可以依赖:

自身 api
其他领域 api
必要的 emoon-common-*
必要的第三方 SDK

实现模块禁止:

依赖入口模块,例如 emoon-openplatform、emoon-admin
依赖其他模块的 impl 包
跨模块注入 Mapper
跨模块直接更新对方业务表

1.5.3 入口模块依赖白名单

入口模块允许依赖:

领域 api
emoon-common-web
emoon-common-security
emoon-common-sse
emoon-common-ratelimiter
emoon-common-tenant

入口模块禁止:

直接依赖领域实现模块
直接依赖 Mapper
直接调用第三方 AI SDK
直接写核心业务状态表

1.6 禁止依赖关系

以下依赖关系默认禁止:

禁止方向 原因
*-api -> *-impl API 层不能依赖实现层
*-api -> Mapper API 层不能暴露数据访问
openplatform -> Mapper 入口层不应绕过领域服务
openplatform -> AgentEngineFactory 实现 入口层不应选择具体引擎
emoon-ai-card -> emoon-ai-mcp 实现 卡片不能绕过 Agent 调工具
emoon-ai-billing -> emoon-ai-agent 实现 账务不应反向依赖调用链
emoon-ai-operation -> 核心表复杂联查 统计不能拖慢主链路
system -> emoon-ai-billing 实现 系统基础域不能反向依赖商业域
knowledge -> emoon-ai-agent 实现 知识库应作为能力被调用,不应控制 Agent

1.7 当前模块迁移建议

1.7.1 emoon-mcp-api

用户已确认后续按以下方向拆分:

emoon-mcp-api
├── emoon-ai-agent-api
├── emoon-ai-card-api
└── emoon-ai-mcp-api

建议迁移归属:

当前内容 目标模块 说明
AgentEngine / AgentRequest / AgentResponse emoon-ai-agent-api 属于引擎契约
AgentEngineFactory emoon-ai-agent 属于实现装配,不应在 API
MockAgentEngine emoon-ai-agent 属于开发/测试实现
AiConversation emoon-ai-agent-apiemoon-ai-agent 如果作为 DO 放实现;如果作为 VO/DTO 放 API
AiConversationMapper emoon-ai-agent Mapper 必须离开 API
AiCardInstance emoon-ai-card-apiemoon-ai-card DTO/VO 放 API,DO/Mapper 放实现
AiCardInstanceMapper emoon-ai-card Mapper 必须离开 API
MCP Tool 契约 emoon-ai-mcp-api 只放工具调用契约
MCP Tool 实现 emoon-ai-mcp 工具注册、调用、审计实现
HospitalActivity 需重新判断 如果是医院活动管理,不应归属 MCP,可考虑运营或系统模块

1.7.2 emoon-openplatform

迁移目标:

当前:Controller -> Mapper / EngineFactory / Dify Client / 业务表
目标:Controller -> Facade API -> 领域实现模块

建议迁移顺序:

阶段 动作
第一步 保留当前接口路径和请求响应,新增 AgentChatFacade
第二步 把会话创建、引擎选择、SSE 事件转换迁入 emoon-ai-agent
第三步 openplatform 只负责鉴权、签名、限流、参数转换
第四步 删除对 AiConversationMapperAiAgentEngineConfigMapper 的直接依赖

1.7.3 emoon-system-api

当前 system-api 中已有 AiAgentEngineConfig,短期可以保留,但要明确边界。

建议:

租户、用户、组织、权限、字典:继续留在 system。
AI 引擎配置、Dify 配置、模型供应商配置:中期迁入 emoon-ai-agent。
合同、套餐、能力值包:不得放入 system。

1.7.4 emoon-knowledge-api

知识库模块应该作为 AI Agent 的能力来源,而不是 Agent 的控制者。

建议:

knowledge-api 提供知识检索、模板、规则、提示词资产契约。
emoon-ai-agent 可以依赖 knowledge-api。
knowledge 不依赖 emoon-ai-agent 实现。

1.8 二期与三期模块落位

1.8.1 二期功能落位

功能 应落模块 不应落模块
Dify Workflow 调用 emoon-ai-agent openplatformemoon-ai-card
DirectLLM 调用 emoon-ai-agent openplatform
Mock 引擎 emoon-ai-agent emoon-ai-agent-api
SSE 事件协议 emoon-ai-agent-api 具体 Controller 私有结构
SSE 输出实现 openplatformemoon-ai-agent 协同 emoon-ai-card
卡片实例状态机 emoon-ai-card openplatform
卡片动作幂等 emoon-ai-card 前端、Controller
MCP 工具注册 emoon-ai-mcp emoon-ai-agent
MCP 工具权限 emoon-ai-mcp Dify、前端
HIS/EMR 工具适配 emoon-ai-mcp 或后续 hospital adapter emoon-ai-card
用量事件生成 emoon-ai-agent / emoon-ai-card / emoon-ai-mcp emoon-ai-billing

1.8.2 三期功能落位

功能 应落模块 不应落模块
合同管理 emoon-ai-contract systemopenplatform
能力值包 emoon-ai-contract + emoon-ai-billing emoon-ai-agent
预扣款 emoon-ai-billing openplatformemoon-ai-agent
Token/次数/分钟计量 emoon-ai-meter emoon-ai-billing
账单生成 emoon-ai-billing emoon-ai-operation
账务冲正 emoon-ai-billing emoon-ai-meter
医院/科室/医生统计 emoon-ai-operation 核心链路 Controller
合理不限量策略 emoon-ai-contract + emoon-ai-meter emoon-ai-agent
区域能力池划拨 emoon-ai-contract + emoon-ai-billing system
客户运营报告 emoon-ai-operation emoon-ai-agent

1.9 事务与一致性边界

复杂 Java 工程最容易写乱的地方不是类名,而是事务边界。以下规则必须统一。

1.9.1 同步事务边界

单个模块内部可以使用本地事务:

emoon-ai-card 内部:卡片动作提交 + 卡片状态更新
emoon-ai-meter 内部:计量事件去重 + 状态流转
emoon-ai-billing 内部:账务流水 + 余额更新

跨模块不要开启大事务。

错误示例:

openplatform 一个事务里同时:
写会话
调 Dify
写卡片
写计量
扣能力值

正确方式:

核心状态先落本模块事务。
跨模块动作通过领域事件或 Facade 调用。
需要最终一致性的地方用 Outbox。

1.9.2 异步一致性边界

推荐事件链路:

emoon-ai-agent 调用完成
  -> 写 Agent 调用结果
  -> 发送 UsageGeneratedEvent
  -> emoon-ai-meter 计量
  -> 发送 MeterEventConfirmed
  -> emoon-ai-billing 入账
  -> emoon-ai-operation 汇总

计量和账务不得只依赖内存回调,必须可重放。

1.10 包名规范

建议后续新模块统一使用以下包名。

com.emoon.ai.agent
com.emoon.ai.card
com.emoon.ai.mcp
com.emoon.ai.meter
com.emoon.ai.billing
com.emoon.ai.contract
com.emoon.ai.operation

API 模块:

com.emoon.ai.agent.api
com.emoon.ai.agent.api.dto
com.emoon.ai.agent.api.enums
com.emoon.ai.agent.api.event
com.emoon.ai.agent.api.facade

实现模块:

com.emoon.ai.agent.application
com.emoon.ai.agent.domain
com.emoon.ai.agent.infrastructure
com.emoon.ai.agent.adapter

说明:

职责
application 应用服务、用例编排、事务入口
domain 领域对象、领域规则、状态机
infrastructure Mapper、Repository、第三方 SDK、消息、Outbox
adapter 入站/出站适配,例如 Dify、DirectLLM、HIS 工具适配

1.11 Maven 依赖检查建议

后续建议引入自动化约束,避免规则只停留在文档。

1.11.1 Maven Enforcer

建议用 maven-enforcer-plugin 检查:

API 模块禁止依赖 spring-boot-starter-web
API 模块禁止依赖 mybatis-plus
API 模块禁止依赖 okhttp / langchain4j / pdfbox / tika
入口模块禁止依赖领域实现模块

1.11.2 源码扫描式架构测试

当前已新增轻量架构测试,不引入额外 Maven 依赖,只基于源码扫描做增量检查:

API 模块不得新增 Mapper / Impl / Controller。
API 模块不得新增 Web / MyBatis / AI SDK / PDF/OCR 等重依赖。
openplatform 不得新增直接 Mapper 依赖。
Controller 不得新增直接 Mapper 依赖。
emoon-ai-card 不得绕过 emoon-ai-agent 直接依赖 emoon-ai-mcp 实现层。
emoon-ai-billing 不得反向依赖 emoon-ai-agent 实现层。
emoon-ai-operation 不得依赖核心链路 infrastructure 做复杂联查。

历史违规已冻结在 docs/architecture/legacy/历史架构违规基线.txt。测试只拦截新增违规,不移动当前业务代码,因此不会影响项目启动。后续完成某个历史文件迁移后,应从 baseline 中删除对应路径,让约束逐步收紧。

1.12 推荐迁移节奏

不要一次性大改 Maven 工程。建议按以下顺序推进:

阶段 目标 说明
P0 冻结依赖规则 新代码先按本章规则落位
P1 拆分 emoon-mcp-api 拆为 emoon-ai-agent-apiemoon-ai-card-apiemoon-ai-mcp-api
P2 下沉实现类 Mapper、EngineImpl、Factory 从 API 模块迁入实现模块
P3 收口 openplatform 改为只依赖 Facade API,不直接操作 Mapper
P4 新增计量模块 建立 emoon-ai-meter-api / emoon-ai-meter
P5 新增合同账务模块 建立 emoon-ai-contract / emoon-ai-billing
P6 新增运营统计模块 建立 emoon-ai-operation,承接报表和客户运营看板
P7 引入自动化检查 轻量源码扫描式架构测试;后续可再升级 Maven Enforcer / ArchUnit
P8 评估独立部署 只对高吞吐或强隔离模块考虑拆服务

1.13 未来微服务拆分判断标准

满足以下条件时,才考虑把 Maven 模块升级为独立服务:

判断项 拆分信号
吞吐压力 模块资源消耗明显独立,例如语音流、OCR、IoMT 事件
隔离要求 医院内网工具调用、敏感数据处理需要独立网络边界
发布频率 某模块发布频率远高于主系统,且影响范围可控
团队责任 有明确负责人和运维能力
数据边界 数据表和事务边界已经稳定
接口稳定 API 契约至少经历一轮线上验证

优先可能独立部署的模块:

MCP Tool Server
AudioStreamGateway
IoMTEventIngestion
File/OCR/ASR Worker
Operation Report Worker

不建议早期独立部署的模块:

emoon-ai-agent
emoon-ai-card
emoon-ai-meter
emoon-ai-billing
emoon-ai-contract

原因是这些模块在早期需要频繁联动调整,过早拆服务会降低开发效率。

1.14 工程师落地检查清单

新增一个类或模块前,先回答以下问题:

问题 判断
这个类是契约还是实现? 契约放 *-api,实现放 *-modules
是否需要操作数据库? 需要则不能放 API 模块
是否调用第三方 SDK? 需要则不能放 API 模块
是否属于入口协议? Controller、SSE 输出放入口层或 adapter
是否属于 Agent 编排? emoon-ai-agent
是否属于卡片状态? emoon-ai-card
是否属于工具治理? emoon-ai-mcp
是否属于用量归集? emoon-ai-meter
是否属于扣款结算? emoon-ai-billing
是否属于合同套餐? emoon-ai-contract
是否属于统计报表? emoon-ai-operation
是否要跨模块改表? 不允许,改为 Facade 或事件
是否为了方便直接注入 Mapper? 不允许,说明模块边界没设计好

1.15 本章强制规则摘要

后续开发默认遵守以下规则:

R1. API 模块只放契约,不放实现。
R2. Mapper 只能存在于实现模块。
R3. Controller 只能调用 Facade / Application Service,不直接调用 Mapper。
R4. openplatform 只做入口适配,不承载 AI 主业务状态。
R5. emoon-ai-agent 负责 AI 编排,但不负责扣款和报表。
R6. emoon-ai-card 负责卡片状态,但不直接调用 MCP 工具。
R7. emoon-ai-mcp 负责工具治理,但不负责 Agent 流程编排。
R8. emoon-ai-meter 负责计量,不负责余额扣减。
R9. emoon-ai-billing 负责账务,不反向依赖 Agent 实现。
R10. emoon-ai-contract 负责合同和套餐,不放入 system。
R11. emoon-ai-operation 负责统计宽表和报表,不拖慢主链路。
R12. 跨模块一致性优先使用 Outbox / 事件 / 幂等键,不做跨模块大事务。
R13. 新模块必须先明确依赖方向,再写代码。
R14. 任何违反规则的例外必须补 ADR。

这份约束的目的不是增加开发成本,而是防止 AI 中台在二期、三期叠加后变成无法维护的巨石。只要依赖方向稳定,当前单体工程也可以支撑生产级医疗项目;未来要拆服务时,也有清晰的模块边界可以承接。

1.16 配套执行资产

为了让工程约束在工程师开发 + 技术总监 Review 的模式下真正执行,当前已配套以下资产:

资产 位置 使用时机 作用
PR 自检模板 .github/pull_request_template.md 每次提交 PR 让开发人员在 Review 前先自查模块边界、幂等、计量、账务、安全、测试
任务拆分模板 docs/templates/AI中台任务拆分模板.md 每个开发任务开始前 把需求拆成可执行任务,提前限定允许修改模块、禁止依赖、核心流程和验收标准
模块骨架示例 docs/templates/AI中台模块骨架示例.md 新增 AI 模块或新功能包时 统一 API / application / domain / infrastructure / adapter 的放置规则
架构边界测试 emoon-admin/src/test/java/com/emoon/architecture/AiPlatformArchitectureTest.java 本地测试和 CI 冻结历史违规,自动拦截新增 Maven / 架构边界问题
历史违规基线 docs/architecture/legacy/历史架构违规基线.txt 架构测试运行时 记录当前遗留问题,避免一次性搬迁影响项目启动

执行要求:

新任务必须先填写任务拆分模板。
新 PR 必须完整填写 PR 自检模板。
新增 AI 模块必须参考模块骨架示例。
新增目标 AI 包后必须运行架构边界测试。

架构边界测试当前采用“历史基线 + 增量失败”的策略。原因是历史模块中已经存在 openplatform 直连 Mapper、*-api 混入实现类等问题,如果现在直接全量强约束,会导致测试立即失败,且大规模移动代码会影响启动稳定性。

后续迁移完成后,应逐步收紧基线和扩大检查范围:

阶段 约束范围
第一阶段 com.emoon.ai.* 新模块
第二阶段 com.emoon.mcp.* 迁移后的 Agent / Card / MCP 模块
第三阶段 com.emoon.openplatform.* 禁止直连 Mapper 和实现层
第四阶段 全工程禁止 API 模块依赖实现层和重依赖

2. 接口归属与调用方向约束

本章基于 v1.2 对外接口文档(docs/api/openapi/医梦AI中台开放平台接口-v1.2.openapi.yaml), 明确每个接口的 Controller 归属模块和核心 Service 归属模块, 并定义 Controller → Service 的合法调用方向和禁止调用模式。

2.1 Controller 层强制规则

所有对外 API 的 Controller 统一放在 emoon-openplatform 模块的 controller/v1/ 包下。

Controller 只做四件事:

允许 不允许
解析 HTTP 请求参数和 Header 直接调用 Mapper
调用鉴权拦截器/工具类 直接调用 Dify API 或第三方 LLM SDK
调用领域 Service(通过 API 接口) 编写业务逻辑(状态机、计费、HIS 调用)
封装统一响应(R<T> 或 SSE) 直接操作数据库表

为什么 Controller 不能直接调 Mapper:

Controller 只负责 HTTP 协议适配。如果直接调 Mapper,会绕过 Application Service、
状态机、幂等校验、审计、计量和 Outbox。后续排障时无法通过 traceId 还原完整调用链。

2.2 接口 → 模块归属表

下表来自 v1.2 正式联调基准版,每个接口对应一个 Controller 模块一个核心 Service 实现模块

P0 接口(联调前必须稳定,21 个)

方法 路径 Controller 所在模块 核心 Service 实现模块 当前工程状态
POST /auth/token emoon-openplatform emoon-openplatform 🔴 需新建(Bearer Token 签发)
GET /health emoon-openplatform emoon-openplatform 🟡 部分存在
GET /capabilities emoon-openplatform emoon-openplatform + emoon-system 🔴 需新建
POST /agent/chat emoon-openplatform emoon-ai-agent 🟡 需升级鉴权
POST /agent/chat/stream emoon-openplatform emoon-ai-agent 🟡 同上
POST /conversations emoon-openplatform emoon-openplatform 🟡 路径需 RESTful
GET /conversations emoon-openplatform emoon-openplatform 🟡 P1,来自旧 conversation/list
GET /conversations/{id} emoon-openplatform emoon-openplatform 🟡 路径需对齐
GET /conversations/{id}/messages emoon-openplatform emoon-openplatform 🔴 需新建
POST /files/upload emoon-openplatform emoon-ai-file 🔴 需新建模块
GET /files/{id} emoon-openplatform emoon-ai-file 🔴 同上
DELETE /files/{id} emoon-openplatform emoon-ai-file 🔴 同上(P1)
POST /devices/register emoon-openplatform emoon-ai-device 🔴 需新建模块
POST /devices/{id}/heartbeat emoon-openplatform emoon-ai-device 🔴 同上
GET /devices/{id}/scene emoon-openplatform emoon-ai-device 🔴 同上
POST /devices/{id}/events emoon-openplatform emoon-ai-device 🔴 同上
GET /devices/{id}/commands/poll emoon-openplatform emoon-ai-device 🔴 同上
POST /devices/{id}/commands/{cmd}/ack emoon-openplatform emoon-ai-device 🔴 同上
GET /cards/{id} emoon-openplatform emoon-ai-card 🔴 需新建
POST /cards/{id}/actions/{name} emoon-openplatform emoon-ai-agent + emoon-ai-card 🟡 路径需对齐;Agent 编排动作,Card 负责状态
POST /tools/{name}/invoke emoon-openplatform emoon-ai-mcp 🟡 雏形存在
GET /usage/summary emoon-openplatform emoon-ai-meter 🔴 meter 模块空壳
GET /meter/events emoon-openplatform emoon-ai-meter 🔴 同上

P1 接口(试点上线增强,14 个)

方法 路径 Controller 所在模块 核心 Service 实现模块
GET /agents emoon-openplatform emoon-system(查 ai_agent_app)
GET /agents/{agentId} emoon-openplatform emoon-system
GET /devices emoon-openplatform emoon-ai-device
GET /devices/{id} emoon-openplatform emoon-ai-device
PATCH /devices/{id}/scene emoon-openplatform emoon-ai-device
GET /devices/{id}/events emoon-openplatform emoon-ai-device
POST /webhooks emoon-openplatform emoon-openplatform
GET /webhooks emoon-openplatform emoon-openplatform
DELETE /webhooks/{id} emoon-openplatform emoon-openplatform
POST /events/ingest emoon-openplatform emoon-openplatform + emoon-ai-device
GET /tools/catalog emoon-openplatform emoon-ai-mcp
GET /licenses/devices emoon-openplatform emoon-ai-contract + emoon-ai-device

P2 接口(远期规划,9 个)

方法 路径 Controller 所在模块 核心 Service 实现模块
POST /partners emoon-openplatform emoon-openplatform
GET /partners/{id} emoon-openplatform emoon-openplatform
GET /contracts emoon-openplatform emoon-ai-contract
GET /credit/accounts emoon-openplatform emoon-ai-billing
POST /credit/accounts/{id}/freeze emoon-ai-billing(内部) emoon-ai-billing
POST /credit/accounts/{id}/settle emoon-ai-billing(内部) emoon-ai-billing
GET /billing/invoices emoon-openplatform emoon-ai-billing
GET /operation/reports emoon-openplatform emoon-ai-operation
GET /audit/logs emoon-openplatform emoon-system(扩展审计表)

2.3 合法调用方向

flowchart LR
    subgraph 入口层
        OC["emoon-openplatform<br/>Controller v1"]
    end
    subgraph 领域实现
        AG["emoon-ai-agent"]
        CD["emoon-ai-card"]
        MC["emoon-ai-mcp"]
        DV["emoon-ai-device"]
        FL["emoon-ai-file"]
        MT["emoon-ai-meter"]
        BL["emoon-ai-billing"]
        CT["emoon-ai-contract"]
        OP["emoon-ai-operation"]
    end
    subgraph 基础域
        SY["emoon-system"]
        KN["emoon-knowledge"]
    end
    subgraph 外部
        DF["Dify / LLM"]
        HS["HIS / EMR / LIS / PACS"]
    end

    OC --> AG & CD & MC & DV & FL & MT & SY
    AG --> CD & MC & MT & CT & KN & SY & DF
    MC --> HS
    DV --> SY
    FL --> SY
    MT --> CT
    BL --> MT & CT
    CT --> SY
    OP --> MT & BL & CT

图中箭头 = 允许调用方向。没有画出的方向默认不允许。关键约束:

调用方向 是否允许 原因
Controller → Service(通过 API 接口) ✅ 允许 标准调用路径
emoon-ai-agent → emoon-ai-mcp ✅ 允许 Dify Workflow 工具调用必须通过 MCP
emoon-ai-agent → emoon-ai-card ✅ 允许 Agent 编排链路需要创建卡片、推进卡片动作和写审计
emoon-ai-card → emoon-ai-mcp ❌ 禁止 卡片动作触发的 HIS 写操作必须回到 Agent 编排链路,再由 Agent 调 MCP
emoon-ai-mcp → emoon-ai-agent ❌ 禁止 工具不编排 Agent 流程
emoon-ai-card → emoon-ai-agent ❌ 禁止 卡片不发起 Agent 调用
emoon-ai-device → emoon-ai-agent ❌ 禁止 设备不编排 AI 流程
emoon-ai-billing → emoon-ai-agent ❌ 禁止 账务不反向依赖调用链
Controller → Mapper ❌ 禁止 绕过 Service 层和状态机
任意模块 → Dify HTTP 直连 ❌ 禁止 必须经过 AgentEngine
前端/设备 → /tools/{name}/invoke ❌ 禁止 必须经过卡片动作或 Agent

2.4 禁止的调用模式(红线清单)

以下 6 条违反即拒绝 PR:

F1. Controller 直接调 Mapper

// ❌ 禁止
@RestController
public class FooController {
    @Autowired
    private AiConversationMapper mapper;  // Controller 不应注入 Mapper
}

正确做法:Controller → Service 接口(API 模块定义)→ Service 实现(实现模块内调 Mapper)。

F2. 任意模块直接 import DifyApiClient

// ❌ 禁止:在 emoon-ai-card、emoon-ai-device 等非 Agent 模块中
import com.emoon.openplatform.dify.DifyApiClient;

Dify 调用只能出现在 emoon-ai-agentadapter 包中,通过 AgentEngine 接口对外暴露。

F3. 卡片绕过 Agent 直接调 MCP 工具

// ❌ 禁止:在 emoon-ai-card 中
import com.emoon.ai.mcp.application.HisLockScheduleService;

卡片需要写 HIS 时,必须由 CardActionController 调 Agent 编排服务,Agent 调 Card 做状态校验和快照,再由 Agent 调 MCP 完成 HIS 写操作。 不能出现 Card → MCP 的短路调用。

F4. 前端/设备端直接调 /tools/{toolName}/invoke

❌ 禁止:机器人、自助机、导诊屏厂商的 HTTP Client 直接 POST /api/v1/tools/his.createRegistration/invoke

普通设备厂商只能通过 /agent/chat/stream/cards/{id}/actions/{name}/files/*/devices/* 接入。 Tool Invoke 仅开放给医梦 MCP Tool Server、HIS/EMR/LIS/PACS 等受控系统适配方。

F5. Service 层写 HMAC 签名逻辑

// ❌ 禁止:在 Service 实现类中
String sign = SignUtil.hmacSha256(payload, project.getSecretKey());

鉴权逻辑只能出现在 emoon-openplatform 的拦截器或 Controller 层。 Service 层接收的是已验证的 projectId/tenantId 上下文。

F6. 把 Dify API Key 暴露到日志或前端

❌ 禁止:log.info("Dify key: {}", difyApiKey)
❌ 禁止:响应体中包含 apiKey 字段
❌ 禁止:前端 JS 中硬编码 Dify Key

Dify API Key 只能存在于 ai_agent_engine_config.config_json 的加密字段中, 运行时由 Agent 模块解密后使用,不出现在任何日志、响应或前端代码中。

2.5 PR 评审检查清单

每个涉及后端 API 或模块的 PR 必须通过以下检查。此清单同时维护在 .github/pull_request_template.md 中。

Controller 检查

  • 新 Controller 放在 emoon-openplatform/controller/v1/ 包下?
  • 路径和方法名与 v1.2 YAML 一致?
  • 已接入 HMAC 或 Bearer Token 鉴权(非 legacy MD5)?
  • 写操作已强制 X-Emoon-Idempotency-Key
  • Controller 未直接注入 Mapper?
  • Controller 未直接 import DifyApiClient?

Service 检查

  • Service 接口在 *-api 模块、实现在 *-modules 模块?
  • 新 Service 放在了正确的模块?(参考 §2.2 归属表)
  • 没有违反 §2.4 中的任何一条禁止调用模式?
  • 涉及 HIS 写操作的,已通过 emoon-ai-mcp 工具封装?

模块边界检查

  • 没有在 emoon-openplatform 里写业务逻辑?
  • 新模块经过技术负责人确认?(禁止私自创建顶级模块)
  • 没有把 DifyApiClient 暴露给不应见的模块?

数据与合规检查

  • 新表有 project_id 字段?
  • 新表有必要的索引(至少覆盖 project、time、status 三个维度)?
  • 日志中不包含身份证、手机号、完整病历、API Key?
  • 敏感字段有加密或脱敏?

接口文档对齐

  • 新接口已在 v1.2 接口设计文档中定义?
  • 请求/响应字段与 YAML schema 一致?
  • 返回的 HTTP 状态码与接口文档一致?

2.6 工程师落地新接口的速查流程

接手一个新接口时,按以下顺序确认归属:

1. 查 §2.2 接口归属表 → 确定 Controller 放 emoon-openplatform,Service 放哪个模块。
2. 如果接口不在表中 → 先在 PR 描述中讨论归属,不得私自决定。
3. 创建 Controller → 放在 emoon-openplatform/controller/v1 包下。
4. Controller 中只写参数解析 + 鉴权调用 + Service 调用 + 响应封装。
5. Service 接口放在对应 `*-api` 模块,实现放在对应 `*-modules` 模块。
6. 完成后对照 §2.5 检查清单自检。
7. 运行架构边界测试(`mvn -pl emoon-admin -Dtest=AiPlatformArchitectureTest test`)。

2.7 本章强制规则摘要

C1. Controller 统一放在 emoon-openplatform/controller/v1/。
C2. Controller 只做参数解析、鉴权、Service 调用、响应封装。
C3. Controller 禁止注入 Mapper、禁止直接调 Dify、禁止写业务逻辑。
C4. 每个接口的 Service 归属以 §2.2 表为准。
C5. Card → MCP 必须经过 Agent 编排,禁止短路调用。
C6. 前端/设备端禁止直接调 /tools/{name}/invoke。
C7. DifyApiClient 只能被 emoon-ai-agent 的 adapter 包 import。
C8. 鉴权逻辑只能出现在 emoon-openplatform 的拦截器或 Controller。
C9. Dify API Key 不出现在日志、响应、前端代码中。
C10. 新模块必须经过技术负责人确认,禁止私建顶级模块。