Files
fastapi/docs/10_function_workflow.md
T
2026-06-11 16:19:50 +08:00

97 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 功能工作流说明
本文档说明当前保留功能的运行方式,重点描述接口、代码入口、提示词、数据库读写和结果去向。本文档与 `docs/03_api_design.md` 配合使用:API 文档面向前端调用,本文档面向后端维护和功能排查。
## 1. 通用链路
所有业务接口先执行用户鉴权:
```text
Authorization: Bearer <access_token>
-> app/core/user_context.py::get_user_context
-> app/services/external_auth_service.py::ExternalAuthService.get_current_user
-> Django /api/user/users/me/
-> UserContext(user_id, role, institution_id, department_id)
```
FastAPI 使用 Django 返回的 `id` 作为业务 `user_id`。训练会话、评价详情、PDF 下载、学习助手会话都按 `user_id` 做访问隔离。
## 2. 功能工作流表
| 功能 | 接口 | Router | Service / Agent | 提示词 | 数据库读取 | 数据库写入 | 结果去向 |
|---|---|---|---|---|---|---|---|
| 用户鉴权 | `GET /api/v1/auth/me` | `app/api/auth.py::auth_me` | `ExternalAuthService.get_current_user` | 无 | Django `user``institution``department` | 无 | 返回前端标准化用户信息 |
| 推荐配置信息 | `GET /api/v1/training-config/recommended` | `training_config.py::get_recommended_training_config` | `TrainingConfigService.get_recommended` | 无 | `case_base``traditional_case` | 无 | 返回前端默认病人配置 |
| 训练配置信息 | `GET /api/v1/training-config/options` | `training_config.py::get_training_config_options` | `TrainingConfigService.get_options` | 无 | `case_base` | 无 | 返回前端可选配置 |
| 新建训练会话 | `POST /api/v1/sessions` | `sessions.py::create_session` | `SessionService.create_session` | 无 | `case_base``traditional_case` | `training_sessions`Redis `mem:*` | 返回 `session_id`、开场白;初始化短期 memory |
| 流式会话 | `POST /api/v1/sessions/{session_id}/chat/stream` | `sessions.py::chat_stream` | `SessionService.stream_chat` -> `PatientAgent.stream_reply` | `PatientAgent._build_messages` 代码内提示;`app/prompts/patient/free_chat.md` 为模板资产 | `training_sessions``case_base`、Redis memory | Redis memory 追加 doctor / patient 消息 | SSE 返回 `message_delta``message_done` |
| 王主任练习提示 | `POST /api/v1/sessions/{session_id}/hints/stream` | `sessions.py::stream_hints` | `SessionService.stream_hints` -> `HintAgent.generate` | `app/prompts/hint/practice_case_hint.md` | `training_sessions``case_base``session_orders`、Redis memory | 无 | SSE 返回一句话练习提示 |
| 结构化练习提示 | `POST /api/v1/sessions/{session_id}/hints` | `sessions.py::generate_hints` | `SessionService.generate_hints` -> `HintAgent.generate` | `app/prompts/hint/practice_case_hint.md` | `training_sessions``case_base``session_orders`、Redis memory | 无 | 返回缺失维度、下一步问题、推荐检查 |
| 体格检查列表 | `GET /api/v1/sessions/{session_id}/physical-exams` | `sessions.py::list_physical_exam_items` | `OrderService.list_physical_exam_items` | 无 | `training_sessions``case_exam_item` | 无 | 返回当前病例 `item_type=physical` 的检查项 |
| 辅助检查列表 | `GET /api/v1/sessions/{session_id}/auxiliary-exams` | `sessions.py::list_auxiliary_exam_items` | `OrderService.list_auxiliary_exam_items` | 无 | `training_sessions``case_exam_item` | 无 | 返回当前病例 `item_type=auxiliary` 的检查项 |
| 体格检查结果 | `POST /api/v1/sessions/{session_id}/physical-exams/{item_code}` | `sessions.py::create_physical_exam_order` | `OrderService.create_physical_exam_order` | 无 | `training_sessions``case_exam_item` | `session_orders`Redis memory 追加 tool 消息 | 返回前端检查结果;结果写入评分依据 |
| 辅助检查结果 | `POST /api/v1/sessions/{session_id}/auxiliary-exams/{item_code}` | `sessions.py::create_auxiliary_exam_order` | `OrderService.create_auxiliary_exam_order` | 无 | `training_sessions``case_exam_item` | `session_orders`Redis memory 追加 tool 消息 | 返回前端检查结果;结果写入评分依据 |
| 完成问诊 | `POST /api/v1/sessions/{session_id}/complete-inquiry` | `sessions.py::complete_inquiry` | `SessionService.complete_inquiry` | 无 | `training_sessions`、Redis memory | `training_sessions.status=diagnosis` | 返回前端新阶段 |
| 提交诊断 | `POST /api/v1/sessions/{session_id}/diagnosis` | `sessions.py::submit_diagnosis` | `SessionService.submit_diagnosis` | 无 | `training_sessions` | `session_submissions``training_sessions.status=treatment` | 返回前端新阶段 |
| 提交治疗 | `POST /api/v1/sessions/{session_id}/treatment` | `sessions.py::submit_treatment` | `SessionService.submit_treatment` | 无 | `training_sessions``session_submissions` | `session_submissions``training_sessions.status=evaluating` | 返回前端新阶段 |
| 训练生成评价 | `POST /api/v1/sessions/{session_id}/evaluation` | `sessions.py::create_evaluation` | `EvaluationService.create_evaluation` -> `ScoringAgent.score` -> `ReportAgent.build_report` | `app/prompts/scoring/default_percentage.md``default_five_point.md``pediatrics_pneumonia.md` 为模板资产;评分系统提示在 `ScoringAgent` 中拼接 | `training_sessions``case_base``session_orders``session_submissions``scoring_rule`、Redis memory | `training_record``training_score_detail`;释放 Redis 训练 memory | 返回前端结构化评价;长期保存评价记录 |
| 获取评价详情 | `GET /api/v1/evaluations/{evaluation_id}` | `evaluations.py::get_evaluation_detail` | `EvaluationService.get_evaluation_detail` | 无 | `training_record``training_score_detail` | 无 | 返回前端评价详情 |
| 下载 PDF | `GET /api/v1/evaluations/{evaluation_id}/download-pdf` | `evaluations.py::download_pdf` | `PdfExportService.export` | 无 | `training_record``training_score_detail` | 更新 `training_record.pdf_file_path` | 浏览器直接下载 PDF 文件流 |
| 教学互动获取教学列表 | `GET /api/v1/teaching/cases/{case_id}/items` | `teaching.py::get_teaching_items` | `TeachingService.get_items` | 无 | `case_base``teaching_case` | 无 | 返回题目、选项、答案、解析文本、视频 |
| 教学互动生成评价 | `POST /api/v1/teaching/evaluation` | `teaching.py::create_teaching_evaluation` | `TeachingService.create_evaluation` -> `ScoringAgent.score_teaching` | `app/prompts/scoring/teaching_interaction_evaluation.md` | `case_base``teaching_case``scoring_rule` | `training_sessions``training_record``training_score_detail` | 返回前端教学评价;长期保存评价记录 |
| 个人中心训练记录列表 | `GET /api/v1/evaluations?page=1&page_size=10` | `evaluations.py::list_evaluations` | `EvaluationService.list_evaluations` | 无 | `training_record` | 无 | 返回前端分页记录 |
| AI 学习助手新建会话 | `POST /api/v1/learning-assistant/sessions` | `learning_assistant.py::create_learning_assistant_session` | `LearningAssistantService.create_session` -> `LearningAssistantSessionStore.create` | 无 | 用户上下文 | Redis `learning_assistant:session:*` | 返回 `assistant_session_id` |
| AI 学习助手流式会话 | `POST /api/v1/learning-assistant/sessions/{assistant_session_id}/chat/stream` | `learning_assistant.py::stream_learning_assistant_session_chat` | `LearningAssistantService.stream_session_chat` -> `VectorSearchService` -> `LearningAssistantAgent.stream_answer` | `app/prompts/learning_assistant/rag_answer.md``no_reference_answer.md` 为模板资产;实际提示在 `LearningAssistantAgent._messages` 中拼接 | `kb_spaces``kb_chunks`、Milvus、Redis 学习助手会话 | `kb_query_logs`;Redis 追加学习助手问答 | SSE 返回检索状态、来源和回答;保存查询日志 |
| 内容管理员上传知识库 | `POST /api/v1/knowledge-admin/documents/upload` | `knowledge_admin.py::upload_knowledge_document` | `DocumentIngestionService.upload_and_ingest` | 无 | 用户角色、机构知识库空间 | `kb_documents``kb_chunks``kb_ingestion_tasks`;Milvus 向量 | 后台接口保留;当前学生端不展示入口 |
## 3. 检查项处理规则
当前体格检查和辅助检查都读取 `case_exam_item`
- `item_type=physical`:体格检查。
- `item_type=auxiliary`:辅助检查。
- 列表接口只返回项目,不返回结果。
- 结果接口按 `item_code` 返回固定结果。
- 同一会话同一 `item_code` 幂等,重复申请不会重复写入 `session_orders` 和 Redis memory。
- 检查结果只来自数据库,不由 LLM 编造。
## 4. 训练评价数据去向
训练评价只在用户完成完整流程后写入长期记录:
```text
新建会话 -> 流式问诊 -> 申请检查 -> 完成问诊 -> 提交诊断 -> 提交治疗 -> 生成评价
-> training_record
-> training_score_detail
-> PDF 下载时生成 storage/reports 文件
```
中途退出、未生成评价的会话不会写入 `training_record`。问诊内容保存在 Redis 短期 memory 中,生成评价后释放。
## 5. AI 学习助手数据去向
AI 学习助手不写入训练记录:
```text
新建学习助手会话 -> Redis 短期会话
流式提问 -> RAG 检索 -> LLM 流式回答
-> kb_query_logs 保存查询、命中来源和耗时
-> Redis 保存最近问答上下文
```
命中知识库时,回答必须带来源。未命中知识库时,回答开头说明未检索到本机构知识库参考,不伪造 PDF、页码或指南名称。
## 6. 内容管理员知识库能力
内容管理员知识库接口当前保留在后端,用于后续后台页面接入。学生端不展示上传入口。
当前已保留:
- PDF 上传接口。
- 文档表、分片表、任务表。
- Embedding 适配器。
- Milvus 适配器。
- 同步构建和 Celery 异步任务扩展点。
后续生产级扩展需要重点补齐任务队列监控、失败重试、分片质量评估、文件去重和权限后台。