无限解析PDF:长文档OCR的显存优化实践

作者:快去debug2026.11.03 23:38浏览量:0

简介:面向超长PDF文档的OCR解析长期受困于显存瓶颈:页数越多,视觉Token计算与KV Cache开销越重。本文围绕稀疏参考滑动窗口注意力、Page Gate与Token Sieve两级筛选、无限跨度解码与边界页缓存复用等思路,拆解如何将长序列推理的显存峰值大幅压低,让解析跨度持续延伸,并给出工程落地要点与调优建议。

无限解析 PDF:长文档 OCR 的显存优化实践

一、问题的起点:为什么“页数一多”就难以为继

OCR 并不是一个新问题,但“整本书级别”的 OCR 是。几十页的论文、合同,常见的识别流水线尚可应付;一旦面对上百页的年报、上千页的档案卷宗,甚至数千页的系列长篇,工程上就会撞到同一堵墙:单步计算随页数增长而变重,显存随上下文变长而吃紧。

传统的应对方式是把文档拆开:按页或按固定窗口切分,逐段识别,再把结果拼回去。拆页本身不难,难的是“接”。跨页的表格会被拦腰截断,段落的语义在页边界处断裂,页眉页脚、页码、脚注与正文的层级关系也会在拼接时错位。对于结构化输出(标题层级、表格单元格、阅读顺序)要求较高的场景,拆分—拼接带来的后处理成本往往被低估。

于是问题可以重新表述为:能否让模型像人一样“持续往下读”,而不是每读一页都回头把前面所有页重扫一遍?

这个类比并非修辞。人抄书到第 500 页时,视线聚焦在当前页,只有在遇到跨页承接的内容时才短暂回看。也就是说,多页文档的信息结构本身具有一个可被利用的先验:页内联系密集,跨页依赖相对稀疏。长文档 OCR 的显存优化,本质上就是把这个先验转化为可计算的选择机制。

二、从文本缓存到视觉开销:两代优化的分工

在讨论具体机制前,需要先厘清长序列推理中显存被谁吃掉。

以 Transformer 类解码结构为例,自回归生成过程中需要缓存历史键值对(KV Cache),其规模大致与“已处理 Token 数 × 层数 × 隐藏维度”成正比。文档 OCR 的特殊之处在于,上下文不止有文本 Token,还有来自页面图像的视觉 Token——后者往往数量更大、粒度更细。

一条常见的优化路径是先控制文本侧 KV Cache 的增长,例如通过滑动窗口注意力,让每个解码步只关注有限范围的文本历史,从而把文本缓存压到近似常数。这一步能显著缓解压力,但如果每个解码步仍然需要关注全部参考视觉 Token,视觉侧的计算与显存就会成为新的瓶颈:页数越多,候选视觉信息越多,单步开销依旧线性上涨。

这就解释了两代优化为何是分工而非替代:第一代管住文本缓存,第二代进一步压低视觉计算开销。二者结合,才使“解析跨度持续延伸”在有限显存下成为可能。

三、SR-SWA:用两道筛子压缩视觉参考范围

针对上述瓶颈,一种思路是稀疏参考滑动窗口注意力(Sparse-Reference Sliding Window Attention,SR-SWA)。其核心是把“关注全部视觉 Token”改为“关注少量相关视觉 Token”,并用两级筛选实现:

3.1 Page Gate:先选页面

第一级是页面级筛选。模型不再把整本书的所有页面图像一视同仁地送入注意力范围,而是先判断哪些页面与当前解码位置相关,将视觉参考范围收缩到相关页面集合,同时保留跨页的位置关系信息。

这一步的关键在于“保留位置关系”。若只是简单地按相似度取 Top-K 页面,跨页承接的先后顺序、页与页之间的相对距离可能丢失,导致表格跨页合并、段落续接判断出错。Page Gate 的设计目标是在缩小范围的同时,维持页面间的序关系,使模型仍能区分“上一页的表格尾部”和“十页之前的相似表格”。

3.2 Token Sieve:再挑重点

第二级是 Token 级筛选。在候选页面确定后,页面内仍有大量视觉信息块。Token Sieve 对候选视觉信息块进行打分,选择少量最相关的远程 Token 桶参与计算。

所谓“桶”,可以理解为对视觉 Token 的分组聚合:与其在细粒度 Token 上做稀疏选择(索引开销大、寻址不连续),不如按语义或空间相近性聚合成桶,再以桶为单位做选择。这样既降低了选择本身的开销,也使被选中的视觉信息在内存中更连续,利于实际硬件上的访存效率。

两级筛选合起来的效果是:每个解码步的视觉参考集合从“全书”降到“相关页面的少量信息块”,单步计算量与显存占用不再随总页数线性增长,而更多取决于当前页及其邻域。

需要强调的是,这里筛选的对象是书页中的图像区域与视觉 Token;而最终能力目标是把超长文档持续转成文字与结构。筛选是手段,结构化输出才是目的。

四、无限跨度解码:分块处理与边界缓存复用

仅有稀疏注意力还不够。要在工程上真正“一直读下去”,还需要一套解码调度策略,通常称为无限跨度解码:

  1. 按页面分块处理:将文档按页(或页组)划分为处理块,逐块推进,而不是一次性把全文塞入上下文。
  2. 复用边界页的 KV Cache:块与块之间存在跨页依赖,因此保留边界页相关的缓存,使下一块解码时可以“接着上文”继续,而不必重新编码。
  3. 持续向下推进:随着块推进,早期页面的缓存可被释放或淘汰,显存占用维持在可控水位。

这套机制与 SR-SWA 是互补的:分块限制了单次处理的规模,缓存复用保证了跨块语义连续,稀疏注意力则压低了块内的视觉开销。三者共同作用,使每一步的解码成本保持近乎稳定,从而把有限显存用于“持续处理”而非“反复重算”。

有一个容易被误读的点需要澄清:“无限”指的是解析跨度可以持续延伸,而不是总耗时不变。整本书的总处理时间仍会随页数正常增加——优化的是显存峰值与单步成本的稳定性,而非把总计算量变魔术般消除。

在长文档基准测试的长序列推理条件下,这类分块与缓存复用方式可将 KV Cache 峰值显存从数十 GB 量级降到 GB 级(公开技术资料中给出的示例为从 47GB 降至 1.77GB)。这个数量级的变化,意义不在于数字本身,而在于它把“整本解析”从需要多卡切分、离线批处理的场景,拉到了更接近单机可承受的范围。

五、工程落地:几条实践建议

理解机制之后,落地时还有若干工程细节值得注意。

第一,分块粒度要与文档结构对齐。 按固定页数切块实现简单,但若能在章节边界、目录层级处切分,跨块依赖会更稀疏,缓存复用收益更明显。可在预处理阶段用轻量规则(字体大小、版面分析)做粗分割。

第二,缓存淘汰策略要保守。 边界页缓存是跨页语义的生命线。淘汰过早会导致表格续接、段落承接判断退化;淘汰过晚则显存回升。实践中可对“含表格、含跨页段落”的页面延长保留窗口。

第三,输出后处理不可省。 即便模型侧已尽量保持连续性,结构化输出仍需一层校验:表格跨页合并、阅读顺序修正、页眉页脚剔除。建议把后处理设计为幂等操作,便于在长文档失败重试时只重跑局部。

第四,评估指标要覆盖“连续性”。 仅看字符准确率不足以反映长文档质量。建议补充跨页表格完整率、段落断裂率、阅读顺序准确率等指标,并在千页级样本上做压力测试。

第五,注意显存与吞吐的权衡。 稀疏筛选降低了单步开销,但选择机制本身也有成本。桶的粒度、候选页面数量、保留窗口长度都是可调参数,需按硬件规格与文档类型做联合调优。

六、小结

长文档 OCR 的难点,表面是“页数太多”,实质是如何在有限显存下维持跨页语义连续性。拆页—拼接的老路把连续性交给了后处理,成本高且易错;而稀疏参考滑动窗口注意力、页面级与 Token 级两级筛选、无限跨度解码与边界缓存复用,则尝试把连续性交还给模型自身的解码过程。

这套思路的价值在于其可迁移性:凡是“局部密集、远程稀疏”的长序列任务——长篇文档理解、多页表单解析、卷宗检索——都可以借鉴“先筛范围、再筛重点、分块推进、复用边界”的基本范式。至于“无限”二字,更准确的理解是:让解析跨度不再被显存硬性截断,而总成本仍诚实地随页数增长。这或许才是长文档处理最务实的目标。