发票自动入账,识字准确还不够
OCR 即使正确识别全部金额,下游仍可能把待付款误当作发票总额。文章提出分别检查文本恢复与字段语义,并用总额、已付款、待付款不同的样本验证提取结果。
AI 深度解读
发票上的数字一个都没识别错,入账金额却可能是错的。作者用一张部分付款的发票说明:OCR 负责读出文字,字段提取负责理解金额含义,业务系统负责判断能否入账。这三件事需要分别验证。
文章的结论很直接:不能拿一个「OCR 置信度超过 95%」的条件,决定是否把 PDF 里的数据写进账务系统。对做文档解析、模型结构化输出和自动审批的程序员来说,这个区分比继续提高识别分数更有用。
为什么数字全读对了,账还是会记错
作者给出的发票包含三个金额:
Invoice total: $1,080
Payment received: $300
Amount due: $780
这里要看清最后一行:$780 是剩余应付金额,发票总额仍然是 $1,080。
OCR 可以毫无字符错误地读出这三行,但下游解析器如果采用「取最后一个金额」的规则,就可能把 $780 填进 invoice_total。这个数字确实来自原文,错误发生在业务含义的分配上。
模型返回合法 JSON,也解决不了这个问题。语法正确只能证明结果可以被程序读取,不能证明 invoice_total、amount_due、以前的欠款和已收款没有混淆。
文字识别正确,不等于字段映射正确,更不等于可以入账。
测试数据也会掩盖这种缺陷。如果测试发票全部未付款,总额与应付金额可能恰好相等。解析器即使一直取错字段,也可能得到正确数字。
把一次自动入账拆成三道验证
作者建议分别回答三个问题,而不是用一个总分代替全部判断。
第一,源文档有没有读对。数字 PDF 如果带有可靠的嵌入文本层,就优先使用它;页面是图片时,可能需要 OCR。检查不能只看数字主体,还应包括小数点、负号、币种和换行。
第二,每个值有没有进入正确字段。测试样本需要让发票总额、剩余应付、此前欠款和已收款出现差异,才能暴露映射错误。
第三,拟写入的记录是否符合业务系统的事实。PDF 无法独自证明 $300 是否已经记入账本,也无法证明供应商已获批准、发票没有重复。这些信息必须来自可信记录和明确规则。
为此,作者提出给重要字段附带来源、校验信息和处理状态:
{
"field": "invoice_total",
"value": "1080.00",
"currency": "USD",
"source_label": "Invoice Total",
"source_page": 1,
"validation": ["subtotal_plus_tax_matches"],
"status": "proposed"
}
要留意最后一行的 status:这个值仍然只是候选结果。工作流还要核验供应商、相关采购订单(PO)或收货记录、重复情况,以及是否具备入账授权。
这份结构的价值在于保留证据。出现争议时,可以追到第几页、哪个标签,以及做过什么校验。但 validation 数组里写了校验名称,并不能替代实际执行校验。
作者还强调,缺失字段应当保持缺失,不能拿附近看起来合理的金额补上。自动补全在这里可能把一个容易发现的缺项,变成一个难以发现的错误记录。
我的判断
我认同作者把评价位置移到业务记录发生变化的地方。相比只统计 OCR 字符准确率或 JSON 输出成功率,检查最终拟入账金额,更接近自动化真正要完成的任务。
不过,文章给出的证据范围很小。作者称在 KelenAI 的字段测试中,用两张合成发票和原始 OCR 输出复现了总额与应付金额混淆。它能证明这类错误可以发生,不能证明某个解析器在真实生产环境中的错误率,也没有提供不同方案的对照数据。
原文还提到评估前至少应覆盖若干类别,但提供的正文没有列出具体清单。作者同时说明,五份文档不足以确立生产准确率,测试集还要覆盖有代表性的供应商、格式、扫描质量和异常量。
因此,这更像一份有具体反例支撑的工程建议,尚不能当作生产效果报告。相比单纯调提示词或提高 OCR 阈值,来源追踪和业务校验覆盖的问题更完整;至于能减少多少错误、增加多少人工处理成本,原文没说清。
能拿来做什么
- 给现有解析流程增加一组部分付款样本,让
invoice_total与amount_due明确不同,检查系统是否把真实数字放错了字段。 - 在 Node 接口或模型输出结构中保留来源标签、页码、币种和
proposed状态,让候选结果经过业务校验后再进入写入流程。 - 在前端审核页同时展示提取金额与对应的文档来源,让审核人员能核对金额含义,而不只是看到一个置信度。
- 将缺失字段作为明确异常返回,并在评估中单独统计错误入账记录,避免一个漂亮的提取分数遮住实际业务失败。