面向 AI 的文档解析:PDF、表格,以及那些乱糟糟的剩余部分
在模型能对你的文档进行推理之前,必须有什么东西先把它们变成干净的文本。这个不起眼的步骤悄悄决定了下游的一切。
大多数处理文档的 AI 项目都有一个安静的失败点,而它几乎从来不是模型本身。它是模型之前的那一步:把一份 PDF、一张扫描的表单或一份电子表格,变成模型真正能读懂的干净文本。这就是文档解析,它是整条流水线里最不起眼、也最被低估的部分。当一个 AI 系统对某份文档给出奇怪的答案时,原因更多是输入被弄乱了,而不是模型糊涂了。本文要谈的,是为什么这一步很难、它在哪里崩溃,以及该如何把它做好。
文档不是文本
困难的根源在于一个人们很少注意到的错位。模型读的是一条线性的文本流——一件接一件,按顺序排列。而文档,尤其是 PDF,并不是这样存储的。PDF 描述的是页面上墨迹的位置:这个字形在这个位置,那条线在那个位置。它并不一定记录这些墨迹构成了一个段落,或者这个块是个标题,又或者这些对齐的数字是个表格。视觉上的含义对你的眼睛显而易见,对一个朴素的文本提取器却是看不见的。
所以解析其实是一种重建。解析器必须看着这些有位置的墨迹,恢复出人类一眼就能看到的逻辑结构:阅读顺序、段落、分栏、标题、列表、表格。当这种重建顺利时,模型收到的是干净有序的文本,表现也合理。当它出错时,模型收到的是一团乱码,于是产出乱七八糟的答案——而这个失败看起来像是模型问题,实际上却是上游一步的解析问题。
从简单到残酷的光谱
并非所有文档都一样难,知道你的文档落在哪里,能让你建立现实的预期。
简单的一端是原生数字、基于文本的文档——从文字处理器导出的 PDF、一个 HTML 页面、一个纯文本文件。文本是真实存在且顺序合理的,提取大体可靠。即便如此,多栏或侧边栏之类的排版特征仍可能让朴素的提取器把本该分开的文本交错在一起。
困难的一端是扫描文档和文本图像——一份拍照的合同、一张传真的表单、一份旧报告的扫描件。这里根本没有文本,只有像素,你需要光学字符识别(OCR)从图像中恢复字符。OCR 已经大有改进,但在劣质扫描、不寻常的字体、手写体和低对比度上仍不完美,而它的错误会悄无声息地传播到下游的一切。
夹在残酷中段的,是那些看起来简单却并非如此的文档:复杂多栏排版的 PDF、结构本身承载含义的表单,以及最重要的——任何带表格的东西。大多数真实世界的文档集合都是这三者的混合,这就是为什么一个在你的测试文件上表现出色的解析器,面对整个集合时仍可能力不从心。
表格是流水线的葬身之地
表格值得单独成节,因为它比任何东西都更容易拖垮文档流水线。一个表格的含义完全寄居于它的二维结构之中——单元格、它所在的行,以及它的列标题之间的关系。把它压平成一条线性的文本流,含义就蒸发了。「营收」「412」和「2019」都是无用的碎片,除非有什么东西保留住「412 是 2019 年的营收」这一关系。
一个朴素的提取器会按墨迹恰好被存储的顺序读取表格,往往产出一堆数字脱离了标题的混乱。模型于是看到一些彼此断裂的数值,要么猜测它们之间的关系,要么干脆编造——而这正是那种自信但错误的答案,会侵蚀人们对整个系统的信任。妥善处理表格,意味着检测出某个区域是一个表格,恢复它的行和列,并以一种让单元格与其标题保持关联的形式来表示它。这确实很难,也是通用解析器最常掉链子的地方,如果你的文档表格密集,它值得专门的关注,而不是寄希望于运气。
各种方法,以及各自擅长什么
没有唯一正确的工具。合理的方法构成一架阶梯,你只爬到文档所要求的那一级。
- 直接文本提取。 对于原生数字、基于文本的文件,直接拉取内嵌文本。当文档配合时,它快、便宜、准确。永远先试这个;不要对不需要的文档动用更重的机器。
- OCR。 当文本被锁在像素里——扫描件和图像——OCR 无法回避。预期结果会不错但不完美,并预期质量会紧随源图像的质量。
- 布局感知解析。 对于复杂排版和表格,那些对文档结构——而不只是字符——建模的工具,在保留阅读顺序和表格关系上明显做得更好。这是大多数被低估的流水线所缺失的那一级。
- 具备视觉能力的模型。 有些模型可以直接接收一张页面图像,并连同布局一起解读其内容。在那些击败传统解析器的乱糟糟文档上,它能大放异彩,代价是更高的成本,以及你对任何模型输出都应有的谨慎:它可能误读,所以要核实。
务实的做法是让方法去匹配文档,而不是为所有东西挑一个工具。一批干净的数字报告和一摞扫描的表单需要不同的处理,硬把两者塞进同一条路径,就注定其中一个会受苦。
分块:解析之后、却由解析决定的一步
解析很少是旅程的终点。对大多数 AI 文档系统来说,文本随后会被切成块以供检索,而这一切分的质量,完全取决于解析是否保留了结构。如果解析器恢复了段落、章节和表格,你就能沿着有意义的边界分块,把相关内容放在一起。如果它产出的是一面没有区分的文本墙,你就只能盲目切分——把表格切成两半,把标题与它的章节割裂,让句子成为孤儿。这就是为什么即使模型从不看到原始解析结果,解析质量依然重要:干净的解析催生干净的分块,而干净的分块才能让检索浮现出正确的上下文。解析步骤上的垃圾不会被关在原地;它会在之后每一步累积放大。
要核实,因为这些失败是无声的
文档解析最危险的特性,是它的失败很安静。一个行为失常的模型很显眼。而一个丢掉一列、打乱一个表格,或悄悄跳过一个章节的解析器,产出的结果看起来没问题——直到有人基于一个建立在被污染输入上的答案采取了行动。防御之道,是把解析器当作任何其他不可信组件来对待:拿它的输出与原始文档抽样核对,尤其是表格和复杂排版;用常识检查提取出的数值是否落在合理范围;并留意一次糟糕解析的蛛丝马迹,比如对不上的数字,或者消失了的章节。一个解析错误的代价不是一个解析错误。它是一个没人质疑过的错误答案,只因为它听起来很自信。
总结
文档解析是那个不起眼、却悄悄左右任何文档 AI 系统好坏的步骤。文档不是文本;它是必须被重建的结构,而这种重建对干净的数字文件来说简单,对扫描件来说困难,对表格来说残酷。让方法去匹配文档——直接提取、OCR、布局感知解析或视觉模型——而不是把一个工具硬套在所有东西上。记住解析质量会向下传播:干净的解析催生干净的分块和良好的检索,而糟糕的解析会污染下游的一切。还要核实输出,因为解析的失败是无声的,而一个自信的错误答案是代价最昂贵的那一种。把这一步做对,模型才真正有机会。做错了,再好的模型也救不了你。
