📰 来源:Towards Data Science | 📅 翻译日期:2026年6月13日
🔗 原文:查看原文
🤖 翻译:DeepSeek AI · 仅供参考
本文是企业文档智能系列中关于解析的补充文章,该系列从四个模块构建企业级RAG系统。第5篇(文档解析)使用PyMuPDF(fitz)构建了解析器。本补充文章保持相同目标和相同的关系表,但将引擎替换为Azure布局(预构建布局模型),这是一个更丰富的包,能够恢复fitz无法处理的内容。这一差距正是我们的起点。
PyMuPDF的盲点与Azure的解决方案
PyMuPDF(fitz)快速、免费且对清晰文本精确。但它在三个方面会失效,而每个方面正是企业RAG悄然失效的地方。
- 表格:合同第14页上的表格。Fitz逐个读取单元格并将它们连接起来。列结构消失了。
“Renewal fee 500 Setup fee 200”落入了块中。你的模型需要猜测哪个数字是哪个费用。 - 扫描件:附在文档末尾的扫描修订页。Fitz读取原生页面,对扫描页面返回空字符串。用户无法获得关于修订页的答案,因为解析器从未读取过它。
- 图片中的文本:内部包含文本的图形。带有轴标签的图表。签名的印章。电子表格的截图。Fitz返回图像的边界框。内部文本消失了。
Azure文档智能能够读取所有这三种情况。它是一种专有的Microsoft Azure云服务,受Microsoft在线服务条款管理。预构建布局模型返回原生表格单元格(行、列、表头)、每页的OCR文本(原生或扫描)、内部包含文本的图形,以及段落角色(标题、章节标题、图注、表格标题)。一次调用。与fitz相同的关系表,其中一半得到了丰富。
下游管道不关心哪个引擎产生了字典。检索、生成、注释读取行。它们从不读取PDF。
1.1 表格:fitz返回扁平文本,Azure返回单元格
合同表格有行和列。标签“Renewal fee”位于第1列,值500位于第2列。Fitz从上到下读取页面,每个文本段输出一行。一行的四个单元格返回为四个孤立的单词。有时如果y坐标接近,下一行的单元格会混入。下游的分块器看到的是单词汤。使表格成为表格的行列结构消失了。
Azure的预构建布局模型将每个表格检测为结构化对象。result.tables是一个表格列表,每个表格的单元格通过(row_index, column_index)索引。标题行被标记(cell.kind == "columnHeader")。单元格内容就是作者输入的文本。我们将表格展平为Markdown行,使其像其他内容一样存在于line_df中。一个四单元格行“Renewal fee | 500 | Setup fee | 200”变成line_df中的一行,包含该Markdown文本。标题行添加| --- | --- | ... |分隔符,以便下游模型读取结构。
1.2 图片:fitz返回边界框,Azure返回文本
许多PDF包含带文本的图形。带框标签的架构图。带轴刻度和图例的图表。签名的印章。电子表格的嵌入式截图。Fitz将每个图像返回为边界框和原始字节。内部文本对解析器不可见。
Azure的OCR运行在每一页上,包括图形区域内的像素。对于每个图形,我们收集所有边界框位于图形区域内的Azure单词,并将它们连接为ocr_text。现在,“Multi-Head Attention Concat Linear h”位于Attention论文第4页图形的image_df.ocr_text中。检索可以匹配关于“multi-head attention”的问题,即使答案在图形内部的文本中。
1.3 扫描页:fitz返回空,Azure返回OCR
一份30页的原生合同在末尾附有10页扫描修订页。Fitz读取原生页面,对扫描页面返回空字符串。解析器不会标记此问题。下游管道静默地覆盖文档的75%。用户不知道25%是缺失的。
Azure对每一页运行OCR,无论来源如何。原生页面和扫描页面通过相同的result.pages[i].lines路径返回,形状相同。line_df上的parsing_method列让下游代码知道哪些行来自哪个引擎。parsing_summary字典中的n_pages字段匹配文档的实际页数,而不仅仅是具有原生文本的页面。
1.4 标题与图注:fitz使用正则,Azure具有明确角色
Fitz通过每行开头的正则表达式(^Figure \d+\b、^Table \d+\b)检测图形/表格的图注。当图注看起来像“Figure 2”时有效,但会错过其他形式(“Fig. 2”、多行换行)。它也可能误报:一个正文句子以“Figure 2”开头时会被当作图注。
Azure的paragraphs字段具有角色标签:结果中的每个段落都带有如"figureCaption"、"tableCaption"、"title"或"sectionHeading"之类的标签,告诉我们它是什么类型的块,无需正则。"figureCaption"和"tableCaption"直接填充object_registry。"title"和"sectionHeading"重建目录。该标签是Azure布局模型对块功能的命名;fitz没有等效项。(object_type, object_id)连接键仍然通过相同的正则从图注文本中提取,因此cross_ref_df以相同方式连接。
评论已关闭