# WiseGrade(智评)交接说明 更新日期:2026-09-27。先阅读 [技术规格](docs/WISEGRADE_TECHNICAL_SPEC.md)、[会话页面与业务 Agent](docs/CHAT_AGENT.md) 和 [部署与使用指南](docs/DEPLOYMENT.md);本文件记录当前实现、验证边界和接手后的优先事项。 ## 当前状态 - 已实现《自动化专业综合实践》的教师端闭环:课程与规则版本、挂载目录扫描和导入、文档解析、课程及项目知识库、独立评分批次、逐项复核、Excel 成绩表和逐生 PDF 反馈。 - 当前源码默认进入空白“会话”草稿;首次发送才原子保存会话与消息,并支持范围编辑、删除、独立后台运行与工具过程恢复。沿用原有持久多轮会话、固定类型工具白名单、DeepSeek 原生工具调用、教师确认卡片、导入后自动索引任务和批次固定项目清单。旧页面继续可用。模型不能确认操作;会话、运行和待确认操作由迁移 `0003` 和 `0004` 持久化。 - 前端为 React/TypeScript/Vite/Ant Design;后端为 FastAPI/SQLAlchemy;PostgreSQL + pgvector 存储数据,Redis + RQ 执行评分任务,Nginx 提供前端并代理 `/api`。 - Compose Web 默认绑定 `127.0.0.1:18080`,本机预览也使用该端口。本机 `.env` 已生成随机加密密钥并填入 DeepSeek API Key,但不在 Git 中。 - 业务数据库已升级到 `0003`,初始课程及其版本已写入 PostgreSQL。本机已从 `docs/` 示例报告导入 1 个验收项目;汇报 PPTX 由示例报告内容生成,并非学生原始 PPT。 - `docs/阶段报告3.pdf` 已纳入示例材料和端到端测试。 - 本机已下载 BGE-M3 到 `models/bge-m3/`,固定 Hugging Face 修订版 `5617a9f61b028005a4858fdac845db406aefb181`;模型目录不提交到 Git。 - 本机已下载 PP-OCRv5 mobile 检测与中文识别模型到 `models/ocr/`;下载与解压命令见部署指南。 ## 代码入口与数据流 | 位置 | 作用 | | --- | --- | | `compose.yaml`、`.env.example` | 五个容器及环境变量;原件目录以只读方式挂载到 `/data/inbox` | | `backend/wisegrade/main.py`、`api.py` | FastAPI 启动、初始化课程、教师端 API | | `backend/wisegrade/models.py`、`migrations/`、`seed.py` | 数据模型、Alembic 迁移、初始课程和规则 | | `backend/wisegrade/storage.py`、`parsing.py` | 相对路径安全检查、目录识别、文件哈希、PDF/DOCX/PPTX 解析与页面资产 | | `backend/wisegrade/rag.py`、`llm.py`、`scoring.py` | 本地嵌入与混合检索、DeepSeek 适配、批次评分 | | `backend/wisegrade/settings_store.py`、`exports.py` | API Key 加密保存、Excel/PDF 导出 | | `backend/wisegrade/services.py`、`indexing.py` | REST 与 Agent 共用导入、入库、建批、复核服务;持久后台索引任务 | | `backend/wisegrade/agent_tools.py`、`actions.py`、`chat_api.py` | 类型化工具注册、确认边界、会话与 SSE 编排 | | `frontend/src/App.tsx`、`frontend/src/api.ts` | 教师端页面及 API 调用 | | `frontend/src/Chat.tsx` | 会话恢复、引用、进度和确认卡片 | | `backend/tests/` | 路径、规则、版本、解析、模型输出、复核、导出及示例材料流程测试 | 教师选择 `/data/inbox` 下的相对目录后,后端扫描 `学号_姓名_选题题目` 子目录;教师确认材料类型后保存路径、大小、时间和 SHA-256。解析结果与页面图像进入 `data/processed/`,知识片段进入 PostgreSQL。评分时复制课程、规则和模型配置快照到独立批次,由 RQ worker 处理。模型原始评分、证据和教师修改记录分别保留;导出文件写入 `data/exports/`。原件不经过浏览器上传。 ## 启动与检查 首次部署复制 `.env.example` 为 `.env`,设置学生目录 `WISEGRADE_DATA_DIR`、随机 `WISEGRADE_SECRET_KEY`、DeepSeek 地址及密钥,并把离线 BGE-M3 模型放在 `models/bge-m3/`。扫描版 PDF 另需 `models/ocr/detection/` 和 `models/ocr/recognition/`。模型目录和 `.env` 均不提交到 Git。详情及 Windows 路径写法见 [部署指南](docs/DEPLOYMENT.md)。 ```bash docker compose up docker compose ps -a curl http://127.0.0.1:18080/api/health ``` 上面的 `curl` 使用默认 Web 端口;若 `.env` 中修改了 `WISEGRADE_WEB_PORT`(默认 `18080`),应使用对应端口。本机预览地址为 。`api` 启动时自动运行 Alembic 迁移。排障先看 `docker compose logs api worker web`。 Python 开发统一使用 `uv`: ```bash cd backend uv sync --extra ocr --group dev uv run pytest -q ``` 前端构建:`cd frontend && npm ci && npm run build`。宿主机缺少 LibreOffice 时,DOCX/PPTX 渲染测试会跳过;生产容器镜像已包含 LibreOffice。 ## 已验证与尚未验证 - 部署镜像内完整后端测试:**19 通过、0 跳过**,包括 DOCX/PPTX 转换与页面图像测试。宿主机运行结果为 18 通过、1 跳过,因为宿主机未安装 LibreOffice;部署容器内为 25.2.3.2。另已用课程 DOCX 和验收 PPTX 实际验证页数、文字及页面图片。 - 2026-09-25:后端测试已改用独立 PostgreSQL + pgvector,并通过真实 DeepSeek 和本地 BGE-M3 模型测试。19 个其他测试通过;使用课程示例材料的完整流程单独重跑通过,22 个评分项全部完成,教师复核和导出检查通过。测试命令见 `docs/DEPLOYMENT.md`。 - 2026-09-25 旧版部署时:前端生产构建通过;Compose 的 PostgreSQL、Redis、API、worker、Web 启动,首页、深链接、`/api/health`、课程及仪表盘 API 返回正常。数据库当时为 `0002`;全新 SQLite 数据库迁移至 `0002` 也已验证。 - 2026-09-26 当前源码:宿主机独立 PostgreSQL 测试执行 `uv run pytest -q -m 'not integration'`,**24 通过、1 跳过、2 个真实集成测试未运行**;使用既有测试镜像加只读源码挂载执行 Compose 同组测试,**25 通过、2 个真实集成测试未运行**。单独构造旧版 `0002` 表结构,在临时 PostgreSQL 数据库升级 `0003` 通过;新数据库迁移也由测试覆盖。前端 `npm run build` 和新 Nginx 配置 `nginx -t` 通过。 - 2026-09-26 最小真实 DeepSeek `tool_calls` 兼容性探针通过,完整工具白名单也返回 `list_courses` 原生调用;该端点拒绝 `tool_choice="required"`,适配层已使用 `auto` 并校验返回的工具调用。未在该探针发送学生原件。 - 完整 Compose 测试首次运行 **25 通过、1 失败**:真实模型证据匹配导致示例流程首轮批次 `partial`。测试改为按既有重试规则继续未完成项后,单独重跑示例流程 **1 通过**(11 分 48 秒);成功项和教师复核结果由生产评分代码保留。此次未重新运行一次完整的所有测试组合,不应把第一次完整命令写成全部通过。 - 测试 Compose 现增设独立 `test-redis`,与业务队列隔离。隔离前完整测试曾把 5 个测试索引作业送入业务 Redis;旧业务 worker 因缺少新模块执行失败,未写入业务数据库,测试作业已从业务 Redis 失败队列和作业键清理。 - 2026-09-26 业务容器已更新:迁移前的 PostgreSQL 自定义格式备份保存在本机 `data/backups/wisegrade-pre-0003-20260926.dump`(权限 `600`,不提交);业务库 Alembic 为 `0003 (head)`。API、worker、Web 已重新创建,健康检查正常。通过 Web 入口验证 `/api/health`、会话列表、课程、项目、批次、索引任务及前端资源均返回 200;worker 可导入索引和评分任务;运行中的 API 对已配置模型的原生 `tool_calls` 探针通过。业务 Redis 队列为空。 - 后端标准 Dockerfile 构建再次卡在 Debian 软件源下载。由于 `backend/pyproject.toml`、`backend/uv.lock` 和 Dockerfile 自上一版镜像以来未变化,本机从已有 `wisegrade-api` 镜像叠加当前 `backend/` 源码构建 `wisegrade-backend-updated:20260926`,并用于 API 和 worker;关键源码与迁移文件的镜像内外哈希已核对。Web 则通过标准 Dockerfile 完整构建。此本机后端镜像依赖旧镜像层,供其他机器分发前仍需在软件源正常时完成一次标准 Dockerfile 构建。 - `docker compose --profile test run --build --rm test pytest -q -m 'not integration'` 曾启动测试镜像重建,但 Debian 软件源下载 LibreOffice 依赖在约 24 分钟后仍未完成,故中止;随后用已有测试镜像加最新源码只读挂载执行相同测试。当时尚未在浏览器中实际点击旧版会话主页、刷新恢复、确认卡片及深链接;目前这些路径由代码检查、后端 API 测试、HTTP 冒烟检查和前端 TypeScript/生产构建覆盖。 - RQ worker 曾在空闲期间因 Redis 连接超时退出,日志显示正常退出码 0;已在 `compose.yaml` 设置 `restart: unless-stopped` 并重新启动。接手后应观察是否反复超时。 - 使用 `docs/` 的四份示例报告及生成的汇报 PPTX,经目录扫描、确认、课程资料入库、真实 BGE-M3/pgvector 检索和真实 DeepSeek API 完成批次 `3`:**22/22 项成功**。首轮有 1 项引文不匹配,重试后成功;保留了成功项。项目索引重建后有 316 段、平均 506 字,向量均为 1024 维;77 条评分证据均能匹配对应文档页的原文和页面图片。 - 对批次 `3` 完成教师复核和修改历史验证;Excel 成绩表及 11 页 PDF 反馈均可下载且可解析,文件位于 `data/exports/`。批次 `2` 保留为首次真实运行的对照记录(16 项成功、6 项证据不匹配)。 - 将 `docs/阶段报告1.pdf` 的一页栅格化为无文本层 PDF 后,离线 PaddleOCR 提取 496 字,识别到目录和章节标题。真实扫描仪产生的不同质量扫描件尚未实测。Windows Docker Desktop 尚未在 Windows 机器上实测。 ## 接手后优先完成 1. 在浏览器中复查新版会话草稿、范围选择、并行运行、删除确认、移动端布局及确认卡片。 2. 使用独立提供、已脱敏的学生目录再次验收五类原始材料,尤其是学生原始 PPTX 和真实扫描仪 PDF;当前验收使用仓库示例报告与生成材料。 3. 在目标 Windows Docker Desktop 环境验证目录挂载、模型路径和完整启动。 4. 持续查看 worker 日志;若 Redis 空闲超时重复出现,再定位 Docker 后端休眠或网络原因。不要仅凭容器显示“已启动”判断评分任务可用。 当前代码位于 `main` 分支,阶段提交使用 Conventional Commits。交接前工作区应保持干净;`.env`、`models/`、`data/`、缓存和构建产物由 `.gitignore` 排除。 ## 2026-09-27 会话更新 新版 UI 的入口仍使用 `?page=chat`,旧 API 与历史记录保持可读。前端按运行 ID 订阅 SSE,并依靠会话列表和详情轮询恢复后台 Agent 运行;服务进程中断后的运行在 15 分钟超时后标为中断。正式 API 启动时会自动应用 `0004` 迁移。此处的测试结果以本次实际命令为准,历史验证记录仍保留在上方。 本次验证:隔离 PostgreSQL + pgvector 测试容器中运行 `pytest -q -m 'not integration'`,32 通过、2 个真实集成测试未运行;前端 `npm run build` 通过,Playwright Chromium `npm run test:e2e` 3 通过(API 使用浏览器路由模拟)。浏览器测试覆盖草稿、范围、历史切换、删除及错误、Markdown/XSS、引用、工具展开、并行运行切换与 390px 布局。后续已在业务数据库应用 `0004`,并通过 Web 入口用真实 DeepSeek 完成只读会话、SSE、刷新恢复和界面删除验收;评分等写入流程未因本次更新重新执行。前端产物有 Vite 大块警告。 ## 2026-09-27 正式启动复验 从当前源码成功执行 `docker compose build api worker web` 与 `docker compose up -d`。业务 PostgreSQL 迁移从 `0003` 到 `0004`,迁移前备份保存在本机 `data/backups/wisegrade-pre-0004-20260927-020450.dump`(权限 `600`,不提交)。Compose 已调整为 API 健康后启动 Web 和 worker,服务设置自动重启。Web `/api/health` 为 200,API、数据库、Web 均健康,worker 在运行,Nginx 检查通过。经 Web 入口实际提交两条无学生资料的只读消息,DeepSeek 调用成功;SSE 收到 `run`、`tool`、`message`、`done`,首事件约 764 毫秒;刷新后打开新草稿,历史回答仍可查看。测试会话已通过界面删除,业务会话数恢复到原先 4 条。`docker compose stop` 后执行 `docker compose up -d --wait` 冷启动复验通过,五个正式服务恢复健康,Web `/api/health` 为 200。`docker compose up` 现在可直接用于正式启动,访问本机配置端口。 ## 2026-09-27 会话引用与工具过程修复 正式回答上方的工具过程现在先整体折叠,每次调用再单独折叠;引用移至回答最后并整体折叠。会话页面移除了全局“后台进度”卡片。`get_scores` 改为按项目和评分项分页,每次最多一个项目、六项评分,并提供后续偏移量;长结果不再以空泛的截断提示替代全部评分。新检索调用会在运行记录中保存最多六条有界原文片段;回答引用对全部工具结果去重,不再只保存前 20 条。 本地业务数据库 6 号会话曾为定位问题补入来源引用和当前评分重查值;用户计划自行删除该会话,界面不保留针对这条旧记录的提示或特殊展示。操作前备份保存在 `data/backups/wisegrade-pre-chat-citation-20260927.dump`(权限 `600`,不提交)。新调用会保存实际每次找到的片段。 后续排查确认“旧结果未保存”来自 6 号会话三条已持久化的工具摘要,而非前端旧版本;这些摘要现已改为简短的评分项数量,会话本身仍在。 隔离 PostgreSQL 测试库执行 `pytest -q -m 'not integration'`:35 通过、2 个集成测试未运行。前端 `npm run build` 通过,Chromium `npm run test:e2e`:3 通过。API 与 Web 镜像已重新构建并以 `docker compose up -d --wait api web` 更新;新评分工具对限定范围返回六项,序列化后 6,820 字符。用真实项目检索“视觉检测 Otsu 光照鲁棒性 第48页”返回六条带原文与链接的结果,其中包含第 48 页。前端产物仍有 Vite 大块警告。 ## 2026-09-27 工具参数与重复调用 7 号会话的四次 `get_scores` 实际分别读取评分项偏移量 0、6、12、18,旧工具记录只保存了批次与项目 ID,造成界面上看似相同参数。新记录保存经校验的默认值、查询词、筛选及分页参数;旧评分记录从结果恢复实际偏移量。7 号会话旧检索记录的查询词没有持久化,无法准确还原,界面会显示“历史调用未保存查询词”。同一轮内同名工具的相同有效参数只执行一次,后续调用标为“已跳过”,不同分页或查询正常执行。复核评语与原因继续省略,未知字段及密钥不保存。 隔离 PostgreSQL 测试容器执行 `pytest -q -m 'not integration'`:37 通过、2 个集成测试未运行;末次后端微调另运行针对性测试,1 通过。前端 `npm run build` 通过,Playwright Chromium `npm run test:e2e`:3 通过。测试覆盖注册工具参数字段、查询词与敏感文本边界、相同参数跳过、不同分页和查询正常执行,以及浏览器中旧记录偏移量恢复与参数展示。API 与 Web 镜像已构建并更新,两个容器均健康;正式页面通过全新 Chromium 会话打开 7 号会话,四次评分调用显示偏移量 0、6、12、18,旧检索调用显示未保存查询词提示。 ## 2026-09-27 引用链接标签 检索引用的 `url` 指向页面文字 JSON 接口,`image_url` 指向页面图像;评分引用现在分别保存评分页 `url` 和证据 `image_url`。界面按目标显示“查看页面文字”“查看评分”“查看图像”;旧评分引用中把图像放在 `url` 的记录也能识别,两个字段指向同一图像时只显示一个链接。无需迁移历史数据。后端评分引用针对性测试 1 通过,前端构建通过,Playwright 3 通过。API 与 Web 容器已更新并健康;正式页面检查 7 号会话 74 个图像链接,均显示“查看图像”。 ## 2026-09-27 评分引用文字页补全 评分证据 `ScoreEvidence` 原已保存 `document_id` 和 `page`,前一版遗漏了这条来源链。现在 `project_result` 将文档 ID 交给 `get_scores`,新回答引用保存 `text_url`;评分页链接和图像链接仍各自保留。历史会话详情按文件 ID、页码、原文摘录与评分证据匹配,并核对当前知识片段包含该摘录;唯一匹配时只在响应中补充文字页链接,不改写数据库,无法确认来源时保持原状。隔离测试容器 `pytest -q -m 'not integration'` 为 38 通过、2 个集成测试未运行;前端构建和 Playwright 3 项测试通过。API 与 Web 容器已更新并健康。正式会话 7 的 74 条引用在浏览器中均显示文字和图像链接;其中 41 条旧评分引用经后端恢复,26 个不同的文字页链接均可打开,且每条引用的摘录都存在于目标页。