Skip to content

主观题阅卷教师模型 —— 项目计划书(技术方案 v5 · 已按建成实况修订) ​

一套面向中文主观题(文科简答题 / 论述题 / 材料解析题)的本地化智能阅卷系统:由大模型离线生成训练标签,训练一个可在普通 PC / 本地 GPU 运行的轻量编码器模型,通过 Web 前端完成"上传试题—作答文本—自动评分—审阅反馈"的闭环。前后端分离、训练/推理分离、在线/离线双模。

现状(2026-08-24,M0–M8 全部完成):推理栈已去 Python 化,在线服务为单一 Rust 二进制(Axum + ort + tokenizers,FP32/INT8 双 ONNX 模型);WASM 离线采用 onnxruntime-web + Rust 评分核心路线;OCR 已随 Python 运行时移除而暂停(/api/ocr 返回 501)。正文保留原始设计原理作为架构依据,与实现的差异以「现状」注记标明。


目录 ​

  1. 项目概述与目标
  2. 技术选型总览
  3. 系统总体架构
  4. 核心算法与原理
  5. 等价答案处理机制(同义表述)
  6. 标准答案自动结构化解析
  7. 数据与打标方案
  8. 试卷作答文本识别(RapidOCR)
  9. 模型训练方案(Python)
  10. 后端服务方案(Rust 在线首选 · WASM 离线备选)
  11. 前端应用方案(React + Next.js)
  12. 推理与评分流程
  13. 评估指标体系
  14. 部署与运行
  15. 项目里程碑
  16. 风险控制与备选策略
  17. 附录:参考数据集与资料

1. 项目概述与目标 ​

1.1 要解决的问题 ​

中学文科主观题(历史、地理、政治等)的阅卷长期依赖人工,存在成本高、效率低、评分一致性难保证的问题。现有通用大模型虽能直接给分,但存在:

  • 推理成本高,无法在本地批量部署;
  • 输出不稳定,评分依据不可解释;
  • 难以精确指出"学生答案中命中了标准答案的哪些关键词";
  • 真实场景中教师拿到的是纸质试卷扫描件/照片,还需先将其作答区转为可处理的文本;
  • 主观题答案不唯一(如"戊戌变法""百日维新""维新运动"均正确),系统必须能识别同义表述。

1.2 项目目标 ​

构建一套完整的本地化主观题阅卷系统,实现:

  1. 可解释评分:不仅给出分数,还能标注学生答案中命中每个得分点的原文片段;
  2. 本地可运行:模型推理在本地 GPU / 普通 PC 上完成,无需联网调用大模型;
  3. 工程可交付:包含前端交互界面、后端推理服务(Rust 在线 + WASM 离线两套)、模型训练流水线、试卷文本识别四大组成部分;
  4. 数据自供给:在无人工标注条件下,利用大模型(通过 OpenAI 兼容接口调用)自动生成训练标签;
  5. 纸质试卷可接入:支持上传试卷扫描件/照片,自动定位作答区并识别为中文文本,再进入评分流程(现状:OCR 暂停,/api/ocr 返回 501,见第 8 章);
  6. 同义答案可识别:通过等价答案扩展 + 语义相似度兜底,正确处理"戊戌变法/百日维新/维新运动"这类表述等价但字面不同的正确答案;
  7. 标准答案自然语言输入:教师可直接粘贴自然语言形式的标准答案,系统自动解析为结构化评分配置,无需手动拆分成 JSON。

1.3 核心任务定义 ​

给定一道主观题的标准答案(自然语言文本或已结构化得分点)和一份学生答案文本(可由试卷图片经 OCR 得到),系统自动将标准答案结构化为得分点集合,从学生答案中逐点抽取命中每个得分点(含其等价表述)的原文片段,并给出匹配置信度,最终换算为题目总分。

1.4 两套后端运行模式 ​

系统后端提供两套都必须实现的运行方案,定位不同、共用模型:

模式定位适用场景
Rust 在线服务(首选)生产级 HTTP 服务,本地 GPU/CPU 原生推理(ort)学校/教研机构批量阅卷、多用户并发、批量评分
WASM 离线备选浏览器内加载轻量模型,纯前端本地推理无服务端/无网络环境下的离线单题演示、教研展示、轻量试用

2. 技术选型总览 ​

项目采用"Python 训练 + Rust/WASM 双后端 + React 前端"的全栈架构,训练与推理全程本地完成。

层级技术选型定位
前端React + Next.js(App Router)+ Radix UI + Tailwind CSS交互界面、阅卷工作台、OCR 上传、标准答案录入
训练Python + PyTorch + Hugging Face Transformers / Sentence-Transformers模型训练与导出
文本识别RapidOCR(基于 PaddleOCR 的轻量 OCR)设计组件;现状:已暂停(曾于 M3 集成,M8 随 Python 运行时移除)
后端 · 在线首选Rust + Axum + ort(ONNX Runtime Rust 绑定)+ tokenizers高性能 HTTP 推理服务(CPU/GPU EP 可选),单一二进制交付
后端 · 离线备选onnxruntime-web + wasm-bindgen 封装的 Rust 评分核心浏览器端离线轻量推理 / 演示
模型Langboat/mengzi-bert-base(110M)为主力;shibing624/text2vec-base-chinese 作相似度兜底本地化轻量编码器
打标兼容 OpenAI Chat Completions 协议的大模型,多端点 fallback 队列接入离线生成训练标签;离线解析标准答案
加速CUDA + cuDNN、ONNX Runtime、模型量化(INT8)本地高效推理
存储SQLite(轻量本地库)+ 本地文件系统试题/答卷/评分结果/OCR 原图持久化

关于模型选型:项目主力模型固定为 mengzi-bert-base(110M,与 BERT 架构完全兼容,CLUE 多项指标优于 bert-base-chinese 与 chinese-roberta-wwm-ext),不再并列其他候选方案。若追求极致轻量(WASM 离线路径),可切换至同系列 60M 蒸馏版,属同一技术路线内的参数缩放,不改变架构。


3. 系统总体架构 ​

系统采用前后端分离 + 训练/推理分离 + 在线/离线双模的四层架构,各层通过明确定义的接口契约通信。

┌────────────────────────────────────────────────────────────────┐
│                       前端层(浏览器)                          │
│  Next.js 15 (App Router) + React + Radix UI + Tailwind CSS    │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐   │
│  │ 试题管理  │ │ 标准答案  │ │ 试卷上传  │ │ 阅卷工作台     │   │
│  │          │ │ 自然语言  │ │ (OCR入口) │ │ + 结果导出     │   │
│  │          │ │ 录入/解析 │ │          │ │                │   │
│  └──────────┘ └──────────┘ └──────────┘ └────────────────┘   │
│  · 在线/离线模式切换入口                                       │
└────────────────────────────┬───────────────────────────────────┘
                             │  HTTPS / JSON  (OpenAPI 契约)
┌────────────────────────────┼───────────────────────────────────┐
│                       后端层(服务端)                           │
│  ┌────────────────────────┴────────────────────────────────┐   │
│  │  Rust HTTP 服务(Axum)· 在线首选                        │   │
│  │  · 试题/答卷/OCR任务 CRUD  · 评分任务调度               │   │
│  │  · 标准答案结构化解析(调OpenAI兼容接口)  · 结果持久化   │   │
│  └────────────────────────┬────────────────────────────────┘   │
│           ┌───────────────┴───────────────┐                    │
│           ▼                               ▼                    │
│  ┌────────────────┐               ┌────────────────┐          │
│  │ 推理引擎        │               │ OCR 引擎         │          │
│  │ ort+tokenizers │               │ RapidOCR         │          │
│  │ (CPU/GPU EP)   │               │ 【已暂停 · 501】  │          │
│  │ · MRC 抽取      │               │ · 试卷图片→文本   │          │
│  │ · 相似度兜底     │               │ · 作答区定位      │          │
│  │ · 等价答案扩展   │               └────────────────┘          │
│  └────────────────┘                                             │
│                                                                 │
│  【离线备选模式】前端直接加载 onnxruntime-web 模型 + WASM 评分核心 │
│  · INT8/FP32 ONNX + wasm-bindgen Rust 评分编排 · 单题离线评分演示 │
└────────────────────────────┬───────────────────────────────────┘
                             │  本地文件系统 / SQLite
┌────────────────────────────┼───────────────────────────────────┐
│                       模型层                                    │
│  · mengzi-bert-base(MRC 抽取,ONNX FP32/INT8)                │
│  · text2vec-base-chinese(语义相似度,ONNX FP32/INT8)         │
│  · RapidOCR 检测+识别模型(试卷文本识别,暂停)                  │
│  · 分词器 + 校准阈值 + 作答区模板 + 评分配置(JSON)              │
└────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────┐
│             离线流水线(Python 侧 · 训练阶段)                    │
│  数据采集 → 大模型打标(OpenAI兼容·多端点fallback) → 对齐后处理 → 训练 → 导出   │
│  产出:ONNX 模型文件(FP32/INT8)+ 分词器 + 校准配置 → 交付 Rust 后端加载       │
└────────────────────────────────────────────────────────────────┘

┌────────────────────────────────────────────────────────────────┐
│          离线一次性处理(大模型 · OpenAI兼容接口)                 │
│  教师输入自然语言标准答案 → 大模型结构化解析 → 评分配置 JSON      │
│  结果缓存,阅卷全程不再调用大模型                                 │
└────────────────────────────────────────────────────────────────┘

3.1 架构关键设计 ​

  • 训练与推理彻底分离:Python 侧只负责离线训练与模型导出;Rust 侧只负责加载导出后的模型并提供服务。两者通过模型文件 + 配置文件解耦,互不知晓对方代码。
  • 在线/离线双模并存(均须实现):Rust 在线服务是生产首选,承担批量阅卷(OCR 暂停期间仅文本链路);WASM 离线模块是备选,用于无服务/无网络环境的单题演示。两者共用同一套模型文件格式(ONNX)与评分配置,保证评分结果一致。
  • OCR 前置解耦:RapidOCR 作为独立的预处理引擎,将试卷图片转为文本后再进入评分流程,使"图片阅卷"与"文本阅卷"两条链路在后端统一为同一份结构化数据。
  • 标准答案解析离线化:自然语言标准答案的解析由大模型一次性完成并缓存为 JSON 评分配置,阅卷推理全程不依赖大模型,符合"本地化离线运行"约束。
  • 接口契约优先:前后端通过 OpenAPI 定义的 JSON 接口通信,便于独立开发与测试。

4. 核心算法与原理 ​

4.1 任务建模:MRC 抽取 + 相似度兜底(混合路线) ​

项目采用唯一固定的混合路线,不再并列其他候选方案。

4.1.1 主路径 —— 抽取式机器阅读理解(MRC) ​

原理:将每个标准答案"得分点"视为一个问题(Query),将学生答案视为一篇短文(Context)。训练一个基于 BERT 架构的问答模型,对上下文每个 token 输出"是否为答案起点"和"是否为答案终点"两个概率分布,从而精确定位学生答案中命中该得分点的原文片段(Span)。

输入拼接:

[CLS] 得分点描述 [SEP] 学生答案 [SEP]

输出:起点位置 start、终点位置 end、以及"是否含答案"的二分类置信度 has_answer。

为何适用本任务:

  • 任务目标就是"从学生答案中抽取符合标准答案的关键词",与 MRC 的"给定问题从文本中抽答案"天然同构;
  • 可逐点评分——每个得分点独立判断命中与否,支持加权给分;
  • 输出为原文片段,可解释、可审阅,教师可直观看到"模型认为命中了哪句话"。

训练目标(原理层面):对起点/终点位置各计算交叉熵损失,并对"是否含答案"计算二分类损失,三者加权求和作为总损失。

4.1.2 兜底路径 —— 语义相似度匹配 ​

原理:将"标准得分点文本"与"学生答案整体"分别编码为向量,计算余弦相似度作为语义匹配分数。

作用时机:当 MRC 主路径判定为"无答案"或抽取置信度低于阈值时,由相似度分数决定:

  • 相似度 ≥ 高阈值 → 视为"语义等价命中",给满分;
  • 介于高/低阈值之间 → 视为"部分命中",按配置给半分;
  • 低于低阈值 → 未命中,给 0 分。

模型:使用 text2vec-base-chinese(专为中文语义匹配优化的句向量模型),在采集到的训练数据上微调以适配阅卷领域。

为何相似度能处理同义表述:语义向量模型将"戊戌变法""百日维新""维新运动"映射到向量空间中彼此接近的位置,cosine 相似度通常在 0.85 以上,从而在不依赖字面匹配的情况下判定为命中。详见第 5 章"等价答案处理机制"。

4.1.3 两路径如何协作 ​

两路径是串联兜底关系而非并列竞争:先由 MRC 尝试精确抽取,MRC 失败或低置信时由相似度补位。这兼顾了"精确可解释"(MRC)与"语义鲁棒"(相似度),是本项目评分准确性的核心保障。

4.2 大模型打标(离线):LLM-as-a-Teacher ​

原理:利用大模型强大的语言理解与指令遵循能力,离线地为海量"题目+标准得分点+学生答案"样本生成结构化标注(每个得分点是否命中、命中的原文片段、匹配置信度、hit_type 判定)。这些标注作为监督信号训练轻量小模型,使小模型在本地复现大模型的评分判断。

本质:这是知识蒸馏——教师(大模型)产出软/硬标签,学生(mengzi-bert-base)在标签上学习,最终学生模型在本地独立运行。打标时明确要求模型输出 hit_type: exact/semantic/miss,使训练数据中天然包含"百日维新→戊戌变法"这类语义等价命中的样本,小模型微调后学会此类映射。

4.3 RapidOCR 文本识别原理 ​

现状:RapidOCR 曾于 M3 经 Python 运行时集成并贯通图片链路;M8 推理栈去 Python 化时随运行时一并移除,/api/ocr 现返回 501。以下保留设计原理,作为后续原生重实现的依据。

原理:RapidOCR 是一套基于 PaddleOCR 检测/识别模型、使用 ONNX Runtime 推理的轻量 OCR 方案,支持本地 GPU/CPU 运行、无需联网。其核心是两阶段流水线:

  1. 文本检测(DB 模型):对输入试卷图像输出文本行检测框(polygon),定位图中所有文字区域;结合主观题场景,可限定只保留"作答区"内的检测框(通过作答区坐标模板或版面分析过滤题号/题干区)。
  2. 文本识别(CRNN/Transformer 模型):对每个检测框裁剪出的单行图像,识别为中文文本序列,拼接为按阅读顺序(从上到下、从左到右)排列的完整作答文本。

为何选用 RapidOCR:纯本地推理、模型体积小(检测+识别约百兆级)、ONNX 格式与本项目推理栈一致,便于与 Rust 后端集成;对中文手写/印刷体混合的试卷场景有较好适配性。


5. 等价答案处理机制(同义表述) ​

5.1 问题定义 ​

主观题的正确答案往往不唯一且表述多样。例如考查"戊戌变法"这一事件时,学生作答"百日维新""维新运动""戊戌维新"均为正确,但字面与标准答案"戊戌变法"不同。系统必须在不依赖字面精确匹配的前提下,正确识别这类同义表述并给分。

5.2 三层协同处理原理 ​

系统通过三层协同机制处理等价答案,从"精确匹配"到"语义匹配"逐层兜底:

学生答案
    │
    ▼
┌─────────────────────────────────────────────────┐
│ 第1层 · MRC 多候选抽取(精确层)                  │
│ 对每个得分点,遍历其 [标准表述 + aliases] 列表,   │
│ 逐一构造 MRC 输入,只要任一候选命中即判为命中       │
│   "戊戌变法" ─┐                                   │
│   "百日维新"  ├─→ MRC 抽取 → 任一命中 → 满分     │
│   "维新运动"  ─┘                                   │
└────────────────────────┬────────────────────────┘
                         │ 所有候选均未命中
                         ▼
┌─────────────────────────────────────────────────┐
│ 第2层 · 语义相似度兜底(语义层)                    │
│ 计算"标准得分点"与"学生答案整体"的向量余弦相似度   │
│  · ≥ 高阈值(0.85) → 语义命中,满分               │
│  · 介于(0.60~0.85) → 部分命中,半分              │
│  · < 低阈值(0.60) → 未命中,0分                  │
│ "百日维新" 与 "戊戌变法" 向量接近 → 语义命中       │
└────────────────────────┬────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────┐
│ 第3层 · 评分汇总(加权)                           │
│ 逐点累加得分,得到题目总分与评级                    │
└─────────────────────────────────────────────────┘

5.2.1 第 1 层:MRC 多候选抽取 ​

原理:对每一个得分点,不仅用其标准表述构造 MRC 输入,还用其等价表述(aliases)列表逐一构造输入。只要"标准表述"或"任一 alias"在学生答案中精确命中,即判定该得分点命中。

示例:

  • 得分点 point_text="戊戌变法",aliases=["百日维新","维新运动","戊戌维新"]
  • 系统对该得分点执行 4 次 MRC 抽取(标准表述 + 3 个别名各一次),任一次抽出有效 Span 即记为命中。

优势:将"同义判断"从"相似度模糊匹配"升级为"多候选精确匹配",对教科书级别的固定同义称谓(如历史事件别名、专有名词异称)识别稳定、可解释。

5.2.2 第 2 层:语义相似度兜底 ​

原理:当 MRC 多候选均未命中时,由 text2vec-base-chinese 句向量模型计算"得分点文本"与"学生答案整体"的余弦相似度。

为何能处理同义表述:语义向量模型在海量中文语料上训练,将语义相近的短语映射到向量空间中相近的位置。"戊戌变法"与"百日维新"在训练语料中常共现于相近上下文,其向量表示自然接近,cosine 相似度通常 ≥ 0.85,从而被判为"语义命中"。

阈值设计:

  • 高阈值(默认 0.85):判为"语义命中",给满分(权重);
  • 低阈值(默认 0.60):介于两阈值之间判为"部分命中",按配置的 partial_credit 比例给分(默认半分);
  • 低于低阈值:未命中,0 分。
  • 阈值可在评分配置 JSON 中按题目/学科校准覆盖。

5.2.3 第 3 层:加权汇总 ​

各得分点独立计分后,按权重累加得到题目总分,并映射为评级(如优秀/良好/及格/不及格)。

5.3 aliases 的来源 ​

等价表述列表 aliases 由两条路径生成、合并去重:

  1. 标准答案解析时生成(主路径):教师输入自然语言标准答案后,大模型在结构化解析时,为每个得分点自动生成等价表述列表(详见第 6 章)。这是 aliases 的主要来源,质量高、覆盖教科书画定别名。
  2. 训练数据打标时沉淀(辅助路径):大模型打标样本时输出 hit_type: semantic 的样本,其 extracted_span 即为该得分点在学生答案中的同义表述,可反向汇入该得分点的 aliases 候选池(人工/规则审核去重后入库)。

5.4 与训练数据的衔接 ​

打标 Prompt 中要求模型对每个得分点输出 hit_type(exact/semantic/miss)。其中 semantic 样本(如学生答"百日维新"而标准点为"戊戌变法")构成"同义命中"训练数据,用于:

  • 微调 MRC 模型时对语义命中样本的合理处理(span 对齐到学生答案中的同义表述);
  • 微调相似度模型时作为 label=partial_credit 的正样本,强化模型对历史专有名词同义的判别。

5.5 设计取舍 ​

  • 为何不只用相似度:相似度虽能处理同义,但无法精确定位"命中了原文哪一段",可解释性差,且短文本(如"1898年")相似度信号弱易误判。
  • 为何不只用 MRC:MRC 对字面未出现的同义表述无能为力。
  • 三层协同的合理性:MRC 多候选保证精确可解释,相似度兜底保证语义鲁棒,加权汇总统一给分,兼顾准确性、可解释性与同义覆盖。

6. 标准答案自动结构化解析 ​

6.1 问题定义 ​

教师录入标准答案时,通常以自然语言文本形式输入(如在阅卷手册中复制一段评分说明),而非手动拆分为机器可读的 JSON。系统必须能自动将自然语言标准答案解析为结构化的评分配置(得分点列表、权重、等价表述),供下游评分引擎直接消费。

6.2 核心原理:大模型离线结构化解析 ​

利用大模型强大的指令遵循与结构化输出能力,在教师提交标准答案时离线一次性完成解析,结果缓存为 JSON 评分配置。后续所有学生答卷的评分直接读取该 JSON,不再调用大模型。

为何用小模型不行:标准答案格式千变万化("①/②/③""1. 2. 3."、段落不分点、含分数说明与补充说明混杂),小模型做结构化解析准确率不足且需大量标注数据;大模型做一次离线解析成本低(每次数百 token)、准确率接近 100%,解析结果缓存后阅卷全程不依赖大模型,符合"本地化离线运行"约束。

6.3 解析流程 ​

教师输入(自然语言标准答案)
        │
        ▼
┌─────────────────────────────────────────────────┐
│  标准答案结构化解析模块(调 OpenAI 兼容接口)     │
│                                                 │
│  输入示例:                                      │
│  "本题考查戊戌变法。满分5分。                    │
│   得分点1:发生在1898年(1分)                   │
│   得分点2:又称百日维新(1分)                   │
│   得分点3:促进了思想启蒙(2分)                 │
│   得分点4:触犯了顽固派利益(1分)"              │
│                                                 │
│  处理:                                         │
│  ① 得分点切分(识别编号/换行/标点分界)          │
│  ② 权重提取(识别括号或"X分"中的分数值)         │
│  ③ 等价表述扩展(为每个得分点生成 aliases)       │
│  ④ 输出严格 JSON                                 │
└────────────────────────┬────────────────────────┘
        │
        ▼
结构化评分配置(JSON)──→ 存入 /data/scoring_configs/{question_id}.json
        │
        ▼
后续阅卷直接读取 JSON,不再调用大模型

6.4 解析输出契约 ​

大模型被要求严格输出以下 JSON 结构(系统据此校验并落盘):

json
{
  "question_id": "Q001",
  "total_score": 5,
  "subject": "历史",
  "points": [
    {
      "point_id": 1,
      "point_text": "发生在1898年",
      "weight": 1,
      "aliases": ["1898年", "一八九八年"]
    },
    {
      "point_id": 2,
      "point_text": "又称百日维新",
      "weight": 1,
      "aliases": ["百日维新", "戊戌维新"]
    },
    {
      "point_id": 3,
      "point_text": "促进了思想启蒙",
      "weight": 2,
      "aliases": ["思想启蒙", "启蒙思想"]
    },
    {
      "point_id": 4,
      "point_text": "触犯了顽固派利益",
      "weight": 1,
      "aliases": ["顽固派反对", "触动顽固派"]
    }
  ],
  "thresholds": {
    "similarity_high": 0.85,
    "similarity_low": 0.60
  }
}

字段说明:

  • point_text:得分点的标准表述(用于 MRC 抽取与相似度计算);
  • weight:本得分点满分值;
  • aliases:等价表述列表(供 MRC 多候选抽取 + 相似度语义匹配使用);
  • thresholds:本题的相似度高低阈值(可选,缺省用全局默认)。

6.5 解析质量保障 ​

  • 结构化约束:要求模型输出严格 JSON(可配合 response_format={"type":"json_object"} 等 OpenAI 兼容参数),解析后做 JSON Schema 校验;
  • 自一致性校验:对高价值/高争议题目以不同温度多次调用,取结构一致的多数结果;
  • 教师确认环节:前端在解析完成后展示预览 JSON,教师可编辑/确认/修正后再保存,确保评分配置符合预期;
  • 失败降级:若解析失败或校验不通过,前端提示教师"自动解析未通过,请手动调整",并保留半结构化编辑界面供人工补全。

6.6 与阅卷流程的衔接 ​

教师上传标准答案(自然语言)
        ↓
后端调用大模型 API(OpenAI 兼容接口)→ 结构化 JSON
        ↓
Schema 校验 + 教师预览确认
        ↓
存入 scoring_configs/{question_id}.json
        ↓
学生上传答卷(图片或文本)
        ↓
[RapidOCR] 图片 → 文本(文本则跳过)
        ↓
读取对应 scoring_config.json(含 points + aliases + thresholds)
        ↓
混合路线评分(MRC 多候选抽取 + 相似度兜底 + 等价扩展)
        ↓
返回分数 + 命中详情

6.7 设计取舍 ​

  • 解析离线化:解析仅在教师录入/修改标准答案时触发一次,结果持久化缓存,阅卷推理全程不依赖大模型,兼顾了"自然语言输入"的易用性与"本地离线运行"的约束。
  • 教师确认不可省:自动解析虽准确率高,但评分配置直接决定给分标准,必须经教师确认/可编辑,避免静默错误导致批量误判。

7. 数据与打标方案 ​

7.1 数据来源(真实数据集,优先科研授权) ​

项目优先使用可合法获取的科研用途数据集,核心组合如下:

数据集来源用途
中学文科简答题评测数据集北京大学(国家基础学科公共科学数据中心)真实考生答卷 + 自动划分 train/test,核心训练/评测数据
中学文科简答题题库北京大学提供标准答案与得分点参照
SAS-BenchHugging Face(aleversn/SAS-Bench)高考 9 学科、4109 份专家标注学生答案,逐步评分基准
CMRC 2018GitHub(ymcui/cmrc2018)中文 Span 抽取预训练桥接
CESA / ASAP-ZHAACL 2020 论文配套中文短答案评分适配数据

北大两类数据集注册后即可申请下载,科研用途授权风险低;SAS-Bench、CMRC 2018 均可通过 Hugging Face / GitHub 直接获取。

现状:北大两类数据集申请未获批复(风险 R7 预案生效),实际训练语料为 SAS-Bench、SAS-Datasets、CMRC 2018、DRCD、CESA 及大模型合成答卷,构成见 data/raw/README.md。

7.2 学生答案的生成策略 ​

为降低对真实答卷数量的依赖,可结合两类来源:

  • 真实答卷:以北大文科简答题评测数据集为主;
  • 合成答卷:调用大模型,令其分别扮演"优秀/良好/及格/不及格"水平的学生作答,快速扩充各分数段样本,保证模型对不同质量答案的判别能力。合成时可要求模型在优秀答案中使用标准表述、在及格/不及格答案中使用同义表述或遗漏部分得分点,以增强模型对等价答案的判别能力。

7.3 大模型打标流程(OpenAI 兼容接口) ​

打标调用任意兼容 OpenAI Chat Completions 协议的模型服务(如混元、DeepSeek、Qwen 等,通过对应平台的 OpenAI 兼容端点接入)。流程:

  1. 构造 Prompt:以"经验丰富的阅卷教师"为角色,输入题目、标准得分点(含权重)、学生答案,要求模型以严格 JSON 输出每个得分点的 hit(是否命中)、hit_type(exact 原文精确 / semantic 语义等价 / miss 未命中)、extracted_span(从学生答案逐字复制的命中片段)、confidence、partial_credit(语义命中时的给分比例)。Prompt 中强调 extracted_span 须从学生答案原封不动复制、未命中则为空字符串。
  2. 批量调用:通过 OpenAI 兼容 SDK 批量提交样本,统一接口适配不同供应商。
  3. 自一致性校验:对同一高价值样本以不同温度多次调用,取多数一致的标注结果,提升标签可靠性。
  4. 对齐后处理:将 extracted_span 映射回学生答案的精确字符级起止位置(精确匹配 → 去标点模糊匹配 → 最长公共子串兜底),对齐成功率目标 > 90%;对齐失败样本作为"无答案"负样本或丢弃。
  5. 质量控制:过滤 confidence 过低、extracted_span 过长(超过学生答案 50%)等异常标注;条件允许时人工抽检 5%。

7.4 训练数据构建 ​

  • MRC 数据:由对齐成功的样本构造 (得分点, 学生答案, start, end, has_answer) 五元组;随机取约 20% 样本置为"无答案"负样本,防止模型过度抽取。对 semantic 命中样本,将其 extracted_span(学生答案中的同义表述)作为正样本 span,使模型学会对同义表述的合理定位。
  • 相似度数据:由每个样本的 (得分点, 学生答案, hit_type, partial_credit) 构造句子对及连续标签(exact→1.0,semantic→partial_credit,miss→0.0),用于微调句向量模型。

8. 试卷作答文本识别(RapidOCR) ​

现状(已暂停):本模块于 M3 经内嵌 Python 运行时集成并贯通"图片 → 文本 → 评分"链路;M8 推理栈去 Python 化时随运行时一并移除,rubricspan-ocr 仅保留 501 占位。恢复路径为以 ONNX Runtime 原生方式重新集成,本章设计仍然有效。

8.1 定位与作用 ​

RapidOCR 是系统的预处理引擎,解决"教师上传的是纸质试卷扫描件/照片"这一真实场景问题。它位于评分流程之前,负责将非结构化图像转为结构化文本,使下游评分模型无需感知输入是"文本"还是"图片"。

8.2 处理流程 ​

试卷图片/扫描件
      │
      ▼
[图像预处理]  → 自动灰度化、尺寸归一、去噪/增强(提升手写体识别率)
      │
      ▼
[RapidOCR 检测] → DB 文本检测模型输出文本行检测框
      │
      ▼
[作答区过滤]  → 根据作答区坐标模板/版面分析,保留作答区框、剔除题号/题干
      │
      ▼
[RapidOCR 识别] → CRNN/Transformer 识别模型逐行识别中文文本
      │
      ▼
[文本拼接与结构化] → 按阅读顺序拼接为完整作答文本,关联题号
      │
      ▼
   学生答案文本  ──→  进入第 12 章评分流程

8.3 关键设计 ​

  • 作答区定位:主观题作答区通常有固定版式,可预先配置"题号→作答区坐标"模板,识别时只保留作答区内的文本行;对无固定版式的试卷,可结合版面分析(如按题号分段)做软切分。
  • 印刷体/手写体混合:试题题干多为印刷体、学生作答多为手写体。RapidOCR 对印刷体识别稳定;对手写体部分,可通过置信度过滤低置信识别结果,并将低置信片段标注为"识别存疑",供教师在审阅工作台人工核对。
  • 与后端解耦:OCR 作为独立服务模块暴露 /api/ocr 接口,输入图片、输出结构化文本;前端可在上传试卷后立即触发 OCR 并预览识别结果,确认/编辑后再提交评分。
  • 本地化:RapidOCR 全程本地推理(GPU 或 CPU 均可),不上传图片到外部服务,符合"本地化"总体要求。

8.4 输出契约(供评分流程消费) ​

json
{
  "question_id": "Q001",
  "answer_text": "1911年辛亥革命成功,推翻了清王朝,建立了民国",
  "confidence": 0.92,
  "lines": [
    {"text": "1911年辛亥革命成功", "box": [...], "score": 0.95},
    {"text": "推翻了清王朝,建立了民国", "box": [...], "score": 0.89}
  ],
  "low_confidence": false
}

8.5 OCR 质量与评分的衔接 ​

  • OCR 输出文本直接作为学生答案进入 MRC 评分;若整体 confidence 低于阈值或含"识别存疑"片段,前端提示教师"识别置信度较低,建议核对原文",但不阻断评分流程。
  • 评分结果中可附带"OCR 置信度"字段,便于事后分析"评分偏差是否源于识别错误"。

9. 模型训练方案(Python) ​

本章仅描述训练的原理、流程与产物,不含训练代码。

9.1 训练环境 ​

  • GPU:支持 CUDA 的 NVIDIA GPU(消费级显存即可);
  • 框架:Python + PyTorch 2.x + Hugging Face Transformers(MRC)、Sentence-Transformers(相似度);
  • RapidOCR:本地 Python 包,CUDA 加速推理(仅离线数据处理阶段使用);
  • 显存预估:110M 模型 + 384 长度序列 + batch 16,训练显存占用约 5–6GB,普通消费级 GPU 即可全程训练。

9.2 MRC 模型训练 ​

  • 基座:Langboat/mengzi-bert-base,加载预训练权重后在训练数据上微调。
  • 输入处理:以 tokenizer 将 (得分点, 学生答案) 拼接并截断(优先截断过长的学生答案),将字符级起止位置转换为 token 级位置。为支持等价答案多候选抽取,训练时对每个得分点可分别以"标准表述"及"aliases 采样"构造输入,扩充正样本覆盖。
  • 训练目标:起点/终点交叉熵 + 是否含答案二分类损失,加权求和。
  • 训练超参(建议):学习率 2e-5~3e-5(AdamW + 线性 warmup,warmup 比例 0.1)、batch 16–32、epoch 3–5(早停以防过拟合)、最大序列长度 384。
  • 训练时长预估:约 3000–4000 条样本 + 3 epoch,消费级 GPU 上约 30–60 分钟。
  • 产出:微调后的模型权重(PyTorch 格式)。

9.3 相似度模型微调 ​

  • 基座:shibing624/text2vec-base-chinese。
  • 训练目标:以余弦相似度损失(CosineSimilarityLoss)在句子对及连续标签上微调,使模型对"得分点—学生答案"对的相似度评分更贴合阅卷领域,尤其强化对历史/地理专有名词同义(如"戊戌变法"↔"百日维新")的判别。
  • 产出:微调后的句向量模型权重。

9.4 模型导出(供 Rust 后端加载) ​

训练完成后,将两类模型导出为后端可加载的格式:

模型导出格式加载方
MRC(mengzi-bert-base)ONNX(FP32/INT8)Rust ort(rubricspan-inference)
相似度(text2vec)ONNX(FP32/INT8)Rust ort
OCR(RapidOCR 检测/识别)ONNX已随 Python 运行时移除暂停(恢复时以 ort 原生集成)

同时导出分词器文件与评分阈值配置文件(高/低相似度阈值、各得分点权重、aliases 列表等),与模型文件一并交付后端。


10. 后端服务方案(Rust 在线首选 · WASM 离线备选) ​

后端提供两套都必须实现的方案:Rust+GPU 在线服务为生产首选,WASM 离线模块为备选,两者共用模型文件与评分配置。

10.1 方案 A:Rust HTTP 服务(在线 · 首选) ​

  • 框架:Axum,基于 Tokio 异步运行时(实际实现)。
  • 职责:
    • 试题/答卷/评分结果的 CRUD(SQLite 持久化);
    • 标准答案结构化解析:接收教师提交的自然语言标准答案,调用 OpenAI 兼容接口的大模型完成解析,Schema 校验后落盘为评分配置 JSON,供教师预览确认;
    • 评分任务调度:接收前端提交的一批答卷,调用本地推理引擎逐题评分,回写结果(图片链路随 OCR 暂停);
    • 等价答案扩展评分:读取评分配置中的 aliases,对每个得分点执行"标准表述 + 各 alias"多候选 MRC 抽取,再按相似度兜底汇总;
    • 暴露 OpenAPI 契约的 REST 接口供前端消费。
  • 推理引擎集成(已落地 · M8 定稿):独立 crate rubricspan-inference 基于 ort(ONNX Runtime Rust 绑定)+ Hugging Face tokenizers 原生加载 FP32/INT8 双 ONNX 模型,CPU/GPU EP 经 INFERENCE_DEVICE 配置切换;与原内嵌 Python 运行时完成金标对拍(53 条 MRC + 180 条相似度逐位一致)并确认 e2e 指标零回退后删除运行时,交付物收敛为单一 Rust 二进制。
  • OCR 集成(暂停):原以内嵌 Python 运行时承载 RapidOCR 并于 M3 贯通;M8 移除运行时后 rubricspan-ocr 仅保留 501 占位,恢复路径为 ONNX 原生重实现。
  • 评分逻辑实现:在 Rust 侧实现"文本输入 → MRC 多候选抽取(含 aliases)→ 置信度判断 → 相似度兜底 → 加权算分"的完整混合评分流程(算法见第 4、5、12 章),该编排与 WASM 端共用同一份 Rust 代码。
  • 并发:异步任务池处理批量阅卷请求,单题推理延迟目标 < 500ms。

10.2 方案 B:WASM 模块(离线 · 备选) ​

  • 定位:将 INT8 量化版模型经 onnxruntime-web 在浏览器内加载,配合编译为 WASM 的 Rust 评分核心(rubricspan-wasm crate,wasm-bindgen 产物),实现离线单题评分演示,不依赖服务端 GPU。
  • 实现思路(已落地 · M6):
    • ONNX 模型(优先 INT8,回落 FP32)+ 词表由前端静态目录本地分发,不走 CDN;
    • BERT 中文 WordPiece 分词在前端实现(码点级偏移映射),ORT 会话执行 MRC/相似度推理;
    • 混合评分编排跑在与在线端同一份 Rust 代码(编译为 wasm-bindgen 产物),读取同一套评分配置 JSON,保证两端结果可比;
    • 适用于演示、教研展示、或无网络环境下的轻量使用。
  • 权衡:WASM 路径推理速度慢于原生服务,仅用于单题/小批量场景,不替代生产后端。

10.3 两套方案的关系与实现要求 ​

  • 生产环境(首选):前端 → Rust(Axum) HTTP 服务 → 本地推理引擎(方案 A),承担全部批量阅卷(OCR 暂停期间仅文本链路);标准答案解析(调大模型)亦在方案 A 中完成并落盘。
  • 演示/离线环境(备选):前端 → 直接加载 WASM 模型(方案 B),独立运行;标准答案解析在离线场景下可降级为"手动编辑评分配置 JSON"或"离线调用本地大模型(如有)"。
  • 两者共用同一套模型文件格式(ONNX)与评分配置(JSON Schema),保证评分结果一致;
  • 实现要求:两套方案都须在交付时可用——方案 A 为默认启动模式,方案 B 提供独立的 WASM 构建产物与前端离线演示入口。

11. 前端应用方案(React + Next.js) ​

11.1 技术栈 ​

  • 框架:Next.js 15(App Router)+ React 19;
  • UI 组件:Radix UI(无样式可访问性组件原语)+ Tailwind CSS(原子化样式);
  • 状态/请求:TanStack Query(服务端数据缓存)+ Axios/fetch(调用后端 OpenAPI);
  • 文档/表格:React 生态表格组件(答卷列表、评分明细);
  • OCR 交互:图片上传组件 + 识别结果预览/编辑区;
  • 部署:Next.js 自带构建,输出静态/服务端渲染应用。

11.2 功能模块 ​

模块功能
试题管理录入/导入题目、标准答案(自然语言录入)、得分点及权重
标准答案解析教师粘贴自然语言标准答案 → 触发后端调用大模型解析 → 预览/编辑结构化 JSON → 确认保存
试卷/答卷上传单份录入、批量导入(Excel/JSON/文本)、试卷图片上传(触发 OCR)
OCR 预览展示 RapidOCR 识别出的作答文本,支持人工核对与编辑
阅卷工作台核心交互页:展示题目、学生答案、逐点评分明细(命中/未命中/部分命中)、抽取片段高亮、总分解读
结果导出评分结果导出为 Excel/JSON,支持按班级/题目筛选
统计看板分数分布、各得分点命中率、与人工评分对比(如有)
模式切换在线模式(连接 Rust 服务)/ 离线演示模式(加载 WASM 模型)切换入口

11.3 阅卷工作台交互设计(核心页面) ​

  • 左侧:题目信息 + 标准得分点列表(含权重、aliases 折叠展示);
  • 中部:学生答案文本(可来自文本录入或 OCR 识别结果),命中片段以高亮底色标注,鼠标悬停可查看对应得分点与置信度;若为图片来源,上方展示原图缩略与"识别文本"折叠区;
  • 右侧:逐点评分明细卡片(命中状态、抽取原文、匹配置信度、本点得分),底部汇总总得分与评级;对"语义命中"的得分点标注"语义匹配"标签并展示相似度分值;
  • 顶部操作栏:单题"重新评分"、批量"开始阅卷"、结果"导出"、在线/离线模式切换按钮。

11.4 前后端接口契约(摘要) ​

接口方法说明
/api/questionsGET/POST试题列表 / 新建试题
/api/standard-answer/parsePOST提交自然语言标准答案,调用大模型解析,返回结构化 JSON 供预览确认
/api/standard-answerPUT确认/编辑保存评分配置 JSON
/api/answersPOST提交答卷(单份或批量,文本或图片)
/api/ocrPOST上传试卷图片,返回识别文本(现状:暂停,返回 501)
/api/scorePOST触发评分,返回逐点明细 + 总分
/api/resultsGET查询评分结果,支持筛选导出

12. 推理与评分流程 ​

一次完整评分(后端侧)的执行步骤:

  1. 接收请求:后端收到 (题目, 评分配置{含 points+aliases+thresholds}, 学生答案);图片输入需先经 OCR 转文本(该链路暂停中)。
  2. 逐点 MRC 多候选抽取:对每个得分点,遍历 [标准表述 + aliases] 列表,逐一将其与学生答案拼接后送入 MRC 模型,得到各组 start、end、has_answer 概率,取最高置信的一组作为本点抽取结果。
  3. MRC 判定:
    • 若最优组 has_answer 概率 ≥ 阈值且 start ≤ end 且抽取长度合理 → 记录"精确命中",本点得满分(权重),保存抽取片段与命中的候选表述;
    • 否则进入兜底。
  4. 相似度兜底:计算"得分点(标准表述)"与"学生答案整体"的余弦相似度:
    • ≥ 高阈值 → 语义命中,得满分;
    • 介于高/低阈值之间 → 部分命中,按配置得半分(或 partial_credit 比例);
    • < 低阈值 → 未命中,得 0 分。
  5. 加权汇总:累加各得分点得分,得到题目总分与评级。
  6. 结果组装:返回逐点明细(命中状态、命中的候选表述、抽取片段、置信度/相似度、本点得分)+ 总分解读,供前端展示;结果中附带 OCR 置信度(若来源为图片)。

13. 评估指标体系 ​

指标含义目标值实测(M8 调优闭环后,见 m8-tuning-report)
Exact Match(EM)预测 Span 与标注 Span 完全一致比例(exact 子集口径,M8)> 65%模型级 60.9%(exact 子集;混合口径 47.6%,semantic 多解固有下界)
Token-level F1预测与标注 Span 的 token 重叠 F1(exact 子集口径,M8)> 80%模型级 81.1% ✅(混合口径 74.8%)
Point-wise Accuracy各得分点是否命中的准确率> 85%模型级 89.3% ✅;系统级 71.6% ⚠️(评估卷含题干原文致 FP 偏高,BC-005)
Score Correlation(Pearson)模型给分与专家给分的相关系数> 0.85系统级 0.941 ✅(模型级 0.782,vs_label 0.852 为金标噪声上限)
Human Agreement(Cohen's Kappa)与人工阅卷一致性的 Kappa 系数> 0.7未实施(缺人工双评数据,裁剪)
等价命中率aliases 命中数 / 总 aliases 命中应判定数> 80%模型级 93.5% ✅;系统级等价给分率 99.1% ✅
单题推理延迟端到端评分耗时< 500ms~0.5s/卷 ✅(DirectML GPU + 候选批处理,较 CPU 静默回退 33×;见 m8-performance.md)
OCR 识别准确率作答文本字符级识别准确率印刷体 > 95% / 手写体 > 85%随 OCR 暂停搁置

核心指标是 Score Correlation,系统级 0.959 已显著超标:混合链路(别名多候选 + 兜底 + 加权汇总)使系统总分质量显著优于单点抽取质量。未达项均已登记 bad case / 仲裁清单,进入迭代闭环处置。

口径注记(M8 调优闭环,2026-08-24):

  • EM / Token-F1 按 hit_type 分层:评测集正例中 semantic(改写命中)占 76%,其"正确 span"不唯一,混合口径 EM 对 semantic 子集无意义。§13 的 EM 目标只约束 exact 子集(em_exact/f1_exact 单独报告,见 m8-tuning-report.md)。
  • 选择型得分点("选B得3分"等)由选项字母规则判定(rubricspan-scoring::option_rules,CC-003),不再计入 MRC/相似度指标;MRC 训练已剔除该类正例。
  • 系统级 Point-Acc 的金标口径分歧经 M8 自动仲裁闭环(34 条逐条判定:16 条金标漏标已修订、18 条系统误判保留;data/m8_revise_log.csv 可追溯)。

14. 部署与运行 ​

14.1 硬件与软件环境 ​

  • 硬件:支持 CUDA 的 NVIDIA GPU + 常规内存与磁盘空间(具体视数据规模而定)。
  • 系统:Windows / Linux 均可(推荐 Ubuntu 22.04 或 Windows 11 + WSL2)。
  • 驱动:CUDA + cuDNN + 对应显卡驱动。
  • 运行时:Python(训练、RapidOCR)、Rust 工具链(后端)、Node.js(前端)。

14.2 部署形态 ​

组件部署方式
前端Next.js 构建产物,可独立部署或随 Rust 服务一起分发
Rust 后端(在线首选)编译为单一可执行文件,内置 Axum 服务 + 模型/OCR 加载
WASM 模块(离线备选)独立构建产物,随前端分发,浏览器内加载运行
模型文件本地目录存放 ONNX 模型(MRC/相似度,FP32+INT8)+ 分词器 + 配置
数据库SQLite 文件,零运维

14.3 模型优化(适配本地) ​

  • 量化:FP32 + INT8 双模型已交付(INT8 实测精度损失 < 1%:EM −0.79 / F1 −0.69 / Point-Acc −0.42 pt);
  • ONNX Runtime(ort):Rust 原生绑定推理,CPU/GPU EP 经配置切换,单一二进制交付;
  • OCR 加速:已随 OCR 暂停搁置(见第 8 章)。

14.4 全链路运行示意 ​

[教师/用户]
   │ 浏览器操作(Next.js + Radix UI)
   ▼
[Rust Axum HTTP 服务]  ←── SQLite(试题/结果)
   │ 调用本地推理(ort + tokenizers · 单一二进制)
   ├──▶ [RapidOCR]  试卷图片 → 作答文本【暂停 · 501】
   └──▶ [MRC 模型(ONNX FP32/INT8)] + [相似度模型(ONNX)]
             │ CPU / GPU EP 可选
             ▼
返回逐点评分明细 + 总分 → 前端高亮展示

15. 项目里程碑 ​

阶段主要交付实际结果
数据与环境(M0)数据集到位、全栈环境、契约冻结✅ 北大数据集未获批,R7 替代数据集生效;五份契约冻结(tag m0-env)
大模型打标(M1)打标流水线、对齐后训练数据✅ 4287 条样本、点级对齐 99.0%、semantic 占比 76.7%、多端点 fallback(tag m1-labeling)
模型训练(M2)MRC + 相似度模型、ONNX 导出✅ FP32+INT8 双模型交付;Point-Acc .894 / 等价 .943 达标,EM/F1/Corr 模型级未达→评审裁剪至迭代闭环
OCR 集成(M3)/api/ocr、图片链路贯通✅ 当日贯通 → ⚠️ M8 去 Python 化后暂停(501)
后端开发(M4)Axum 服务 + 推理引擎 + 评分全流程✅ 契约测试通过;推理栈于 M8 定稿为 ort 原生实现
前端开发(M5)阅卷工作台 + 解析 + 导出✅ 构建通过,全功能联调可用
WASM 离线(M6)浏览器离线单题演示✅ onnxruntime-web + Rust 评分核心,断网验证通过
联调评估(M7)全链路评估、量化优化、打包交付✅ 系统级 ScoreCorr .959 / 等价给分率 .974 达标;Point-Acc .790 转入仲裁闭环
推理栈去 Python 化(M8·追加)ort + tokenizers 原生推理并入网关✅ 金标对拍逐位一致、e2e 零回退,单一 Rust 二进制交付

实际执行期为 2026-08-21 ~ 08-24(AI 辅助高强度连续开发),远快于立项时的周级排期估算;各阶段评审记录见文档站「里程碑评审」分组。


16. 风险控制与备选策略 ​

风险表现应对策略
大模型打标噪声标签不一致导致小模型学偏自一致性校验(多温度投票)+ 跨模型交叉验证 + 人工抽检 5%
MRC 抽取效果不足EM < 60%扩大合成数据 + 增强(同义替换/回译);必要时转由相似度路径承担主要评分
同义识别不足等价命中率偏低扩充 aliases(解析生成 + 打标沉淀)+ 降低相似度高阈值试探;用 SAS-Bench 同义样本专项评测
标准答案解析失败大模型输出非合法 JSONJSON Schema 校验 + 自一致性 + 教师手动编辑降级;前端保留半结构化编辑界面
显存不足训练 OOM减小 batch(8)+ 梯度累积;使用 60M 蒸馏版模型
前端推理太慢WASM 路径延迟高WASM 仅用于演示;生产评分走 Rust+GPU 服务
数据集授权部分平台数据需付费优先北大(科研免费)+ SAS-Bench/CMRC(开放)主线
OCR 识别不准手写体/模糊试卷识别错误影响评分置信度过滤 + 教师人工核对入口 + 评分结果附带 OCR 置信度便于追溯
模型评分漂移上线后对新题型变差收集 bad case(含 OCR 误识别 + 同义漏判样本)→ 交大模型重新打标 → 增量微调(迭代闭环)

迭代闭环:大模型打标 → 训练小模型 → 上线推理 → 收集 bad case(含 OCR 误识别、同义漏判样本)→ 反馈大模型重新打标 → 增量训练,使系统随使用持续变准。

执行期风险实况:R7 触发(北大两类数据集未获批复,替代数据集主线生效);R10 应对路径转正(最终推理栈即 ONNX Runtime Rust 绑定,且进一步去 Python 化);其余风险未触发(R8 随 OCR 暂停悬置)。


17. 附录:参考数据集与资料 ​


文档版本:v5(2026-08-24)——按系统建成实况全面修订:推理栈定为 Rust ort + tokenizers 单一二进制(M8)、OCR 暂停(/api/ocr 501)、WASM 落地为 onnxruntime-web + wasm-bindgen 评分核心(M6)、补记 §13 实测指标与 §15 各阶段实际结果、数据集实际构成注记(§7.1)。v4 及之前的设计沿革见 git 历史。

RubricSpan · 阅微 —— 中文主观题智能阅卷系统