一个完整的医院信息系统(HIS),覆盖门诊、药房、住院、护理、收费等15个核心业务模块,并深度融合 AI 多智能体引擎实现智能分诊、处方审核和院长问数。

项目概览

这是一个真正「能用」的医院信息系统——不只是 CRUD 原型,而是完整的业务闭环。后端基于 FastAPI + SQLAlchemy 2.0 + MySQL,前端使用 Vue 3 + Vite + Element Plus,AI 引擎层采用 LangGraph + LangChain + Qdrant + Redis 架构,接入阿里云百炼 Dashscope 大模型。

技术栈速览

层级 技术选型
后端框架 FastAPI (async)
ORM SQLAlchemy 2.0 (aiomysql 异步驱动)
数据库 MySQL 8.0 (utf8mb4)
前端 Vue 3 + Vite + Element Plus
AI 引擎 LangGraph StateGraph + LangChain
向量数据库 Qdrant (COSINE 距离, 1536 维)
缓存 Redis 7 (会话/查询/结果三级缓存)
LLM 阿里云百炼 Dashscope qwen-turbo
认证 JWT (HS256) + bcrypt 密码哈希
部署 Docker Compose (Qdrant + Redis)

15 个业务模块,覆盖医院全流程

系统的设计思路是:一线医务人员能真正用它干活。从患者进门到出院结算,信息流贯穿所有环节。

门诊流程

1. 触摸屏导诊(Kiosk) — 患者自助查询 IC 卡、药价、科室分布、一日清单,减少窗口排队。

2. 挂号管理(Registration) — 四种号别:普通/专家/急诊/专科。支持智能分诊:输入症状描述,AI 自动推荐科室、号别和医生,一键填入挂号表单。

3. 处方管理(Prescription) — 医生开立处方,系统自动划价。提交时触发 AI 处方审核:检查药物相互作用、剂量合理性、重复用药,高危问题弹框确认。

药房药库

4. 药房管理(Pharmacy) — 库存盘点、退药处理、发药统计。处方自动推送到药房待发药列表。

5. 药库管理(Warehouse) — 西药库/中药库双库管理,支持药库→药房的库存调拨,含事务性库存校验。

6. 药品主档(Drug) — 药品基本信息管理,与库存系统联动。

住院与护理

7. 出入院管理(Admission) — 入院登记、押金管理、一日清单、出院结算全流程。

8. 护士工作站(Nurse Station) — 床位状态看板(64 张床位可视化)、医嘱执行、生命体征录入(体温/脉搏/呼吸/血压)。

9. 医嘱管理(Medical Orders) — 长期/临时医嘱,支持药品、检验、手术、中医多种类型。

收费与财务

10. 收费管理(Charge) — 门诊处方收费、住院结算、检验/手术/功能科室收费统一入口。

11. 院长驾驶舱(Director Dashboard) — 今日挂号量/收入/药占比概览、7 日收入趋势折线图、科室挂号排行榜、药品销量 TOP10。支持自然语言问数,直接问”哪个科室最忙?”。

AI 特色模块

12. AI 智能对话(AI Chat) — 多会话管理,页面刷新自动恢复上次会话。左侧栏支持搜索、批量删除、内联重命名。

13. 知识库管理(KB Manage) — 上传 PDF/Word 文档,自动切片向量化存入 Qdrant,支持知识库检索。


架构设计:为什么这么搭?

后端:扁平化但清晰

所有 Python 源文件放在项目根目录,没有嵌套包。这不是偷懒——这个项目的业务逻辑就在 15 个模块的 API 路由里,扁平结构让「找文件」的成本降到最低。

1
2
3
4
5
6
7
8
9
10
# routers.py 的典型路由模式
@router.get("/", response_model=List[PatientOut])
async def list_patients(
q: str = None,
page: int = 1,
page_size: int = 20,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
# 统一的分页 + 模糊搜索 + 鉴权模式

关键设计决策:

  • 单文件路由routers.py ~2356 行,15 个 APIRouter 集中管理,跨模块调用时不需要交叉 import
  • 统一鉴权get_current_user 依赖注入 + require_role(*roles) 工厂函数
  • 自动事务get_db 依赖自动 commit/rollback,视图函数内无需手写事务

AI 引擎:LangGraph 多智能体编排

最初的 AI 功能是简单的函数调用,后来演进为完整的 LangGraph StateGraph 多智能体架构:

1
2
3
4
5
Router Agent → 意图分类 → Consultant / Medical / Science / Tool

Medical/Science 需要数据?

Tool Agent → 结果返回原 Agent → 生成回复

5 个 Agent 各司其职:

  • Router — 关键词 + LLM 双重意图分类
  • Consultant — 日常健康咨询/闲聊
  • Medical — 诊疗分析,可调用 search_kb/drug_interaction/summarize_patient 工具
  • Science — 健康科普,自动判断是否需要检索知识库
  • Tool — 自然语言匹配工具 + 执行 + 结果回复

同时配有完整的降级机制:LangGraph 执行失败→自动降级到直接 Dashscope 调用,用户无感知。

RAG 引擎:从文档到向量

1
2
3
4
PDF/Word/Text → LangChain DocumentLoader
→ RecursiveCharacterTextSplitter (chunk_size=800)
→ DashScopeEmbeddings (text-embedding-v2)
→ QdrantVectorStore (cosine, 1536d)

MySQL 现有知识数据通过 migrate_kb_to_qdrant.py 迁移。Redis 缓存层对 RAG 查询结果缓存 1 小时,知识库更新时自动失效。


前端亮点

布局策略

所有页面嵌套在 /index 路由下作为 children,统一布局壳。登录态用 localStorage token 守卫:

1
2
3
4
5
router.beforeEach((to) => {
if (to.path !== '/login' && !localStorage.getItem('token')) {
return '/login'
}
})

AI Chat 的多会话管理

前端实现了完整的多会话体验:

  • 恢复机制:onMounted → fetchSessions → 尝试恢复 lastAiSessionId
  • 碰撞保护:AI 回复期间禁止切换会话 / 创建新对话
  • 自动标题:后台异步用 AI 将首条消息概括为 2~5 字标题
  • 侧栏交互:折叠/展开、搜索过滤、复选框常显、内联重命名、删除 loading

API 层

通过 openapi-typescript-codegen 从 OpenAPI 规范生成类型安全的服务层,确保前后端接口一致。


数据库设计

18 张业务表,核心表关系:

1
2
3
4
5
6
7
8
9
10
User (角色: admin/doctor/nurse/cashier/pharmacist)
└─ AiSession (多会话)
Patient ── Registration ── Prescription ── PrescriptionItem
│ └─ Drug
└─ Admission ── AdmissionFeeItem
└─ Bed
└─ MedicalOrder ── VitalSign
Drug ── PharmacyInventory
└─ WarehouseInventory ── DrugTransaction
ChargeItem ── SpecialCharge

字段和索引设计遵循实际业务场景:挂号单用 registration_no 做业务主键,处方用 prescription_no,药品编码带库存校验。


一些有意思的细节

业务号生成

1
2
3
4
5
def _gen_no(prefix: str, length: int = 8) -> str:
"""生成业务编号: 前缀 + 时间戳(6位) + 随机数"""
ts = datetime.now().strftime("%y%m%d%H%M%S")[-6:]
rand = "".join(random.choices(string.digits, k=length - 2))
return f"{prefix}{ts}{rand}"

异步数据库 URL 替换

1
2
3
# database.py 故意用 pymysql URL 配,运行时替换为 aiomysql
# 这样 Alembic(同步)和 应用(异步)共享同一份配置
url = str(settings.DATABASE_URL).replace("pymysql", "aiomysql")

种子脚本的注意事项

seed.py 每次执行都是 drop_all → create_all → insert。这在开发阶段很方便——改完模型跑一次就重置——但 绝对不要在生产环境运行


部署指南

开发环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 后端
git clone <repo>
python -m venv .venv && source .venv/bin/activate
uv sync
cp .env.example .env # 填入数据库密码和 API Key
python seed.py # 初始化数据库
python main.py # 启动服务 → localhost:8000

# 前端
cd his-frontend
npm install
npm run dev # → localhost:5173,API 代理到 8000

# AI 基础设施(可选)
docker-compose up -d # 启动 Qdrant + Redis

默认账号

用户名 密码 角色
admin Admin@123 管理员
doctor1 Doctor@123 医生
nurse1 Nurse@123 护士
cashier1 Cashier@123 收费员
pharmacist1 Pharma@123 药师

项目结构一览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
his-system/
├── main.py # FastAPI 入口
├── config.py # pydantic-settings 配置
├── models.py # 18 ORM 模型
├── schemas.py # Pydantic v2 schema
├── routers.py # 15 模块 API 路由 (~2356行)
├── auth.py # JWT + bcrypt
├── database.py # 异步数据库连接池
├── ai_service.py # AI 服务入口 (委托 LangGraph)
├── rag_service.py # RAG 服务入口 (委托 LangChain)
├── ai_engine/ # LangGraph 多智能体引擎
│ ├── agents.py # 5 Agent + 4 工具函数
│ ├── graph.py # StateGraph 编排
│ ├── connections.py # Qdrant + Redis 连接
│ └── tools.py # 工具实现
├── rag_engine.py # LangChain RAG 引擎
├── redis_cache.py # Redis 缓存层
├── seed.py # 种子数据
├── docker-compose.yml # Qdrant + Redis
└── his-frontend/ # Vue 3 前端
└── src/
├── views/ # 16 个页面组件
├── api/ # 类型安全的 API 客户端
└── router/ # 路由守卫

写在最后

这个项目从最初的 FastAPI CRUD 原型,逐步演进到集成 LangGraph 多智能体引擎的完整医院信息系统。回头来看,最有价值的部分不是技术选型本身,而是 让 AI 真正嵌入业务流程——分诊不是展示 demo,而是直接填充挂号表单;审方不是输出分析报告,而是拦截高危处方;院长问数不是对话玩具,而是预取全量数据后用 AI 分析回答。

这种「AI 即功能」而非「AI 即演示」的取向,是医疗行业落地最需要的东西。


如果你对这个项目的某个模块感兴趣,或者想了解具体的实现细节,欢迎留言交流。