Files
aerospaceboy ebe33392ca fix: improve import, evidence indexing and material-scoped grading
Preserve document revisions and evidence, harden indexing and export behavior, add explicit material selection and direct-folder import, validate model JSON schemas with safe error messages, and retain student selection while loading scoring data.
2026-10-14 13:52:56 +08:00

23 KiB
Raw Permalink Blame History

WiseGrade(智评)交接说明

2026-10-13 用户 PDF 实流程验证

真实 PDF 的扫描、确认导入、索引和检索测试发现:无点线、以多空格对齐页码的目录条目被误判为正文。已按目录上下文修复,增加 4 项匿名回归,并将分类器和索引算法升级至 5,新增迁移 0009。实际材料专项 38 passed,后端回归 66 passed, 1 skipped。此前的页级检查通过不能代替片段权限验证;详见 PDF 实流程说明。没有生成真实模型成绩或更新正式环境。

2026-10-13 第二轮优化

索引重建改为创建文档修订,保留历史页面和片段 ID;修复数据库失败后的任务状态保存、课程资料部分失败后继续入库、历史引用动态标记及知识库列表的逐文档计数查询。新增迁移 0008,已有历史修订时拒绝有损降级。详见 第二轮优化说明。当前仍只完成本地隔离验证,未执行正式迁移或部署。

2026-10-12 源码优化

本轮修复解析与证据政策、索引重建、复核状态、历史来源保留和零分导出,增加迁移 0007(索引版本 4)及独立回归测试。详见 优化说明。仅完成本地源码及隔离验证,未更新正式业务环境。以下旧部署和模型验收记录仍作为历史记录保留,不能代替本轮目标容器验收。

更新日期:2026-09-30。先阅读 项目指南(部署、使用、技术设计与会话实现);本文件记录当前实现、验证边界和接手后的优先事项。

当前状态

  • 已实现《自动化专业综合实践》的教师端闭环:课程与规则版本、挂载目录扫描和导入、文档解析、课程及项目知识库、独立评分批次、逐项复核、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。评分证据和 Agent 检索引用共用文档 ID、页码和资料页链接。评分时复制课程、规则和模型配置快照到独立批次,由 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 路径写法见 部署指南。

docker compose up
docker compose ps -a
curl http://127.0.0.1:18080/api/health

上面的 curl 使用默认 Web 端口;若 .env 中修改了 WISEGRADE_WEB_PORT(默认 18080),应使用对应端口。本机预览地址为 http://127.0.0.1:18080。api 启动时自动运行 Alembic 迁移。排障先看 docker compose logs api worker web。

Python 开发统一使用 uv:

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/GUIDE.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-30 目录、摘要与正文证据治理

本次改动

新增 backend/wisegrade/pages.py(页面分类、混合页切块、真实章节路径)和 backend/wisegrade/evidence.py(证据政策)。rag.py 重写为按目标检索:页面类型过滤在候选上限之前完成,语义与中文二元组关键词各自召回后按排名倒数融合,名额先分散到不同页面并对同章节设软上限。scoring.py 按必备证据目标分别检索,正文补检走目录导航,内容目标缺失时进入 needs_review。迁移 0006 添加页面类型、章节、证据目标与历史标记、评分项缺证据记录列,并按已保存的解析结果重新分类页面;索引版本升到 3。

关键词召回不再使用 PostgreSQL to_tsvector('simple', …)。在隔离测试库中对真实页面实测:该配置把整个中文串当成一个词元,查询"文献调研"无法命中含"第2章文献调研与技术现状"的页面(文献调研、串级PID 结构、视觉伺服与闭环控制 均不匹配),因此旧实现的关键词分实际上长期接近零。现改为字符二元组加 ASCII/数字整词的重叠度。

修复的缺陷

批次 3 的 77 条评分引文中 14 条来自目录页(涉及 9 个评分项),会话 6 的 20 条引用中 5 条指向阶段报告 1 的目录页。根因有两层:目录页文本被当作正文片段参与检索并占用候选名额;评分提示词只要求引文原文和页码一致,没有任何来源类型约束。现在目录页作为导航块单独存放,内容目标只接受正文和附录,引文必须标注它要支持的证据目标。

本次验证(隔离环境)

隔离 PostgreSQL + pgvector 测试容器执行 pytest -q -m 'not integration':59 通过、2 个真实集成测试未运行。新增 backend/tests/test_evidence_pages.py 覆盖阶段报告 1 目录与第 6–7 页文献调研正文的区分、阶段报告 3 目录与第 11–12 页测试正文的区分、最终报告摘要/跨页目录/正文/附录的区分、混合页与目录续页与重复页眉与识别不确定页、内容性判断拒绝目录与摘要与单独标题、结构性判断仍可用目录、正文补检不足时模型分为 null 且状态为待教师复核且教师可复核且缺证据记录保留、Agent 引用页面类型标记与历史评分引用标记、检索过滤先于候选上限、学生项目与课程版本隔离、批次快照记录证据政策。前端 npm run build 通过(仍有 Vite 大块提示)。

真实报告的分类结果已逐页核对:阶段报告 1 第 1 页封面、第 2–3 页目录、第 4–21 页正文、第 22 页参考文献;阶段报告 3 第 2–3 页目录、第 11–12 页为测试正文;最终报告第 2–3 页摘要、第 4–5 页跨页目录、第 49 页参考文献、第 50–53 页附录。

未验证与待业务环境执行

  • 使用真实 DeepSeek 的完整评分批次未在本次运行。需要模型的部分(评分调用、事实抽取、一致性检查、Agent 回答)只用测试替身验证了编排与校验逻辑,尚未用真实模型端到端复跑。
  • 未对业务数据库执行迁移、重建索引或重新评分,也未运行 PDF/Excel 导出(导出代码已更新,但未实际生成文件)。
  • 未在 Windows Docker Desktop 实测。

业务环境应用步骤与批次 3 复核清单见 docs/EVIDENCE_POLICY_BATCH3.md。

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。界面按目标显示“查看页面文字”“查看评分”“查看图像”。本阶段尚未迁移历史数据,后续由 0005 一次性迁移,见下文。后端评分引用针对性测试 1 通过,前端构建通过,Playwright 3 通过。API 与 Web 容器已更新并健康;正式页面检查 7 号会话 74 个图像链接,均显示“查看图像”。

2026-09-27 评分引用文字页补全

评分证据 ScoreEvidence 原已保存 document_id 和 page,前一版遗漏了这条来源链。该阶段 project_result 将文档 ID 交给 get_scores,新回答引用保存 text_url;历史会话曾在读取时匹配评分证据,但不改写数据库。隔离测试容器 pytest -q -m 'not integration' 为 38 通过、2 个集成测试未运行;前端构建和 Playwright 3 项测试通过。API 与 Web 容器已更新并健康。正式会话 7 的 74 条引用在浏览器中均显示文字和图像链接;其中 41 条旧评分引用经后端恢复。随后 0005 已将这一读取时匹配改为一次性数据迁移。

2026-09-27 统一资料页与评分证据

迁移 0005 新增 knowledge_pages,以文档 ID 和页码保存完整提取文字、处理目录内的相对 PNG 路径。knowledge_chunks 继续保存检索片段和 pgvector 向量;原始学生文件仍只读挂载在 /data/inbox,PNG 实体位于 data/processed/。检索、评分模型的页面图像、评分证据、评分复核和 Agent 引用现在都从同一资料页取得文字与图像地址。/api/knowledge/documents/{id}/pages/{page} 返回完整页文字,末尾 /image 返回 PNG。数据库生成的课程目标与评分规则没有原始实体图像,因而只提供文字链接。迁移直接改写已保存的会话引用和工具结果;会话 API 不再做旧图像直链的读取时补全。

迁移前备份为本机 data/backups/wisegrade-pre-0005-20260927-174222.dump(权限 600,不提交)。先将备份还原到隔离库演练迁移:157 个资料页、155 个图像页、0 个旧图像直链留在会话或工具记录、161 条评分证据均有资料页;随后正式数据库升级到 0005,155 个 PNG 路径均能找到实体文件,161 条证据原文均存在于对应完整页,199 条历史会话引用都有统一的文字和图像链接。Web 入口健康与页面接口均返回 200,抽查图像为 image/png;真实 Chromium 打开 7 号会话检查 74 张引用卡片,均有文字和图像链接,390px 页面无横向溢出。独立 PostgreSQL 测试容器 pytest -q -m 'not integration':40 通过、2 个真实集成测试未运行;前端 npm run build 与 Playwright 3 项通过。API、worker、Web 镜像从当前源码重新构建并更新。前端构建仍有 Vite 大块提示。