登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

RAG 处理 PDF 表格时怎么避免只提取正文文本

来源:17golang原创

时间:2026-09-08 09:58:52 244浏览 收藏

PDF 放进 RAG 后只能搜到正文,通常不是向量数据库的问题,而是摄取阶段已经把表格和图片丢掉了。处理这类文档时,应先把页面拆成正文、表格、图片等元素,再为每类元素保留合适的文本或视觉表示,并把页码、元素类型写进元数据。这样检索结果才有机会回答“表格中的数值是多少”,而不是只返回表格前后的说明段落。

最小可行方案是:PDF 解析开启布局和表格识别,表格保留结构化文本或 HTML,图片保留图像/描述;随后按内容类型建立表示,召回时检查 page 与 element_type,最后再送入生成模型。
要点速览
  • 文本抽取速度快,但会漏掉扫描页、表格结构和图表语义。
  • 表格不要只拼成无列名的长字符串,至少保留行列关系、页码和元素类型。
  • 多模态检索不是“所有内容都转图片”,而是按查询和文档形态组合文本、结构化表格与视觉表示。

先把 PDF 拆成可检索的元素,而不是一段正文

先抽查一份真实 PDF:能否复制文字、表格是否有清晰行列、扫描页是否只有图片、图表旁边是否有解释。如果直接采用 text-only 或快速规则抽取,最容易得到一串连续段落;表格的列关系、图片里的文字和页面布局就不会进入索引。

NVIDIA RAG Blueprint 的配置文档把表格、图像、信息图和 PDF 解析方式拆成独立选项;其摘要文档也明确区分了跳过 OCR/表格/图片处理的浅层文本路径与完整多模态摄取。独立实验时,Unstructured 的 PDF 表格示例则使用 hi_res 和表格结构推断,并从元素元数据取 HTML。两种路径的共同原则是:先保留元素边界,再谈切块。

PDF 页面中的正文、表格和图片分别保留,并写入带页码和元素类型的索引记录
图1:PDF 摄取时分别保留正文、表格和图片元素,并给每条记录附上页码与元素类型。

摄取阶段同时保留结构和可回溯元数据

下面的示例只演示一个独立的抽取检查点,不代表所有 RAG 框架的固定 API。关键不在于把表格转成某种特定格式,而在于每个元素都能回到原页,并且表格仍能表达行列关系。

from unstructured.partition.pdf import partition_pdf

# hi_res 让解析器关注页面布局;表格元素保留结构推断结果
elements = partition_pdf(
    filename="reports/quarterly.pdf",
    strategy="hi_res",
    skip_infer_table_types=False,
)

records = []
for element in elements:
    # 只保存可回溯字段,避免把整个对象直接塞进向量库
    kind = getattr(element, "category", "Unknown")
    metadata = getattr(element, "metadata", None)
    page = getattr(metadata, "page_number", None)
    table_html = getattr(metadata, "text_as_html", None)
    text = table_html if kind == "Table" and table_html else element.text
    if text and page is not None:
        records.append({
            "text": text,
            "page": page,
            "element_type": kind,
        })

# 写入索引前检查表格是否仍带有列结构
table_count = sum(item["element_type"] == "Table" for item in records)
print({"records": len(records), "tables": table_count})

这里的检查结果只回答“有没有识别出表格”,不能证明表格数值一定正确。生产环境还要抽样比对原 PDF:合并单元格、跨页表头和扫描表格往往需要 OCR 或更强的布局模型。若使用 NVIDIA 的摄取服务,可从其配置项启用表格抽取、图片抽取或更强的 PDF 解析;是否开启应结合 GPU、延迟和文档复杂度决定。

为表格和图片选择不同的表示通道

正文通常适合文本 embedding;表格可以同时保留“可读文本”和 HTML/结构化版本;图片则需要原图、图片描述或视觉 embedding。不要为了追求“多模态”把每个正文段落都渲染成图片,这会增加摄取成本,也让精确的关键词匹配更难。

NVIDIA 的多模态检索文档说明,VLM embedding 可以让文本段落、PDF 页面、表格、图表和图片元素由多模态模型表示;结构化元素或整页作为图像的模式则应根据 PDF 工作流选择,并注意实验性能力和资源要求。对表格问答来说,一个稳妥的组合是:表格结构化文本负责列名、单位和精确值,视觉表示负责复杂版式或图片化表格,二者都带 page 与 element_type。

元素建议保存召回核对
正文纯文本、页码、标题层级文本相似度与来源页
表格行列结构、HTML/规范化文本、页码列名、单位、表格类型
图片或图表原图或描述、页码、区域类型图片是否真的来自目标页
用户问题连接文本向量、表格结构和视觉向量,最终汇合为带页码的证据卡片
图2:多模态检索将文本、结构化表格和视觉表示汇合到带页码的证据卡片。

检索时要验证召回的不是“看似相关的正文”

查询“第二季度毛利率是多少”时,召回结果应至少能指出表格所在页、元素类型和对应片段。如果前五条结果全是“本季度经营情况如下”之类正文,说明切块或表示选择仍在丢表格。可以把召回记录先转成证据卡片,再交给生成模型:

def evidence_card(hit):
    # 让生成阶段知道证据来自哪一页、哪一种元素
    return {
        "page": hit.metadata.get("page"),
        "element_type": hit.metadata.get("element_type"),
        "content": hit.text,
    }

cards = [evidence_card(hit) for hit in retrieved_hits]
table_cards = [card for card in cards if card["element_type"] == "Table"]
if not table_cards:
    # 没有表格证据时不要假装已经回答了精确数值
    raise LookupError("没有召回表格元素,需要调整摄取或检索策略")

如果查询本身带图片,NVIDIA 的多模态查询路径还要求明确选择 collection,并且图像查询有单页检索等限制。落地时应记录“文本命中、表格命中、图片命中”的数量,抽样检查页码和元素类型,再观察答案是否引用了真正的表格证据。这样排查的是数据链路,而不只是盯着最终回答像不像。

常见误区与落地清单

  • 只调大 chunk:大块正文仍然不会凭空恢复表格结构;先确认元素是否被识别。
  • 只保存表格纯文本:列名和单位容易与数值脱节,至少保存结构化版本和页码。
  • 全量开启视觉处理:先用少量复杂 PDF 评估准确率、显存和延迟,再扩大范围。
  • 没有回溯字段:没有 page、element_type 或原文片段时,召回错误很难定位。

判断是否修好,可以用三类问题做小样本回归:正文事实、表格精确值、图片/图表含义。每类都检查召回证据是否来自正确页码和元素类型。只要表格问题仍然返回正文,优先回到摄取和表示层排查,而不是继续堆生成提示词。

相关问题

表格一定要转成图片才能进入多模态 RAG 吗?

不一定。结构化文本更适合列名、单位和数值匹配;复杂版式或图片化表格再补充视觉表示,按查询和文档特点组合即可。

PDF 能复制文字,为什么还要做布局识别?

可复制只说明有字符层,不代表表格行列、页面区域和图片语义被保留。需要回答表格问题时,布局和元素边界同样重要。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>