当前位置:首页 > AI工作类

发票上盖了个歪歪扭扭的红章,AI还能认出上面的金额吗?文档智能解析的技术拆解

2小时前AI工作类2

某天凌晨两点,财务系统日志里跳出来一条报错:一张增值税发票解析失败,金额字段提取为空。值班同事翻出那张发票的扫描件看了一眼——印章刚好盖在了金额那一栏上,红色的印泥糊住了数字,人眼都得眯着辨认。

这张发票最终靠人工兜底处理了,但它引发了一个问题:AI文档解析到底是怎么工作的?为什么大部分发票它都能认,偏偏盖了章的那张就认不出?这块技术看着像"扫描一下就出结果"的魔法,背后其实是一条好几道环节的流水线,每个环节都有自己的能力和短板。我把这条流水线拆开来看了一遍,下面按顺序梳理。

先搞清楚:这跟普通OCR不是一回事

很多人把文档解析跟OCR(光学字符识别)画了等号,觉得不就是"图片转文字"嘛。这个理解差了一截。

传统OCR做的事情确实就是"认字"——把图片里的文字一个一个识别出来,输出一串字符。但一份真实的业务文档里,信息不是以"一串字"的形式存在的。发票有表格结构,合同有条款编号,报关单有嵌套的明细栏。光把字认出来,不把字所在的"位置"和"结构"搞清楚,你拿到的是一堆打散的字符,而不是一份能被系统直接使用的数据。金额"3280.00"这串数字,你得知道它填在"价税合计"那一栏,它才有意义;如果它跟旁边一栏的"税率"搞混了,入账就是错的。

所以文档智能解析(Document AI)在OCR之上还得多干两件事:一是版面分析,搞清楚文档的物理结构——哪里是标题、哪里是表格、哪里是印章、哪里是正文;二是信息提取,从识别出来的文字和结构里,把业务需要的字段(发票号、金额、日期、购方名称)精准地抽出来,填到结构化的数据格式里。这两件事加上底层的OCR,才是文档智能解析的完整面貌。

版面分析:先理解文档的"骨架"

ai-meeting-minutes-cover.jpg

整条管线的第一步是版面分析。它的任务是拿到一张文档图片之后,先把整个版面"切块"——哪些区域是文本块、哪些是表格、哪些是图片、哪些是印章、哪些是签名。

早期的版面分析靠规则。比如设定"水平方向连续的黑色像素聚集成一条线就是表格框线""字号最大的那行是标题"。这种规则方法在标准化程度高的文档上还行——印刷整齐的正规发票、固定模板的报表——但遇到版式灵活的文档就抓瞎。手写的报销单、格式各异的合同附件、拍照歪了的小票,规则方法的准确率掉得厉害。

现在主流的做法是用视觉模型来做版面分析。具体来说,把文档图片当作一张普通图片,用目标检测类的模型去识别页面上的各种区域。模型在大量标注好的文档版面数据上训练,学会了"这种外观的区域是表格""那种外观的区域是印章"。比起规则方法,模型方法对版式变化的适应性好得多,印刷的、扫描的、拍照的,歪的斜的,都能给出一个基本的区域划分。

但版面分析有一个"宁可漏不可错"的难点:表格的识别。表格在文档里不只是"一堆线条和文字",它有行列结构、有合并单元格、有嵌套表头。版面分析阶段需要做的,是先识别出"这块区域是一个表格",然后把它的行列结构解析出来——哪一行是表头,哪些单元格属于同一行,合并单元格的跨行跨列关系是什么。这个"表格结构识别"本身就是一个独立的子问题,做好不容易。歪斜扫描的表格、没有框线的表格(靠空格对齐的那种)、跨页表格,都是当前技术的痛点。

文字识别:认字不难,认"有遮挡的字"难

版面分析把区域切好之后,就轮到OCR上场了,把每个文本区域里的文字认出来。单纯"认字"这个环节,技术已经比较成熟。印刷体的中文识别准确率,主流厂商都能做到95%以上,英文和数字更高。这个水平对于大部分场景已经够用。

真正的麻烦出在"认字的条件不好"的时候。回到开头那张盖了章的发票——印章是红色的,金额数字是黑色的,两者叠在一起,像素层面是混的。OCR模型看到的不是清晰的数字,而是红黑交叠的一团。这种情况下,模型会把一部分被印章盖住的笔画当成"不存在",识别出来的数字就缺胳膊少腿。

这类问题的解法分两个层次。第一个层次是图像预处理:在OCR之前,先用图像处理把印章的颜色去掉。原理是印章通常是红色(或者蓝色),在特定颜色通道里跟黑色文字的对比度不同,通过颜色过滤可以把红色分量压下去,让黑色文字凸显出来。这个方法对红色印章有效,但如果印章颜色跟文字接近、或者扫描件本身偏色严重,效果就打折扣。

第二个层次是让模型本身学会"透过遮挡看文字"。这需要在训练数据里加入大量"有遮挡的文档"样本——给模型看各种被印章、水印、污渍覆盖的文字,让它学会从不完整的笔画里推断完整的字符。这条路理论上更通用,但数据构建成本高,效果也取决于训练数据的覆盖面。目前做得好的产品,通常是两层方法叠加使用。

除了遮挡,手写体是另一个老大难。打印体的字形是固定的,模型见过一次就会。但手写体因人而异,同一个人写的"3"和"5",换个人可能就完全不一样。手写中文的OCR准确率远低于印刷体,尤其是不规则连笔、潦草书写的情况。这也是为什么手写报销单的自动化程度,至今远低于打印发票。

信息提取:从"一堆字"到"一份结构化数据"

文字认出来之后,还需要做最后一步——把业务需要的字段从一堆文字里提取出来。一份发票上有几十上百个字,但你的财务系统只需要其中十几个字段:发票号码、开票日期、购方名称、货物明细、金额、税额、价税合计。怎么从一堆文字里精准地找到这些字段?

早期的做法靠模板和规则。给每一种发票版式预先画一个模板——发票号在左上角第几行第几列、金额在右下角哪个位置——然后按坐标去抓取。这个方法在固定版式上效率很高,但通用性差。国内增值税发票的版式相对固定,规则方法还能用;但一旦碰到各省市自制的票据、国外的发票、格式五花八门的合同,模板就画不过来了。

现在主流的做法是基于大模型的信息提取。把OCR识别出来的文字连同它们的位置信息一起喂给大模型,用提示词告诉模型"从这份文本里提取发票号、金额、日期等字段,以JSON格式输出"。大模型理解文本语义,能根据上下文判断"这串数字是发票号还是金额",不依赖固定的坐标位置,泛化能力比规则方法好得多。

但大模型提取也有它的坑。一是位置信息的丢失。OCR输出的文字带着坐标信息(这个字在页面上的x/y坐标),但如果直接把这些坐标信息去掉、只把纯文本喂给模型,模型就失去了"这个字段在文档的什么位置"的线索。而文档里很多字段的识别恰恰依赖位置——"价税合计"这个标签右边的那串数字才是金额,左边那串可能是税额。所以做得好的方案,会把关键的位置信息编码进文本里一起给模型,而不是只给纯文本。

二是多页文档和跨页字段。一份合同可能十几页,某个条款的金额在第三页,但金额的说明在第五页。大模型的上下文窗口虽然能装下十几页文本,但注意力分配不均的问题会冒出来——中间页面的信息容易被忽略。这个问题的解法和会议纪要类似:分层处理,先做全局摘要定位相关页面,再针对相关页面做精细化提取。

端到端模型:一个趋势但还没完全替代流水线

前面讲的是一条"分步流水线"——版面分析、OCR、信息提取,各做各的。近两年有一个趋势是把这些步骤融合到一个端到端的模型里:直接输入文档图片,输出结构化数据,中间的版面分析、文字识别、字段提取全部由一个模型一起完成。

这个方向的理论优势是明显的。分步流水线里,每一步的错误会往后传——版面分析把一个表格区域误分成了文本块,OCR就没法正确识别表格结构,信息提取自然也拿不到正确的字段。端到端模型理论上不存在这种错误传递,因为它一开始就是对着最终目标(结构化数据)训练的。

但实际落地中,端到端模型目前还没法完全替代流水线。原因有几个:一是训练数据的要求极高——端到端模型需要大量"文档图片直接到结构化数据"的配对训练样本,这种数据的标注成本远高于分步流水线里每一步各自的训练数据。二是可解释性和可调试性差——流水线出了问题,你能定位到是哪一步出了错然后针对性优化;端到端模型出了错,你只知道结果不对,很难知道模型内部哪个环节出了问题。三是计算成本高——端到端处理一张文档图片的计算量,通常比流水线分步处理大不少,大规模商用时成本压力明显。

所以目前做得好的产品,往往是"分步流水线为主、端到端模型为辅"的混合架构。流水线负责处理大量标准化的文档,端到端模型用来处理流水线搞不定的复杂场景——版式罕见的手写单据、跨页表格、遮挡严重的文档。两条路线互补,谁也还没法完全替代谁。

那一张盖了章的发票

回到开头那张发票。后来技术团队去查了那天晚上报错的原因,发现问题出在版面分析阶段:印章盖在金额栏上,导致版面分析把那一块区域的"表格框线"识别成了"印章的一部分",没有正确判断出那是一个表格单元格。后面的OCR自然就没拿到那个区域的文字,字段提取也就提取了个空。

修复方式是在版面分析模型里补充了一批"印章覆盖表格"的训练样本,让模型学会"即使有印章叠加,仍然识别出下方的表格结构"。这个修复提高了同类场景的识别率,但谈不上彻底解决——印章盖得再歪一点、颜色再深一点、面积再大一点,模型可能又会认错。

文档解析技术目前就处在这么一个阶段:标准场景的准确率已经很高,对于大部分日常文档能胜任,但各种边角情况——遮挡、手写、跨页、非标版式——还在一个一个地被处理和优化。每修掉一类边角情况,整体可用率就往上挪一截。这个迭代过程没有捷径,靠的是训练样本一点一点地覆盖那些长尾场景。

财务那边后来反馈,那天的报错是他们当月唯一一次人工兜底。其余几千张发票,系统都正确解析了。那张盖了章的发票,某种程度上不算系统的失败,而是长尾场景里一个还没被覆盖到的角落。把它修掉之后,下一个角落会是什么,谁也说不准。但每修掉一个,需要人工兜底的事就少一件。

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。