OCR 置信度检测不出内容遗漏:近乎满分的质量分数掩盖了什么

核心结论: 我们在 85 页真实退化的 SEC EDGAR 文件(FinCriticalED 数据集)上,用专家事实级标注测量了 OCR 遗漏。结果:491 个专家标注事实中有 7.7% 在 OCR 输出里完全找不到——静默丢失——而文档级质量分数却是 0.998。更糟的是:任何 OCR 置信度阈值都无法标记这种丢失,因为被遗漏的事实不会产生低置信度块——它根本不产生任何块。解法是覆盖率信号,而不是置信度阈值;我们实现了一个几何版本,并如实报告它在哪里有效(被遮挡的签名区域上有 5.4 倍的信号强度)、在哪里无效(单个数字的缺失)。本文所有数字均为定点实测(2026-07-07),以数据文件形式提交在 content/fincritical_results.toml 中,文末给出可复现的命令。

核心矛盾

同样这 85 页,一对数字:

流水线报告的 真实标注显示的
文档质量分数 0.998 7.7% 的专家标注事实在输出中完全消失

恰恰在每 13 个关键事实就有 1 个已经消失的时候,质量分数近乎满分。这不是某一个公式的 bug——而是几乎所有生产环境 OCR 质量信号共有的结构性盲区:乱码率、空块率、置信度,衡量的都是引擎输出了的东西。引擎从未输出的事实,一个信号都碰不到。

我们最早是在 100 页真实扫描件(Tobacco800,上世纪 40–90 年代的打字机和传真文件)上撞见这个盲区的:现代 OCR 连很难看的扫描件都读得信心十足,平均质量 0.987,零页被标记复核。FinCriticalED 让我们得以给这个分数看不见的部分标上数字,因为它有一样罕见的东西:页面上每个关键事实的专家标注。

测量方法

FinCriticalED(HuggingFace TheFinAI/FinCriticalED,Apache-2.0)是一组真实退化的 SEC EDGAR 财务页面,带专家标注的事实标签:数字、日期、货币单位、报告主体、财务概念。我们渲染每一页,经解析路由送入 paddleocr,然后检查每个标注事实是否出现在解析产出的任何位置。

规范化对标注值和 OCR 文本完全一致地施加,对格式宽容、对含义严格:千位分隔符和货币符号会被去掉(1,200,0001200000 永远不算错误),但小数点、负号和跟在数字后的 % 保留——小数点移位或负号丢失就是关键错误,绝不能被规范化抹掉。匹配采用词元边界子串,所以 3.5 永远不会在 13.5 内部误匹配。

结果:491 个标注事实中有 7.7% 在 OCR 输出里完全找不到,集中在纯数字(8.3%)和报告主体(8.3%)——恰恰是财务文档流水线最丢不起的两类。

置信度标记不了它——结构性地

最直觉的对策是置信度阈值:把低置信度的输出转人工复核。我们恰恰校准了这件事——每个标注事实配对其所在块的 OCR 置信度(若没有任何块包含它,则取其上下文落入的块的置信度,作为局部 OCR 质量的代理):

置信度分箱 事实存活率 n
[0.95, 0.99) 0.912 80
[0.99, 1.0) 0.925 411

每个事实配对的置信度都落在最高的两个分箱里,且两箱存活率几乎相同。可靠性曲线是平的:在这份数据上,达到 ≥95% 事实存活率的最低置信度不存在。无论把置信度门槛设多高,都买不来遗漏安全。

原因是结构性的,且不限于这个数据集:被遗漏的事实产生的不是低置信度块——是根本没有块。置信度是已输出文本的属性;遗漏是文本未被输出这件事本身。对前者设阈值,从构造上就对后者失明。(置信度对其他失败模式仍有一些信号:在扫描件上,与签名、印章等被遮挡区域重叠的块平均置信度 0.893,其余区域 0.963——真实存在,但在块粒度上远不足以作为路由依据。)

有效的替代方案:覆盖率信号——部分有效

置信度看不见遗漏,那什么看得见?一个把页面上肉眼可见的内容OCR 实际产出做对比的信号。我们实现了可行方案里最便宜的版本——几何墨迹覆盖率,不引入任何新模型依赖:渲染页面,用 Otsu 阈值得到"墨迹"掩码(深色像素 = 可见内容),然后测量落在任何 OCR 块包围盒之外的墨迹占比。这个 uncovered_ink_ratio 看见的恰恰是置信度看不见的东西:产生了零个块的可见内容。

在两个带遗漏/遮挡真值的数据集上验证后,结果清晰地分成一项胜利和一项局限:

这是一个诚实的部分答案。区域级遗漏——被遮挡的签名、印章、标志——今天用纯几何就能检测。单个事实的遗漏需要更精细的仪器:版面模型覆盖率,用版面检测器找到的区域对照实际填充它们的 OCR 块来打分。我们选择公开这个缺口而不是粉饰它,因为这个缺口就是当前技术的真实边界。

对你的流水线意味着什么

诚实的局限

自己复现

git clone <repo> && cd contract-rag && uv sync --extra dev
# 一次性操作:在 HuggingFace 数据集页面同意条款(门控自动通过),然后 hf auth login
uv run python -m contract_rag.eval.fincritical   # 遗漏率 + 置信度可靠性表
uv run python -m contract_rag.eval.coverage      # 在两个真值数据集上验证墨迹覆盖率

OCR 解析结果有缓存,重跑很快。如果你的数字有实质性差异,欢迎开 issue——公开测量的意义正在于此。