contract-rag

你的合同 RAG 检索出来的全是乱码。这是一个可衡量的修复方案。

contract-rag 解析、清洗并为脏合同 PDF 打分,再抽取可按文本块溯源、带置信度分级的事实。这个页面上的每一个数字都能从开源仓库复现——凡是模拟输入,我们都会如实标注。

脏→净字段 F1 0.333 → 0.701 质量评分 0.64 → 0.97

40 篇真实 CUAD 合同、模拟脏数据(带种子的破坏套件)

把你最脏的一份合同发给我们 — 48 小时内交付 PoC 报告

它做什么

解析路由,覆盖真实扫描件

按文本覆盖率探测每份文档并路由到合适的解析器(docling / VLM / paddleOCR);按页路由能识别整份文档级路由会漏掉的"数字件+扫描件"混合合同——实测:EDiTh 混合文档中有 98.8% 会有至少一页路由错误(整份路由时)。

可解释的质量评分 + 人工复核

一个可解释的加权评分(乱码、表格完整性、空白块、OCR 置信度)会标出需要人工复核的内容——我们也如实说明它看不到什么:置信度无法标记遗漏,因为被遗漏的事实根本不会产生任何文本块,而不是一个低置信度的块。我们已经测量过这个盲区,并为此构建了一个基于几何墨迹覆盖率的信号。

可溯源抽取,经过验证,可直接对接 CLM

每一个抽取出的值,都必须是其引用源文本块的原文片段——溯源关系由结构保证,而非靠提示词承诺。verify() 会把低置信度或无法溯源的字段挂起待人工复核,同一批事实还能导出为 CSV/JSON,并提供 Salesforce/Ironclad 的字段名最佳对齐映射。

在公开数据集上的实测

CUAD(40 篇真实合同)规则抽取器字段 F1 0.676(95% 置信区间 [0.594, 0.746]),溯源准确率 1.000;本地结构化约束解码(qwen2.5-32B)0.661–0.672,schema 失败 0/40,对比标准 TOOLS 模式函数调用的 12/40。模拟脏数据提升:字段 F1 0.333 → 0.701,质量分 0.64 → 0.97。
Kleister-NDA(40 份真实 SEC EDGAR NDA)规则抽取器字段 F1 经过两轮针对性修复后从 0.523 提升到 0.697,溯源准确率 1.0——这也是与合成金标集 0.98 分数之间那道诚实的差距。
Tobacco800(100 页真实扫描件)签名存在性检测器:精确率 0.981,召回率 0.773,F1 0.864——能标记出 33/34 份未签署文档,而朴素的"默认已签署"基线一份也找不到。
FinCriticalED(85 页真实降质 SEC 文件)491 条专家标注事实中有 7.7% 在 OCR 输出里完全消失,而文档级质量评分依然显示 0.998——这是一个置信度阈值无法捕捉的盲区。
EDiTh(86 份真实混合格式文档)整份文档级路由下,98.8% 的数字件+扫描件混合文档至少有一页路由错误(共 204/464 页)——正是这个测量结果促使我们构建了按页路由。

我们发布负面结果

  • 我们复现了 DAPEI 风格的"定义注入"检索增强手法:在哈希与语义两种向量模型下,混合检索均无任何提升(哈希模型 hybrid 0.586 → 0.586,持平;语义模型下仅注入稠密侧的结果与基线逐项完全一致,hybrid 0.698 → 0.698);全量注入反而拖累 BM25(0.690 → 0.664),并把语义模型的 hybrid 拉低到 0.681。我们保留了用于分析的埋点,但没有采用这项技术。
  • 我们试验过一个替代的本地 OCR 引擎(FrankenOCR):字段 F1 打平,速度却慢了 25–50×,而且在被切碎的扫描件上会产生幻觉文本。最终未采用。
  • 我们自己的质量评分也有盲区:在 FinCriticalED 上,7.7% 的专家标注事实从 OCR 输出中消失,而评分依然显示 0.998。OCR 置信度同样无法标记它——被遗漏的事实根本不产生任何文本块,而不是一个低置信度的块。我们选择把这个差距公开测量,而不是藏起来。

常见问题

为什么脏合同 PDF 会破坏 RAG 检索和抽取?

乱码(Mojibake)、单词中间被换行拆开、每页重复的页眉,以及近似重复的文本块,都会同时污染分块检索并干扰结构化抽取——模型检索到的是噪声,引用的也是错误片段。在建索引或抽取之前,先清洗成一个有类型的文档 IR,是从根源解决问题,而不是靠更大的模型硬扛。

在真实合同上(而不是合成 demo 上)抽取准确率如何?

在公开的 CUAD 基准(40 份真实合同)上,确定性规则抽取器字段 F1 达到 0.676(95% 置信区间 [0.594, 0.746]),溯源准确率 1.000。在真实的 SEC EDGAR NDA(Kleister-NDA)上,同一套方法达到 0.697,而我们自己的合成金标集分数是 0.981——这个合成与真实数据之间的差距,我们选择公开发布,而不是隐藏。

能处理扫描件、以及数字件+扫描件混合的合同吗?

可以。文本覆盖率探测会为每一页路由到合适的解析器(原生数字文本 vs OCR)——这一点很重要:98.8% 的真实混合文档在整份文档级路由下至少有一页会路由错误,这正是我们把路由做到按页而非按文档粒度的原因。扫描件的签名检测同样已经构建并测量(Tobacco800:F1 0.864)。

"可溯源、经过验证"具体是什么意思?

每一个抽取出的值都必须是其引用文本块(source_block_id)的原文片段——溯源关系由结构强制保证,而不是靠提示词承诺。verify() 守卫会把低置信度或无法溯源的字段挂起,转交人工复核,而不是悄悄给出一个可能错误的答案。

抽取出的事实能对接进我们的 CLM(Salesforce、Ironclad)吗?

可以——CSV/JSON 导出会携带 doc_id、字段名、值、source_block_id、置信度、风险分级,以及一个 verified 标记,并提供 Salesforce/Ironclad 的字段名最佳对齐映射(供导入参考,并非官方 schema)。

为什么要公开负面结果,而不是只展示成功的那部分?

因为只展示成功数字的供应商,是在要求你相信营销话术,而不是证据。我们测量过 DAPEI 风格的定义注入,结果没有帮助;我们试验过一个替代 OCR 引擎,最终没有采用;我们测量过自己的质量评分对 OCR 遗漏的盲区。这三项负面结果都和其他有效的结果并列展示在这个页面上。