810 lines
20 KiB
Markdown
810 lines
20 KiB
Markdown
# 前端 API 对接文档
|
||
|
||
本文档面向 Vue 前端与后续正式前端开发,描述当前第一版 Demo 已实现的后端接口、请求头、状态流转、字段结构和错误处理规则。
|
||
|
||
## 1. 通用约定
|
||
|
||
### 1.1 Base URL
|
||
|
||
本地开发默认地址:
|
||
|
||
```text
|
||
http://127.0.0.1:8000/api/v1
|
||
```
|
||
|
||
前端默认配置:
|
||
|
||
```text
|
||
Vite dev server: http://127.0.0.1:5173
|
||
API base: http://127.0.0.1:8000/api/v1
|
||
```
|
||
|
||
### 1.2 必传 Header
|
||
|
||
所有业务接口都必须携带以下 Header:
|
||
|
||
| Header | 类型 | 说明 |
|
||
|---|---:|---|
|
||
| `X-User-Id` | string | 宿主系统传入的用户标识。后端按该字段隔离会话、提交、评价和历史记录。 |
|
||
| `X-Entry-Scene` | string | 入口场景。Demo 前端默认 `vue_demo`。 |
|
||
|
||
可选 Header:
|
||
|
||
| Header | 类型 | 说明 |
|
||
|---|---:|---|
|
||
| `X-Tenant-Id` | string | 租户、机构或项目 ID。第一版只透传和审计。 |
|
||
| `X-User-Role` | string | 用户角色。第一版只透传和审计。 |
|
||
| `X-Class-Id` | string | 班级或课程 ID。第一版只透传和审计。 |
|
||
| `X-Request-Id` | string | 请求链路 ID。前端有链路追踪需求时传入。 |
|
||
|
||
### 1.3 统一响应结构
|
||
|
||
除 SSE 流式接口外,后端统一返回:
|
||
|
||
```json
|
||
{
|
||
"code": "OK",
|
||
"message": "success",
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
前端处理规则:
|
||
|
||
- `code === "OK"`:读取 `data`。
|
||
- `code !== "OK"`:展示 `message`,不要直接展示底层异常。
|
||
- HTTP 401 通常表示缺少 `X-User-Id`。
|
||
- HTTP 404 通常表示资源不存在或不属于当前 `user_id`。
|
||
- HTTP 400 通常表示当前状态不允许操作或入参不合法。
|
||
|
||
### 1.4 常见错误码
|
||
|
||
| code | 场景 | 前端处理 |
|
||
|---|---|---|
|
||
| `USER_ID_REQUIRED` | 缺少 `X-User-Id` | 回到入口设置页,提示填写 user_id。 |
|
||
| `CASE_NOT_FOUND` | 病例不存在、未启用或已删除 | 刷新病例列表。 |
|
||
| `CASE_DELETE_CONFIRM_REQUIRED` | 删除病例未传 `confirm=true` | 保持确认弹窗,不执行删除。 |
|
||
| `CASE_DELETE_TRAINING_DATA_EXISTS` | 病例存在训练数据但未允许删除训练数据 | 当前前端固定传 `delete_training_data=true`。 |
|
||
| `SESSION_NOT_FOUND` | 会话不存在或不属于当前用户 | 回到病例页重新创建会话。 |
|
||
| `SESSION_STATUS_INVALID` | 当前阶段不允许执行该操作 | 根据 `status` 禁用按钮并提示原因。 |
|
||
| `INQUIRY_REQUIRED` | 完成问诊前没有医生提问 | 提示至少完成一轮问诊。 |
|
||
| `DIAGNOSIS_REQUIRED` | 提交治疗前未提交诊断 | 引导到诊断表单。 |
|
||
| `TREATMENT_REQUIRED` | 生成评价前未提交治疗 | 引导到治疗表单。 |
|
||
| `ORDER_ITEM_NOT_FOUND` | 检查项不存在 | 刷新检查项列表。 |
|
||
| `LLM_CALL_TIMEOUT` | 非流式模型调用超时 | 提示重试。 |
|
||
| `LLM_STREAM_TIMEOUT` | 流式模型调用超时 | 结束 pending,提示重试或关闭流式。 |
|
||
| `LLM_STREAM_FAILED` | 流式模型调用失败 | 结束 pending,提示模型服务异常。 |
|
||
| `CASE_SQL_FILE_INVALID` | 上传文件不是 `.sql` | 提示选择 SQL 文件。 |
|
||
| `CASE_SQL_FILE_EMPTY` | SQL 文件为空 | 提示重新导出文件。 |
|
||
| `CASE_SQL_FILE_TOO_LARGE` | 文件超过 5MB | 提示压缩或拆分。 |
|
||
| `CASE_SQL_IMPORT_INVALID` | SQL 解析或字段映射失败 | 展示 `errors`,不允许确认导入。 |
|
||
|
||
## 2. 前端主流程
|
||
|
||
```text
|
||
入口页
|
||
-> GET /agent/hello
|
||
病例页
|
||
-> GET /cases
|
||
-> GET /cases/{case_id}
|
||
-> GET /cases/{case_id}/delete-preview
|
||
-> DELETE /cases/{case_id}
|
||
训练配置页
|
||
-> POST /sessions
|
||
Chat 页
|
||
-> POST /sessions/{session_id}/chat 或 /chat/stream
|
||
-> POST /sessions/{session_id}/hints
|
||
-> GET /sessions/{session_id}/order-items
|
||
-> POST /sessions/{session_id}/orders
|
||
提交页
|
||
-> POST /sessions/{session_id}/complete-inquiry
|
||
-> POST /sessions/{session_id}/diagnosis
|
||
-> POST /sessions/{session_id}/treatment
|
||
报告页
|
||
-> POST /sessions/{session_id}/evaluation
|
||
-> POST /evaluations/{evaluation_id}/export-pdf
|
||
历史页
|
||
-> GET /evaluations
|
||
-> GET /evaluations/{evaluation_id}
|
||
导入页
|
||
-> POST /imports/case-sql/preview
|
||
-> POST /imports/case-sql/apply
|
||
LLM 测试页
|
||
-> POST /llm/test/deepseek-fast
|
||
-> POST /llm/test/deepseek-reason
|
||
```
|
||
|
||
训练会话状态流转:
|
||
|
||
```text
|
||
inquiry -> diagnosis -> treatment -> evaluating -> evaluated
|
||
```
|
||
|
||
前端按钮启用规则:
|
||
|
||
| 阶段 | 允许操作 |
|
||
---|---|
|
||
| `inquiry` | 问诊、查看提示、申请检查、完成问诊 |
|
||
| `diagnosis` | 提交诊断 |
|
||
| `treatment` | 提交治疗方案 |
|
||
| `evaluating` | 生成评价报告 |
|
||
| `evaluated` | 查看报告、导出 PDF、查看历史 |
|
||
|
||
## 3. Agent Hello
|
||
|
||
### `GET /agent/hello`
|
||
|
||
用途:检查后端连接,返回当前用户上下文和 Demo 能力开关。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"user": {
|
||
"user_id": "demo_user_001",
|
||
"tenant_id": null,
|
||
"role": null
|
||
},
|
||
"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-v4-pro",
|
||
"llm_reason_model": "deepseek-v4-pro",
|
||
"runtime_memory_backend": "redis"
|
||
}
|
||
}
|
||
```
|
||
|
||
前端展示说明:
|
||
|
||
- `stream_chat`:是否支持 SSE 流式问诊。
|
||
- `score_types`:评分输出类型,`percentage` 为百分制,`five_point` 为五分制。
|
||
- `pdf_export`:是否支持 PDF 导出。
|
||
- `knowledge_search`:是否已接入评分参考指南检索。
|
||
- `llm_mock_enabled`:是否强制使用 mock 模型。
|
||
- `llm_fallback_to_mock`:真实模型失败时是否回退 mock。
|
||
- `runtime_memory_backend`:短期记忆后端,通常为 `redis` 或 `memory`。
|
||
|
||
## 4. 病例接口
|
||
|
||
### `GET /cases`
|
||
|
||
用途:获取病例列表。不会返回标准答案、隐藏病史、评分细则。
|
||
|
||
Query:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---:|---:|---|
|
||
| `department_id` | number | 否 | 科室筛选。 |
|
||
| `training_type` | string | 否 | 训练类别筛选:`case_analysis`、`diagnosis_treatment`、`consultation`。 |
|
||
| `mode` | string | 否 | 模式筛选:`practice`、`teaching`。 |
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"id": 2,
|
||
"case_code": "SRC_2",
|
||
"department_id": 1,
|
||
"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
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### `GET /cases/{case_id}`
|
||
|
||
用途:获取病例训练入口详情。不会返回标准诊断、标准治疗、隐藏病史。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"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": ["lab", "imaging", "vital_sign"]
|
||
}
|
||
```
|
||
|
||
### `GET /cases/{case_id}/delete-preview`
|
||
|
||
用途:删除病例前统计影响范围。前端删除弹窗先调用该接口。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"case_id": 2,
|
||
"case_title": "支气管肺炎 - 6岁男性患儿",
|
||
"can_delete": true,
|
||
"affected": {
|
||
"case_base": 1,
|
||
"traditional_case": 1,
|
||
"teaching_case": 0,
|
||
"scoring_rule": 1,
|
||
"case_exam_item": 6,
|
||
"training_session": 1,
|
||
"training_order": 6,
|
||
"training_submission": 1,
|
||
"training_record": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
### `DELETE /cases/{case_id}`
|
||
|
||
用途:确认后删除病例及关联业务数据。审计日志只记录删除行为,不反删。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"confirm": true,
|
||
"delete_training_data": true
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"deleted": true,
|
||
"case_id": 2,
|
||
"deleted_counts": {
|
||
"training_order": 6,
|
||
"training_submission": 1,
|
||
"training_record": 1,
|
||
"training_session": 1,
|
||
"case_exam_item": 6,
|
||
"scoring_rule": 1,
|
||
"traditional_case": 1,
|
||
"teaching_case": 0,
|
||
"case_base": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
前端交互规则:
|
||
|
||
- 删除按钮只放在病例详情区,不放在病例卡片上。
|
||
- 点击删除后先调用 `delete-preview`。
|
||
- 弹窗展示 `affected`。
|
||
- 用户输入固定确认文案后再调用 `DELETE`。
|
||
- 删除成功后清空当前病例、会话、检查结果、报告缓存,并刷新 `/cases`。
|
||
|
||
## 5. 会话与问诊接口
|
||
|
||
### `POST /sessions`
|
||
|
||
用途:创建训练会话,初始化短期 memory。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"case_id": 2,
|
||
"training_type": "diagnosis_treatment",
|
||
"mode": "practice",
|
||
"score_type": "percentage"
|
||
}
|
||
```
|
||
|
||
字段说明:
|
||
|
||
| 字段 | 允许值 | 说明 |
|
||
|---|---|---|
|
||
| `training_type` | `case_analysis`、`diagnosis_treatment`、`consultation` | 训练类别。 |
|
||
| `mode` | `practice`、`teaching` | 训练模式。后端兼容旧值 `novice`,会归一为 `practice`。 |
|
||
| `score_type` | `percentage`、`five_point` | 评分输出类型。 |
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"session_id": 10,
|
||
"session_code": "sess_20260528100000_abcd1234",
|
||
"status": "inquiry",
|
||
"patient_opening": "家长:医生,孩子发热咳嗽好几天了,昨天开始喘得厉害,精神也不太好。"
|
||
}
|
||
```
|
||
|
||
### `POST /sessions/{session_id}/chat`
|
||
|
||
用途:普通非流式问诊。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"message": "孩子发热几天了?最高体温多少?"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"reply": "发热有4天了,最高烧到39度多,吃了退烧药能降下来,但过几个小时又会烧。",
|
||
"latency_ms": 2500,
|
||
"model": "deepseek-v4-pro",
|
||
"fallback_used": false
|
||
}
|
||
```
|
||
|
||
校验:
|
||
|
||
- 会话必须属于当前 `X-User-Id`。
|
||
- 当前状态必须为 `inquiry`。
|
||
- `message` 长度 1 到 2000。
|
||
|
||
### `POST /sessions/{session_id}/chat/stream`
|
||
|
||
用途:SSE 流式问诊。当前 Chat 页面优先使用该接口。
|
||
|
||
Request 同普通问诊。
|
||
|
||
SSE 事件:
|
||
|
||
```text
|
||
event: message_delta
|
||
data: {"delta":"发热有4天了,"}
|
||
|
||
event: message_done
|
||
data: {"latency_ms":3200,"first_token_ms":800,"model":"deepseek-v4-pro","fallback_used":false}
|
||
|
||
event: error
|
||
data: {"code":"LLM_STREAM_TIMEOUT","message":"AI 病人回复超时,请重试"}
|
||
```
|
||
|
||
前端处理规则:
|
||
|
||
- 收到 `message_delta`:追加到当前 AI 病人气泡。
|
||
- 收到 `message_done`:结束 pending,启用发送按钮。
|
||
- 收到 `error`:结束 pending,展示错误。
|
||
- fetch abort 或 reader done 但未收到 `message_done`:结束 pending,提示“AI 病人回复超时或失败,请重试”。
|
||
|
||
### `POST /sessions/{session_id}/hints`
|
||
|
||
用途:练习模式下手动生成提示。提示基于病例、当前对话和已申请检查动态生成。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"last_user_message": "孩子发热几天了?最高体温多少?",
|
||
"scope": "current_conversation"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"hints": [
|
||
"可以继续追问最高体温、热型和退热药反应。"
|
||
],
|
||
"missing_dimensions": [
|
||
"既往史",
|
||
"严重程度评估"
|
||
],
|
||
"next_questions": [
|
||
"孩子以前有没有喘息、哮喘或过敏史?",
|
||
"现在血氧是多少?有没有呼吸困难?"
|
||
],
|
||
"recommended_orders": [
|
||
{
|
||
"item_code": "oxygen_saturation",
|
||
"reason": "用于判断低氧和病情严重程度"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
前端处理规则:
|
||
|
||
- 提示不自动弹出。
|
||
- 只在练习模式中显示“查看提示”按钮。
|
||
- 练习模式中是否点击提示不影响评分链路。
|
||
- 教学互动模式当前不显示提示入口。
|
||
|
||
## 6. 检查/检验接口
|
||
|
||
### `GET /sessions/{session_id}/order-items`
|
||
|
||
用途:获取当前病例可申请的检查项目。只返回名称和类型,不返回检查结果。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"item_code": "complete_blood_count",
|
||
"item_name": "血常规",
|
||
"item_type": "lab"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### `POST /sessions/{session_id}/orders`
|
||
|
||
用途:申请检查/检验,结果必须来自数据库 `case_exam_item`,不允许 LLM 编造。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"item_code": "complete_blood_count"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"item_code": "complete_blood_count",
|
||
"item_name": "血常规",
|
||
"item_type": "lab",
|
||
"result_text": "WBC 12.4×10^9/L,中性粒细胞72%。",
|
||
"result_structured": {},
|
||
"is_key": true,
|
||
"is_abnormal": true,
|
||
"context_written": true,
|
||
"already_ordered": false
|
||
}
|
||
```
|
||
|
||
幂等规则:
|
||
|
||
- 同一 `session_id + item_code` 只写入一次。
|
||
- 重复申请返回已有结果,`already_ordered=true`。
|
||
- 重复申请不重复写入 runtime memory。
|
||
- 前端按 `item_code` 去重展示。
|
||
|
||
## 7. 阶段提交接口
|
||
|
||
### `POST /sessions/{session_id}/complete-inquiry`
|
||
|
||
用途:完成问诊,进入诊断阶段。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"session_id": 10,
|
||
"status": "diagnosis"
|
||
}
|
||
```
|
||
|
||
校验:至少存在一轮医生提问。
|
||
|
||
### `POST /sessions/{session_id}/diagnosis`
|
||
|
||
用途:提交诊断。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"primary_diagnosis": "支气管肺炎",
|
||
"differential_diagnoses": ["毛细支气管炎", "支气管哮喘急性发作", "上呼吸道感染"],
|
||
"diagnosis_basis": "结合发热、咳嗽、喘息、肺部体征、炎症指标升高、胸片异常和血氧情况,符合儿童支气管肺炎表现。"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"status": "treatment"
|
||
}
|
||
```
|
||
|
||
### `POST /sessions/{session_id}/treatment`
|
||
|
||
用途:提交治疗方案。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"treatment_principle": "抗感染、止咳平喘、改善氧合、严密观察病情变化。",
|
||
"treatment_measures": "根据病情选择抗感染治疗,必要时雾化吸入缓解喘息,监测体温、呼吸、血氧和精神反应。",
|
||
"risk_plan": "关注低氧、呼吸困难加重、持续高热、精神反应差、脱水等情况。",
|
||
"communication": "向家属说明肺炎病情、用药注意事项、观察指标和复诊/住院指征。",
|
||
"follow_up": "治疗后复查体温、呼吸、血氧和必要炎症指标,症状加重时及时就诊。"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"status": "evaluating"
|
||
}
|
||
```
|
||
|
||
## 8. 评价与报告接口
|
||
|
||
### `POST /sessions/{session_id}/evaluation`
|
||
|
||
用途:生成 AI 评价报告。后端读取评分规则、知识检索结果、检查申请、问诊过程和提交内容后调用 Scoring Agent。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"score_type": "percentage"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"evaluation_id": 1,
|
||
"score_type": "percentage",
|
||
"total_score": 82,
|
||
"dimension_scores": [
|
||
{
|
||
"dimension": "信息采集",
|
||
"score": 18,
|
||
"max_score": 25,
|
||
"comment": "已覆盖发热和咳嗽,但既往喘息史和家族过敏史追问不足。",
|
||
"evidence": ["询问发热天数和最高体温", "申请血常规和CRP"],
|
||
"deductions": ["未充分询问既往喘息史"],
|
||
"improvement": "补充既往史、过敏史、严重程度评估相关问题。"
|
||
}
|
||
],
|
||
"errors": [],
|
||
"improvement_plan": ["加强儿童肺炎严重程度评估训练。"],
|
||
"evidence_summary": ["检查结果已写入评分依据。"],
|
||
"guideline_refs": [],
|
||
"overall_comment": "诊断方向正确,检查利用和沟通细节仍需加强。"
|
||
}
|
||
```
|
||
|
||
评价完成后:
|
||
|
||
- 写入 `training_record`。
|
||
- 释放当前会话短期 memory。
|
||
- 历史记录只保存评价报告,不长期保存完整聊天记录。
|
||
|
||
### `GET /evaluations`
|
||
|
||
用途:按当前 `X-User-Id` 查询历史评价。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"evaluation_id": 1,
|
||
"case_title": "支气管肺炎 - 6岁男性患儿",
|
||
"score_type": "percentage",
|
||
"total_score": 82,
|
||
"created_at": "2026-05-29T10:00:00",
|
||
"pdf_exported": true
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### `GET /evaluations/{evaluation_id}`
|
||
|
||
用途:获取评价详情。只能读取当前用户自己的评价。
|
||
|
||
Response `data`:继承评价报告字段,并额外包含:
|
||
|
||
```json
|
||
{
|
||
"session_id": 10,
|
||
"case_id": 2,
|
||
"case_title": "支气管肺炎 - 6岁男性患儿",
|
||
"created_at": "2026-05-29T10:00:00",
|
||
"pdf_file_path": "storage/reports/training_record_1_percentage_xxx.pdf"
|
||
}
|
||
```
|
||
|
||
### `POST /evaluations/{evaluation_id}/export-pdf`
|
||
|
||
用途:生成本地 PDF 报告并保存文件路径。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"export_id": 1,
|
||
"file_path": "storage/reports/training_record_1_percentage_xxx.pdf"
|
||
}
|
||
```
|
||
|
||
## 9. 病例 SQL 导入接口
|
||
|
||
### `POST /imports/case-sql/preview`
|
||
|
||
用途:上传接口解析后的 SQL 文件,只解析和校验,不写入数据库。
|
||
|
||
Request:
|
||
|
||
```text
|
||
Content-Type: multipart/form-data
|
||
file: case.sql
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"file_name": "case.sql",
|
||
"encoding": "utf-8",
|
||
"tables": {
|
||
"case_base": 1,
|
||
"traditional_case": 1,
|
||
"teaching_case": 0,
|
||
"scoring_rule": 1
|
||
},
|
||
"can_import": true,
|
||
"warnings": [
|
||
"源 SQL 未包含 case_exam_item,导入器会按当前业务规则处理。"
|
||
],
|
||
"errors": [],
|
||
"preview_cases": [
|
||
{
|
||
"id": 2,
|
||
"title": "支气管肺炎 - 6岁男性患儿",
|
||
"case_type": "traditional",
|
||
"difficulty": "medium"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
规则:
|
||
|
||
- 只识别 `case_base`、`traditional_case`、`teaching_case`、`scoring_rule`。
|
||
- 不执行源 SQL 中的 `DROP TABLE`、`CREATE TABLE`、`ALTER TABLE`、`LOCK TABLES`。
|
||
- 字段数量不匹配、JSON 损坏、字符串未闭合时返回 `can_import=false`。
|
||
- `preview` 不写库。
|
||
|
||
### `POST /imports/case-sql/apply`
|
||
|
||
用途:确认导入,将 SQL 中的病例源表数据映射写入当前数据库。
|
||
|
||
Request 同预检接口。
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"imported": true,
|
||
"file_name": "case.sql",
|
||
"encoding": "utf-8",
|
||
"inserted_or_updated_cases": 1,
|
||
"imported_traditional_cases": 1,
|
||
"imported_teaching_cases": 0,
|
||
"imported_scoring_rules": 1,
|
||
"generated_exam_items": 6,
|
||
"warnings": []
|
||
}
|
||
```
|
||
|
||
前端处理:
|
||
|
||
- 先调用 `preview`,只有 `can_import=true` 才允许点击“确认导入”。
|
||
- 导入成功后刷新病例列表。
|
||
- 如果源 SQL 缺少 `case_exam_item`,后端会生成基础检查项,保证新病例可训练。
|
||
|
||
## 10. 知识检索接口
|
||
|
||
### `GET /knowledge/search`
|
||
|
||
用途:按科室、训练类别和关键词检索评分参考指南。第一版主要供评价链路和调试使用。
|
||
|
||
Query:
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|---|---:|---:|---|
|
||
| `department_id` | number | 是 | 科室 ID。 |
|
||
| `training_type` | string | 是 | 训练类别。 |
|
||
| `q` | string | 否 | 关键词,多个关键词用英文逗号分隔。 |
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"matched_chunks": [],
|
||
"source_refs": [],
|
||
"no_match": true
|
||
}
|
||
```
|
||
|
||
## 11. LLM 测试接口
|
||
|
||
### `POST /llm/test/deepseek-fast`
|
||
|
||
用途:测试快速模型耗时。
|
||
|
||
Request:
|
||
|
||
```json
|
||
{
|
||
"message": "请用一句话说明医疗问诊训练 Demo 的用途。"
|
||
}
|
||
```
|
||
|
||
Response `data`:
|
||
|
||
```json
|
||
{
|
||
"model": "deepseek-v4-pro",
|
||
"first_token_ms": null,
|
||
"total_latency_ms": 3000,
|
||
"stream": false,
|
||
"mock_mode": false,
|
||
"fallback_used": false,
|
||
"thinking_enabled": false,
|
||
"reasoning_effort": null
|
||
}
|
||
```
|
||
|
||
### `POST /llm/test/deepseek-reason`
|
||
|
||
用途:测试 reason 模型耗时。接口内部会优先按配置执行,流式不兼容时降级为非流式,不影响问诊主链路。
|
||
|
||
Request 同 Fast 测试。
|
||
|
||
Response 字段同 Fast 测试。
|
||
|
||
## 12. 前端字段枚举
|
||
|
||
| 字段 | 允许值 |
|
||
|---|---|
|
||
| `score_type` | `percentage`、`five_point` |
|
||
| `mode` | `practice`、`teaching` |
|
||
| `training_type` | `case_analysis`、`diagnosis_treatment`、`consultation` |
|
||
| `session.status` | `inquiry`、`diagnosis`、`treatment`、`evaluating`、`evaluated` |
|
||
| `patient.gender` | `male`、`female`、`null` |
|
||
|
||
## 13. 前端联调注意事项
|
||
|
||
1. 所有请求必须带 `X-User-Id`,否则后端返回 `USER_ID_REQUIRED`。
|
||
2. 当前 Demo 不做登录注册,`user_id` 由宿主系统或测试页传入。
|
||
3. 病例详情不返回标准答案,避免前端泄露训练答案。
|
||
4. 检查结果只来自数据库,不来自 LLM。
|
||
5. 聊天记录只在 runtime memory 中短期保存,评价完成后释放。
|
||
6. 历史页读取的是 `training_record`,只展示完整训练结束后的评价。
|
||
7. 删除病例会级联删除该病例训练数据,前端必须保留二次确认。
|
||
8. `.env` 不进入 Git,前端不能写死 API Key。
|