docs: update frontend api handoff docs

This commit is contained in:
刘金宝
2026-06-01 10:39:07 +08:00
parent a7733243b2
commit b80e298b4f
4 changed files with 577 additions and 409 deletions
+27 -14
View File
@@ -1,15 +1,16 @@
# 医疗问诊 Agent 第一版 Demo
这是大系统中的“医疗问诊 Agent”子功能 Demo。系统不做独立注册登录,宿主系统进入时通过请求头传入 `X-User-Id`,后端按该用户隔离会话、检查申请、诊断治疗提交、评价报告和历史记录。
这是大系统中的“医疗问诊 Agent”子功能 Demo。系统不做独立注册登录,宿主系统进入本 Agent 时通过请求头传入 `X-User-Id`,后端按该用户标识隔离训练会话、检查申请、诊断治疗提交、AI 评价报告和历史记录。
## 当前功能
```text
病例列表
-> 病例详情
-> 病例 SQL 导入/删除病例
-> 创建训练会话
-> 多轮问诊 Chat / SSE 流式 Chat
-> 提示辅助(练习模式中手动点击)
-> 练习提示
-> 检查/检验申请
-> 完成问诊
-> 提交诊断
@@ -34,7 +35,7 @@
## 核心数据表
当前功能依赖表:
当前功能依赖以下表:
```text
case_base
@@ -54,7 +55,7 @@ user_learning_profiles
audit_logs
```
旧表 `cases``case_exam_items``training_sessions``session_orders``session_submissions``evaluation_records``evaluation_report_exports``rubric_templates` 已清理
旧表已不参与运行
## 启动后端
@@ -85,31 +86,27 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
## 导入接口解析后的病例 SQL
接口提供的 SQL dump 不能直接在正式库执行。项目提供安全导入脚本,只解析病例数据并按当前新表字段映射写入,不执行源 SQL 中的 `DROP TABLE``CREATE TABLE``ALTER TABLE`
后端提供安全导入能力,只解析源 SQL 中的 `case_base``traditional_case``teaching_case``scoring_rule` 四类病例数据,不执行源 SQL 中的删表、建表或锁表语句
先检查不写库
命令行预检
```powershell
cd D:\Code\newfounder\medical-consultation-agent\backend
.\.venv\Scripts\python.exe scripts\import_source_case_sql.py "C:\path\to\case.sql"
```
确认检通过后写入:
确认检通过后写入:
```powershell
.\.venv\Scripts\python.exe scripts\import_source_case_sql.py "C:\path\to\case.sql" --apply
```
如果源 SQL 缺少 `case_exam_item`,脚本会根据病例描述生成基础检查项目,保障练习模式可继续申请检查。源 SQL 存在乱码、字段数量不匹配或损坏的 `INSERT` 时,脚本会拒绝导入。
前端也提供同一套安全导入能力:
前端导入页:
```text
http://127.0.0.1:5173/#/import
```
页面流程为“选择 SQL 文件 -> 解析检查 -> 确认导入 -> 刷新病例库”。后端接口只接受 `.sql` 文件,最大 5MB,只解析 `case_base``traditional_case``teaching_case``scoring_rule` 四类源表数据;`case_exam_item` 仍由后端按病例内容自动补齐。确认导入成功后,病例列表会重新请求后端,新病例可以直接进入练习模式或教学互动模式。
## 启动前端
```powershell
@@ -143,6 +140,8 @@ http://127.0.0.1:5173
## 验证命令
后端:
```powershell
cd D:\Code\newfounder\medical-consultation-agent\backend
.\.venv\Scripts\python.exe -m compileall app scripts tests
@@ -162,13 +161,27 @@ npm.cmd run build
| 文档 | 内容 |
|---|---|
| [docs/00_development_log.md](docs/00_development_log.md) | 开发过程和本轮变更记录 |
| [docs/00_development_log.md](docs/00_development_log.md) | 开发过程和变更记录 |
| [docs/01_functional_scope.md](docs/01_functional_scope.md) | 当前功能范围 |
| [docs/02_database_design.md](docs/02_database_design.md) | 数据库总体设计 |
| [docs/02_database_table_dictionary.md](docs/02_database_table_dictionary.md) | 表字段字典 |
| [docs/03_api_design.md](docs/03_api_design.md) | 前端对接 API 文档 |
| [docs/03_api_design.md](docs/03_api_design.md) | 前端 API 对接文档 |
| [docs/04_data_collection.md](docs/04_data_collection.md) | 数据采集和存储边界 |
| [docs/05_agent_prompt_design.md](docs/05_agent_prompt_design.md) | Agent 和提示词模板调用说明 |
| [docs/06_demo_testing_guide.md](docs/06_demo_testing_guide.md) | 前端测试指南 |
| [docs/07_demo_function_traceability.md](docs/07_demo_function_traceability.md) | 功能到代码和数据表追踪 |
| [docs/08_pediatric_case_demo_script.md](docs/08_pediatric_case_demo_script.md) | 儿科病例演示脚本 |
## Git 管理说明
仓库上传范围包含 `backend``frontend``docs``scripts` 和项目说明文件。
不上传:
- `demo_frontend/`
- `.env`
- `backend/.venv/`
- `frontend/node_modules/`
- `frontend/dist/`
- `storage/`
- 本地 PDF、日志、数据库文件和临时 SQL 文件
+437 -300
View File
File diff suppressed because it is too large Load Diff
+81 -76
View File
@@ -1,5 +1,7 @@
# Demo 前端测试指南
本文档用于本地演示和前后端联调。前端页面覆盖当前第一版 Demo 的完整训练闭环。
## 1. 启动服务
后端:
@@ -17,7 +19,7 @@ cd D:\Code\newfounder\medical-consultation-agent\frontend
npm.cmd run dev -- --host 127.0.0.1 --port 5173
```
浏览器访问:
访问:
```text
http://127.0.0.1:5173
@@ -30,49 +32,11 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
.\.venv\Scripts\python.exe scripts\migrate_to_new_schema.py
```
当前数据库为 `medical_consultation_agent`核心表为 `case_base``traditional_case``teaching_case``scoring_rule``case_exam_item``training_session``training_order``training_submission``training_record`
当前数据库为 `medical_consultation_agent`
## 3. 导入接口解析后的病例 SQL
## 3. 入口页测试
接口提供的 SQL dump 先走安全检查,不直接执行原始 SQL:
```powershell
cd D:\Code\newfounder\medical-consultation-agent\backend
.\.venv\Scripts\python.exe scripts\import_source_case_sql.py "C:\path\to\case.sql"
```
检查通过后再写入当前库:
```powershell
.\.venv\Scripts\python.exe scripts\import_source_case_sql.py "C:\path\to\case.sql" --apply
```
导入脚本规则:
- 忽略源 SQL 中的 `DROP TABLE``CREATE TABLE``ALTER TABLE``LOCK TABLES`
- 按字段名映射导入 `case_base``traditional_case``teaching_case``scoring_rule`
- 源 SQL 缺少 `case_exam_item` 时,根据病例描述生成基础检查项目。
- 源 SQL 缺少 `teaching_case` 时,只影响教学互动模式入口,不影响练习模式。
- 源 SQL 存在乱码、字段数量不匹配或损坏字符串时拒绝导入。
前端上传测试:
1. 进入 `http://127.0.0.1:5173/#/import`
2. 选择接口解析后的 `.sql` 文件。
3. 点击“解析检查”。
4. 查看识别到的表、病例预览、警告和错误。
5. `can_import=true` 后点击“确认导入”。
6. 导入成功后点击“刷新病例库”,或直接进入病例页查看新增病例。
预期结果:
- 预检阶段不写数据库。
- 确认导入阶段写入 `case_base``traditional_case``teaching_case``scoring_rule`,并自动补齐基础检查项目。
- 新增病例出现在病例列表中,可继续创建训练会话。
- 损坏 SQL 会显示错误,不会写入任何表。
## 4. 入口页测试
1. 打开入口页。
1. 打开前端首页。
2. 确认 `user_id``demo_user_001`
3. 确认 API Base 为 `http://127.0.0.1:8000/api/v1`
4. 点击连接或进入 Agent。
@@ -80,22 +44,67 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
预期结果:
- 页面显示后端地址、当前 user_id、入口场景和最近连接时间。
- “已连接”只在 `GET /api/v1/agent/hello` 成功返回后显示。
- “已连接”只在 `GET /api/v1/agent/hello` 成功后显示。
- 功能卡片显示流式问诊、PDF 导出、知识检索、评分类型、LLM mock/fallback 状态。
## 5. 病例测试
## 4. 病例 SQL 导入测试
进入:
```text
http://127.0.0.1:5173/#/import
```
步骤:
1. 选择接口解析后的 `.sql` 文件。
2. 点击“解析检查”。
3. 查看识别到的表、病例预览、警告和错误。
4. `can_import=true` 后点击“确认导入”。
5. 导入成功后刷新病例库。
预期结果:
- 预检阶段不写数据库。
- 后端只解析 `case_base``traditional_case``teaching_case``scoring_rule`
- 源 SQL 中的 `DROP TABLE``CREATE TABLE``ALTER TABLE``LOCK TABLES` 不会执行。
- 缺少 `case_exam_item` 时,后端按当前业务规则生成基础检查项。
- 新病例出现在病例列表中,可继续创建训练会话。
## 5. 病例列表与详情测试
1. 进入病例页。
2. 点击“支气管肺炎 - 6岁男性患儿”病例卡片。
2. 点击病例卡片。
3. 查看病例详情。
4. 点击“开始训练”。
预期结果:
- 点击病例卡片只展开详情,不直接创建会话。
- 详情展示科室、年龄、性别、主诉、训练类型、检查项目数量和是否有教学知识
- 点击病例卡片只选中病例,不直接创建会话。
- 详情展示科室、年龄、性别、主诉、训练类型、教学资源和可申请检查类型
- 详情不展示标准答案、隐藏病史和评分细则。
## 6. 创建会话
## 6. 删除病例测试
该功能用于联调阶段清理导入错误或不再需要的病例。
步骤:
1. 在病例详情中点击“删除病例”。
2. 弹窗中查看删除影响范围。
3. 输入 `确认删除`
4. 点击“确认删除”。
5. 删除成功后刷新病例列表。
预期结果:
- 前端先调用 `GET /api/v1/cases/{case_id}/delete-preview`
- 确认后调用 `DELETE /api/v1/cases/{case_id}`
- 后端删除病例主表、扩展表、评分规则、检查项、训练会话、检查申请、提交内容和训练评价记录。
- `audit_logs` 只记录删除操作,不被反删。
- 删除后访问病例详情返回 `CASE_NOT_FOUND`
## 7. 创建训练会话
1. 选择训练模式:`练习模式``教学互动模式`
2. 选择评分类型:`百分制``五分制`
@@ -104,14 +113,10 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
预期结果:
- 后端创建 `training_session`
- Redis/进程内 memory 生成 `memory_key`
- Chat 页显示 AI 病人首句
- Redis进程内 memory 生成短期记忆
- Chat 页显示 AI 病人开场白
## 7. 多轮问诊
1. 在 Chat 输入框提问。
2. 保持流式开关开启。
3. 点击“发送问诊”。
## 8. 多轮问诊测试
推荐问题:
@@ -125,23 +130,23 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
预期结果:
- 前端显示流式增量内容
- 流式模式下逐步显示 AI 病人回复
- 收到 `message_done` 后停止“正在生成”。
- 出错时显示错误,不会无限 pending。
## 8. 查看提示
## 9. 查看提示测试
练习模式中点击“查看提示”。
预期结果:
- 调用 `POST /api/v1/sessions/{session_id}/hints`
- 示缺失问诊维度、下一步可问问题推荐检查。
- 示缺失问诊维度、下一步问题推荐检查。
- 提示不自动弹出,不写入长期历史。
## 9. 检查/检验申请
## 10. 检查/检验申请测试
在检查面板依次申请:
建议申请:
- 血常规
- CRP
@@ -152,18 +157,18 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
预期结果:
- 检查结果来自 `case_exam_item`
- 同一检查重复点击不重复写入,只显示“已申请”
- 页面提示“该检查结果已写入本次会话上下文和评分依据
- 同一 `item_code` 重复点击不重复写入。
- 页面提示检查结果已写入本次会话上下文和评分依据。
## 10. 诊断与治疗提交
## 11. 诊断与治疗提交测试
1. 点击“完成问诊”。
2. 在提交页填写诊断。
2. 填写诊断。
3. 点击“提交诊断”。
4. 填写治疗方案。
5. 点击“提交治疗方案”。
演示模板可通过“填入演示模板”按钮填充,默认表单为空。
演示时可以点击“填入演示模板”,正常测试时表单默认为空。
预期结果:
@@ -171,7 +176,7 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
- 诊断提交后进入治疗阶段。
- 治疗提交后进入评价阶段。
## 11. 评价、PDF 与历史
## 12. 评价、PDF 与历史记录测试
1. 点击“生成 AI 评价报告”。
2. 查看维度评分、证据摘要、扣分点和改进计划。
@@ -185,7 +190,7 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
- PDF 路径写入 `training_record.pdf_file_path`
- 历史记录按当前 `user_id` 查询。
## 12. LLM 测试
## 13. LLM 测试
进入 LLM 测试页:
@@ -195,16 +200,16 @@ cd D:\Code\newfounder\medical-consultation-agent\backend
预期结果:
- 页面展示模型名、总耗时、是否流式、是否 mock、是否 fallback。
- 真实模型异常时显示错误,不静默伪装为真实回复
- 真实模型异常时显示错误,不静默伪装为真实响应
## 13. 常见问题
## 14. 常见问题
| 问题 | 排查 |
|---|---|
| 页面显示未连接 | 检查后端是否在 `127.0.0.1:8000` 启动 |
| 缺少 `X-User-Id` | 入口页填写 user_id 后重新进入 |
| 病例为空 | 运行 `scripts\migrate_to_new_schema.py` |
| Chat 卡在生成中 | 查看浏览器控制台 SSE 是否收到 `message_done``error` |
| 检查重复出现 | 刷新页面后复测,同一 `item_code` 应只出现一次 |
| 评价无法生成 | 确认已完成问诊、提交诊断、提交治疗 |
| Redis 中有 TTL | 正常行为,短期 memory 使用 TTL 自动过期 |
| 页面显示未连接 | 检查后端是否在 `127.0.0.1:8000` 启动 |
| 缺少 `X-User-Id` | 入口页填写 user_id 后重新进入 |
| 病例为空 | 运行 `scripts\migrate_to_new_schema.py` 或导入病例 SQL。 |
| Chat 卡在生成中 | 查看浏览器控制台 SSE 是否收到 `message_done``error` |
| 检查重复出现 | 刷新页面后复测,同一 `item_code` 应只出现一次 |
| 评价无法生成 | 确认已完成问诊、提交诊断、提交治疗 |
| Redis 中有 TTL | 正常行为,短期 memory 使用 TTL 自动过期 |
+32 -19
View File
@@ -1,26 +1,30 @@
# Demo 功能追踪表
本文档用于说明当前 Demo 功能、前端入口、后端接口、核心函数和数据表之间的对应关系。
## 1. 功能到代码映射
| 功能 | 前端页面/按钮 | API | Router 函数 | Service / Agent | 数据表 | 状态 |
|---|---|---|---|---|---|---|
| Agent 入口连接 | 入口页“连接/进入” | `GET /api/v1/agent/hello` | `agent.hello` | `AuditService.log` | `audit_logs` | 已实现 |
| 病例列表 | 病例页刷新 | `GET /api/v1/cases` | `cases.list_cases` | `CaseService.list_cases` | `case_base` | 已实现 |
| Agent 连接检查 | 入口页“连接/进入” | `GET /api/v1/agent/hello` | `agent.hello` | `AuditService.log` | `audit_logs` | 已实现 |
| 病例列表 | 病例页刷新 | `GET /api/v1/cases` | `cases.list_cases` | `CaseService.list_cases` | `case_base` | 已实现 |
| 病例详情 | 点击病例卡片 | `GET /api/v1/cases/{case_id}` | `cases.get_case_detail` | `CaseService.get_case_detail` | `case_base``traditional_case``teaching_case``case_exam_item` | 已实现 |
| 删除病例预览 | 病例详情“删除病例” | `GET /api/v1/cases/{case_id}/delete-preview` | `cases.get_case_delete_preview` | `CaseService.get_delete_preview` | 病例表、训练表统计 | 已实现 |
| 删除病例 | 删除弹窗“确认删除” | `DELETE /api/v1/cases/{case_id}` | `cases.delete_case` | `CaseService.delete_case``CaseRepository.delete_case_cascade` | `case_base``traditional_case``teaching_case``scoring_rule``case_exam_item``training_session``training_order``training_submission``training_record` | 已实现 |
| 病例 SQL 预检 | 导入页“解析检查” | `POST /api/v1/imports/case-sql/preview` | `imports.preview_case_sql` | `CaseSqlImportService.preview` | 不写库 | 已实现 |
| 病例 SQL 导入 | 导入页“确认导入” | `POST /api/v1/imports/case-sql/apply` | `imports.apply_case_sql` | `CaseSqlImportService.apply``scripts.import_source_case_sql` | `case_base``traditional_case``teaching_case``scoring_rule``case_exam_item` | 已实现 |
| 创建训练会话 | “创建训练会话” | `POST /api/v1/sessions` | `sessions.create_session` | `SessionService.create_session` | `training_session`、runtime memory | 已实现 |
| 普通问诊 | Chat“发送问诊” | `POST /api/v1/sessions/{session_id}/chat` | `sessions.chat` | `SessionService.chat``PatientAgent.reply` | runtime memory | 已实现 |
| 流式问诊 | Chat 流式开关开启 | `POST /api/v1/sessions/{session_id}/chat/stream` | `sessions.chat_stream` | `SessionService.stream_chat``PatientAgent.stream_reply` | runtime memory | 已实现 |
| 查看提示 | Chat“查看提示” | `POST /api/v1/sessions/{session_id}/hints` | `sessions.generate_hints` | `SessionService.generate_hints``HintAgent.generate` | runtime memory、`training_order` | 已实现 |
| 创建训练会话 | 训练配置页“创建训练会话” | `POST /api/v1/sessions` | `sessions.create_session` | `SessionService.create_session` | `training_session`、runtime memory | 已实现 |
| 普通问诊 | Chat“发送问诊” | `POST /api/v1/sessions/{session_id}/chat` | `sessions.chat` | `SessionService.chat``PatientAgent.reply` | runtime memory | 已实现 |
| 流式问诊 | Chat 流式开关开启 | `POST /api/v1/sessions/{session_id}/chat/stream` | `sessions.chat_stream` | `SessionService.stream_chat``PatientAgent.stream_reply` | runtime memory | 已实现 |
| 查看提示 | Chat“查看提示” | `POST /api/v1/sessions/{session_id}/hints` | `sessions.generate_hints` | `SessionService.generate_hints``HintAgent.generate` | runtime memory、`training_order` | 已实现 |
| 检查项目列表 | 检查面板刷新 | `GET /api/v1/sessions/{session_id}/order-items` | `sessions.list_order_items` | `OrderService.list_order_items` | `case_exam_item` | 已实现 |
| 申请检查 | “申请该检查” | `POST /api/v1/sessions/{session_id}/orders` | `sessions.create_order` | `OrderService.create_order` | `case_exam_item``training_order` | 已实现 |
| 完成问诊 | “完成问诊” | `POST /api/v1/sessions/{session_id}/complete-inquiry` | `sessions.complete_inquiry` | `SessionService.complete_inquiry` | `training_session` | 已实现 |
| 提交诊断 | “提交诊断” | `POST /api/v1/sessions/{session_id}/diagnosis` | `sessions.submit_diagnosis` | `SessionService.submit_diagnosis` | `training_submission` | 已实现 |
| 提交治疗 | “提交治疗方案” | `POST /api/v1/sessions/{session_id}/treatment` | `sessions.submit_treatment` | `SessionService.submit_treatment` | `training_submission` | 已实现 |
| 生成评价 | “生成 AI 评价报告” | `POST /api/v1/sessions/{session_id}/evaluation` | `sessions.create_evaluation` | `EvaluationService.create_evaluation``ScoringAgent.score``ReportAgent` | `scoring_rule``knowledge_chunks``training_record` | 已实现 |
| 历史列表 | 历史页刷新 | `GET /api/v1/evaluations` | `evaluations.list_evaluations` | `EvaluationService.list_history` | `training_record` | 已实现 |
| 报告详情 | 历史详情/报告页 | `GET /api/v1/evaluations/{evaluation_id}` | `evaluations.get_evaluation_detail` | `EvaluationService.get_detail` | `training_record` | 已实现 |
| 申请检查 | 检查面板“申请该检查” | `POST /api/v1/sessions/{session_id}/orders` | `sessions.create_order` | `OrderService.create_order` | `case_exam_item``training_order` | 已实现 |
| 完成问诊 | Chat 页“完成问诊” | `POST /api/v1/sessions/{session_id}/complete-inquiry` | `sessions.complete_inquiry` | `SessionService.complete_inquiry` | `training_session` | 已实现 |
| 提交诊断 | 提交页“提交诊断” | `POST /api/v1/sessions/{session_id}/diagnosis` | `sessions.submit_diagnosis` | `SessionService.submit_diagnosis` | `training_submission` | 已实现 |
| 提交治疗 | 提交页“提交治疗方案” | `POST /api/v1/sessions/{session_id}/treatment` | `sessions.submit_treatment` | `SessionService.submit_treatment` | `training_submission` | 已实现 |
| 生成评价 | 报告页“生成 AI 评价报告” | `POST /api/v1/sessions/{session_id}/evaluation` | `sessions.create_evaluation` | `EvaluationService.create_evaluation``ScoringAgent.score``ReportAgent` | `scoring_rule``knowledge_chunks``training_record` | 已实现 |
| 历史评价列表 | 历史页刷新 | `GET /api/v1/evaluations` | `evaluations.list_evaluations` | `EvaluationService.list_history` | `training_record` | 已实现 |
| 评价详情 | 历史详情/报告页 | `GET /api/v1/evaluations/{evaluation_id}` | `evaluations.get_evaluation_detail` | `EvaluationService.get_detail` | `training_record` | 已实现 |
| PDF 导出 | 报告页“导出 PDF” | `POST /api/v1/evaluations/{evaluation_id}/export-pdf` | `evaluations.export_pdf` | `PdfExportService.export` | `training_record` | 已实现 |
| 知识检索 | 后端预留/评价内部使用 | `GET /api/v1/knowledge/search` | `knowledge.search_knowledge` | `KnowledgeService.search_guidelines` | `knowledge_sources``knowledge_documents``knowledge_chunks` | 已实现 |
| LLM Fast 测试 | LLM 测试页“测试 Fast” | `POST /api/v1/llm/test/deepseek-fast` | `llm_test.test_deepseek_fast` | `OpenAICompatibleLLMClient.chat` | 无长期表 | 已实现 |
@@ -28,7 +32,7 @@
## 2. 当前数据表状态
当前功能只依赖新表:
当前运行只依赖新表:
```text
case_base
@@ -48,16 +52,25 @@ user_learning_profiles
audit_logs
```
旧表不参与运行。旧表删除后,后端测试和前端构建均已通过。
旧表不参与运行。旧表删除后,后端测试和前端构建均已通过。
## 3. 核心状态流
## 3. 关键业务边界
- `X-User-Id` 是会话、提交、评价和历史记录的隔离依据。
- Chat 消息只作为短期 memory 使用,不作为长期历史保存。
- 检查/检验结果只来自 `case_exam_item`,不由 LLM 编造。
- 完整训练结束后只沉淀 `training_record`
- 删除病例会删除病例相关业务数据和训练记录,但保留 `audit_logs`
- 病例详情接口不返回标准答案和隐藏病史。
## 4. 核心状态流
```text
inquiry -> diagnosis -> treatment -> evaluating -> completed
inquiry -> diagnosis -> treatment -> evaluating -> evaluated
```
- `inquiry`:允许 Chat、提示、申请检查。
- `inquiry`:允许 Chat、查看提示、申请检查、完成问诊
- `diagnosis`:允许提交诊断。
- `treatment`:允许提交治疗方案。
- `evaluating`:允许生成 AI 评价。
- `completed`:允许查询历史、查看详情、导出 PDF。
- `evaluated`:允许查看报告、导出 PDF、查看历史