TL;DR: 在OCR 遗漏一文中我们展示过:7.7% 的专家标注事实从 OCR 输出中消失,而文档级质量分却是 0.998;几何墨迹覆盖率能抓住区域尺度的丢失,却抓不住单个丢失的数字(点二列相关 0.18)。当时我们点名了那个显而易见的更细粒度方案:版面模型覆盖率——用版面检测器找到的区域,对照实际填充它们的 OCR 块打分。现在我们把它实现并在同样两套真值数据集上测完了。结果:它是我们测过的最锐利的遮挡检测器(签名/印章标注区 11× 分离度,几何信号是 5.4×)——但它没有通过它为之而生的单事实测试:点二列相关 0.136,低于几何基线的 0.18。文中所有数字均为定点测量值(2026-07-12),提交在 content/layout_results.toml,可用文末命令复现。
几何信号的弱点有一个干净的解释:一个被丢掉的财务数字只是几千个像素中的几个,几乎撼不动整页的未覆盖墨迹比率。自然的修法是提高粒度:不再问“这一页的墨迹是否都有着落”,而是问“版面检测器找到的每个区域是否真的被 OCR 块填充了”。区域尺寸的问题,应该能注意到区域尺寸的空洞。
于是我们实现了它:PaddleOCR 的 LayoutDetection(PP-DocLayout_plus-L)逐页提出版面区域;每个区域按其面积被 OCR 块包围盒覆盖的比例打分(fill_ratio);低于填充阈值的区域计为未覆盖,文档的 layout_omission_score 就是未被填充区域的占比。推理按页落盘缓存;信号是纯增量的——质量报告上新增两个可选字段,质量分本身逐字节不变。
在 57 页带专家签名/印章区域标注的真实扫描件(Tobacco800)上:
| 标注区内 | 区外 | |
|---|---|---|
| 平均区域填充率 | 0.503 | 0.866 |
| 未覆盖区域率 | 0.495 | 0.044 |
未覆盖区域率的分离度达到 11×——约为几何墨迹信号 5.4× 的两倍,且 45/57 页(79%)的区内填充率更低。对合同档案迁移中真正要紧的问题——这份文件到底有没有实体签署过、印章是否正在被静默丢弃——版面区域正是路由人工复核的正确粒度,明显优于我们之前的任何信号。
如果标题只到这里,这会是一篇报捷文。但它不是,因为遮挡场景本来就不是那个悬而未决的问题。
悬而未决的问题是单事实遗漏——那 7.7% 静默消失的专家标注事实。与几何信号完全相同的测量,在同样 85 页退化 SEC 文件上(其中 21 页至少含一个被遗漏的金标事实):
| 信号 | 点二列相关(是否有遗漏) | 结论 |
|---|---|---|
| 几何墨迹覆盖率(基线) | 0.18 | 弱 |
| 版面模型覆盖率(“修复方案”) | 0.136 | 更弱 |
均值差距其实拉大了——含遗漏页的平均版面遗漏分 0.095,干净页仅 0.031(约 3×,几何信号约 1.8×)——但逐页相关性被噪声淹没(皮尔逊 -0.058)。均值差距更宽、相关性却更差,意味着这个信号太频繁地在错误的页面上触发,无法用于路由。
这次否证比数字本身更有用,因为它把机制磨得更锋利了。被丢掉的数字通常并不住在版面检测器标为空的区域里,而是住在一个 OCR 部分填充了的区域里:检测器画出一个文本块,OCR 读出其中大部分,其中一个值静默消失。该区域的填充率仍高于任何合理阈值,于是被算作已覆盖。
这否掉的不只是这一个方案,而是整个方案家族。在任何几何粒度上——整页、区域、行——部分填充看起来都和完全填充一样,因为失败根本不是空间性的。丢失的信息是一个值,只有对值本身做推理的东西才能察觉它的缺席:数值交叉验证(必须相加成立的合计、必须闭合的百分比)、对低填充区域做定向二遍 OCR、或用两个独立引擎互相比对。覆盖率信号——无论几何还是版面模型——就是区域尺度的遮挡检测器,仅此而已。
git clone <repo> && cd contract-rag && uv sync --extra dev
uv pip install paddleocr paddlepaddle
# 先构建 OCR 缓存(数据集需申请/外部下载——见 OCR 遗漏一文):
uv run python -m contract_rag.eval.fincritical
uv run python -m contract_rag.eval.realscan
# 再跑版面覆盖率验证(版面推理按页落盘缓存):
uv run python -m contract_rag.eval.layout_coverage
如果你的数字有实质性差异,请开 issue——负面结果只有在保持为真时才有价值。