发票字段提取如何划定自动入账边界
示例用规则生成候选字段,再由逻辑回归结合上下文、位置与格式选择结果,低置信度字段转人工,IBAN 另做校验和验证。实验使用 484 张固定版式合成发票,不能直接代表真实票据表现。
AI 深度解读
发票识别真正难的,不是从 OCR 文本里找出金额,而是决定哪些字段可以直接写入财务系统,哪些必须交给人确认。作者用一个小型 Demo 展示了这条流程:先提取候选值,再结合上下文评分,能用确定规则校验的地方优先校验。
它值得看的地方,是把「识别准确率」拆成了自动入账比例和入账后的正确率。但所有结果都来自固定版式的合成数据,不能直接当作真实业务的交付指标。
先找候选值,再判断哪个才是答案
Demo 的输入是发票 OCR 文本,输出是发票号、日期、IBAN 和含税总额,每个字段都带置信度。低置信度字段进入人工审核。
数据来自 mychen76/invoices-and-receipts_ocr_v1,包含 OCR 文本和标准答案。约 2,200 份文档中,作者只使用了 484 份发票;其余是收据,字段结构不同。
提取分两步:先通过模式匹配生成候选值,再由一个小型逻辑回归模型,根据候选值附近的词、位置和格式进行排序。
这对金额尤其重要。一张发票里可能同时出现净额、税额、商品明细和含税总额,取最大的数字并不可靠。系统需要判断金额在文档里的含义,而不只是识别出它长得像金额。
这里没有要求大模型包办整条流程。模式匹配负责缩小范围,模型负责处理上下文歧义。
IBAN 能不能通过,不能只听模型打分
IBAN 是国际银行账户号码。作者对它采用了比置信度更硬的条件:检查 ISO 13616 校验和。
下面是原文用于检查校验和的代码:
def iban_ok(s: str) -> bool:
s = s.replace(" ", "").upper()
rearranged = s[4:] + s[:4]
digits = "".join(str(int(c, 36)) for c in rearranged)
return int(digits) % 97 == 1
要看的是最后一行:转换后的数字必须满足模 97 余 1,模型给出高分也不能绕过这个条件。这段函数展示的是校验和检查,原文没有展示完整的输入防护。
遇到 OCR 把 S 和 5、O 和 0 混淆,或者漏掉、重复一个字符时,Demo 会尝试修复。只有恰好一个修复结果能通过校验,才采用它;没有唯一有效值,就交给人。
有确定规则的字段,规则应该成为自动入账的门槛。
但校验和通过,并不能证明这个账号属于正确的收款方。它解决的是编码有效性问题,业务归属仍需其他依据。

96.4% 的自动化率,要连着测试条件看
作者在 74 份留出测试文档上报告了两个数字:
- 96.4% 的「干净文档」实现了四个字段全部自动处理。
- 在这些自动处理的文档中,98.2% 的文档所有字段都正确。
阈值是在验证集上按 98% 的目标调出来的,留出测试集只用于报告结果。原文没有完整解释「干净文档」的统计口径,也没有给出这些百分比对应的具体文档数量,不能自行补齐分母。
还有一个更值得程序员留意的发现:74 份文档中,有 18 份的 IBAN 标准答案无法通过校验和,OCR 文本里的值反而能通过。作者将这些标签判定为损坏,从 IBAN 评分中排除,并在 results.json 中单独计数。
标准答案也可能错。只看模型输出和标签是否一致,可能把正确结果算成错误。
测试边界也很明确:这是固定版式的合成发票,样本量小。作者承认真实、多样的发票表现会更差,试点应该先在客户自己的样本上测量。另外,扫描件和 PDF 转 OCR 文本属于独立、可替换的步骤,这次结果不能代表整条扫描识别链路的效果。
我的判断
我认可这套设计把「提取」和「是否允许入账」分开处理。前者可以依靠模型,后者需要阈值、校验规则和人工审核共同决定。相比把整张发票一次性交给模型,再凭一个总分决定放行,逐字段处理更容易定位问题。
但原文没有提供与纯规则、大模型提取或其他排序方法的对照数据,因此不能据此认定逻辑回归更准确、成本更低。这是一个有明确边界的 Demo,尚不足以证明生产收益。
唯一修复结果通过校验,也只是自动采用的条件之一。固定版式下成立的策略,换成复杂真实票据后,仍需重新验证。人工审核是否方便、错误入账代价多大,原文也没有给出实测数据。
能拿来做什么
- 给发票提取接口按字段返回结果、置信度和校验状态,让审核页面能直接指出需要确认的字段,减少用户重复检查。
- 在 Node 服务中,把校验和、日期范围和金额勾稽检查做成独立步骤,并为无法确认的字段保留人工处理入口。
- 用自己的发票样本划分验证集和测试集,在验证集调阈值,分别报告自动处理比例和自动处理后的正确率。
- 评估前先审查标准答案,单独记录损坏标签;同时把 OCR 转换与字段提取分开测量,避免把上游识别错误全部归到提取模型上。