基于大模型的多轮对话智能导诊 HTTP API,推荐中国三甲医院标准科室。
- 完全自持:skill 代码内嵌在项目中,无外部项目依赖
- 多轮对话:服务端管理会话状态,客户端只需传
session_id - 危急重症熔断:每轮自动检测,命中即中止并建议拨打 120
- 状态机:
collecting→done/emergency_halted - SQLite 持久化:重启不丢失会话,零额外依赖
- 分层配置:系统参数从 YAML/环境变量启动加载;科室和急症存 SQLite 并在管理后即时刷新内存缓存
- 可信推荐:每个推荐科室包含
0-1置信度;无合适科室时明确返回原因 - 单镜像部署:
smart-triage:latest同时运行 API 与响应式 Web - 响应式管理 Web:支持手机、PAD、PC,包含登录、历史会话和完整配置管理
- 分级账号权限:管理员维护系统参数和用户,普通用户维护科室与急症规则
- API 使用文档 — 完整的端点说明、字段定义、错误码、客户端代码示例
- 交互式 Swagger 文档 — 服务启动后可在线调试
- skill 设计文档 — 科室清单、危急重症清单、问诊指南
smart-triage/
├── app/ # API 代码
│ ├── main.py # FastAPI 路由
│ ├── engine.py # 对话编排引擎
│ ├── config.py # YAML 启动配置 + SQLite 规则缓存
│ ├── session.py # SQLite 会话管理
│ └── schemas.py # Pydantic 模型
├── skill/ # 内嵌的导诊 skill(自持)
│ ├── scripts/triage.py
│ └── references/
│ ├── departments.md # 30 个三甲标准科室
│ ├── emergency.md # 危急重症清单
│ └── dialogue_guide.md # 问诊六维度
├── docker/
│ ├── Dockerfile # 自持镜像构建
│ ├── build.sh # 构建脚本
│ └── run.sh # 运行 API + Web 一体化容器
├── web/ # H5 页面、认证网关和进程监督程序
├── docs/
│ └── API.md # 完整 API 使用文档
├── tests/
│ └── test_api.py # API、配置、缓存与并发测试
├── config.yaml # LLM 与导诊启动配置
├── requirements.txt
├── .env.example
├── .dockerignore
├── run.sh # 本地运行脚本
└── README.md
# 1. 可直接使用 config.yaml;需要覆盖时设置环境变量
# export OPENAI_API_KEY=sk-your-key
# 2. 构建一体化镜像 smart-triage:latest
docker/build.sh
# 3. 运行容器
docker/run.sh
# Web: http://localhost:8080
# API: http://localhost:8000/docs管理员初始账号为 admin,初始密码为 dsti@****。管理员新增的普通用户初始密码为 triage@****。登录页不显示默认密码,所有用户均可退出登录并修改自己的密码。
Web 管理页支持导诊对话与独立历史记录、Markdown 回复、推荐科室和置信度、业务规则配置。右上角头像菜单提供个人信息、修改密码和退出登录。管理员额外拥有模型与策略、用户管理、服务日志和重启 API 权限;普通用户只能维护科室与急症清单。
容器内先启动 API,健康就绪后再启动 Web。API 与 Web 只使用宿主机 ~/.smart-triage-data 一个持久化目录,生效配置保存为其中的 config.yaml;首次运行从项目配置初始化,后续不会覆盖页面修改。页面展示带秒级日期时间的最新 1000 行 API 日志;重启按钮会重启 API 子进程。容器不挂载 Docker Socket,也不使用 root 用户。
# 1. 安装依赖
pip install -r requirements.txt
# 2. 按需编辑 config.yaml,或复制 .env.example 使用环境变量覆盖
# 3. 同时启动 API 与 Web
./run.sh启动后访问 http://localhost:8080 使用 Web,或访问 http://localhost:8000/docs 查看交互式 API 文档。
| 方法 | 路径 | 说明 |
|---|---|---|
GET |
/v1/health |
健康检查 |
POST |
/v1/sessions |
创建会话,返回 session_id + 首问 |
POST |
/v1/sessions/{id}/messages |
发送一轮对话 |
GET |
/v1/sessions/{id} |
查询会话状态与历史 |
DELETE |
/v1/sessions/{id} |
删除会话 |
GET |
/v1/config |
查询当前启动配置(不返回 API Key 明文) |
GET/POST/PATCH/DELETE |
/v1/config/departments |
管理科室清单 |
GET/POST/PATCH/DELETE |
/v1/config/emergencies |
管理急症清单 |
完整的端点说明、请求/响应字段、错误码、客户端代码示例见 docs/API.md。
# 创建会话
SID=$(curl -s -X POST http://localhost:8000/v1/sessions | python3 -c "import sys,json;print(json.load(sys.stdin)['session_id'])")
# 多轮对话
curl -X POST http://localhost:8000/v1/sessions/$SID/messages \
-H "Content-Type: application/json" \
-d '{"text":"我胃痛,饭后更明显"}'
# → {"status":"collecting","reply":"请问您的性别和年龄?...","turn_count":1}
curl -X POST http://localhost:8000/v1/sessions/$SID/messages \
-H "Content-Type: application/json" \
-d '{"text":"男,35岁,反酸两周"}'
# → {"status":"done","reply":"### 导诊建议\n...","result":{...}}
# 危急重症自动熔断
curl -X POST http://localhost:8000/v1/sessions/$SID/messages \
-d '{"text":"我爸突然胸痛,冒冷汗"}'
# → {"status":"emergency_halted","reply":"⚠️ 危急重症提示\n请立即拨打 120..."}status |
含义 | 是否终态 |
|---|---|---|
collecting |
信息收集中,返回下一个问题 | 否 |
done |
推荐已生成,含 result 字段 |
是 |
emergency_halted |
检测到危急重症,已中止 | 是 |
| 环境变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
OPENAI_API_KEY |
否 | config.yaml 中的 sk-xxx |
覆盖 YAML 中的 LLM API Key |
OPENAI_BASE_URL |
否 | https://api.deepseek.com/v1 |
覆盖 YAML 中的接口地址 |
OPENAI_MODEL |
否 | deepseek-v4-flash |
覆盖 YAML 中的模型 |
TRIAGE_MAX_TURNS |
否 | 6 |
覆盖 YAML 中的最大追问轮数 |
TRIAGE_RECOMMENDATION_COUNT |
否 | 2 |
覆盖 YAML 中的推荐科室数 |
TRIAGE_CONFIDENCE_THRESHOLD |
否 | 0.7 |
覆盖 YAML 中的置信度阈值 |
TRIAGE_CONFIG_PATH |
否 | ./config.yaml |
指定 YAML 配置文件路径 |
TRIAGE_DB_PATH |
否 | ./triage.db(本地)/ /app/data/triage.db(Docker) |
SQLite 文件路径 |
PORT |
否 | 8000 |
服务端口 |
TRIAGE_SKILL_PATH |
否 | 项目内 ./skill/scripts |
覆盖内嵌 skill 路径 |
- 镜像:
python:3.11-slim基础,非 root 用户运行 - 数据卷:
/app/data→ 宿主机~/.smart-triage-data(可改DATA_DIR环境变量) - 健康检查:容器内置
HEALTHCHECK,每 30s 探测/v1/health - 重启策略:
unless-stopped - 多实例:挂载同一数据卷时,SQLite 用
WAL模式 +BEGIN IMMEDIATE保证写安全;高并发建议改 Redis(需自行扩展session.py)
系统参数在服务启动时读取一次,优先级为“环境变量 > config.yaml”。修改这些参数后需要重启服务:
llm:
base_url: https://api.deepseek.com/v1
model: deepseek-v4-flash
api_key: sk-xxx
triage:
max_turns: 6
recommendation_count: 2
confidence_threshold: 0.7科室和急症清单保存在 SQLite。服务启动时加载到线程安全的内存快照;管理 API 写入成功后立即刷新缓存,下一轮导诊生效且不需要重启:
curl http://localhost:8000/v1/config/departments
curl http://localhost:8000/v1/config/emergencies配置约束:追问轮数 3-10;推荐科室数 1-3;置信度阈值 0-1;年龄上下限可为空;性别为 男、女 或 不限。配置管理 API 当前按内网服务设计,公网部署时应在网关增加管理员鉴权。
DATA_DIR=/var/lib/triage docker/run.shIMAGE_NAME=my-registry/triage IMAGE_TAG=v1.1.0 docker/build.sh
IMAGE_NAME=my-registry/triage IMAGE_TAG=v1.1.0 docker/run.shcollecting ──check emergency──> emergency_halted (终态)
│
│ check ok + collect
▼
collecting ──collect done / 达到配置轮次上限──> done (终态)
pip install pytest httpx
pytest tests/
# 36 passed(用 mock LLM,无需真实 API key)任意 OpenAI 兼容接口:
| 服务 | BASE_URL | MODEL |
|---|---|---|
| OpenAI | https://api.openai.com/v1 |
gpt-4o-mini |
| DeepSeek | https://api.deepseek.com/v1 |
deepseek-chat / deepseek-v4-flash |
| 通义千问 | https://dashscope.aliyuncs.com/compatible-mode/v1 |
qwen-plus |