docs: update project docs and evaluation history pagination

This commit is contained in:
刘金宝
2026-06-11 10:15:06 +08:00
parent 6b40ba1079
commit a54c2d1c85
17 changed files with 607 additions and 211 deletions
+8 -5
View File
@@ -76,7 +76,7 @@ fastapi/
│ ├── schemas/ # Pydantic 入参/出参
│ ├── services/ # 业务服务
│ └── tasks/ # Celery 异步任务预留
├── docs/ # API、架构、数据库、部署和交接文档
├── docs/ # API、架构、数据库、部署和项目文档
├── scripts/ # 初始化和维护脚本
├── tests/ # 自动化测试
├── Dockerfile
@@ -90,8 +90,8 @@ fastapi/
```powershell
cd D:\Code\newfounder\medical-consultation-agent
python -m venv .venv
.\.venv\Scripts\activate
python -m venv backend\.venv
.\backend\.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
uvicorn app.main:app --host 127.0.0.1 --port 9000
@@ -209,17 +209,20 @@ event: answer_done
.\backend\.venv\Scripts\python.exe tests\test_api_contract.py
```
## 9. 交接文档
## 9. 项目文档
| 文档 | 用途 |
|---|---|
| `docs/00_project_overview.md` | 项目总览和功能讲解顺序 |
| `docs/01_architecture.md` | 系统架构、调用链路和模块边界 |
| `docs/02_database.md` | 核心数据库表和读写边界 |
| `docs/03_api_design.md` | 前端联调 API 文档 |
| `docs/04_deployment.md` | 云服务器部署、更新和回滚 |
| `docs/05_modules.md` | 功能模块说明 |
| `docs/06_handover.md` | 离职交接说明和风险清单 |
| `docs/06_maintenance_guide.md` | 开发维护说明和风险清单 |
| `docs/07_troubleshooting.md` | 常见故障排查 |
| `docs/08_feature_code_map.md` | 功能到接口、代码和数据表的映射表 |
| `docs/09_prompt_template_catalog.md` | 提示词模板目录和调用说明 |
## 10. 重要约定
+8 -3
View File
@@ -1,6 +1,6 @@
from pathlib import Path
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Query
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
@@ -15,9 +15,14 @@ router = APIRouter()
@router.get("", response_model=ApiResponse[EvaluationListResponse])
def list_evaluations(ctx: UserContext = Depends(get_user_context), db: Session = Depends(get_db)):
def list_evaluations(
page: int = Query(default=1, ge=1, description="页码,从 1 开始"),
page_size: int = Query(default=10, ge=1, le=100, description="每页数量,最大 100"),
ctx: UserContext = Depends(get_user_context),
db: Session = Depends(get_db),
):
"""历史评价:基于 user_id 查询完整训练后的评价记录。"""
return ok(EvaluationService(db).list_history(ctx.user_id))
return ok(EvaluationService(db).list_history(ctx.user_id, page=page, page_size=page_size))
@router.get("/{evaluation_id}", response_model=ApiResponse[EvaluationDetailResponse])
+9 -2
View File
@@ -1,4 +1,4 @@
from sqlalchemy import delete, select
from sqlalchemy import delete, func, select
from sqlalchemy.orm import Session
from app.models.training_record import TrainingRecord, TrainingScoreDetail
@@ -46,12 +46,19 @@ class EvaluationRepository:
)
return self.db.scalar(stmt)
def list_by_user(self, user_id: str) -> list[TrainingRecord]:
def count_by_user(self, user_id: str) -> int:
"""历史评价计数:按外部 user_id 统计完整训练后的评价记录总数。"""
stmt = select(func.count()).select_from(TrainingRecord).where(TrainingRecord.external_user_id == user_id)
return int(self.db.scalar(stmt) or 0)
def list_by_user(self, user_id: str, limit: int, offset: int) -> list[TrainingRecord]:
"""历史评价:按外部 user_id 查询完整训练后的评价记录。"""
stmt = (
select(TrainingRecord)
.where(TrainingRecord.external_user_id == user_id)
.order_by(TrainingRecord.created_at.desc())
.limit(limit)
.offset(offset)
)
return list(self.db.scalars(stmt).all())
+12
View File
@@ -61,10 +61,22 @@ class EvaluationListItem(BaseModel):
pdf_exported: bool
class PaginationMeta(BaseModel):
"""分页信息:用于历史训练记录列表的前端分页展示。"""
page: int
page_size: int
total: int
total_pages: int
has_next: bool
has_prev: bool
class EvaluationListResponse(BaseModel):
"""历史评价列表响应。"""
items: list[EvaluationListItem]
pagination: PaginationMeta
class ExportPdfResponse(BaseModel):
+15 -3
View File
@@ -19,6 +19,7 @@ from app.schemas.evaluation import (
EvaluationListItem,
EvaluationListResponse,
EvaluationResponse,
PaginationMeta,
ScoreDetailItem,
)
from app.services.audit_service import AuditService
@@ -235,9 +236,12 @@ class EvaluationService:
"""用户 ID 兼容:Django 返回的 id 写入 external_user_id,纯数字时同步写入源库 user_id。"""
return int(user_id) if str(user_id).isdigit() else None
def list_history(self, user_id: str) -> EvaluationListResponse:
def list_history(self, user_id: str, page: int = 1, page_size: int = 10) -> EvaluationListResponse:
"""历史评价:按 Django 用户中心 ID 查询完整训练后的 training_record。"""
records = self.eval_repo.list_by_user(user_id)
total = self.eval_repo.count_by_user(user_id)
offset = (page - 1) * page_size
records = self.eval_repo.list_by_user(user_id, limit=page_size, offset=offset)
total_pages = (total + page_size - 1) // page_size if total else 0
return EvaluationListResponse(
items=[
EvaluationListItem(
@@ -249,7 +253,15 @@ class EvaluationService:
pdf_exported=bool(record.pdf_file_path),
)
for record in records
]
],
pagination=PaginationMeta(
page=page,
page_size=page_size,
total=total,
total_pages=total_pages,
has_next=page < total_pages,
has_prev=page > 1 and total_pages > 0,
),
)
def get_detail(self, evaluation_id: int, user_id: str) -> EvaluationDetailResponse:
+135
View File
@@ -0,0 +1,135 @@
# 项目总览
本文档用于快速说明医疗问诊 Agent FastAPI 后端的项目边界、功能现状、代码入口、部署方式、测试方法和后续维护重点。团队成员优先阅读本文,再按链接进入详细文档。
## 1. 项目定位
本项目是医疗教学平台中的 FastAPI 后端子服务,负责医疗问诊训练、教学互动、AI 评价、PDF 报告、AI 学习助手和机构知识库预留能力。
本项目不负责:
- 用户注册登录
- 用户管理后台
- 病例 PDF 解析入库
- 病例增删改后台
- 多租户权限后台
- HIS/LIS/PACS 对接
- 前端最终 UI
用户身份来自 Django 用户中心。前端携带 `Authorization: Bearer <access_token>` 调用 FastAPIFastAPI 转发 token 到 Django `/api/user/users/me/`,以 Django 返回的 `id` 作为本服务统一 `user_id`
## 2. 当前已实现功能
| 模块 | 状态 | 主要入口 |
|---|---|---|
| 用户鉴权 | 已实现 | `GET /api/v1/auth/me` |
| 病例读取 | 已实现 | `GET /api/v1/cases``GET /api/v1/cases/{case_id}` |
| 训练配置 | 已实现 | `GET /api/v1/training-config/recommended``GET /api/v1/training-config/options` |
| 训练会话 | 已实现 | `POST /api/v1/sessions` |
| 流式问诊 | 已实现 | `POST /api/v1/sessions/{session_id}/chat/stream` |
| 王主任练习提示 | 已实现 | `POST /api/v1/sessions/{session_id}/hints/stream` |
| 体格检查 / 辅助检查 | 已实现 | `physical-exams``auxiliary-exams` 相关接口 |
| 诊断 / 治疗提交 | 已实现 | `complete-inquiry``diagnosis``treatment` |
| AI 评价 | 已实现 | `POST /api/v1/sessions/{session_id}/evaluation` |
| 个人中心训练记录 | 已实现,支持分页 | `GET /api/v1/evaluations?page=1&page_size=10` |
| PDF 下载 | 已实现 | `GET /api/v1/evaluations/{evaluation_id}/download-pdf` |
| 教学互动 | 已实现 | `GET /api/v1/teaching/cases/{case_id}/items``POST /api/v1/teaching/evaluation` |
| AI 学习助手 | 已实现流式问答 | `POST /api/v1/learning-assistant/chat/stream` |
| 内容管理员知识库上传 | 基础链路已实现 | `POST /api/v1/knowledge-admin/documents/upload` |
| 健康检查 | 已实现 | `/health/live``/health/ready` |
## 3. 推荐讲解顺序
1. 项目边界:FastAPI 是后端子服务,不做登录、病例管理和最终 UI。
2. 认证链路:前端 token -> FastAPI -> Django `/me` -> 统一 `user_id`
3. 训练链路:病例 -> 配置 -> 会话 -> 问诊 -> 检查 -> 诊断 -> 治疗 -> 评价 -> PDF -> 历史记录。
4. 教学互动链路:题目列表 -> 答题 -> 评价 -> PDF。
5. AI 学习助手链路:机构知识库检索 -> LLM 流式回答;无知识库时降级通用回答。
6. 数据库边界:平台基础数据由 Django/平台维护,FastAPI 主要写训练过程和训练结果。
7. 部署和验证:Docker、`.env``/fastapi/docs`、测试命令。
8. 后续生产化工作:索引补齐、任务队列、知识库构建、权限细化、日志监控。
## 4. 重点代码入口
| 目录/文件 | 作用 |
|---|---|
| `app/main.py` | FastAPI 应用工厂、CORS、路由挂载、异常处理 |
| `app/api/router.py` | 所有业务路由聚合 |
| `app/core/user_context.py` | 从请求中解析当前用户上下文 |
| `app/services/external_auth_service.py` | 调用 Django 用户中心 `/me` |
| `app/api/sessions.py` | 训练链路接口 |
| `app/services/session_service.py` | 训练会话、问诊、诊断治疗状态流转 |
| `app/services/order_service.py` | 体格检查和辅助检查 |
| `app/services/evaluation_service.py` | 训练评价生成和训练记录查询 |
| `app/services/teaching_service.py` | 教学互动题目与评价 |
| `app/services/pdf_export_service.py` | PDF 报告生成与下载 |
| `app/services/learning_assistant_service.py` | AI 学习助手 RAG + LLM 编排 |
| `app/services/document_ingestion_service.py` | 内容管理员 PDF 上传入库 |
| `app/agents` | Patient、Hint、Scoring、Report、Learning Assistant 等 LLM Agent |
| `app/prompts` | Markdown 提示词模板 |
完整功能映射见 [08_feature_code_map.md](08_feature_code_map.md)。
## 5. 核心文档索引
| 文档 | 用途 |
|---|---|
| [01_architecture.md](01_architecture.md) | 系统架构、核心链路、模块边界 |
| [02_database.md](02_database.md) | 数据库表、读写边界、表含义 |
| [03_api_design.md](03_api_design.md) | 前端联调用 API 文档 |
| [04_deployment.md](04_deployment.md) | 云服务器部署、更新、回滚 |
| [05_modules.md](05_modules.md) | 模块职责、接口、代码入口 |
| [06_maintenance_guide.md](06_maintenance_guide.md) | 开发维护、风险、发布检查清单 |
| [07_troubleshooting.md](07_troubleshooting.md) | 常见故障排查 |
| [08_feature_code_map.md](08_feature_code_map.md) | 功能到接口、代码、数据表的映射表 |
| [09_prompt_template_catalog.md](09_prompt_template_catalog.md) | 提示词模板目录和调用说明 |
## 6. 本地测试命令
```powershell
cd D:\Code\newfounder\medical-consultation-agent
.\backend\.venv\Scripts\python.exe -m compileall app scripts tests
.\backend\.venv\Scripts\python.exe tests\test_core_logic.py
.\backend\.venv\Scripts\python.exe tests\test_demo_flow.py
.\backend\.venv\Scripts\python.exe tests\test_api_contract.py
```
## 7. 数据库与 Redis 检查
```powershell
.\backend\.venv\Scripts\python.exe scripts\check_final_schema.py
.\backend\.venv\Scripts\python.exe scripts\check_final_demo_readiness.py
```
推荐索引缺失不会阻断当前功能,但生产并发前需要补齐。
## 8. 云端部署验证
```bash
cd /home/code/medical-ai/fastapi
git pull origin main
cd /home/code/medical-ai
docker compose build fastapi
docker compose up -d fastapi
docker compose logs --tail=200 fastapi
curl http://127.0.0.1:9000/health/ready
```
公网访问:
```text
http://8.160.178.88/fastapi/docs
```
## 9. 发布前检查
- `git status --short` 无未确认改动,或已明确哪些改动尚未提交。
- `.env` 不提交 Git。
- `docs/03_api_design.md` 是前端联调依据。
- `docs/02_database.md` 与当前 ORM 表名一致。
- 自动化测试全部通过。
- 云端 `/fastapi/docs` 可访问。
- `GET /api/v1/auth/me` 可用。
- 训练链路、教学互动、PDF、AI 学习助手各跑通一次。
+1 -1
View File
@@ -1,6 +1,6 @@
# 系统架构说明
本文档用于交接医疗问诊 Agent FastAPI 后端的系统边界、核心链路和外部依赖。
本文档用于说明医疗问诊 Agent FastAPI 后端的系统边界、核心链路和外部依赖。
## 1. 项目定位
+7 -7
View File
@@ -1,6 +1,6 @@
# 数据库说明
本文档说明医疗问诊 Agent FastAPI 后端依赖的核心数据表、读写边界和交接注意事项。
本文档说明医疗问诊 Agent FastAPI 后端依赖的核心数据表、读写边界和维护注意事项。
## 1. 数据库边界
@@ -156,35 +156,35 @@ FastAPI 使用 Django 返回的 `id` 作为业务 `user_id`。
## 5. 知识库预留表
### `kb_knowledge_space`
### `kb_spaces`
| 项 | 说明 |
|---|---|
| 用途 | 机构知识空间和 Milvus collection 映射 |
| 关键字段 | `institution_id``collection_name``embedding_model``embedding_dim``status` |
### `kb_knowledge_document`
### `kb_documents`
| 项 | 说明 |
|---|---|
| 用途 | 内容管理员上传 PDF 的元数据 |
| 关键字段 | `institution_id``uploaded_by``file_name``file_sha256``status``parse_status``embedding_status``chunk_count` |
### `kb_knowledge_chunk`
### `kb_chunks`
| 项 | 说明 |
|---|---|
| 用途 | PDF 分片文本和页码来源 |
| 关键字段 | `document_id``institution_id``chunk_uid``page_start``page_end``chunk_text` |
### `kb_knowledge_ingestion_task`
### `kb_ingestion_tasks`
| 项 | 说明 |
|---|---|
| 用途 | PDF 入库任务进度 |
| 关键字段 | `document_id``institution_id``status``progress``current_step``error_message` |
### `kb_knowledge_query_log`
### `kb_query_logs`
| 项 | 说明 |
|---|---|
@@ -204,7 +204,7 @@ Redis 用于短期会话 memory
Redis 不作为长期训练历史存储。
## 7. 数据库交接注意事项
## 7. 数据库维护注意事项
- FastAPI 不维护用户注册登录。
- FastAPI 不直接修改病例基础数据。
+1 -1
View File
@@ -201,7 +201,7 @@ data: {"latency_ms":1200,"first_token_ms":300,"model":"deepseek-chat","fallback_
| 接口名称 | url | api | methods | params(入参) | response(返回参数) |
|---|---|---|---|---|---|
| 训练记录列表 | `http://8.160.178.88/fastapi/api/v1/evaluations` | `/api/v1/evaluations` | `GET` | Query`limit` 可选,默认20`offset` 可选,默认0 | `data.items[]` 当前用户完整训练后的评价记录 |
| 训练记录列表 | `http://8.160.178.88/fastapi/api/v1/evaluations?page=1&page_size=10` | `/api/v1/evaluations` | `GET` | Query`page` 选填,页码,从1开始,默认1`page_size` 选填,每页数量,1-100,默认10 | `data.items[]` 当前用户完整训练后的评价记录`data.pagination` 分页信息 |
| 训练记录详情 / 评价详情 | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}` | `/api/v1/evaluations/{evaluation_id}` | `GET` | Path`evaluation_id` 必填 | 完整评价详情,训练和教学互动共用 |
| 导出 PDF | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/export-pdf` | `/api/v1/evaluations/{evaluation_id}/export-pdf` | `POST` | Path`evaluation_id` 必填 | `data.file_path``data.exported_at` |
| 下载 PDF | `http://8.160.178.88/fastapi/api/v1/evaluations/{evaluation_id}/download-pdf` | `/api/v1/evaluations/{evaluation_id}/download-pdf` | `GET` | Path`evaluation_id` 必填 | `application/pdf` 文件流,浏览器可直接下载 |
+1 -1
View File
@@ -1,6 +1,6 @@
# 部署说明
本文档用于交接云服务器部署、更新、回滚和验证流程。
本文档用于说明云服务器部署、更新、回滚和验证流程。
## 1. 服务器目录
+4 -4
View File
@@ -111,11 +111,11 @@
|---|---|
| 主要作用 | 查询当前用户训练记录和评价详情 |
| 当前状态 | 已实现 |
| 相关接口 | `GET /api/v1/evaluations``GET /api/v1/evaluations/{evaluation_id}` |
| 相关接口 | `GET /api/v1/evaluations?page=1&page_size=10``GET /api/v1/evaluations/{evaluation_id}` |
| 相关代码 | `app/api/evaluations.py``app/services/evaluation_service.py` |
| 相关表 | `training_record``training_score_detail` |
| 重要规则 | 必须按 `user_id` 隔离 |
| 后续优化 | 增加分页筛选、统计图表和能力画像 |
| 后续优化 | 增加筛选条件、统计图表和能力画像 |
## 11. AI 学习助手模块
@@ -125,7 +125,7 @@
| 当前状态 | 已实现正式流式接口;无知识库时自动降级为通用 LLM 回答 |
| 相关接口 | `POST /api/v1/learning-assistant/chat/stream` |
| 相关代码 | `app/api/learning_assistant.py``app/services/learning_assistant_service.py``app/agents/learning_assistant_agent.py` |
| 相关表 | `kb_knowledge_space``kb_knowledge_chunk``kb_knowledge_query_log` |
| 相关表 | `kb_spaces``kb_chunks``kb_query_logs` |
| 外部依赖 | LLM、Embedding、Milvus |
| 后续优化 | 查询改写、rerank、多轮记忆、来源引用格式优化、成本统计 |
@@ -137,6 +137,6 @@
| 当前状态 | 接口和数据结构已预留,生产级大规模入库仍需压测 |
| 相关接口 | `POST /api/v1/knowledge-admin/documents/upload`、文档列表、文档详情 |
| 相关代码 | `app/api/knowledge_admin.py``app/services/document_ingestion_service.py``app/integrations/*` |
| 相关表 | `kb_knowledge_space``kb_knowledge_document``kb_knowledge_chunk``kb_knowledge_ingestion_task` |
| 相关表 | `kb_spaces``kb_documents``kb_chunks``kb_ingestion_tasks` |
| 外部依赖 | Milvus、Embedding 服务、Celery |
| 后续优化 | 任务队列监控、失败重试、分片策略、文件去重、权限后台 |
-182
View File
@@ -1,182 +0,0 @@
# 交接文档
本文档用于说明医疗问诊 Agent FastAPI 后端当前状态、接手重点、风险和后续工作。
## 1. 当前项目状态
当前 FastAPI 后端已经完成第一阶段核心功能,并已接入 Django 用户中心、MySQL、Redis、LLM、PDF 下载和 AI 学习助手。
已完成能力:
- Django access token 鉴权
- 训练配置和推荐配置
- 新建训练会话
- AI 病人流式问诊
- 王主任练习提示
- 体格检查和辅助检查
- 完成问诊、提交诊断、提交治疗
- AI 评价和评分明细
- PDF 报告导出和下载
- 教学互动题目和评价
- 个人中心训练记录和详情
- AI 学习助手流式问答
- 后台知识库上传和 RAG 架构预留
当前不是最终生产级完整系统,后续上线后仍需要逐模块做稳定性、监控、权限、性能和运维增强。
## 2. 优先关注
接手后建议按顺序确认:
1. 能否本地启动 FastAPI。
2. 能否连接云端 MySQL 和 Redis。
3. `GET /api/v1/auth/me` 是否能通过 Django token 返回用户信息。
4. 训练全流程是否能跑通。
5. 教学互动是否能跑通。
6. PDF 下载是否正常。
7. AI 学习助手流式接口是否正常。
8. 云服务器 `docker compose build fastapi` 是否成功。
9. `.env` 是否与云服务器 docker-compose 服务名一致。
## 3. 当前重要约定
- FastAPI 不负责登录注册。
- 用户身份来自 Django `/api/user/users/me/`
- FastAPI 使用 Django 返回的 `id` 作为 `user_id`
- 普通业务接口需要 `Authorization: Bearer <access_token>`
- 训练记录只有完整流程完成后写入。
- 问诊过程主要存在 Redis 短期 memory。
- 检查结果只来自数据库。
- AI 学习助手正式接口只保留流式接口。
- 知识库未初始化时,学习助手仍应正常回答。
## 4. 发布前必须检查
本地检查:
```powershell
cd D:\Code\newfounder\medical-consultation-agent
.\backend\.venv\Scripts\python.exe -m compileall app scripts tests
.\backend\.venv\Scripts\python.exe tests\test_core_logic.py
.\backend\.venv\Scripts\python.exe tests\test_demo_flow.py
.\backend\.venv\Scripts\python.exe tests\test_api_contract.py
```
Git 检查:
```bash
git status --short
git grep -n "<<<<<<<\|=======\|>>>>>>>"
git diff --check
```
敏感信息检查:
```bash
git grep -n "sk-"
git grep -n "api_key"
git grep -n "password"
git grep -n "access_token"
git grep -n "secret"
```
服务器检查:
```bash
cd /home/code/medical-ai
docker compose build fastapi
docker compose up -d fastapi
docker compose logs --tail=200 fastapi
curl http://127.0.0.1:9000/health/ready
```
## 5. 已知风险
| 风险 | 当前处理 | 后续建议 |
|---|---|---|
| LLM 调用超时或失败 | 已有异常返回和 mock/fallback 配置 | 增加限流、重试、熔断、成本统计 |
| 知识库真实大规模入库 | 当前为生产预留能力 | 压测 PDF 解析、embedding、Milvus 写入 |
| Celery 任务监控 | 已预留任务模块 | 增加 worker 部署、重试、任务状态看板 |
| 部分宽异常处理 | 保证 Demo 稳定 | 逐步收窄异常类型并补充结构化日志 |
| PDF 报告样式 | 当前可下载 | 后续按医院模板优化 |
| 前端最终样式 | 不在本仓库维护 | 以后按 API 文档继续联调 |
## 6. 后续生产级优化建议
### 6.1 工程与质量
- 增加 CI/CD。
- 增加 lint 和格式化。
- 增加数据库 migration 管理。
- 增加更多 service 单元测试。
- 增加接口压测。
### 6.2 安全与权限
- 完善内容管理员角色来源。
- 对后台知识库接口增加更细权限。
- 增加审计日志检索。
- 增加敏感信息脱敏。
### 6.3 AI 与 Agent
- 优化 Patient Agent 回答稳定性。
- 优化 Scoring Agent JSON 结构校验。
- 增加评分重试和人工复核。
- 增加 LLM 调用耗时、token、费用统计。
- 增加提示词版本管理。
### 6.4 知识库
- 完善 PDF 解析质量检测。
- 优化分片策略。
- 接入真实 embedding 批量任务。
- 增加 Milvus collection 生命周期管理。
- 增加 RAG 命中率和用户反馈统计。
## 7. 常用命令
本地测试:
```powershell
.\backend\.venv\Scripts\python.exe tests\test_api_contract.py
```
服务器日志:
```bash
docker compose logs -f fastapi
```
服务器重启:
```bash
docker compose up -d fastapi
```
拉取最新代码:
```bash
cd /home/code/medical-ai/fastapi
git pull origin main
```
## 8. 交接清单
- [ ] `main` 分支是最新代码
- [ ] `git status` 干净
- [ ] 无 Git 冲突标记
- [ ] 无真实密钥提交
- [ ] `.env.example``.env.production.example` 已更新
- [ ] README 已更新
- [ ] API 文档已更新
- [ ] 架构、数据库、部署、模块、排障文档已补齐
- [ ] 本地测试全部通过
- [ ] Docker build 通过
- [ ] 云端 `/fastapi/docs` 可访问
- [ ] `auth/me` 可用
- [ ] 训练链路可用
- [ ] 教学互动可用
- [ ] PDF 下载可用
- [ ] AI 学习助手流式可用
+125
View File
@@ -0,0 +1,125 @@
# 开发维护指南
本文档面向后续开发和运维人员,说明当前 FastAPI 后端的维护重点、发布检查、风险项和排查路径。
## 1. 维护目标
当前项目已经具备训练页面、教学互动、个人中心训练记录、PDF 报告、AI 学习助手和知识库预留链路。后续维护应优先保持以下原则:
- 不改变已稳定 API 的语义。
- 不把业务逻辑写入 API router。
- 不在 FastAPI 中实现登录注册。
- 不让 LLM 编造检查检验结果。
- 不长期保存完整问诊聊天记录。
- 不提交 `.env`、token、API Key、日志、PDF 生成物。
## 2. 重点维护模块
| 模块 | 代码入口 | 维护重点 |
|---|---|---|
| 用户鉴权 | `app/services/external_auth_service.py` | Django `/me` 地址、Authorization 透传、用户字段标准化 |
| 训练会话 | `app/services/session_service.py` | 状态流转、Redis memory、Patient Agent 调用 |
| 检查申请 | `app/services/order_service.py` | 数据库检查项、幂等写入、结果写入 memory |
| 评价生成 | `app/services/evaluation_service.py` | 评分规则、评分明细、PDF 数据结构 |
| 教学互动 | `app/services/teaching_service.py` | 教学题读取、答案评分、训练记录复用 |
| 个人中心 | `app/api/evaluations.py` | 分页、user_id 隔离、PDF 下载 |
| 学习助手 | `app/services/learning_assistant_service.py` | RAG 检索、来源引用、流式输出 |
| 知识库 | `app/services/document_ingestion_service.py` | 内容管理员权限、PDF 解析、embedding、Milvus |
## 3. 发布前检查清单
```powershell
.\backend\.venv\Scripts\python.exe -m compileall app scripts tests
.\backend\.venv\Scripts\python.exe tests\test_core_logic.py
.\backend\.venv\Scripts\python.exe tests\test_demo_flow.py
.\backend\.venv\Scripts\python.exe tests\test_api_contract.py
.\backend\.venv\Scripts\python.exe scripts\check_final_demo_readiness.py
```
通过标准:
- Python 编译无错误。
- 核心逻辑测试通过。
- Demo 流程测试通过。
- API 契约测试通过。
- 就绪检查 `ready=true`
## 4. 数据库维护说明
FastAPI 当前依赖平台合并后的数据库,核心表包括:
- `user`
- `institution`
- `department`
- `case_base`
- `traditional_case`
- `teaching_case`
- `case_exam_item`
- `scoring_rule`
- `training_session`
- `training_order`
- `training_submission`
- `training_record`
- `training_score_detail`
- `audit_logs`
- `prompt_templates`
- `kb_spaces`
- `kb_documents`
- `kb_chunks`
- `kb_query_logs`
生产并发前需要重点确认推荐索引:
- `case_base.case_type`
- `case_base.difficulty`
- `case_base.publish_status`
- `case_base.status`
- `scoring_rule.dimension`
- `scoring_rule.competency_dimension`
- `training_score_detail.dimension`
## 5. Redis 维护说明
Redis 用于训练会话短期 memory,不作为长期训练记录保存。
生命周期:
1. 创建训练会话时写入开场消息。
2. 流式问诊时写入医生问题和 AI 病人回复。
3. 申请检查时写入工具结果。
4. 生成评价后释放当前会话 memory。
5. 未完成训练依赖 TTL 自动过期。
## 6. LLM 和提示词维护说明
提示词模板说明见 [09_prompt_template_catalog.md](09_prompt_template_catalog.md)。
维护规则:
- Patient Agent 只回答患者或家属视角,不输出诊断和治疗方案。
- Hint Agent 用于练习提示,不能直接给完整答案。
- Scoring Agent 必须输出可解析 JSON。
- Report Agent 只整理报告,不重新评分。
- Learning Assistant 命中知识库时必须引用 PDF 来源和页码;未命中时必须声明未检索到机构知识库参考。
## 7. 常见风险
| 风险 | 表现 | 处理 |
|---|---|---|
| Django 鉴权失败 | `AUTH_CREDENTIAL_REQUIRED``AUTH_INVALID` | 检查 token、`AUTH_USER_ME_URL`、Django 服务 |
| 问诊流式卡住 | 前端一直等待 SSE | 检查 LLM Key、Base URL、模型名、超时配置 |
| 检查项为空 | 前端无体格/辅助检查 | 检查 `case_exam_item.case_id``item_type` |
| 评价失败 | 无法生成报告 | 检查 `scoring_rule`、提交内容、LLM JSON 输出 |
| PDF 下载失败 | 文件不存在或 404 | 检查 `REPORT_STORAGE_DIR` 和文件权限 |
| 学习助手无来源 | `retrieval_hit=false` | 检查知识库表、Milvus、embedding 配置 |
## 8. 开发规范
- API 层只做参数接收、用户上下文获取和响应封装。
- Service 层承载业务流程。
- Repository 层只做数据库读写。
- Agent 层只做提示词拼接、LLM 调用和输出校验。
- Model 层只定义 ORM。
- Schema 层只定义 Pydantic 入参/出参。
- 新增接口必须同步更新 `docs/03_api_design.md``docs/08_feature_code_map.md`
- 新增提示词必须同步更新 `docs/09_prompt_template_catalog.md`
+2 -2
View File
@@ -1,6 +1,6 @@
# 常见故障排查
本文档用于接手人快速定位本地和云服务器常见问题。
本文档用于开发人员快速定位本地和云服务器常见问题。
## 1. `/fastapi/docs` 打不开
@@ -155,7 +155,7 @@ retrieval_error=当前机构知识库暂未初始化或检索不可用...
排查知识库:
- 用户是否有 `institution_id`
- 是否已有 `kb_knowledge_space`
- 是否已有 `kb_spaces`
- Milvus 是否运行
- Embedding 是否配置
+99
View File
@@ -0,0 +1,99 @@
# 功能-接口-代码-数据表映射表
本文档说明每个功能对应的 API、Router、Service、Repository、Model/数据表和关键逻辑。开发人员排查问题时优先从本表定位代码入口。
## 1. 通用调用规则
除健康检查外,业务接口都需要携带:
```http
Authorization: Bearer <access_token>
X-Entry-Scene: vue_frontend
X-Request-Id: <>
```
普通 JSON 接口统一返回:
```json
{
"code": "OK",
"message": "success",
"data": {}
}
```
SSE 流式接口返回 `event + data`,不包裹上述 JSON 结构。
## 2. 功能映射总表
| 功能模块 | 功能点 | API | Router | Service | Repository | Model/表 | 关键说明 |
|---|---|---|---|---|---|---|---|
| 用户鉴权 | 当前用户信息 | `GET /api/v1/auth/me` | `app/api/auth.py::auth_me` | `app/services/external_auth_service.py::authenticate` | 无本地仓储 | Django `user``institution``department` | FastAPI 转发 token 到 Django `/api/user/users/me/`,使用 Django `id` 作为统一 `user_id` |
| Agent 状态 | Hello / 功能开关 | `GET /api/v1/agent/hello` | `app/api/agent.py::agent_hello` | `app/core/config.py::as_public_dict` | `app/services/audit_service.py` | `audit_logs` | 给前端展示当前模型、PDF、知识库等能力开关 |
| 病例读取 | 病例列表 | `GET /api/v1/cases` | `app/api/cases.py::list_cases` | `app/services/case_service.py::list_cases` | `app/repositories/case_repository.py` | `case_base``traditional_case``teaching_case` | 只读已发布启用病例,不做病例新增/删除 |
| 病例读取 | 病例详情 | `GET /api/v1/cases/{case_id}` | `app/api/cases.py::get_case_detail` | `app/services/case_service.py::get_case_detail` | `app/repositories/case_repository.py` | `case_base``traditional_case``teaching_case` | 前端展示病例基础信息,不作为病例管理后台 |
| 训练配置 | 推荐配置信息 | `GET /api/v1/training-config/recommended?case_id=1` | `app/api/training_config.py::get_recommended_training_config` | `app/services/training_config_service.py::get_recommended` | `app/repositories/case_repository.py` | `case_base``traditional_case` | 返回默认就诊环境、年龄段、文化程度、性格等病人初始化信息 |
| 训练配置 | 可选配置信息 | `GET /api/v1/training-config/options?case_id=1` | `app/api/training_config.py::get_training_config_options` | `app/services/training_config_service.py::get_options` | `app/repositories/case_repository.py` | `case_base` | 返回前端可选配置项,用于自定义病人信息 |
| 训练页面 | 新建会话 | `POST /api/v1/sessions` | `app/api/sessions.py::create_session` | `app/services/session_service.py::create_session` | `app/repositories/session_repository.py``case_repository.py` | `training_session`、Redis memory | 创建会话、写入 user_id、初始化短期 memory 和病人开场白 |
| 训练页面 | 流式问诊 | `POST /api/v1/sessions/{session_id}/chat/stream` | `app/api/sessions.py::chat_stream` | `app/services/session_service.py::stream_chat` | `session_repository.py``case_repository.py` | `training_session`、Redis memory | Patient Agent SSE 输出 `message_delta``message_done``error` |
| 训练页面 | 王主任练习提示 | `POST /api/v1/sessions/{session_id}/hints/stream` | `app/api/sessions.py::stream_hints` | `app/services/session_service.py::stream_hints` | `session_repository.py``case_repository.py` | `training_session`、Redis memory | 根据病例和当前会话生成一句话练习提示 |
| 训练页面 | 结构化提示 | `POST /api/v1/sessions/{session_id}/hints` | `app/api/sessions.py::generate_hints` | `app/services/session_service.py::generate_hints` | `session_repository.py``case_repository.py` | `training_session`、Redis memory | 返回缺失维度、下一步问题、推荐检查;当前前端主用流式提示 |
| 训练页面 | 检查项列表 | `GET /api/v1/sessions/{session_id}/order-items` | `app/api/sessions.py::list_order_items` | `app/services/order_service.py::list_order_items` | `case_repository.py``session_repository.py` | `case_exam_item` | 返回当前病例全部可申请检查项,不返回结果 |
| 训练页面 | 体格检查列表 | `GET /api/v1/sessions/{session_id}/physical-exams` | `app/api/sessions.py::list_physical_exam_items` | `app/services/order_service.py::list_physical_exam_items` | `case_repository.py``session_repository.py` | `case_exam_item` | 过滤 `item_type=physical_exam` |
| 训练页面 | 辅助检查列表 | `GET /api/v1/sessions/{session_id}/auxiliary-exams` | `app/api/sessions.py::list_auxiliary_exam_items` | `app/services/order_service.py::list_auxiliary_exam_items` | `case_repository.py``session_repository.py` | `case_exam_item` | 过滤非体格检查项 |
| 训练页面 | 体格检查结果 | `POST /api/v1/sessions/{session_id}/physical-exams/{item_code}` | `app/api/sessions.py::create_physical_exam_order` | `app/services/order_service.py::create_physical_exam_order` | `case_repository.py``session_repository.py` | `case_exam_item``training_order`、Redis memory | 检查结果只来自数据库;同一会话同一 `item_code` 幂等 |
| 训练页面 | 辅助检查结果 | `POST /api/v1/sessions/{session_id}/auxiliary-exams/{item_code}` | `app/api/sessions.py::create_auxiliary_exam_order` | `app/services/order_service.py::create_auxiliary_exam_order` | `case_repository.py``session_repository.py` | `case_exam_item``training_order`、Redis memory | 检查结果写入短期 memory,供后续评价使用 |
| 训练页面 | 完成问诊 | `POST /api/v1/sessions/{session_id}/complete-inquiry` | `app/api/sessions.py::complete_inquiry` | `app/services/session_service.py::complete_inquiry` | `session_repository.py` | `training_session`、Redis memory | 校验至少有医生问诊后进入诊断阶段 |
| 训练页面 | 提交诊断 | `POST /api/v1/sessions/{session_id}/diagnosis` | `app/api/sessions.py::submit_diagnosis` | `app/services/session_service.py::submit_diagnosis` | `session_repository.py` | `training_submission``training_session` | 保存主诊断、鉴别诊断、诊断依据 |
| 训练页面 | 提交治疗 | `POST /api/v1/sessions/{session_id}/treatment` | `app/api/sessions.py::submit_treatment` | `app/services/session_service.py::submit_treatment` | `session_repository.py` | `training_submission``training_session` | 保存治疗原则、措施、风险预案、沟通和随访 |
| 训练页面 | 生成评价 | `POST /api/v1/sessions/{session_id}/evaluation` | `app/api/sessions.py::create_evaluation` | `app/services/evaluation_service.py::create_evaluation` | `evaluation_repository.py``source_case_repository.py``session_repository.py` | `training_record``training_score_detail``scoring_rule` | 读取评分规则、短期 memory、诊断治疗提交内容,调用 Scoring Agent |
| 个人中心 | 训练记录列表 | `GET /api/v1/evaluations?page=1&page_size=10` | `app/api/evaluations.py::list_evaluations` | `app/services/evaluation_service.py::list_history` | `app/repositories/evaluation_repository.py` | `training_record` | 按 Django user_id 隔离,支持分页 |
| 个人中心 | 评价详情 | `GET /api/v1/evaluations/{evaluation_id}` | `app/api/evaluations.py::get_evaluation_detail` | `app/services/evaluation_service.py::get_detail` | `evaluation_repository.py` | `training_record``training_score_detail` | 训练评价和教学互动评价共用详情接口 |
| 个人中心 | 导出 PDF | `POST /api/v1/evaluations/{evaluation_id}/export-pdf` | `app/api/evaluations.py::export_pdf` | `app/services/pdf_export_service.py::export` | `evaluation_repository.py` | `training_record` | 生成本地 PDF 并写入 `pdf_file_path` |
| 个人中心 | 下载 PDF | `GET /api/v1/evaluations/{evaluation_id}/download-pdf` | `app/api/evaluations.py::download_pdf` | `app/services/pdf_export_service.py::export` | `evaluation_repository.py` | `training_record` | 校验 user_id 后返回 `application/pdf` 文件流 |
| 教学互动 | 获取教学列表 | `GET /api/v1/teaching/cases/{case_id}/items` | `app/api/teaching.py::get_teaching_items` | `app/services/teaching_service.py::list_items` | `teaching_repository.py``case_repository.py` | `case_base``teaching_case` | 返回题目、选项、答案、解析文本、视频 |
| 教学互动 | 生成评价 | `POST /api/v1/teaching/evaluation` | `app/api/teaching.py::create_teaching_evaluation` | `app/services/teaching_service.py::create_evaluation` | `evaluation_repository.py``teaching_repository.py` | `training_record``training_score_detail``teaching_case` | 根据作答结果生成教学互动评价 |
| AI 学习助手 | 流式问答 | `POST /api/v1/learning-assistant/chat/stream` | `app/api/learning_assistant.py::learning_assistant_stream_chat` | `app/services/learning_assistant_service.py::stream_chat` | `knowledge_base_repository.py` | `kb_spaces``kb_chunks``kb_query_logs` | 优先 RAG 检索;无知识库时返回 `retrieval_hit=false` 后继续 LLM 回答 |
| AI 学习助手 | 非流式调试问答 | `POST /api/v1/learning-assistant/chat` | `app/api/learning_assistant.py::learning_assistant_chat` | `app/services/learning_assistant_service.py::chat` | `knowledge_base_repository.py` | `kb_spaces``kb_chunks``kb_query_logs` | `include_in_schema=False`,正式前端不使用 |
| 知识库管理 | 上传 PDF | `POST /api/v1/knowledge-admin/documents/upload` | `app/api/knowledge_admin.py::upload_knowledge_document` | `app/services/document_ingestion_service.py::upload_pdf` | `knowledge_base_repository.py` | `kb_spaces``kb_documents``kb_ingestion_tasks``kb_chunks` | 仅内容管理员使用;学生端不展示入口 |
| 健康检查 | 存活检查 | `GET /health/live` | `app/api/health.py::live` | 无 | 无 | 无 | 检查 FastAPI 进程可响应 |
| 健康检查 | 就绪检查 | `GET /health/ready` | `app/api/health.py::ready` | `settings.deployment_config_errors` | 数据库连接 | MySQL、Redis 配置 | 用于部署验证 |
## 3. 核心流程说明
### 3.1 训练链路
1. 前端调用 `GET /api/v1/auth/me` 验证用户。
2. 前端读取病例和训练配置。
3. 前端调用 `POST /api/v1/sessions` 创建 `training_session`,后端初始化 Redis 短期 memory。
4. 前端调用 `POST /api/v1/sessions/{session_id}/chat/stream` 进行流式问诊。
5. 用户申请体格检查或辅助检查,后端从 `case_exam_item` 返回固定结果并写入 `training_order` 和 Redis memory。
6. 用户完成问诊、提交诊断、提交治疗。
7. 后端读取 `scoring_rule`、问诊 memory、检查结果、诊断治疗提交内容,调用 Scoring Agent。
8. 完成评价后写入 `training_record``training_score_detail`,释放 Redis memory。
9. 用户通过评价详情或 PDF 下载查看结果。
### 3.2 教学互动链路
1. 前端调用 `GET /api/v1/teaching/cases/{case_id}/items` 获取题目、选项、答案、解析、视频。
2. 前端提交作答到 `POST /api/v1/teaching/evaluation`
3. 后端生成评价并写入 `training_record``training_score_detail`
4. 评价详情和 PDF 下载复用个人中心接口。
### 3.3 AI 学习助手链路
1. 前端调用 `POST /api/v1/learning-assistant/chat/stream`
2. 后端根据当前用户 `institution_id` 查找知识空间。
3. 有知识库时:问题 embedding -> Milvus 检索 -> MySQL 读取 chunk 元数据 -> 拼接来源给 LLM。
4. 无知识库或检索失败时:返回 `retrieval_hit=false`,继续给出通用 LLM 学习回答。
5. 后端写入 `kb_query_logs`,记录命中、来源和耗时。
## 4. 重要边界
- FastAPI 不维护用户注册登录。
- FastAPI 不负责病例 PDF 解析入库。
- 检查结果必须来自 `case_exam_item`,不允许 LLM 编造。
- 问诊聊天记录只作为 Redis 短期 memory,评价完成后释放。
- 长期训练结果只写入 `training_record``training_score_detail`
- 教学互动评价和训练评价共用评价详情、PDF 下载、个人中心记录列表。
- 知识库上传是内容管理员能力,学生端不展示入口。
+161
View File
@@ -0,0 +1,161 @@
# 提示词模板目录
本文档说明当前项目中 Markdown 提示词模板的用途、调用位置、输入数据和输出要求。新增或修改提示词时,需要同步更新本文档。
## 1. 提示词加载规则
当前提示词分为两类:
1. 文件模板:存放在 `app/prompts`,由对应 Agent 或服务读取。
2. 代码内系统提示:部分 Agent 会在代码中拼接系统提示,同时结合病例、会话、检查结果和评分规则构造输入。
维护要求:
- 医疗问诊训练类提示词不得替代真实临床诊疗。
- AI 病人不得主动泄露病例隐藏信息。
- 检查检验结果只能来自数据库。
- 评分提示词必须要求结构化 JSON,不能返回纯长文本。
- 学习助手命中知识库时必须引用来源;未命中时必须说明未检索到机构知识库参考。
## 2. 模板清单
| 提示词模板 | 文件路径 | 使用场景 | 调用模块 | 触发接口 | 输入数据 | 输出格式 | 说明 |
|---|---|---|---|---|---|---|---|
| 新手病例提示 | `app/prompts/hint/novice_case_hint.md` | 生成结构化练习提示 | `app/agents/hint_agent.py::HintAgent.generate` | `POST /api/v1/sessions/{session_id}/hints` | 病例标题、主诉、关键症状、关键检查、当前会话 memory、已申请检查、最后一句用户问题 | JSON | 返回 `hints``missing_dimensions``next_questions``recommended_orders`LLM 失败时使用兜底提示 |
| 新手提示旧模板 | `app/prompts/hint/novice_hint.md` | 早期新手提示模板保留 | 当前主流程不直接调用 | 无主入口 | 无 | 文本 | 保留用于兼容和后续提示词对比,当前推荐使用 `novice_case_hint.md` |
| AI 病人通用模板 | `app/prompts/patient/free_chat.md` | AI 病人通用问诊风格参考 | 当前 `PatientAgent` 主要在代码内拼接系统提示 | `POST /api/v1/sessions/{session_id}/chat/stream` | 病例、隐藏信息、初始化配置、短期 memory、医生问题 | 纯文本 | 文件作为模板资产保留;实际回复规则见 `PatientAgent._build_messages` |
| AI 病人新手模板 | `app/prompts/patient/novice.md` | 新手/练习模式风格参考 | 当前 `PatientAgent` 主要在代码内拼接系统提示 | `POST /api/v1/sessions/{session_id}/chat/stream` | 同上 | 纯文本 | 新手与练习模式已合并为训练模式,提示功能由王主任练习提示承担 |
| AI 病人练习模板 | `app/prompts/patient/practice.md` | 练习模式风格参考 | 当前 `PatientAgent` 主要在代码内拼接系统提示 | `POST /api/v1/sessions/{session_id}/chat/stream` | 同上 | 纯文本 | 练习时只回答被问到的信息,不主动给诊断建议 |
| AI 病人教学模板 | `app/prompts/patient/teaching.md` | 教学风格参考 | 当前 `PatientAgent` 主要在代码内拼接系统提示 | 训练流式问诊相关接口 | 同上 | 纯文本 | 用于后续教学模式对话扩展 |
| 医生问题润色 | `app/prompts/polish/doctor_question_polish.md` | 医学生提问润色能力预留 | 当前主流程不直接调用 | 无主入口 | 医生原始问题、病例场景 | JSON 或文本 | 后续用于前端输入优化时启用 |
| 百分制评分 | `app/prompts/scoring/default_percentage.md` | 训练评价百分制评分模板 | 当前 `ScoringAgent` 在代码内拼接评分系统提示,文件作为模板资产 | `POST /api/v1/sessions/{session_id}/evaluation` | 病例、问诊 memory、检查、诊断治疗、评分规则、指南引用 | JSON | 输出 `total_score``dimension_scores``score_details``errors``improvement_plan` 等 |
| 五分制评分 | `app/prompts/scoring/default_five_point.md` | 训练评价五分制评分模板 | 当前 `ScoringAgent` 支持五分制转换,文件作为模板资产 | `POST /api/v1/sessions/{session_id}/evaluation` | 同百分制 | JSON | `score_type=five_point` 时将百分制结构转换为五分制 |
| 儿科肺炎评分 | `app/prompts/scoring/pediatrics_pneumonia.md` | 儿科支气管肺炎病例评分参考 | 当前评分依赖 `scoring_rule` 和病例数据,文件作为病例专科提示资产 | `POST /api/v1/sessions/{session_id}/evaluation` | 儿科病例、检查、诊断、治疗、评分规则 | JSON | 用于病例专科评分要求维护 |
| 教学互动评分 | `app/prompts/scoring/teaching_interaction_evaluation.md` | 教学互动答题评价 | `app/agents/scoring_agent.py::ScoringAgent.score_teaching` | `POST /api/v1/teaching/evaluation` | 病例、教学题、标准答案、解析、学生作答、评分规则 | JSON | 评价答题正确率、错误原因、学习建议和教学维度表现 |
| 报告整理 | `app/prompts/report/evaluation_report.md` | 评价报告整理模板资产 | `app/agents/report_agent.py::ReportAgent.build_report` 使用代码内校验整理 | 评价生成、PDF 下载 | Scoring Agent 输出 | JSON | Report Agent 不重新评分,只补齐报告字段 |
| 学习助手命中知识库 | `app/prompts/learning_assistant/rag_answer.md` | RAG 命中时的回答模板资产 | 当前 `LearningAssistantAgent._messages` 在代码内拼接同等规则 | `POST /api/v1/learning-assistant/chat/stream` | 用户问题、知识库片段、PDF 名称、页码、chunk_uid | 流式纯文本 | 回答中必须引用来源编号,不得编造 PDF 和页码 |
| 学习助手未命中知识库 | `app/prompts/learning_assistant/no_reference_answer.md` | 未命中知识库时的回答模板资产 | 当前 `LearningAssistantAgent._messages` 在代码内拼接同等规则 | `POST /api/v1/learning-assistant/chat/stream` | 用户问题 | 流式纯文本 | 开头必须说明“未检索到本机构知识库参考” |
## 3. 训练问诊提示词调用链
```text
POST /api/v1/sessions/{session_id}/chat/stream
-> app/api/sessions.py::chat_stream
-> app/services/session_service.py::stream_chat
-> app/agents/patient_agent.py::PatientAgent.stream_reply
-> PatientAgent._build_messages
-> LLM stream_chat
```
输入包括:
- `case_base.chief_complaint`
- `case_base.ai_patient_profile`
- `case_base.hidden_patient_info`
- `patient_config`
- Redis 短期 memory
- 医学生当前问题
输出要求:
- 纯文本
- 1 到 3 句话
- 患者或家属口吻
- 不输出 JSON / Markdown / 思考过程
- 不主动泄露隐藏信息
- 不编造检查结果
## 4. 王主任练习提示调用链
```text
POST /api/v1/sessions/{session_id}/hints/stream
-> app/api/sessions.py::stream_hints
-> app/services/session_service.py::stream_hints
-> HintAgent 或业务兜底逻辑
```
结构化提示接口:
```text
POST /api/v1/sessions/{session_id}/hints
-> app/api/sessions.py::generate_hints
-> app/services/session_service.py::generate_hints
-> app/agents/hint_agent.py::HintAgent.generate
-> app/prompts/hint/novice_case_hint.md
```
输出字段:
```json
{
"hints": [],
"missing_dimensions": [],
"next_questions": [],
"recommended_orders": []
}
```
LLM 输出非法 JSON 或调用失败时,`HintAgent._fallback_output` 会根据病例关键点和已申请检查生成稳定提示。
## 5. 训练评价提示词调用链
```text
POST /api/v1/sessions/{session_id}/evaluation
-> app/api/sessions.py::create_evaluation
-> app/services/evaluation_service.py::create_evaluation
-> app/agents/scoring_agent.py::ScoringAgent.score
-> app/agents/report_agent.py::ReportAgent.build_report
```
输入包括病例、Redis 问诊 memory、`training_order` 检查结果、`training_submission` 诊断治疗提交、`scoring_rule` 评分规则和预留指南引用。
输出必须包含 `score_type``total_score``dimension_scores``score_details``errors``improvement_plan``evidence_summary``guideline_refs``overall_comment`
异常处理:
- LLM 异常、JSON 解析失败、字段缺失时,`ScoringAgent._fallback_score` 返回稳定结构。
- `ReportAgent` 只整理字段,不重新评分。
## 6. 教学互动评价提示词调用链
```text
POST /api/v1/teaching/evaluation
-> app/api/teaching.py::create_teaching_evaluation
-> app/services/teaching_service.py::create_evaluation
-> app/agents/scoring_agent.py::ScoringAgent.score_teaching
```
输入包括病例信息、教学题列表、标准答案、解析文本、学生作答和评分规则。输出复用训练评价结构,写入 `training_record``training_score_detail`
## 7. AI 学习助手提示词调用链
```text
POST /api/v1/learning-assistant/chat/stream
-> app/api/learning_assistant.py::learning_assistant_stream_chat
-> app/services/learning_assistant_service.py::stream_chat
-> app/agents/learning_assistant_agent.py::LearningAssistantAgent.stream_answer
```
命中知识库时:
- 输入用户问题和检索到的知识片段。
- 每个来源包含 PDF 名称、页码、chunk_uid、引用文本。
- 回答必须标注来源编号,例如 `【来源1】`
未命中知识库时:
- 开头必须说明未检索到机构知识库参考。
- 不得伪造 PDF、页码或指南名称。
- 回答仅作为医学学习参考。
## 8. 后续维护规则
新增提示词时必须同时确认:
- 是否有明确调用接口。
- 是否有明确 Agent。
- 输入字段是否来自可信数据源。
- 输出格式是否可被前端或服务稳定解析。
- 是否有 fallback。
- 是否需要同步 `prompt_templates` 元数据。
- 是否需要新增 API 测试或 Agent 单元测试。
+19
View File
@@ -362,6 +362,25 @@ def run_api_contract_tests() -> None:
assert detail.status_code == 200
assert detail.json()["data"]["evaluation_id"] == evaluation_id
history_page_one = client.get("/api/v1/evaluations?page=1&page_size=1", headers=headers)
assert history_page_one.status_code == 200
history_data = history_page_one.json()["data"]
assert len(history_data["items"]) == 1
assert history_data["pagination"]["page"] == 1
assert history_data["pagination"]["page_size"] == 1
assert history_data["pagination"]["total"] >= 2
assert history_data["pagination"]["total_pages"] >= 2
assert history_data["pagination"]["has_next"] is True
assert history_data["pagination"]["has_prev"] is False
empty_cross_user_history = client.get(
"/api/v1/evaluations?page=1&page_size=10",
headers={"Authorization": "Bearer api_user_002_token", "X-Entry-Scene": "api_test"},
)
assert empty_cross_user_history.status_code == 200
assert empty_cross_user_history.json()["data"]["items"] == []
assert empty_cross_user_history.json()["data"]["pagination"]["total"] == 0
cross_user_detail = client.get(
f"/api/v1/evaluations/{evaluation_id}",
headers={"Authorization": "Bearer api_user_002_token", "X-Entry-Scene": "api_test"},