智能问诊的流程

从症状分析到治疗建议:用 FastAPI 构建医疗多 Agent 工作流
随着大语言模型能力的提升,AI 应用正在从“单轮问答”逐渐发展为能够执行完整业务流程的智能体系统。医疗辅助问诊就是一个很典型的场景:系统不仅需要理解患者描述,还要完成症状分析、检查判断、诊断推理和治疗建议生成。
本文介绍一个医疗多 Agent 项目——MediAgent。它使用 FastAPI 提供 Web 服务,通过多个医疗 Agent 协作完成问诊流程,并结合 MySQL、RabbitMQ 和 Docker 构建了一套可运行的工程化方案。
本项目仅用于技术演示,生成内容不能替代专业医生的诊断和治疗建议。
一、项目解决什么问题?
传统的医疗问答通常采用一次请求、一次回答的模式,但真实问诊并不是一个单步骤任务。
一次完整问诊大致包含:
-
记录患者症状;
-
分析关键症状和潜在疾病;
-
判断是否需要化验检查;
-
根据症状和化验结果进行诊断;
-
根据诊断生成治疗建议;
-
保存问诊记录并展示报告。
MediAgent 将这些步骤拆分成多个职责明确的智能体:
-
症状分析 Agent:提取症状特征,判断可能疾病和所需检查;
-
诊断分析 Agent:结合症状、历史记录和化验结果进行诊断;
-
治疗建议 Agent:根据诊断结果生成治疗、用药和随访建议。
这种设计比单个超长 Prompt 更容易维护,也方便后续增加新的专业 Agent。
二、系统整体架构
MediAgent 主要由五部分组成:
-
原生 HTML、CSS、JavaScript 前端;
-
FastAPI 接口服务;
-
医疗多 Agent 模块;
-
MySQL 数据持久化;
-
RabbitMQ 异步消息通道。
项目中的主要目录如下:
MediAgent-LLM-main/ ├── agents/ # 医疗智能体 │ ├── symptom_analysis.py │ ├── diagnosis_analysis.py │ └── treatment_advice.py ├── async_engine/ # RabbitMQ 通信 ├── data_models/ # Pydantic 医疗数据模型 ├── memory/ # SQLAlchemy 数据模型和数据库操作 ├── static/ # 前端代码 │ ├── index.html │ ├── styles.css │ └── app.js ├── tools/ # LLM 客户端和授权模块 ├── workflow/ # 医疗工作流 ├── app.py # FastAPI 入口 └── docker-compose.yml # 容器编排
系统主流程如下:
不需要
需要
患者或医生填写症状
前端提交问诊
POST /workflow/start
创建问询记录
症状分析 Agent
是否需要化验
诊断分析 Agent
进入 WAITING_LAB 状态
提交化验结果
保存诊断结果
治疗建议 Agent
保存治疗建议
工作流完成
前端展示诊断报告
三、FastAPI 如何连接前后端?
项目入口位于 app.py。
FastAPI 将 static 目录挂载为静态资源目录,并在访问根路径时返回前端首页:
app.mount(
"/static",
StaticFiles(directory=BASE_DIR / "static"),
name="static"
)
@app.get("/", include_in_schema=False)
async def frontend():
return FileResponse(BASE_DIR / "static" / "index.html")
因此,这个项目不需要额外启动 Node.js 或前端开发服务器。
前端代码集中在:
static/index.html static/styles.css static/app.js
其中:
-
index.html负责页面结构; -
styles.css负责界面样式; -
app.js负责表单提交、状态轮询和结果展示。
前端启动问诊时会调用:
fetch("/workflow/start", {
method: "POST",
body: JSON.stringify({
patient_id: patientId,
doctor_id: doctorId,
symptom_description: symptom
})
})
获得工作流 ID 后,前端继续轮询状态接口:
GET /workflow/{workflow_id}/status
四、多 Agent 如何协同?
1. 症状分析 Agent
症状分析 Agent 接收患者的症状描述,并读取历史问诊数据。
它需要完成:
-
提取主要症状;
-
判断可能疾病;
-
评估风险;
-
判断是否需要化验;
-
生成建议检查项目。
分析结果会写入 MySQL,供后续诊断 Agent 使用。
2. 诊断分析 Agent
诊断 Agent 接收:
-
症状分析结果;
-
化验结果;
-
患者历史诊断。
它会生成主要诊断、鉴别诊断、诊断依据以及风险提示。
如果症状分析阶段判断不需要化验,该 Agent 会被直接调用;如果需要化验,则工作流进入等待状态,收到检查结果后再继续。
3. 治疗建议 Agent
治疗建议 Agent 根据诊断结果生成:
-
治疗方案;
-
用药建议;
-
注意事项;
-
随访建议。
项目中还预留了过敏禁忌检查逻辑。不过在当前工作流里,患者过敏史暂时使用空列表,后续可以连接真实患者档案。
五、工作流的一个重要实现细节
项目中已经使用 LangGraph 定义了完整工作流图,包括:
create_inquiry ↓ symptom_analysis ↓ check_lab_needed ↓ diagnosis_analysis ↓ treatment_advice ↓ complete_workflow
不过,当前真正运行的主流程没有直接调用编译后的 LangGraph,而是在 start_workflow() 中显式执行各个步骤。
简化后的代码逻辑类似:
state = self._create_inquiry_record(initial_state) state = self._perform_symptom_analysis(state) state = self._check_lab_tests_needed(state) if state.current_status == InquiryStatus.WAITING_LAB: return workflow_id state = self._perform_diagnosis_analysis(state) state = self._perform_treatment_advice(state) state = self._complete_workflow(state)
这样做可以规避旧版本 LangGraph 对普通 Python 状态对象合并和持久化不稳定的问题,但也意味着 LangGraph 当前更多承担“工作流定义”的角色。
后续可以将状态重构为 TypedDict 或符合 LangGraph 要求的数据结构,让实际执行重新回到图引擎。
六、化验结果为什么有两条通道?
项目中存在两种化验结果接入方式。
第一种是 HTTP 接口:
POST /lab/results
该接口会调用 handle_lab_results(),然后继续执行:
诊断分析 → 治疗建议 → 完成工作流
第二种是 RabbitMQ 消息队列。
应用启动时会创建一个后台消费者,监听:
exchange: lab_results_exchange queue: lab_results routing key: lab_result
不过需要特别注意:当前 RabbitMQ 消费者只负责解析消息、记录日志并确认消息,还没有调用 handle_lab_results() 恢复工作流。
因此,目前真正可用的化验续跑通道仍然是 /lab/results 接口。
可以在后续将消费者改造成:
def handle_lab_result(self, message): inquiry_record_id = message["inquiry_record_id"] lab_results = message["lab_results"] medical_workflow.handle_lab_results( inquiry_record_id=inquiry_record_id, lab_results=lab_results ) return True
这样 RabbitMQ 才会真正参与业务流程。
七、如何启动项目?
项目已经提供 Docker Compose 配置,可以一次启动 FastAPI、MySQL、Redis 和 RabbitMQ。
进入项目目录:
cd E:\WorkSpace\MediAgent-LLM-main\MediAgent-LLM-main
构建并启动:
docker compose up -d --build
查看容器状态:
docker compose ps
启动完成后可以访问:
-
问诊工作台:
http://127.0.0.1:8000/ -
API 文档:
http://127.0.0.1:8000/docs -
健康检查:
http://127.0.0.1:8000/health -
RabbitMQ 管理页:
http://127.0.0.1:15672/
停止服务:
docker compose down
如果希望保留数据库数据,不要删除 Compose volumes。
八、目前还可以改进什么?
MediAgent 已经具备完整的工程骨架,但距离生产环境还有一些工作。
工作流状态持久化
当前工作流状态主要保存在进程内存的 _states 字典中。服务重启后,等待化验的工作流无法继续。
可以将状态保存到 Redis 或数据库中,并在服务启动时恢复。
RabbitMQ 与工作流真正联动
消费者需要调用工作流恢复方法,而不是只记录消息。
同时还应增加:
-
消息幂等控制;
-
重试次数限制;
-
死信队列;
-
重复化验结果检测。
患者档案系统
当前过敏史等信息还没有接入真实档案。可以增加:
-
既往病史;
-
过敏史;
-
当前用药;
-
慢性疾病;
-
检查和诊断历史。
医疗安全控制
医疗类 AI 系统不能只依赖模型自由生成结果。生产方案还需要:
-
高风险症状规则;
-
紧急就医提示;
-
药物禁忌校验;
-
医生人工审核;
-
操作审计;
-
敏感信息脱敏。
九、总结
MediAgent 展示了一条比较完整的医疗多 Agent 工程化路线:
前端采集信息 → FastAPI 接收请求 → 症状分析 Agent → 化验条件分支 → 诊断分析 Agent → 治疗建议 Agent → MySQL 持久化 → 前端展示报告
它的价值不只在于“使用大模型生成医疗文本”,更重要的是把模型调用放进了一个可追踪、可持久化、可扩展的业务流程中。
如果继续完善状态持久化、消息队列联动、人工审核和医疗安全规则,这套架构还可以扩展到检验报告解读、慢病管理、远程随访和医院内部辅助决策等场景。
更多推荐


所有评论(0)