32 KiB
医疗问诊 Agent 前端联调 API 文档
文档版本:2026-06-04
对应后端:FastAPImain分支当前版本
本文档以当前真实代码行为为准,用于正式 Vue 前端功能联调。
1. 联调地址
1.1 当前公网测试环境
| 项目 | 地址 |
|---|---|
| 网关根地址 | http://8.160.178.88/fastapi |
| API Base URL | http://8.160.178.88/fastapi/api/v1 |
| Swagger | http://8.160.178.88/fastapi/docs |
| OpenAPI JSON | http://8.160.178.88/fastapi/openapi.json |
| 存活检查 | http://8.160.178.88/fastapi/health/live |
| 就绪检查 | http://8.160.178.88/fastapi/health/ready |
当前 /health/ready 已验证 MySQL、Redis 和生产配置处于就绪状态。
如果服务器关闭 Nginx 的 /fastapi/ 公网代理,公网地址将不可用,前端需要改用局域网、VPN、SSH 隧道或新的测试网关。
1.2 Docker 主机内部地址
http://127.0.0.1:9000
该地址只用于服务器本机检查,不提供给远程前端。
2. 前端接入规则
2.1 认证链路
医疗问诊 Agent 不实现登录注册,也不接受前端传入 user_id。
前端从宿主系统获得 access token
-> 请求 FastAPI 时携带 Authorization: Bearer <access_token>
-> FastAPI 将 token 转发给 Django /api/user/users/me/
-> Django 返回 200 和用户资料
-> FastAPI 使用 Django 返回的 id 隔离会话、检查、提交和评价记录
前端禁止传递或信任 X-User-Id。
2.2 通用请求头
除健康检查外,所有业务接口必须携带:
Authorization: Bearer <access_token>
X-Entry-Scene: vue_frontend
X-Request-Id: <可选的请求追踪ID>
| Header | 必填 | 说明 |
|---|---|---|
Authorization |
是 | Django 用户中心 access token。 |
X-Entry-Scene |
否 | 入口场景,例如 vue_frontend、production_vue。 |
X-Request-Id |
否 | 前端生成的请求追踪 ID。 |
2.3 统一响应
除 SSE 流式问诊外,接口统一返回:
{
"code": "OK",
"message": "success",
"data": {}
}
前端必须同时判断 HTTP 状态码和业务 code:
if (!response.ok || body.code !== "OK") {
throw new Error(body.message || body.code || "request failed");
}
3. 当前接口总览
3.0 训练页面交付接口表
以下表格为前端训练页面当前交付接口。url 使用公网网关前缀,前端实际调用时统一在 api 前拼接 http://8.160.178.88/fastapi。
| 模块 | 接口名称 | url | api | methods | params | response | 说明 |
|---|---|---|---|---|---|---|---|
| 训练页面 | 推荐配置信息 | http://8.160.178.88/fastapi/api/v1/training-config/recommended |
/api/v1/training-config/recommended |
GET |
Query:case_id |
recommended、recommended_labels、options |
初始化训练页病人配置,默认选中门诊、青年、高等教育、平和。 |
| 训练页面 | 训练配置信息 | http://8.160.178.88/fastapi/api/v1/training-config/options |
/api/v1/training-config/options |
GET |
Query:case_id |
recommended、recommended_labels、options |
返回自定义配置全部可选项,用于前端渲染就诊环境、年龄段、文化程度、性格。 |
| 训练页面 | 新建会话 | http://8.160.178.88/fastapi/api/v1/sessions |
/api/v1/sessions |
POST |
Body:case_id、training_type、mode、score_type、patient_config |
session_id、session_code、status、patient_opening、patient_config |
创建训练会话并把病人初始化配置写入会话 metadata。 |
| 训练页面 | 流式会话 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/chat/stream |
/api/v1/sessions/{session_id}/chat/stream |
POST |
Path:session_id;Body:message |
SSE:message_delta、message_done、error |
医学生问诊,AI 病人按病例和配置流式回复。 |
| 训练页面 | 练习提示 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/hints/stream |
/api/v1/sessions/{session_id}/hints/stream |
POST |
Path:session_id;Body:last_user_message、scope |
SSE:hint_delta、hint_done、error |
返回一句话形式的练习提示,前端点击后按需展示。旧 JSON 接口 /hints 保留兼容。 |
| 训练页面 | 体格检查列表获取 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/physical-exams |
/api/v1/sessions/{session_id}/physical-exams |
GET |
Path:session_id |
items[] |
从当前病例检查项中筛选体格检查类项目。暂无独立表,复用 case_exam_item。 |
| 训练页面 | 辅助检查列表获取 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/auxiliary-exams |
/api/v1/sessions/{session_id}/auxiliary-exams |
GET |
Path:session_id |
items[] |
从当前病例检查项中筛选辅助检查类项目。暂无独立表,复用 case_exam_item。 |
| 训练页面 | 体格检查某项结果 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/physical-exams/{item_code} |
/api/v1/sessions/{session_id}/physical-exams/{item_code} |
POST |
Path:session_id、item_code |
检查结果结构 | 返回数据库固定检查结果,并写入本次会话上下文。 |
| 训练页面 | 辅助检查某项结果 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/auxiliary-exams/{item_code} |
/api/v1/sessions/{session_id}/auxiliary-exams/{item_code} |
POST |
Path:session_id、item_code |
检查结果结构 | 返回数据库固定检查结果,并写入本次会话上下文。 |
| 训练页面 | 完成问诊 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/complete-inquiry |
/api/v1/sessions/{session_id}/complete-inquiry |
POST |
Path:session_id |
session_id、status |
从问诊阶段进入诊断阶段。 |
| 训练页面 | 提交诊断 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/diagnosis |
/api/v1/sessions/{session_id}/diagnosis |
POST |
Path:session_id;Body:诊断内容 |
status |
保存主要诊断、鉴别诊断和诊断依据。 |
| 训练页面 | 提交治疗 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/treatment |
/api/v1/sessions/{session_id}/treatment |
POST |
Path:session_id;Body:治疗内容 |
status |
保存治疗原则、措施、风险预案、沟通和随访。 |
| 训练页面 | 生成评价 | http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/evaluation |
/api/v1/sessions/{session_id}/evaluation |
POST |
Path:session_id;Body:score_type |
评价报告结构 | 调用评分 Agent,写入 training_record 和 training_score_detail。 |
| 训练页面 | 获取评价(详情) | http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id} |
/api/v1/evaluations/{evaluation_id} |
GET |
Path:evaluation_id |
评价详情和评分明细 | 按当前 token 对应用户隔离查询。 |
| 训练页面 | 下载 PDF | http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/export-pdf |
/api/v1/evaluations/{evaluation_id}/export-pdf |
POST |
Path:evaluation_id |
export_id、file_path |
生成本地 PDF 报告路径。 |
| 训练页面 | 历史评价列表 | http://8.160.178.88/fastapi/api/v1/evaluations |
/api/v1/evaluations |
GET |
无 | items[] |
查询当前 token 对应用户的完整训练评价历史。 |
3.1 无需认证
| Method | Path | 用途 |
|---|---|---|
GET |
/health/live |
FastAPI 进程存活检查。 |
GET |
/health/ready |
MySQL、Redis 和关键配置就绪检查。 |
3.2 需要 Bearer Token
以下路径均以 /api/v1 为前缀。
| Method | Path | 用途 | 前端范围 |
|---|---|---|---|
GET |
/auth/me |
校验 token 并获取当前用户。 | 必须 |
GET |
/agent/hello |
获取 Agent 能力开关。 | 必须 |
GET |
/cases |
获取病例列表。 | 必须 |
GET |
/cases/{case_id} |
获取病例入口详情。 | 必须 |
GET |
/training-config/recommended |
获取推荐配置信息。 | 必须 |
GET |
/training-config/options |
获取训练配置选项。 | 必须 |
POST |
/sessions |
创建训练会话。 | 必须 |
POST |
/sessions/{session_id}/chat |
非流式问诊。 | 必须 |
POST |
/sessions/{session_id}/chat/stream |
SSE 流式问诊。 | 必须 |
POST |
/sessions/{session_id}/hints |
练习模式提示。 | 必须 |
POST |
/sessions/{session_id}/hints/stream |
SSE 一句话练习提示。 | 必须 |
GET |
/sessions/{session_id}/order-items |
获取病例可申请检查项。 | 必须 |
POST |
/sessions/{session_id}/orders |
申请检查并返回结果。 | 必须 |
GET |
/sessions/{session_id}/physical-exams |
获取体格检查列表。 | 必须 |
GET |
/sessions/{session_id}/auxiliary-exams |
获取辅助检查列表。 | 必须 |
POST |
/sessions/{session_id}/physical-exams/{item_code} |
获取体格检查某项结果。 | 必须 |
POST |
/sessions/{session_id}/auxiliary-exams/{item_code} |
获取辅助检查某项结果。 | 必须 |
POST |
/sessions/{session_id}/complete-inquiry |
完成问诊。 | 必须 |
POST |
/sessions/{session_id}/diagnosis |
提交诊断。 | 必须 |
POST |
/sessions/{session_id}/treatment |
提交治疗方案。 | 必须 |
POST |
/sessions/{session_id}/evaluation |
生成 AI 评价。 | 必须 |
GET |
/evaluations |
查询当前用户历史评价。 | 必须 |
GET |
/evaluations/{evaluation_id} |
查询评价详情和评分明细。 | 必须 |
POST |
/evaluations/{evaluation_id}/export-pdf |
生成 PDF 报告。 | 必须 |
GET |
/knowledge/search |
调试知识检索。 | 调试 |
POST |
/llm/test/deepseek-fast |
测试快速模型。 | 调试 |
POST |
/llm/test/deepseek-reason |
测试 Reason 模型。 | 调试 |
病例接口为只读接口。病例新增、解析、修改和删除由外部病例管理系统负责,正式前端不得调用本服务管理病例。
4. 前端完整业务流程
GET /auth/me
-> GET /agent/hello
-> GET /cases
-> GET /cases/{case_id}
-> POST /sessions
-> 多轮问诊、提示、检查申请
-> POST /sessions/{session_id}/complete-inquiry
-> POST /sessions/{session_id}/diagnosis
-> POST /sessions/{session_id}/treatment
-> POST /sessions/{session_id}/evaluation
-> GET /evaluations/{evaluation_id}
-> POST /evaluations/{evaluation_id}/export-pdf
会话状态流转:
inquiry -> diagnosis -> treatment -> evaluating -> completed
| 状态 | 允许操作 |
|---|---|
inquiry |
问诊、提示、检查申请、完成问诊。 |
diagnosis |
提交诊断、继续申请检查。 |
treatment |
提交治疗、继续申请检查。 |
evaluating |
生成评价。 |
completed |
查看评价、导出 PDF、查看历史记录。 |
当前没有“获取会话详情”“恢复聊天记录”接口。页面刷新或中断后,前端不能恢复短期对话,应重新创建训练会话。
5. 认证与 Agent
5.1 获取当前用户
GET /api/v1/auth/me
Authorization: Bearer <access_token>
成功响应:
{
"code": "OK",
"message": "success",
"data": {
"user_id": "37",
"source": "django_user_center",
"username": "13700000099",
"display_name": "测试用户",
"tenant_id": "1",
"role": "student",
"phone": "13700000099",
"avatar": null,
"gender": 0,
"institution": 1,
"institution_id": 1,
"institution_name": "测试机构",
"department": 2,
"department_id": 2,
"department_name": "儿科",
"title_name": null,
"major": null,
"training_stage": null,
"learning_target": null,
"competency_profile": {},
"weak_dimensions": [],
"strong_dimensions": [],
"ai_preference": {},
"total_training_count": 0,
"total_case_count": 0,
"current_level": null,
"status": 1
}
}
前端规则:
- 进入 Agent 后首先调用本接口。
- 返回 200 且
code=OK才允许进入训练页面。 - 后续所有请求继续携带相同 token。
user_id只用于展示或前端状态标识,不能由前端覆盖。
5.2 获取 Agent 能力
GET /api/v1/agent/hello
Authorization: Bearer <access_token>
响应核心结构:
{
"code": "OK",
"message": "success",
"data": {
"user": {
"user_id": "37",
"role": "student",
"source": "django_user_center",
"username": "13700000099",
"display_name": "测试用户"
},
"features": {
"stream_chat": true,
"score_types": ["percentage", "five_point"],
"pdf_export": true,
"knowledge_search": true,
"llm_mock_enabled": false,
"llm_mode": "real",
"llm_fallback_to_mock": false,
"llm_fast_model": "deepseek-chat",
"llm_reason_model": "deepseek-reasoner",
"runtime_memory_backend": "redis",
"auth_validate_enabled": true,
"auth_source": "django_user_center"
}
}
}
6. 病例接口
6.1 病例列表
GET /api/v1/cases?department_id=2&mode=practice
Query 参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
department_id |
integer | 否 | 科室 ID。 |
training_type |
string | 否 | case_analysis、diagnosis_treatment、consultation。 |
mode |
string | 否 | practice 或 teaching。 |
响应:
{
"code": "OK",
"message": "success",
"data": {
"items": [
{
"id": 2,
"case_code": "SRC_2",
"department_id": 2,
"title": "支气管肺炎 - 6岁男性患儿",
"difficulty": "medium",
"chief_complaint": "发热、咳嗽4天,喘息1天",
"supported_training_type": "diagnosis_treatment",
"supported_mode": "free_chat",
"has_teaching_video": false,
"has_knowledge_points": true,
"has_quiz": false
}
]
}
}
6.2 病例详情
GET /api/v1/cases/{case_id}
响应不会返回标准诊断、标准治疗、隐藏病史、评分规则和检查结果:
{
"code": "OK",
"message": "success",
"data": {
"id": 2,
"case_code": "SRC_2",
"title": "支气管肺炎 - 6岁男性患儿",
"department": "儿科",
"difficulty": "medium",
"patient": {
"name": null,
"age": 6,
"gender": "male",
"occupation": null
},
"chief_complaint": "发热、咳嗽4天,喘息1天",
"supported_training_type": "diagnosis_treatment",
"supported_mode": "free_chat",
"has_teaching_video": false,
"has_knowledge_points": true,
"has_quiz": false,
"order_item_types": ["imaging", "lab", "vital_sign"]
}
}
7. 创建训练会话
7.1 推荐配置信息
GET /api/v1/training-config/recommended?case_id=2
响应:
{
"code": "OK",
"message": "success",
"data": {
"case_id": 2,
"recommended": {
"visit_environment": "outpatient",
"age_group": "youth",
"education_level": "higher",
"personality": "calm"
},
"recommended_labels": {
"visit_environment": "门诊",
"age_group": "青年",
"education_level": "高等教育",
"personality": "平和"
},
"options": {
"visit_environment": [
{"value": "outpatient", "label": "门诊", "description": "适合常规问诊训练"}
],
"age_group": [],
"education_level": [],
"personality": []
}
}
}
7.2 训练配置信息
GET /api/v1/training-config/options?case_id=2
该接口返回和推荐配置信息相同的结构,前端使用 options 渲染自定义配置按钮,使用 recommended 初始化默认选中项。
7.3 新建会话
POST /api/v1/sessions
Content-Type: application/json
请求:
{
"case_id": 2,
"training_type": "diagnosis_treatment",
"mode": "practice",
"score_type": "percentage",
"patient_config": {
"visit_environment": "outpatient",
"age_group": "youth",
"education_level": "higher",
"personality": "calm"
}
}
字段:
| 字段 | 允许值 | 说明 |
|---|---|---|
training_type |
case_analysis、diagnosis_treatment、consultation |
训练类别。 |
mode |
practice、teaching |
正式前端使用的两种模式。 |
score_type |
percentage、five_point |
百分制或五分制。 |
patient_config.visit_environment |
outpatient、emergency、ward |
就诊环境。 |
patient_config.age_group |
child、youth、middle_aged、elderly |
病人年龄段配置。 |
patient_config.education_level |
primary_or_below、secondary、higher |
病人文化程度配置。 |
patient_config.personality |
calm、anxious、impatient、cooperative、suspicious |
病人性格配置。 |
后端仍接受旧值 novice,但会自动转换为 practice。正式前端不要继续使用 novice。
响应:
{
"code": "OK",
"message": "success",
"data": {
"session_id": 10,
"session_code": "sess_20260604100000_abcd1234",
"status": "inquiry",
"patient_opening": "家长:医生,孩子发热咳嗽好几天了,昨天开始喘得厉害,精神也不太好。",
"patient_config": {
"values": {
"visit_environment": "outpatient",
"age_group": "youth",
"education_level": "higher",
"personality": "calm"
},
"labels": {
"visit_environment": "门诊",
"age_group": "青年",
"education_level": "高等教育",
"personality": "平和"
}
}
}
}
前端创建新会话时必须清空上一轮 Chat、检查结果、诊断、治疗和评价状态。
8. 问诊接口
8.1 非流式问诊
POST /api/v1/sessions/{session_id}/chat
Content-Type: application/json
请求:
{
"message": "孩子发热几天了?最高体温多少?"
}
响应:
{
"code": "OK",
"message": "success",
"data": {
"reply": "发热有4天了,最高烧到39度多,吃了退烧药能降下来,但过几个小时又会烧。",
"latency_ms": 2500,
"model": "deepseek-chat",
"fallback_used": false
}
}
8.2 SSE 流式问诊
POST /api/v1/sessions/{session_id}/chat/stream
Content-Type: application/json
Accept: text/event-stream
请求体与非流式接口相同。
事件格式:
event: message_delta
data: {"delta":"发热有4天了,"}
event: message_done
data: {"latency_ms":3200,"first_token_ms":800,"model":"deepseek-chat","fallback_used":false}
event: error
data: {"code":"LLM_STREAM_TIMEOUT","message":"AI 病人首段回复超时,请重试或关闭流式模式"}
前端必须处理:
| 事件 | 处理 |
|---|---|
message_delta |
将 delta 追加到当前 AI 气泡。 |
message_done |
结束 pending,启用发送按钮。 |
error |
结束 pending,显示错误信息。 |
请求中断或流结束但没有 message_done |
结束 pending,提示重试。 |
流式请求使用 fetch,不要使用原生 EventSource,因为该接口是 POST 且需要请求体和 Authorization。
async function streamChat(baseUrl: string, token: string, sessionId: number, message: string) {
const response = await fetch(`${baseUrl}/sessions/${sessionId}/chat/stream`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "text/event-stream",
Authorization: `Bearer ${token}`,
"X-Entry-Scene": "vue_frontend",
},
body: JSON.stringify({ message }),
});
if (!response.ok || !response.body) {
throw new Error(`stream request failed: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
let completed = false;
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const blocks = buffer.split("\n\n");
buffer = blocks.pop() || "";
for (const block of blocks) {
const event = block.match(/^event:\s*(.+)$/m)?.[1];
const rawData = block.match(/^data:\s*(.+)$/m)?.[1];
if (!event || !rawData) continue;
const data = JSON.parse(rawData);
if (event === "message_delta") {
// appendAiText(data.delta)
} else if (event === "message_done") {
completed = true;
} else if (event === "error") {
throw new Error(data.message);
}
}
}
if (!completed) throw new Error("AI 流式回复未正常结束");
}
8.3 练习提示
8.3.1 JSON 兼容接口
POST /api/v1/sessions/{session_id}/hints
请求:
{
"last_user_message": "孩子发热几天了?最高体温多少?",
"scope": "current_conversation"
}
响应:
{
"code": "OK",
"message": "success",
"data": {
"hints": ["可以继续追问热型、退热药反应和呼吸困难表现。"],
"missing_dimensions": ["既往史", "严重程度评估"],
"next_questions": [
"孩子以前有没有喘息、哮喘或过敏史?",
"孩子现在有没有呼吸困难或口唇发紫?"
],
"recommended_orders": [
{
"item_code": "spo2",
"reason": "用于评估低氧和病情严重程度"
}
]
}
}
约束:
- 仅
practice模式可调用。 - 仅
inquiry状态可调用。 - 前端默认不自动展示提示,由用户点击后调用。
8.3.2 SSE 一句话提示
POST /api/v1/sessions/{session_id}/hints/stream
Content-Type: application/json
Accept: text/event-stream
请求:
{
"last_user_message": "孩子发热几天了?最高体温多少?",
"scope": "current_conversation"
}
事件格式:
event: hint_delta
data: {"delta":"当前可补充既往史、严重程度评估;"}
event: hint_done
data: {"latency_ms":1200}
event: error
data: {"code":"HINT_STREAM_FAILED","message":"练习提示生成失败,请稍后重试"}
前端规则:
- 该接口用于训练页面“查看提示”的新交互。
- 返回内容为一句话形式,适合在提示区域流式展示。
- 如果收到
error,前端结束 loading 并展示错误。 - 旧 JSON 接口
/hints保留,用于需要结构化缺失维度和推荐检查的页面。
9. 检查与检验
9.1 获取当前病例检查项
GET /api/v1/sessions/{session_id}/order-items
响应:
{
"code": "OK",
"message": "success",
"data": {
"items": [
{
"item_code": "blood_routine",
"item_name": "血常规",
"item_type": "lab"
}
]
}
}
前端不得写死检查项编码。不同病例拥有不同检查项,必须使用本接口返回的 item_code。
9.2 获取体格检查列表
GET /api/v1/sessions/{session_id}/physical-exams
响应结构与 /order-items 相同。当前没有独立体格检查表,后端按 item_type、category、item_name 从 case_exam_item 中识别体格检查类项目。
9.3 获取辅助检查列表
GET /api/v1/sessions/{session_id}/auxiliary-exams
响应结构与 /order-items 相同。当前没有独立辅助检查表,非体格检查类项目均归入辅助检查。
9.4 申请检查
POST /api/v1/sessions/{session_id}/orders
请求:
{
"item_code": "blood_routine"
}
响应:
{
"code": "OK",
"message": "success",
"data": {
"item_code": "blood_routine",
"item_name": "血常规",
"item_type": "lab",
"result_text": "WBC 12.5×10^9/L,中性粒细胞比例72%,提示感染及炎症反应。",
"result_structured": {
"wbc": "12.5×10^9/L",
"neutrophil": "72%"
},
"is_key": true,
"is_abnormal": true,
"context_written": true,
"already_ordered": false
}
}
规则:
- 检查结果只来自数据库,不由 LLM 生成。
- 检查结果会写入本次会话上下文和评分依据。
- 同一会话重复申请相同
item_code时,返回已有结果并设置already_ordered=true。 - 前端按
item_code去重;点击后立即禁用,避免重复请求。 - 检查申请允许在
inquiry、diagnosis、treatment状态执行。
9.5 获取体格检查某项结果
POST /api/v1/sessions/{session_id}/physical-exams/{item_code}
响应结构与 /orders 相同。该接口用于前端按“体格检查”分区调用,内部仍复用检查申请逻辑。
9.6 获取辅助检查某项结果
POST /api/v1/sessions/{session_id}/auxiliary-exams/{item_code}
响应结构与 /orders 相同。该接口用于前端按“辅助检查”分区调用,内部仍复用检查申请逻辑。
10. 阶段提交
10.1 完成问诊
POST /api/v1/sessions/{session_id}/complete-inquiry
请求体:无。
响应:
{
"code": "OK",
"message": "success",
"data": {
"session_id": 10,
"status": "diagnosis"
}
}
至少完成一轮医生提问,否则返回 INQUIRY_REQUIRED。
10.2 提交诊断
POST /api/v1/sessions/{session_id}/diagnosis
请求:
{
"primary_diagnosis": "支气管肺炎",
"differential_diagnoses": [
"支气管哮喘急性发作",
"上呼吸道感染"
],
"diagnosis_basis": "结合发热、咳嗽、喘息、肺部体征、炎症指标、胸片和血氧结果,符合儿童支气管肺炎表现。"
}
成功响应:
{
"code": "OK",
"message": "success",
"data": {
"status": "treatment"
}
}
10.3 提交治疗
POST /api/v1/sessions/{session_id}/treatment
请求:
{
"treatment_principle": "抗感染、止咳平喘、改善氧合并严密观察病情变化。",
"treatment_measures": "根据病情进行抗感染治疗,必要时雾化缓解喘息,监测体温、呼吸和血氧。",
"risk_plan": "关注低氧、呼吸困难加重、持续高热、精神反应差和脱水。",
"communication": "向家属说明病情、用药注意事项、危险信号和复诊指征。",
"follow_up": "治疗后复查体温、呼吸、血氧和必要的炎症指标。"
}
成功响应:
{
"code": "OK",
"message": "success",
"data": {
"status": "evaluating"
}
}
11. AI 评价、历史记录与 PDF
11.1 生成评价
POST /api/v1/sessions/{session_id}/evaluation
请求:
{
"score_type": "percentage"
}
响应:
{
"code": "OK",
"message": "success",
"data": {
"evaluation_id": 101,
"score_type": "percentage",
"total_score": 82,
"dimension_scores": [
{
"dimension": "信息获取",
"score": 18,
"max_score": 25,
"comment": "已覆盖主要症状,但既往喘息史追问不足。",
"evidence": ["询问发热天数和最高体温"],
"deductions": ["未充分询问既往喘息史"],
"improvement": "补充既往史、过敏史和严重程度评估。"
}
],
"score_details": [
{
"id": 501,
"record_id": 101,
"rule_id": 1,
"dimension": "信息获取",
"score": 18,
"deducted_reason": "未充分询问既往喘息史",
"evidence_message_ids": ["询问发热天数和最高体温"],
"ai_confidence": 0.85,
"comment": "补充既往史和过敏史。"
}
],
"errors": [],
"improvement_plan": ["加强儿童肺炎严重程度评估训练。"],
"evidence_summary": ["检查结果已写入评分依据。"],
"guideline_refs": [],
"overall_comment": "诊断方向正确,问诊完整性和沟通细节仍需加强。"
}
}
评价成功后:
- 会话状态变为
completed。 - 写入
training_record和training_score_detail。 - 当前 Redis 短期聊天 memory 被释放。
- 相同会话再次调用评价接口时返回已存在的评价,不重复创建。
11.2 历史评价列表
GET /api/v1/evaluations
响应:
{
"code": "OK",
"message": "success",
"data": {
"items": [
{
"evaluation_id": 101,
"case_title": "支气管肺炎 - 6岁男性患儿",
"score_type": "percentage",
"total_score": 82,
"created_at": "2026-06-04T10:00:00",
"pdf_exported": true
}
]
}
}
11.3 评价详情
GET /api/v1/evaluations/{evaluation_id}
返回字段包含完整评价结构,并额外包含:
{
"session_id": 10,
"case_id": 2,
"case_title": "支气管肺炎 - 6岁男性患儿",
"created_at": "2026-06-04T10:00:00",
"pdf_file_path": "/app/storage/reports/training_record_101_percentage_xxx.pdf"
}
11.4 导出 PDF
POST /api/v1/evaluations/{evaluation_id}/export-pdf
响应:
{
"code": "OK",
"message": "success",
"data": {
"export_id": 101,
"file_path": "/app/storage/reports/training_record_101_percentage_xxx.pdf"
}
}
当前接口只生成 PDF 并返回服务器内部文件路径,没有提供浏览器文件下载流。前端功能测试阶段展示“导出成功”和文件路径即可。正式下载接口需要后续增加受鉴权保护的文件响应接口。
12. 调试接口
12.1 知识检索
GET /api/v1/knowledge/search?department_id=2&training_type=diagnosis_treatment&q=肺炎,血氧
12.2 LLM 测试
POST /api/v1/llm/test/deepseek-fast
POST /api/v1/llm/test/deepseek-reason
请求:
{
"message": "请用一句话说明医疗问诊训练的用途。"
}
13. 前端 Axios 封装示例
import axios from "axios";
export const apiClient = axios.create({
baseURL: "http://8.160.178.88/fastapi/api/v1",
timeout: 60000,
});
apiClient.interceptors.request.use((config) => {
const token = sessionStorage.getItem("access_token");
if (token) config.headers.Authorization = `Bearer ${token}`;
config.headers["X-Entry-Scene"] = "vue_frontend";
config.headers["X-Request-Id"] = crypto.randomUUID();
return config;
});
apiClient.interceptors.response.use(
(response) => {
if (response.data?.code !== "OK") {
return Promise.reject(new Error(response.data?.message || response.data?.code));
}
return response;
},
(error) => {
if (error.response?.status === 401) {
// 返回宿主系统登录页或触发 token 刷新
}
return Promise.reject(error);
},
);
14. 常见错误码
| HTTP | code | 说明 |
|---|---|---|
| 401 | AUTH_CREDENTIAL_REQUIRED |
缺少 Authorization。 |
| 401 | AUTH_USER_INVALID |
token 无效、过期或 Django 返回非 200。 |
| 403 | AUTH_USER_DISABLED |
Django 用户状态被禁用。 |
| 503 | AUTH_USER_CENTER_UNAVAILABLE |
Django 用户中心超时或不可达。 |
| 404 | CASE_NOT_FOUND |
病例不存在、未发布或已停用。 |
| 404 | SESSION_NOT_FOUND |
会话不存在或不属于当前用户。 |
| 400 | SESSION_STATUS_INVALID |
当前状态不允许执行该操作。 |
| 400 | INQUIRY_REQUIRED |
完成问诊前没有医生提问。 |
| 400 | DIAGNOSIS_REQUIRED |
提交治疗前没有提交诊断。 |
| 400 | TREATMENT_REQUIRED |
生成评价前没有提交治疗。 |
| 404 | ORDER_ITEM_NOT_FOUND |
当前病例不存在该检查项。 |
| 404 | EVALUATION_NOT_FOUND |
评价不存在或不属于当前用户。 |
| 504 | LLM_CALL_TIMEOUT |
非流式问诊超时。 |
| SSE error | LLM_STREAM_TIMEOUT |
流式问诊首段或总耗时超时。 |
| SSE error | LLM_STREAM_FAILED |
流式模型调用失败。 |
| SSE error | LLM_EMPTY_RESPONSE |
模型未返回有效文本。 |
| 500 | PDF_EXPORT_FAILED |
PDF 生成失败。 |
15. 前端功能验收顺序
- 打开
/health/ready,确认返回status=ready。 - 使用真实 token 调用
/auth/me,确认返回 Django 用户id。 - 调用
/agent/hello,确认llm_mode=real、runtime_memory_backend=redis。 - 获取病例列表和病例详情。
- 创建
practice会话。 - 测试普通问诊和 SSE 流式问诊。
- 点击查看提示,确认返回动态提示。
- 动态读取检查项并申请检查,重复申请时确认
already_ordered=true。 - 完成问诊、提交诊断、提交治疗。
- 生成评价,确认包含
dimension_scores和score_details。 - 查询历史列表和评价详情。
- 导出 PDF,确认接口返回文件路径。
16. 当前前端必须了解的限制
- 无会话详情和聊天恢复接口,页面刷新后无法恢复短期问诊。
- 问诊聊天只保存在 Redis 短期 memory 中,评价完成后释放。
- PDF 导出当前只返回服务器文件路径,不直接下载文件。
- 病例库为只读数据源;新增、解析、修改和删除由外部病例管理系统完成。
- 所有检查项必须从
/order-items动态读取,不能写死。 - 正式训练模式只有
practice和teaching;novice仅为旧接口兼容值。