Files
fastapi/docs/03_api_design.md
T
2026-06-08 16:49:45 +08:00

18 KiB
Raw Blame History

医疗问诊 Agent API 文档

当前文档只描述前端联调需要的后端能力。

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

2. 通用规则

除健康检查外,所有业务接口都需要携带:

Authorization: Bearer <access_token>
X-Entry-Scene: vue_frontend
X-Request-Id: <可选>

普通 JSON 接口统一返回:

{
  "code": "OK",
  "message": "success",
  "data": {}
}

前端判断规则:

  • HTTP 状态码为 2xx
  • code 等于 OK
  • 业务数据从 data 读取

SSE 流式接口不返回上述 JSON 包装,而是返回 event + data 事件流。

3. 前置接口

3.1 当前用户

接口名称 url api methods params(入参) response(返回参数)
当前用户 http://8.160.178.88/fastapi/api/v1/auth/me /api/v1/auth/me GET HeaderAuthorization 必填,格式 Bearer <access_token>X-Entry-Scene 建议传。 data.user_iddata.usernamedata.display_namedata.roledata.phonedata.institution_iddata.department_iddata.status 等 Django 用户中心字段。

请求示例:

GET /api/v1/auth/me
Authorization: Bearer <access_token>
X-Entry-Scene: vue_frontend

成功返回示例:

{
  "code": "OK",
  "message": "success",
  "data": {
    "user_id": "37",
    "source": "django_user_center",
    "username": "13700000099",
    "display_name": "测试用户",
    "tenant_id": "1",
    "role": "student",
    "phone": "13700000099",
    "avatar": "",
    "gender": 0,
    "institution_id": 1,
    "institution_name": "测试机构",
    "department_id": 2,
    "department_name": "儿科",
    "status": 1
  }
}

3.2 病例读取

接口名称 url api methods params(入参) response(返回参数)
病例列表 http://8.160.178.88/fastapi/api/v1/cases /api/v1/cases GET Querydepartment_id 选填,科室 IDtraining_type 选填;mode 选填,允许 practiceteaching data.items[],包含 idtitledepartment_iddifficultychief_complainthas_teaching_videohas_quiz
病例详情 http://8.160.178.88/fastapi/api/v1/cases/{case_id} /api/v1/cases/{case_id} GET Pathcase_id 必填,病例 ID。 病例入口展示信息,不返回标准答案、隐藏病史、检查结果和评分规则。

4. 训练页面接口

接口名称 url api methods params(入参) response(返回参数)
推荐配置信息 http://8.160.178.88/fastapi/api/v1/training-config/recommended?case_id={case_id} /api/v1/training-config/recommended GET Querycase_id 必填,病例 ID。 data.recommended 默认配置;data.recommended_labels 中文标签。
训练配置信息 http://8.160.178.88/fastapi/api/v1/training-config/options?case_id={case_id} /api/v1/training-config/options GET Querycase_id 必填,病例 ID。 data.options 全部可选项;data.recommended 推荐默认值。
新建会话 http://8.160.178.88/fastapi/api/v1/sessions /api/v1/sessions POST Bodycase_id 必填;training_type 必填;mode 必填,当前训练填 practicescore_type 选填,允许 percentagefive_pointpatient_config 选填。 data.session_iddata.session_codedata.statusdata.patient_openingdata.patient_config
流式会话 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/chat/stream /api/v1/sessions/{session_id}/chat/stream POST Pathsession_id 必填;Bodymessage 必填,医学生问句。 SSEmessage_delta 返回患者回复增量;message_done 返回耗时;error 返回错误。
王主任练习提示 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/hints/stream /api/v1/sessions/{session_id}/hints/stream POST Pathsession_id 必填;Bodylast_user_message 选填;scope 选填,默认 current_conversation SSEhint_delta 返回一句话提示增量;hint_done 返回结束事件。
体格检查列表获取 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/physical-exams /api/v1/sessions/{session_id}/physical-exams GET Pathsession_id 必填。 data.items[],包含体格检查项 item_codeitem_nameitem_type。不返回结果。
辅助检查列表获取 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/auxiliary-exams /api/v1/sessions/{session_id}/auxiliary-exams GET Pathsession_id 必填。 data.items[],包含辅助检查项 item_codeitem_nameitem_type。不返回结果。
体格检查某项结果 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 Pathsession_id 必填;item_code 必填,必须属于体格检查。 data.result_textdata.result_structureddata.context_writtendata.already_ordered
辅助检查某项结果 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 Pathsession_id 必填;item_code 必填,必须属于辅助检查。 data.result_textdata.result_structureddata.context_writtendata.already_ordered
完成问诊 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/complete-inquiry /api/v1/sessions/{session_id}/complete-inquiry POST Pathsession_id 必填。至少完成一轮医生问诊。 data.session_iddata.status=diagnosis
提交诊断 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/diagnosis /api/v1/sessions/{session_id}/diagnosis POST Pathsession_id 必填;Bodyprimary_diagnosis 必填;diagnosis_basis 必填;differential_diagnoses 选填数组。 data.status=treatment
提交治疗 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/treatment /api/v1/sessions/{session_id}/treatment POST Pathsession_id 必填;Bodytreatment_principletreatment_measures 必填;risk_plancommunicationfollow_up 选填。 data.status=evaluating
生成评价 http://8.160.178.88/fastapi/api/v1/sessions/{session_id}/evaluation /api/v1/sessions/{session_id}/evaluation POST Pathsession_id 必填;Bodyscore_type 选填,允许 percentagefive_point。必须已提交治疗。 data.evaluation_iddata.total_scoredata.dimension_scores[]data.score_details[]data.overall_comment
获取评价(详情) http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id} /api/v1/evaluations/{evaluation_id} GET Pathevaluation_id 必填。只允许当前用户访问自己的评价。 评价详情,包含病例、总分、维度评分、评分明细、改进建议、PDF 路径。
下载 PDF http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/download-pdf /api/v1/evaluations/{evaluation_id}/download-pdf GET Pathevaluation_id 必填。HeaderAuthorization 必填。 成功时返回 application/pdf 文件流,浏览器可下载;失败时返回统一错误 JSON。

4.1 训练配置入参和返回示例

请求:

GET /api/v1/training-config/options?case_id=2
Authorization: Bearer <access_token>
X-Entry-Scene: vue_frontend

返回:

{
  "code": "OK",
  "message": "success",
  "data": {
    "case_id": 2,
    "recommended": {
      "visit_environment": "outpatient",
      "age_group": "child",
      "education_level": "higher",
      "personality": "calm"
    },
    "recommended_labels": {
      "visit_environment": "门诊",
      "age_group": "儿童",
      "education_level": "高等教育",
      "personality": "平和"
    },
    "options": {
      "visit_environment": [
        {"value": "outpatient", "label": "门诊"},
        {"value": "emergency", "label": "急诊"},
        {"value": "ward", "label": "病房"}
      ],
      "age_group": [
        {"value": "child", "label": "儿童"},
        {"value": "youth", "label": "青年"},
        {"value": "middle_aged", "label": "中年"},
        {"value": "elderly", "label": "老年"}
      ],
      "education_level": [
        {"value": "primary_or_below", "label": "小学及以下"},
        {"value": "secondary", "label": "中等教育"},
        {"value": "higher", "label": "高等教育"}
      ],
      "personality": [
        {"value": "calm", "label": "平和"},
        {"value": "anxious", "label": "焦虑"},
        {"value": "impatient", "label": "急躁"},
        {"value": "cooperative", "label": "配合"},
        {"value": "suspicious", "label": "多疑"}
      ]
    }
  }
}

4.2 新建会话入参和返回示例

请求:

{
  "case_id": 2,
  "training_type": "diagnosis_treatment",
  "mode": "practice",
  "score_type": "percentage",
  "patient_config": {
    "visit_environment": "outpatient",
    "age_group": "child",
    "education_level": "higher",
    "personality": "calm"
  }
}

返回:

{
  "code": "OK",
  "message": "success",
  "data": {
    "session_id": 12,
    "session_code": "sess_20260608120000_xxxx",
    "status": "inquiry",
    "patient_opening": "家长:医生,孩子发热咳嗽好几天了,昨天开始喘得厉害,精神也不太好。",
    "patient_config": {
      "values": {
        "visit_environment": "outpatient",
        "age_group": "child",
        "education_level": "higher",
        "personality": "calm"
      },
      "labels": {
        "visit_environment": "门诊",
        "age_group": "儿童",
        "education_level": "高等教育",
        "personality": "平和"
      }
    }
  }
}

4.3 SSE 流式会话返回格式

请求:

{
  "message": "孩子发热几天了?最高体温多少?"
}

返回:

event: message_delta
data: {"delta":"发热有4天了,"}

event: message_delta
data: {"delta":"最高烧到39度多。"}

event: message_done
data: {"latency_ms":1800,"first_token_ms":500,"model":"deepseek-chat","fallback_used":false}

4.4 检查结果返回示例

{
  "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 生成。
  • 检查结果会写入本次会话短期 memory 和评分依据。
  • 同一会话重复申请相同 item_code 时返回已有结果,already_ordered=true

4.5 诊断和治疗提交示例

提交诊断:

{
  "primary_diagnosis": "支气管肺炎",
  "differential_diagnoses": ["支气管哮喘急性发作", "上呼吸道感染"],
  "diagnosis_basis": "结合发热、咳嗽、喘息、肺部湿啰音、胸片异常、炎症指标升高和血氧情况,符合儿童支气管肺炎表现。"
}

提交治疗:

{
  "treatment_principle": "抗感染、止咳平喘、改善氧合并严密观察病情变化。",
  "treatment_measures": "根据病情进行抗感染治疗,必要时雾化吸入缓解喘息,监测体温、呼吸和血氧。",
  "risk_plan": "关注低氧、呼吸困难加重、持续高热、精神反应差和脱水。",
  "communication": "向家属说明病情、用药注意事项、危险信号和复诊指征。",
  "follow_up": "治疗后复查体温、呼吸、血氧和必要炎症指标。"
}

5. 教学互动接口

接口名称 url api methods params(入参) response(返回参数)
获取教学列表(题目 选项 答案 解析文本 视频) http://8.160.178.88/fastapi/api/v1/teaching/cases/{case_id}/items /api/v1/teaching/cases/{case_id}/items GET Pathcase_id 必填,必须存在 teaching_case 数据。 data.case 病例摘要;data.questions[] 题目列表,包含 stemoptions[]answeranalysisvideo
生成评价 http://8.160.178.88/fastapi/api/v1/teaching/evaluation /api/v1/teaching/evaluation POST Bodycase_id 必填;answers[] 必填;answers[].question_id 必填;answers[].selected_answer 必填;score_type 选填。 data.session_iddata.evaluation_iddata.total_scoredata.dimension_scores[]data.score_details[]data.overall_comment
获取评价(详情) http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id} /api/v1/evaluations/{evaluation_id} GET Pathevaluation_id 必填。 教学互动评价详情,结构与训练评价一致。
下载 PDF http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/download-pdf /api/v1/evaluations/{evaluation_id}/download-pdf GET Pathevaluation_id 必填。 返回 application/pdf 文件流。

获取教学列表返回示例:

{
  "code": "OK",
  "message": "success",
  "data": {
    "case": {
      "case_id": 2,
      "title": "支气管肺炎 - 6岁男性患儿",
      "chief_complaint": "发热、咳嗽4天,喘息1天"
    },
    "teaching_goal": "围绕儿科肺炎问诊、检查选择、诊断依据、治疗决策和医患沟通完成互动训练。",
    "questions": [
      {
        "question_id": "q1",
        "question_type": "single_choice",
        "stem": "该患儿最需要优先关注的病情严重程度指标是?",
        "options": [
          {"key": "A", "text": "体温峰值"},
          {"key": "B", "text": "血氧饱和度"}
        ],
        "answer": "B",
        "analysis": "血氧饱和度能帮助判断低氧和肺炎严重程度。",
        "video": {"title": "儿童肺炎教学示例视频", "url": ""},
        "knowledge_points": ["严重程度评估", "血氧判断"]
      }
    ]
  }
}

生成教学评价请求示例:

{
  "case_id": 2,
  "score_type": "percentage",
  "answers": [
    {"question_id": "q1", "selected_answer": "B"},
    {"question_id": "q2", "selected_answer": "A"}
  ]
}

6. 个人中心接口

接口名称 url api methods params(入参) response(返回参数)
训练记录列表 http://8.160.178.88/fastapi/api/v1/evaluations /api/v1/evaluations GET HeaderAuthorization 必填。 data.items[] 当前用户完整训练后的评价记录,包含 evaluation_idcase_titlescore_typetotal_scorecreated_atpdf_exported
训练记录详情(评价详情) http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id} /api/v1/evaluations/{evaluation_id} GET Pathevaluation_id 必填。 完整评价详情,训练和教学互动评价共用。

训练记录列表返回示例:

{
  "code": "OK",
  "message": "success",
  "data": {
    "items": [
      {
        "evaluation_id": 101,
        "case_title": "支气管肺炎 - 6岁男性患儿",
        "score_type": "percentage",
        "total_score": 82,
        "created_at": "2026-06-08T12:00:00",
        "pdf_exported": true
      }
    ]
  }
}

7. PDF 下载前端写法

因为下载接口需要 Bearer token,前端不能直接使用普通 <a href>。使用 fetch 获取 blob 后触发下载:

async function downloadEvaluationPdf(baseUrl: string, token: string, evaluationId: number) {
  const response = await fetch(`${baseUrl}/evaluations/${evaluationId}/download-pdf`, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${token}`,
      "X-Entry-Scene": "vue_frontend",
    },
  });

  if (!response.ok) {
    const error = await response.json().catch(() => null);
    throw new Error(error?.message || `PDF 下载失败:${response.status}`);
  }

  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `evaluation_${evaluationId}.pdf`;
  document.body.appendChild(a);
  a.click();
  a.remove();
  URL.revokeObjectURL(url);
}

8. 常见错误码

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 当前病例不存在该检查项。
400 ORDER_ITEM_TYPE_MISMATCH 检查接口类型和检查项类型不匹配。
404 EVALUATION_NOT_FOUND 评价不存在或不属于当前用户。
SSE error LLM_STREAM_TIMEOUT 流式问诊首段或总耗时超时。
SSE error LLM_STREAM_FAILED 流式模型调用失败。
500 PDF_EXPORT_FAILED PDF 生成失败。

9. 当前保留接口清单

当前后端业务模块:

  • 训练页面:推荐配置、训练配置、新建会话、流式会话、王主任练习提示、检查列表、检查结果、完成问诊、诊断、治疗、评价、评价详情、PDF 下载。
  • 教学互动:教学列表、教学评价、评价详情、PDF 下载。
  • 个人中心:训练记录列表、训练记录详情。