How to extract meaning from charts and tables in PDFs

TL;DR · AI 摘要
Weaviate提出Late Interaction RAG方法,通过多向量模型直接解析PDF图表,解决传统RAG无法提取图表信息的缺陷。
核心要点
- 传统RAG处理PDF图表时,30%的查询会因图表信息缺失导致错误
- Late Interaction RAG模型可直接嵌入页面图像,无需OCR预处理
- Weaviate提供50行Python代码实现完整图表解析流水线
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- PDF图表解析革命
- 传统RAG缺陷
- OCR文本提取
- 30%查询失败率
- Late Interaction方案
- 多向量模型
- 图像直接嵌入
- Weaviate实现
金句 / Highlights
值得收藏与分享的关键句。
传统RAG处理PDF时,30%的查询因图表信息缺失导致错误
Late Interaction模型直接嵌入页面图像,无需OCR预处理
Weaviate提供50行Python代码实现完整图表解析流水线
如何从PDF中的图表和表格中提取信息 | Weaviate
如何从PDF中的图表和表格中提取信息
2026年9月1日
·
16分钟阅读
Etienne Dilocker
首席技术官
Augustas Skaburskas
高级全栈工程师
介绍
如果您曾经尝试将一堆投资者演示文稿、科学论文或年度报告通过RAG流水线处理,您就会了解这个流程:设置光学字符识别(OCR)或文本提取步骤,选择分块策略,嵌入文本,最后检索信息。完成所有这些操作后,有人可能会询问关于FY25财年第二季度收入的问题,而您的检索结果会返回三页不相关的要点,因为实际答案位于一个对索引不可见的柱状图中。
过去人们不得不这样做——仅仅忽略PDF中对RAG来说有趣的部分,例如带有趋势的柱状图、对比表格、架构图以及让PDF比纯文本更有价值的各种元素。
在本文中,我们将向您展示一种更好的方法:不仅能提取图表中丰富的信息,还能消除复杂的处理步骤。我们将涵盖以下内容:
- 经典RAG:为什么OCR和文本嵌入对某些(结构化和非结构化)数据效果很好,但对内容丰富的PDF却不够。
- 晚期交互RAG:什么是晚期交互多向量模型,以及为什么它们能让您完全跳过文本提取。
- 拖放即完成:如何通过几次点击在Weaviate Cloud中导入多个PDF。
- 实际案例:针对NVIDIA FY2026季度财报的查询示例,每个最佳结果都是直接回答问题的图表。
- 复杂的智能体推理:如何使用Weaviate查询代理包装相同数据,生成带页面图像引用的综合答案。
- 可编码且可部署:相同的导入流水线用大约50行Python代码实现,适合生产环境部署。
如果您更倾向于先查看演示,之后再阅读解释,可以直接跳到下方的查询部分。
传统RAG的局限性
首先,我们来看看目前大多数人构建PDF RAG流水线时通常的做法:
- 对文件进行OCR(或文本提取)(使用Python库或第三方工具)。
- 对文本进行分块。
- 使用文本嵌入模型对分块进行嵌入。
- 检索(可能重新排序),生成。
这种工作流程本身并没有什么问题,但其背后存在一个天真的假设:页面可以被简化为一系列文本标记而不会丢失内容的丰富性。对于新闻稿或维基百科文章来说,这基本可行,但对于充满图表的幻灯片、包含对比表格的10-K文件或带有插图的学术论文来说,这显然不够。
您可以构建一个复杂的ETL流水线来提取图表并单独向量化,但这意味着流水线中需要另一个模型,并且会增加堆栈的复杂性,同时在查询时引入合并问题。
使用晚期交互多向量模型,您根本不需要这些:您嵌入的是页面本身,而不是页面中的文本。模型看到图表的方式与您一样。没错,您听对了,甚至没有分块步骤——页面本身就是分块。
传统密集嵌入模型将整个文档(或文档块)压缩为一个向量。晚期交互多向量模型则采用不同方式:它们将文档编码为一组向量,通常每个标记对应一个向量(对于即将使用的视觉模型,每个图像块对应一个向量)。在查询时,查询也会被编码为一组向量,相关性评分是查询标记与文档标记最佳匹配的总和(称为MaxSim)。
模型不再需要问“整页内容是否完全对应我的问题?”,而是可以问“这页中关于Q4 FY26的部分是否与我问题中关于‘随时间变化’的部分匹配良好?”对于图表密集的页面,这种粒度正是所需的。模型无需将整个幻灯片总结为一个向量,而是可以为页面的每个区域保留一个向量,查询可以挑选出相关区域。
实际上,这里存在两个明显优势:
- 作为视觉模型,可以保留布局、图表、表格等元素,并且
- 通过在向量集合上使用MaxSim,可以消除对文档分块的需求。
Weaviate提供multi2multivec-weaviate模块,这是一个在Weaviate Cloud上运行的托管晚期交互多向量模型的向量化模块,因此无需自行托管或管理模型即可从PDF生成多向量。
通过拖放导入PDF
最快捷的尝试方式是使用Weaviate Cloud的拖放导入器。
- 在控制台中打开你的集群。
- 转到集合并创建新集合。
- 选择从文件上传选项并拖入你的PDF文件。
这就是整个导入过程。在后台,Weaviate正在执行以下操作:
- 将每页PDF渲染为高分辨率图像。
- 将该图像作为BLOB属性存储在新集合中。
- 使用multi2multivec-weaviate模块进行向量化,每页生成多个向量。
需要注意几点:
- 一个对象对应一页。检索的单位是页面,这也是人类浏览文档时的导航单位。
- 不使用OCR。模型从未以文本形式看到文字,而是将页面作为图像处理。这就是为什么没有图注的图表与段落一样可搜索。
- 向量经过压缩。晚期交互模型每页可能生成数百个向量,直接存储成本较高。Weaviate采用多向量编码方案保持索引紧凑。(更多细节请参见下文的权衡部分。)
在本次演示中,我们导入了NVIDIA的四份FY2026季度投资者演示文稿(Q1至Q4)。这些文档涵盖截至2026年1月的财年,包含大量图表和表格,总计92页。整个导入过程仅耗时约1分半钟。
查询NVIDIA季度财报
在进行任何复杂操作(如基于数据的智能体推理)之前,我们想先展示原始检索结果,因为它们本身已经非常出色。
导入完成后,你可以在控制台(或通过任何Weaviate客户端)直接查询数据。查询使用普通英语,结果会以带页面图像的排序页面列表形式呈现。
让我们通过三个查询示例展示返回结果:
查询1:“汽车业务收入随时间如何变化?”
最高匹配结果来自Q2 FY26报告中的Automotive页面。左侧是展示五个季度营收的条形图($346M → $449M → $570M → $567M → $586M,同比+69%),右侧包含关于Thor SoC和DRIVE AV的三个要点。
该页面未出现"over time"或"change"等关键词。模型并非通过语义匹配文本,而是基于页面图像识别:五根高度递增的条形图配合季度标签,已足以确认该页面与时间趋势相关问题的匹配性。
查询2:"gross margin trend"
最佳匹配是Q2 FY26财务摘要页面。左侧是组合图表:五季度营收条形图与非GAAP毛利率折线图。右侧是包含GAAP/非GAAP关键指标的表格,显示同比和环比变化。
虽然页面没有直接出现"gross margin trend",但存在可视化毛利率变化的折线图:FY26 Q1毛利率从75.7%降至61.0%,Q2恢复至72.7%。这就是趋势的典型表现,也是模型检索到的结果。
补充说明:同一页还包含详细财务表格。若后续追问"毛利率环比恢复了多少基点?",答案已包含在模型返回的页面中。相关内容将在介绍查询代理时进一步说明。
查询3:"数据中心营收随时间如何变化?"
最佳匹配是Q4 FY26营收页面——包含同比条形图($39.3B → $68.1B)及标注:自ChatGPT问世以来数据中心营收增长13倍。这是模型在文本匹配更优时仍尊重文字的典型案例。此处图表相关性较低,但明确标注答案的文本框在该页面获得最高相似度(MaxSim)。因此实现了文本与视觉信息的双重优势。
次佳匹配是其他季度的数据中心专用页面,将该细分领域拆分为计算和网络两个部分:
注意次佳匹配并非"另一个数据中心页面",而是采用不同拆分方式呈现相同营收数据的页面。这对需要多视角交叉验证的代理系统具有重要价值。
从搜索到答案:Weaviate查询代理
向量搜索返回结果,但有时你想要直接答案。
Weaviate查询代理是一个开箱即用的托管代理,将向量检索与多步骤推理、来源引用和内联页面图像相结合。它支持所有Weaviate云集群,只需指定集合并提问即可。
若对相同集合提问"FY26各季度汽车营收如何变化?驱动因素是什么?",代理将返回综合答案(条形图数据+Thor SoC和DRIVE AV采用情况要点)及来源页面图像。代理自主决定检索页面,通过视觉分析直接引用幻灯片内容。
打开"来源"面板即可查看支撑答案的具体页面。引用来源包含Q1 FY26报告中的Automotive页面——与早期原始向量搜索结果相同类型的条形图,只是对应不同季度。
每个响应中的数字声明都与特定PDF中的特定页面相关联,页面图像就在那里供验证。您无需盲目信任代理,可以自行阅读幻灯片内容。
使用 Python 构建可部署的管道
拖放式 UI 是创建概念验证 (POC) 的最快途径,但大多数生产管道需要代码,以下代码大约需要 50 行。
首先,安装依赖项:
pip install "weaviate-client>=4.21" PyMuPDF然后,将每一页 PDF 渲染为 2000 像素的 PNG,并将其作为 BLOB 存储在使用 multi2multivec-weaviate 向量化的集合中:
import os
from base64 import b64encode
from pathlib import Path
import fitz # PyMuPDF
from weaviate import connect_to_weaviate_cloud
from weaviate.classes.config import Configure, DataType, Property
def page_to_b64(page, long_edge: int = 2000) -> str:
scale = long_edge / max(page.rect.width, page.rect.height)
pix = page.get_pixmap(matrix=fitz.Matrix(scale, scale))
return b64encode(pix.tobytes(output="png")).decode()
client = connect_to_weaviate_cloud(
os.environ["WEAVIATE_URL"],
auth_credentials=os.environ["WEAVIATE_API_KEY"],
)
if not client.collections.exists("PDF"):
client.collections.create(
name="PDF",
properties=[
Property(name="pdf_name", data_type=DataType.TEXT),
Property(name="page_number", data_type=DataType.INT),
Property(name="page_image", data_type=DataType.BLOB),
],
vector_config=Configure.MultiVectors.multi2vec_weaviate(image_field="page_image"),
)
col = client.collections.get("PDF")
for pdf_path in Path("pdfs").glob("*.pdf"):
with col.batch.fixed_size(batch_size=2), fitz.open(pdf_path) as doc:
for i, page in enumerate(doc, start=1):
batch.add_object(
properties={
"pdf_name": pdf_path.name,
"page_number": i,
"page_image": page_to_b64(page),
}
)
client.close()关于上述内容的一些说明:
- Python 调用
MultiVectors.multi2vec_weaviate(image_field="page_image")配置了 multi2multivec-weaviate 模块。这是控制台导入 UI 使用的相同向量化器。
- PyMuPDF 负责光栅化。2000 像素长边目标是一个合理的默认值;较小的目标可以节省时间,而较大的目标会为模型提供更多细节。我们尚未发现低于 1500 或高于 2500 的强烈需求。
batch_size=2是有意为之的。每个对象携带多兆字节的图像,因此小批次可以保持 gRPC 负载合理。
查询创建的集合以返回排序后的页面:
from weaviate.classes.query import MetadataQuery
res = col.query.near_text(
query="how did automotive revenue change over time",
limit=5,
return_properties=["pdf_name", "page_number"],
return_metadata=MetadataQuery(distance=True),
)
for o in res.objects:
print(o.metadata.distance, o.properties)在 NVIDIA 语料库上,这会返回 Q2 FY26 Automotive 页面作为结果 #1:与您上面看到的相同五季度柱状图,通过一个不包含任何 OCR 的端到端管道检索。
您在控制台中看到的相同查询代理也可以从 Python 访问。将其要推理的集合传递给它,然后调用 ask():
from
weaviate
.
agents
.
query
import
QueryAgent
from
weaviate_agents
.
classes
import
QueryAgentCollectionConfig
agent
=
QueryAgent
(
client
=
client
,
collections
=
[
QueryAgentCollectionConfig
(
name
=
"PDF"
)
,
]
,
)
response
=
agent
.
ask
(
"How did automotive revenue change across FY26 quarters? What's driving it?"
)
response
.
display
(
)response.display() 会渲染与控制台中看到的相同合成答案以及页面图像引用。
这是处理 PDF 的银弹吗?
当然不是。在工程领域,始终存在权衡取舍:
- 每个对象/页面包含大量向量。后期交互多向量模型会为每页生成大量向量。可以通过压缩技术(如 Weaviate 原生支持的 Muvera)部分抵消这一问题。这确实有所帮助,但也引入了压缩率与准确性的权衡。对于以大量纯文本为主的数据集(如法律合同、转录文本或日志文件),文本嵌入模型仍然更经济且同样准确。
- 页面级检索粒度较粗。如果答案隐藏在密集合同中的某个段落里,返回整个页面可能会提供过多上下文信息。实际上,我们通常通过代理层(如 Weaviate 的 Query agent)解决这个问题,无需消耗大量 token 即可识别相关段落。
- 模型必须理解你的图表。它能很好地泛化到训练数据中的公开语料库,但如果你有高度领域特定的视觉惯例(如高度风格化的内部模板),应先验证其检索质量。
那么后期交互多向量模型在什么场景下表现更优?主要是在以 PDF 为主的领域,包含季度幻灯片、尽职调查文件、科学图表和技术图纸等资产。对于以文本为主的语料库,文本处理流程通常更经济且性能足够。
进一步优化时,可以考虑混合方法:识别包含图表的页面作为多向量处理,其余语料库作为文本处理,然后在查询时使用 RRF 风格方法合并结果。
结论
总结关键要点:
- 图表和表格不是通过更优 OCR 解决的问题,而是提取过程中被破坏的主要信息。如果管道仅索引文本,在开始嵌入之前,图表中的有价值信息已丢失。
- 后期交互多向量模型可完全跳过提取步骤。渲染页面、嵌入图像、询问图像含义。模型通过页面外观(图表、表格、布局等)检索页面。
- 在 Weaviate 云平台上,数据摄入是拖放操作。将 Query Agent 指向生成的集合,提问即可获得带正确图像引用的答案。
- 将相同基础转化为可部署代码。MultiVectors.multi2vec_weaviate(image_field="page_image") 就是完整的向量化器配置。其余部分是使用 PyMuPDF 对页面进行光栅化以及一个小型 batch.add_object 循环。
如果你一直因索引管道使图表密集型 PDF 处理过于痛苦而绕开处理,这值得尝试。你过去因文件“主要是图表”而跳过的文件类型,正是这种方案设计的初衷。
现在启动 Weaviate 云集群,上传你的 PDF,立即开始提问。
准备开始构建?
查看快速入门教程,或注册免费的Weaviate Cloud账户。
GitHub
Forum
X (Twitter)
不想错过任何博客文章?
订阅我们的双周通讯以保持更新!
通过提交,我同意
服务条款
和
隐私政策 。