# 功能工作流说明 本文档说明当前保留功能的运行方式,重点描述接口、代码入口、提示词、数据库读写和结果去向。本文档与 `docs/03_api_design.md` 配合使用:API 文档面向前端调用,本文档面向后端维护和功能排查。 ## 1. 通用链路 所有业务接口先执行用户鉴权: ```text Authorization: Bearer -> 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 异步任务扩展点。 后续生产级扩展需要重点补齐任务队列监控、失败重试、分片质量评估、文件去重和权限后台。