当前位置: 首页 > news >正文

中医智能诊疗系统-阶段一

一、项目概述:我们要做什么?

1.1 项目背景

中医诊疗强调“辨证论治”,需要医生通过多轮问诊收集患者信息,综合分析后给出诊断。传统的线上问诊系统要么是填表单(冰冷、不灵活),要么是单轮问答(缺乏引导)。我们希望构建一个AI中医智能诊疗系统,让AI像真正的医生一样,通过多轮引导式问诊收集症状,进行辨证分析,并给出可解释的诊疗建议,系统也可以作为中医问诊的辅助工具。

1.2 第一阶段目标

第一阶段的核心任务是搭建可运行的基础设施,实现:

模块目标
项目架构建立前后端分离的项目骨架,配置开发环境
智能问诊实现会话Agent,支持多轮引导式对话
记忆功能管理会话上下文,结构化提取症状
数据库持久化存储会话、消息、诊疗记录

简单说:让系统能“聊起来”,并且“记住”聊了什么。

二、技术选型与架构设计

2.1 技术栈

层级技术选型理由
前端Vue3 + Pinia响应式框架,状态管理清晰
后端FastAPI + Python异步支持好,开发效率高
数据库PostgreSQL + SQLAlchemy+FAISS关系型数据库,ORM成熟
大模型LongCat/DeepSeek API成本低,中文理解优秀
部署Uvicorn轻量级ASGI服务器

2.2 架构分层

text

┌─────────────────────────────────────────────────────────┐ │ 前端(Vue3) │ │ ┌──────────┬──────────────────┬──────────────────────┐ │ │ │ 左侧导航 │ 中间聊天区域 │ 右侧诊疗面板 │ │ │ │ 历史记录 │ 多轮问诊交互 │ 症状提取实时展示 │ │ │ └──────────┴──────────────────┴──────────────────────┘ │ └─────────────────────────────────────────────────────────┘ │ HTTP/SSE ┌─────────────────────────────────────────────────────────┐ │ 后端(FastAPI) │ │ ┌─────────────────────────────────────────────────────┐│ │ │ API层(路由) ││ │ │ conversation.py / diagnosis.py ││ │ └─────────────────────────────────────────────────────┘│ │ ┌─────────────────────────────────────────────────────┐│ │ │ Agent层(智能体) ││ │ │ ChatAgent / BaseAgent / orchestrator ││ │ └─────────────────────────────────────────────────────┘│ │ ┌─────────────────────────────────────────────────────┐│ │ │ Core层(核心能力) ││ │ │ SessionMemory / LLM / prompts / symptom_extractor ││ │ └─────────────────────────────────────────────────────┘│ │ ┌─────────────────────────────────────────────────────┐│ │ │ 数据层(持久化) ││ │ │ PostgreSQL + SQLAlchemy + async CRUD ││ │ └─────────────────────────────────────────────────────┘│ └─────────────────────────────────────────────────────────┘

分层设计的原则

  • 依赖方向从上到下:API → Agent → Core → 数据层

  • 下层不依赖上层,保证可测试性和可替换性

三、项目初始化:搭建开发环境

3.1 后端目录结构

text

backend/ ├── main.py # FastAPI入口 ├── config.py # 配置管理(单例模式) ├── requirements.txt # 依赖清单 ├── .env # 环境变量(不入库) ├── .env.example # 环境变量模板 │ ├── api/ # 路由层 │ ├── conversation.py # 会话管理API │ └── diagnosis.py # 诊疗API │ ├── agent/ # 智能体层 │ ├── base.py # Agent基类 │ ├── chat.py # 会话Agent │ └── orchestrator.py # Agent编排器 │ └── agents/ # 多个诊疗agent ├── core/ # 核心能力层 │ ├── llm.py # LLM封装(单例模式) │ ├── memory.py # 会话记忆管理 │ ├── prompts.py # 提示词模板 │ └── symptom_extractor.py # 症状提取器 │ ├── db/ # 数据层 │ ├── base.py # ORM基类 │ ├── session.py # 数据库会话管理 │ ├── models/ # 表结构定义 │ └── crud/ # CRUD操作 │ ├── models/ # Pydantic模型 │ └── schemas.py # API请求/响应校验 │ └── utils/ # 工具函数 ├── logger.py # 日志配置 └── helpers.py # 辅助函数

3.2 配置管理设计

配置管理的核心是环境隔离敏感信息保护

配置管理的两个关键技术点

  1. 单例模式:确保整个程序只有一个配置实例,避免配置不一致

  2. 环境变量模板.env.example提交到仓库,.env不入库,保障API密钥安全

3.3 数据库表设计

-- 会话表(顶层容器) CREATE TABLE sessions ( id VARCHAR(36) PRIMARY KEY, name VARCHAR(200), type ENUM('diagnosis', 'tongue'), created_at TIMESTAMP, updated_at TIMESTAMP ); -- 消息表(聊天记录) CREATE TABLE messages ( id BIGINT AUTO_INCREMENT PRIMARY KEY, session_id VARCHAR(36), role ENUM('user', 'assistant'), content TEXT, created_at TIMESTAMP, FOREIGN KEY (session_id) REFERENCES sessions(id) ); -- 诊疗记录表(一次“开始诊疗”一条记录) CREATE TABLE diagnoses ( id VARCHAR(36) PRIMARY KEY, session_id VARCHAR(36), sequence_num INT, -- 第几次诊疗 symptoms JSON, -- 症状快照 diagnosis TEXT, prescription TEXT, created_at TIMESTAMP, FOREIGN KEY (session_id) REFERENCES sessions(id) );

设计点sequence_num字段记录会话内第几次诊疗,为后续的多次诊疗对比功能预留扩展空间。

四、核心功能一:LLM封装与单例模式

4.1 设计目标

LLM封装层需要统一管理大模型调用,提供稳定的接口给上层Agent使用。

4.2 技术亮点:单例模式

为什么用单例?

问题没有单例有单例
连接池管理每次请求创建新连接池,内存泄漏一个连接池,复用HTTP连接
配置一致性可能创建不同配置的实例全局配置统一
API限流多个实例并发更容易触发限流统一管理请求速率

我的理解:单例模式是解决资源管理问题的工程实践。LLM实例封装了HTTP客户端,每个客户端维护连接池,如果每次调用都创建新实例,会导致连接泄漏和内存膨胀。

4.4 技术点:异步安全考虑

当前LLM()构造函数是同步的,用全局变量+None检查即可。但如果未来需要异步初始化(如加载远程配置),需要改用asyncio.Lock

_lock = asyncio.Lock() async def get_llm(): global _llm_instance if _llm_instance is None: async with _lock: if _llm_instance is None: _llm_instance = await create_llm_async() return _llm_instance

这种“双重检查锁定”模式确保了异步环境下的线程安全。

五、核心功能二:会话记忆管理

5.1 设计目标

记忆系统需要支持:

  • 多会话独立存储(诊疗会话和舌诊会话互不干扰)

  • 消息历史管理(限制数量,防止内存溢出)

  • 症状结构化提取(从自然语言中抽取标准化症状)

  • 诊疗记录保存(支持多次诊疗对比)

5.2 技术亮点:内存-数据库双重存储

存储用途读写速度持久性
内存(SessionMemory)当前活跃会话读写微秒级服务重启丢失
数据库(PostgreSQL)历史数据归档毫秒级永久保存

一致性策略:先写数据库,成功后更新内存。如果数据库写入失败,不更新内存,保持状态一致。

5.3 踩坑记录:历史会话显示不完全

现象:前端只能看到当前会话,历史会话部分消失。

原因get_patient_sessions方法返回的是self.memory.get_all_sessions(),而内存中的_metadata只在用户与某个会话交互后才会同步,导致大量历史会话“消失”。

解决方案:查询操作直接返回数据库查询结果,不依赖内存:

async def get_patient_sessions(self, patient_id: str, db: AsyncSession): # 直接从数据库查询 db_sessions = await self.db_manager.get_sessions_by_patient(db, patient_id) return [{"session_id": s.id, "name": s.name, ...} for s in db_sessions]

教训:内存只应用于加速当前活跃会话的读写,归档性质的读取操作应该直接从数据库读取。

六、核心功能三:会话Agent与提示词工程

6.1 设计目标

会话Agent是系统的“前台医生”,需要:

  • 理解用户症状描述

  • 按照中医问诊逻辑引导对话

  • 每轮只问1-2个问题,不给用户压力

  • 自动提取症状并结构化存储

6.2 提示词工程:从“无序提问”到“状态机问诊”

问题:如果只是简单告诉LLM“你是一名中医医生”,它的问诊往往是无序的、重复的,甚至会在用户刚说“头痛”时就问“您胃口好吗”。

解决方案:将中医“十问歌”的逻辑编码为结构化提示词:

# backend/core/prompts.py class TCMPrompts: @staticmethod def chat_agent(chat_history: str, current_message: str, extracted_symptoms: List[str] = None) -> str: return f"""你是一位经验丰富的中医医生。 【核心原则 - 必须遵守】 1. 每次只问1-2个问题 2. 遵循问诊顺序:主诉→伴随症状→寒热→汗→饮食→二便→睡眠 3. 不要重复问已回答的问题 4. 先表示共情再追问 【问诊顺序参考】 - 第一步:了解主诉(哪里不舒服?) - 第二步:询问伴随症状(还有其他不舒服吗?) - 第三步:问寒热(怕冷还是怕热?) - 第四步:问汗(出汗多吗?) - 第五步:问饮食(胃口怎么样?) - 第六步:问二便(大便成形吗?) 【示例回复 - Few-shot】 - “我了解了,头痛确实很影响生活。请问您头痛的同时,有没有怕冷或者发热的感觉呢?” - “感谢您的描述。根据您说的怕冷、不出汗,我再问一下,您最近胃口怎么样?” 【已有症状】{', '.join(extracted_symptoms) if extracted_symptoms else '无'} 【历史对话】 {chat_history} 用户最新消息:{current_message} 请直接输出你的回复(50-120字): """

6.3 技术点:Few-shot学习与约束设计

提示词中用了4个示例回复,本质上是在做模式匹配

示例适用场景作用
示例1用户刚描述主诉先共情,再追问寒热
示例2用户已回答部分信息总结已有信息,追问缺失项
示例3信息已比较完整给出初步分析,不再追问
示例4用户描述模糊请求具体化描述

这相当于给LLM提供了4种场景下的“标准答案模板”,让AI不再随意发挥。

6.4 会话Agent核心流程

# backend/agent/chat.py class ChatAgent: async def process_message(self, session_id: str, user_message: str, db: AsyncSession) -> Dict[str, Any]: # 1. 确保会话存在 if not self.memory.get_session_metadata(session_id): await self._load_session_from_db(session_id, db) # 2. 提取症状(LLM智能提取) new_symptoms = await self.memory.extract_and_update_symptoms( session_id, user_message ) # 3. 添加用户消息到内存 self.memory.add_message(session_id, "user", user_message) # 4. 保存到数据库 await self.db_manager.add_message(db, session_id, "user", user_message) # 5. 构建提示词并调用LLM prompt = self._build_prompt(session_id, user_message) response = await self.llm.generate(prompt) # 6. 保存助手回复 self.memory.add_message(session_id, "assistant", response) await self.db_manager.add_message(db, session_id, "assistant", response) return {"response": response, "symptoms": new_symptoms}

七、核心功能四:Agent基类与三级容错

7.1 设计目标

后续需要实现6个诊疗Agent(症状解析、辨证、方药等),需要一个统一的基类来:

  • 统一LLM调用接口

  • 统一状态管理

  • 统一输出解析

  • 统一进度推送

7.2 三级容错JSON解析

问题:LLM输出格式极其不可控,经常在JSON前后添加解释文字、Markdown标记等。

错误类型实际输出示例
添加解释文字"好的,这是结果:{\"symptoms\": [\"头痛\"]}"
Markdown包裹json\n{"symptoms": ["头痛"]}\n
自然语言混搭"根据您的描述,症状是:头痛、怕冷"

解决方案:三级降级容错

# backend/agent/base.py def _extract_json(self, text: str) -> Dict[str, Any]: """三级容错JSON提取器""" # 第一级:直接解析 try: return json.loads(text) except: pass # 第二级:提取 ```json ... ``` 代码块 json_pattern = r'```json\s*(.*?)\s*```' match = re.search(json_pattern, text, re.DOTALL) if match: try: return json.loads(match.group(1)) except: pass # 第三级:提取花括号内容 brace_pattern = r'\{[\s\S]*\}' match = re.search(brace_pattern, text, re.DOTALL) if match: try: return json.loads(match.group(0)) except: pass raise ValueError(f"无法提取JSON: {text[:200]}")

效果:解析成功率从约60%提升到90%以上。

7.3 之所以是三级

级别处理场景成功率
第一级纯净JSON约40%
第二级Markdown包裹的JSON约30%(累计70%)
第三级自然语言包裹的JSON约26%(累计96%)
全部失败完全非结构化输出约4%

核心认知:没有哪一级能覆盖所有情况。LLM的输出模式是多样的,必须用多层“筛子”逐级过滤。

八、API接口设计

8.1 会话管理接口

接口方法功能
/api/conversation/createPOST创建新会话
/api/conversation/messagePOST发送消息
/api/conversation/history/{session_id}GET获取会话历史
/api/conversation/rename/{session_id}PUT重命名会话
/api/conversation/delete/{session_id}DELETE删除会话
/api/conversation/patient/{patient_id}GET获取患者所有会话

8.2 关键代码

from fastapi import APIRouter, Depends from sqlalchemy.ext.asyncio import AsyncSession from agent.chat import get_chat_agent router = APIRouter(prefix="/api/conversation", tags=["conversation"]) @router.post("/message") async def send_message( session_id: str, message: str, db: AsyncSession = Depends(get_async_db) ) -> Dict[str, Any]: chat_agent = get_chat_agent() return await chat_agent.process_message(session_id, message, db)

8.3 路由注册

# backend/main.py from api.conversation import router as conversation_router app = FastAPI(title="中医智能诊疗系统") app.include_router(conversation_router)
http://www.jsqmd.com/news/706153/

相关文章:

  • DriveBench基准测试:揭示自动驾驶VLM可靠性挑战与评估方法
  • 质量优先:环保移动公厕、移动公厕租赁、连排移动公厕、免水冲移动公厕、单体移动厕所、塑料移动厕所出租、塑料移动厕所租赁选择指南 - 优质品牌商家
  • AI建站工具怎么选:一份中立实用的选型标准与对比指南
  • 2026年地暖技术深度解析:全屋公元家/公元五金/公元优家管/公元优管家/公元公司/公元农业/公元净水/公元品牌/选择指南 - 优质品牌商家
  • 计算机毕业设计:Python金融大数据可视化与LSTM预测系统 Flask框架 深度学习 机器学习 AI 大模型(建议收藏)✅
  • 海能达数字对讲机找哪家 - 速递信息
  • Redis如何通过永不过期策略规避击穿
  • 2026佛山短视频代运营公司实力大比拼 最新佛山代运营榜单TOP4 - 速递信息
  • 一套Unity框架解决所有RPG问题:ORK的系统设计哲学
  • 幼儿识字动画 1000 字 动画
  • 昆明黄金回收怎么不被坑?内行人教你选靠谱实体店 - 速递信息
  • #2026山东大学软件学院项目实训(四)——AI应用生成模块完整实现
  • AI Agent Harness Engineering 盈利模式设计:订阅制、按次付费与定制化服务
  • 零基础极速上手:普通人如何用AI建站工具10分钟搭建个人网站
  • Copilot Next 工作流配置全解析,深度拆解TypeScript项目自动测试生成+PR注释+文档同步链路
  • MCP 2026集成合规红线预警:5类非标组件已列入2026Q2禁用目录,你还在用吗?
  • 2026年想选好用的郑州联想电脑代理?哪家公司靠谱值得一探究竟! - 速递信息
  • 惯性摩擦焊机早期故障检测与排除技术实现【附代码】
  • 2026年祠堂升级!揭秘祠堂石雕定制,这些雕刻内容你知道吗?
  • 2026Q2优质家用预适应训练仪排行:便携预适应训练仪/全自动缺血预适应训练仪/家用超声波治疗仪/缺氧预适应训练仪/选择指南 - 优质品牌商家
  • 汕头海门木松鱼丸总店在哪?唯一正宗地址、电话与购买指南 - 速递信息
  • 2026年家谱软件技术解析:家谱软件那个好、族谱制作软件哪个好、族谱软件哪个好用、望族家史数字化家谱平台、比较好的家谱软件选择指南 - 优质品牌商家
  • 【Backend Flow工程实践 08】LEF / Liberty / Verilog / DEF:Backend Flow 为什么依赖多格式协同?
  • 知识图谱本体论体系:理论基础、构建方法与应用展望
  • 【Backend Flow工程实践 09】Design Import 不是读文件:它是在建立设计数据库的第一层语义
  • 2026氨分解纯化技术解析:制氮机氮气纯化、制氮机维修、制氮机设备改造、变压吸附制氮机、工业制氮机、氨分解发生炉选择指南 - 优质品牌商家
  • 算法训练营第十四天|18.四数之和
  • DocsGPT 二次开发:打造面向国内用户的私有 AI 知识库平台
  • 高精度 98陀螺 0.01度/小时 2.7w
  • Cubase15.0.21 Pro一键安装完整版下载安装Cubase 15 Pro最新版下载安装教程支持Win/Mac双系统版送104G原厂音源Mac系统苹果不关SIP安装Cubase15.0.21