← 返回首页
React FastAPI Flask SQLite Docker 全栈 · 生产级

⚙️ 多语言试卷审校 Agent

exam_checker_agent — 自动拆题 + 逐题路由检测 + 四段式图文一致性审校 + 三类查重 + 可量化评测;生产级批处理重构版本

项目概览

本项目是 exam_smart_checker 的生产级重构版本,将单机 Streamlit 工具升级为支持多用户并发、 任务批量管理的 Web 平台。核心能力:试卷批次管理、任务调度、5 步自动化审校流水线、结果下载。

应用场景:多机构并发审校、后台批量任务管理、SaaS 化部署
📖 完整设计文档(脱敏归档) 架构、Prompt 工程、四段式图片审校链路、去重聚合、量化指标等深度内容(含 Mermaid 流程图)整理在独立文档仓库, 不含可运行源码与题目数据: 在 GitHub 阅读 →

技术栈

Python 3.12 FastAPI(主 API) Flask(遗留 WSGI,in-process) React + Vite(前端) SQLite(任务持久化) Docker + Dockerfile LLM 多语言检测

架构与模块结构

┌─────────────────────────────────────────────────────┐ │ 前端层 (React + Vite) │ │ 批次管理 / 任务列表 / 结果查看 / 文件下载 │ └────────────────────┬────────────────────────────────┘ │ HTTP port 8777 ┌────────────────────▼────────────────────────────────┐ │ FastAPI 主服务 (backend/main.py) │ │ /api/v2/* → FastAPI routers │ │ /api/v1/* → LegacySmartCheckerService.dispatch() │ │ (in-process Flask WSGI bridge) │ └──────┬─────────────────────────┬────────────────────┘ │ │ ┌──────▼──────┐ ┌────────▼──────────┐ │ 任务状态机 │ │ Flask API Server │ │ parse │ │ (api_server.py) │ │ → review │ │ ~1356 lines │ │ → int_plag │ └───────────────────┘ │ → crs_plag │ │ → his_plag │ └─────────────┘

核心目录:

  • backend/app/routers/ — FastAPI 路由层
  • backend/app/services/ — 业务逻辑服务层
  • backend/app/repositories/ — 数据访问层(SQLite)
  • backend/app/domain/ — 任务状态机定义
  • backend/api_server.py — 遗留 Flask 服务(WSGI in-process)
  • frontend/ — React 前端
  • run.py — 统一启动入口,port 8777
  • Dockerfile / deploy.sh

核心算法 / 关键设计

1. 双 Web 框架 WSGI In-Process 融合

FastAPI 作为主服务,通过 LegacySmartCheckerService.dispatch()/api/v1/* 路由在进程内转发给 Flask WSGI 应用处理, 实现在不重写遗留逻辑的前提下完成平滑迁移,零额外网络跳跃。

2. 5 步任务状态机

每个审校任务经历 5 个串行阶段: parse → review → internal_plag → cross_plag → history_plag, 每步完成后更新状态,支持断点恢复。状态机使用乐观锁防止并发竞争, 心跳机制自动检测并恢复僵尸任务(超时未心跳的运行中任务)。

3. AppRuntime 依赖注入容器

统一的 AppRuntime 单例管理所有服务实例的生命周期, FastAPI 依赖注入系统通过它获取 Repository、Service 等组件,避免全局变量。

4. X-Client-Id 多租户隔离

每个请求通过 Header X-Client-Id 携带客户端标识, 任务查询、结果读取均在对应客户端 owner 范围内隔离, 防止多机构数据交叉。

5. 多语言检测提示词动态选择

语言检测模块识别试卷语言(中/日/德/法),动态加载对应的 LLM 审校提示词, 实现同一套系统的多语言适配。

创新点 / 我做了什么

  • 设计整体批处理平台架构(FastAPI + SQLite + React 全栈)
  • 实现 FastAPI ↔ Flask WSGI in-process 融合方案,保留遗留能力零迁移成本
  • 设计 5 步任务状态机 + 乐观锁 + 心跳僵尸恢复机制
  • 构建 AppRuntime DI 容器,统一管理服务生命周期
  • 实现 X-Client-Id per-client 数据隔离
  • 编写 Docker 镜像与一键部署脚本

端到端流程

一份文档进来,依次经过六个节点;Excel/zip 评测集走「解析 → 检测 → 评测」短主线。

1
解析
转文本 · 骨干提取 · 并发填充 · 展平
2
路由
每题判定跑哪些检测
3
检测
文本类 + 图文一致性
4
去重聚合
确定性优先级 + LLM 聚合
5
查重/评测
卷内·卷间·历史 / 混淆矩阵
6
报告
Word / Excel / ZIP + 逐题清单

★ 图片审校:四段式多模态链路

图文一致性(图里标的值和题干说的不一样、或配错了别题的图)是审校最难、最有价值的部分。 多模态模型常「看图说话很流畅、却对图中关键锚点视而不见」。为此设计了一条四段式链路:

分类 + 公式 OCR
VLM 分 formula/diagram(边界图保守归 diagram 防漏检);公式图 OCR 回填进题干,得到「增强题干」。
多图单次检测
所有示意图 + 增强题干一次调用;强制输出「图像观察清单 + 题干断言对账表」,逼模型逐项枚举对账,而非印象式肯定。
纯文本复审兜底
Step3 判无错时触发:不看图,只读 VLM 写下的观察清单与题干对账,专攻漏报,只允许 false→true 翻转以保护精确率。
工程巧思
全局 base64 缓存(8 线程预下载)、SVG→PNG、最小尺寸放大、zip+xlsx 图像桥接与跨行占位符全局重编号。
量化收益(mmdataset-v3 基准) 把「一次性扔图给 VLM」重构为四段式链路 + 强制对账 Prompt + 纯文本复审后,图文不一致检测 召回率达 0.84(qwen3.6-27B 本地)~ 0.88(plus 云端)、F1 0.89~0.92、精准 0.95+、FPR≈0.10 (弱实现版本召回仅约 0.26),且通过「复审只许 false→true」保住了精确率。仅纳入具备视觉能力的多模态模型对比。
🔬 Prompt/流程消融实验(同集对比) 在同一数据集(973 样本)、同一 judge 口径下对比「极简 prompt / 单一强 prompt / 四段式全流程 × qwen3.6-plus / 27b」6 种配置,得到: 模型能力决定上限、Prompt 是精确率↔召回率的拨盘、四段式流程脚手架对弱模型(27b)才显著(强模型 plus 一句话 prompt 已接近全流程)。完整表格 + 图表 + 详细结论见 消融实验文档 →

Agent 还是工作流?(诚实剖析)

它是一条确定性多阶段流水线,里面嵌了两个受约束的 LLM 决策点

  • 路由:每题判定跑哪些检测(输出布尔开关,缺键即视为 false 的 fail-closed 设计)。
  • 错误聚合:对一道题的多条报错决定 keep / merge / delete(锁死 error_type,失败回退不丢错)。

LLM 不驱动控制流分支、不自我重规划。设计哲学是「能用可复现规则的地方就用规则,只有需要语义理解处才交给 LLM,并把 LLM 输出空间约束到最小」——这正是它「稳」的原因,也是它当前「不那么 agentic」的取舍。面试中会把它诚实定位为「带 LLM 决策点的可靠工作流」,并给出向真 agent 演进的路线。

错误类别与 Prompt 工程

20 个检测任务 / 4 语言(中 10、日 4、德 3、法 3)。UI 上一个「错别字」勾选自动展开 4 语言任务, 统一错误类型映射解耦「展示口径(10 类)」与「执行任务(20 个)」。

检测 Prompt 有稳定解剖结构:角色(只检测不解题)→ 输入说明(reference 只读)→ 核心目标 → 严格禁止 → 工作流程(含 ≥0.7 置信度门槛)→ 样例 → 严重度规则 → 锁死 error_type,所有任务复用同一份固定 JSON 输出模板(think/reason/errors[...],含 anchor_text 用于在 Word 中唯一定位)。人工复核可沉淀为动态 Few-shot,按向量相似度召回注入后续检测。

量化指标与韧性

📏
评测闭环
带标注数据集跑混淆矩阵,输出 precision / recall / F1 / F2(召回加权) / FPR;审校宁可多报别漏,故重 F2。
💰
Token 计量
按阶段拆分 prompt/completion/total token;长短调用预算分档,控成本。
🔁
四级容错
调用级(超时/退化重复/坏 JSON 修复/配置错快速失败)→ 状态机重试 → 心跳僵尸回收 → 单题重试。
🧹
双层去重
确定性优先级聚合(根因抑制症状,可审计)+ LLM 语义聚合(失败回退不丢错)。

效果截图

新建批次任务
新建跑批任务 — 上传试卷、4 步向导配置
任务仪表板
任务仪表板 — 批次进度与流水线状态
案例库
Few-shot 案例库 — Excel 导入、嵌入缓存、题型分类

相关链接

📖 完整设计文档(含流程图) GitHub 主页 查看 README