基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-02 15:54

RAG 文档处理:先保留结构,再切分

dev.to · AI#RAG#文档解析#Agent
Editor brief · 编辑速览

文章指出,PDF 扁平化提取与固定字符切分会破坏检索上下文,应先恢复布局、阅读顺序和表格,再按章节等结构切分。保留标题、页码及父子关系可支持过滤和引用,视觉密集页面则可考虑直接检索页面图像。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

PDF 问答答错,不一定是模型不够强。表格失去表头、标题脱离正文、多栏内容顺序错乱之后,再好的检索和生成也只能处理残缺材料。原文的核心主张是:先恢复文档结构,再按结构切块,最后才考虑长度限制。

作者用 Docling 和 LangChain 跑通了一个小样例,也讨论了父子检索、摘要树和 Agent 接入。它值得读的地方,是把排查顺序从「换模型」前移到「检查入库材料」;但样例简单,不能直接当成复杂 PDF 的效果保证。

为什么切得整齐,检索却可能更差

传统流程常把 PDF 提取成连续文本,再每隔 1,000 个字符切一块。丢失的信息却可能早在切分前就发生:多栏阅读顺序、标题与正文的归属,以及表格的行列关系,都不一定保得住。

RecursiveCharacterTextSplitter 会优先沿段落等分隔符切分,适合干净正文,但它看不见表格。作者用 chunk_size=200、chunk_overlap=0 演示:收入说明落在第一块,表格和下一节的 Risk Factors 标题落在第二块,风险正文落在第三块。字符数符合要求,内容却无法独立理解。

原文提到,LangChain 教程采用 chunk_size=1000、chunk_overlap=200。放大预算能推迟断裂,重叠能补回部分上下文,但都不能保证表头与数据、标题与正文始终同行。

切块的第一目标,是保住能独立解释的信息单元。

平铺提取与结构感知入库流程对比

文档智能(Document Intelligence)先识别标题、正文、表格、图片和页脚,再恢复阅读顺序、表格结构,扫描件还需要 OCR。Docling 用布局检测模型识别区域,再由 TableFormer 恢复表格,包括缺失边线、空单元格和跨行跨列关系。

训练材料也影响适用范围。原文介绍的 DocLayNet 包含 80,863 页人工标注数据、11 类元素,覆盖财务、专利、法律和手册等版式。它比只用论文版式更广,但不代表你的票据和扫描件一定能识别准确。

Docling 能恢复结构,但输出仍要检查

作者的运行环境是 Python 3.13、langchain 1.4.7、langchain-docling 3.0.0、docling-slim 2.145.0 和 langchain-text-splitters 1.1.3。安装命令为 pip install -U "langchain-docling[local]" langchain langchain-text-splitters。其中 [local] 会带入标准本地模型依赖;作者裸装时曾因缺少格式依赖遇到 ImportError。

先查看解析结果,是整条流程中很有用的一步:

from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType

docs = DoclingLoader(file_path="acme_10k.pdf", export_type=ExportType.MARKDOWN).load()
print(docs[0].page_content)

要看的是 export_type=ExportType.MARKDOWN:它每个文件返回一个完整 Markdown Document,便于人工检查;ExportType.DOC_CHUNKS 则每块返回一个 Document,默认使用 HybridChunker。加载接口还提供一次性读取的 load() 和流式读取的 lazy_load()。

测试里表格保住了表头,但所有标题都变成 ##,文档标题还与首节标题合并。因此,MarkdownHeaderTextSplitter 的标题匹配规则必须依据实际输出设置,不能照搬手写 Markdown 的层级。

切分方面,HierarchicalChunker 按检测到的文档元素输出,默认只合并列表项;HybridChunker 再拆分过大的块,并通过默认开启的 merge_peers 合并共享标题和图注的小块。表格跨块时,默认开启的 repeat_table_header 会重复表头。

还有三个容易漏掉的细节:

  • 作者显式使用 MarkdownTableSerializer,才避免默认序列化把表头与数值的对应关系弄丢。
  • 示例用 sentence-transformers/all-MiniLM-L6-v2 的 tokenizer,设置 max_tokens=512;计数器应与实际 embedding 模型对齐。
  • DoclingLoader 已将 chunker.contextualize(chunk) 放进 page_content,而 source、section、pages、has_table 被提成平铺元数据,方便过滤和引用。

Markdown 表格不能表达合并单元格。原文以 Mistral OCR 3 输出 HTML 的 colspan、rowspan 为例,提醒选型时检查表达能力。作者建议拿最难处理的 10 页测试,比只看整洁样例更有价值。

检索小块、返回大块,比一味加长切块更灵活

有标题时,可以先用 MarkdownHeaderTextSplitter 分节,再用 RecursiveCharacterTextSplitter 限制长度。需要让 embedding 看到标题,应设置 strip_headers=False,默认值是 True。

父子检索进一步拆开了两个需求:小块负责精确匹配,大块负责提供上下文。子块进入向量库,父节保存在文档存储中,命中子块后返回完整父节。

父子检索通过子块匹配并返回完整父章节

作者在 langchain-classic 1.0.8 中验证了 ParentDocumentRetriever,配合 InMemoryVectorStore、InMemoryStore 和 child_splitter,示例子块大小为 80 字符。父节太长时可加 parent_splitter;测试设置 150 字符上限后产生 3 个父块,最长 148 字符。不过这里使用假 embedding,只验证了返回完整父节的机制,不能证明排序更准。

全篇归纳则是另一类问题。RAPTOR 来自 ICLR 2024:先切成 100 token 的叶子块,经 UMAP 降维、Gaussian Mixture Models 软聚类,由 BIC 选择聚类数量,再用 LLM 生成摘要并递归建树。

查询既可逐层遍历,也可用 collapsed tree,把所有层节点放在一起排序。论文在 QASPER 上后者表现更好,并报告结合 GPT-4 后,QuALITY 的最佳结果提高了 20 个绝对准确率百分点。代价是索引阶段增加 LLM 调用;作者还引用约 4% 摘要存在轻微幻觉的分析。这些是论文结果,不是本文样例测出的收益。

没有标题的转录稿或长文,才更适合考虑语义切分和 Agent 切分。原文同时提醒,SemanticChunker 所在的 langchain-experimental 已出现停止积极维护的弃用警告,采用前应与普通递归切分比较。

Agent 能引用来源,前提是入库时留下来源

Agentic RAG 让 Agent 决定何时检索,但检索工具返回什么,仍由入库流程决定。作者通过 @tool 包装 search_filings,调用 similarity_search(query, k=4),返回带章节和页码的文本,再交给 create_agent。

示例模型字符串是 anthropic:claude-sonnet-5。作者只用 stub chat model 测试了工具输出与 Agent 构建,没有验证真实模型的回答质量。

结构元数据的用途很直接:章节和页码支持回查;向量库支持过滤后,section、has_table 可以成为工具参数;多轮检索内容太多时,原文引用 Deep Agents 教程,把材料写入 Agent 文件系统,只返回文件路径供后续分析。

检索内容还可能包含针对 Agent 的指令。提示词要求只把文档当数据,属于缓解措施,仍要限制工具权限。

对于幻灯片、图表和密集表单,原文最后提出直接检索页面图像:ColPali 基于 PaliGemma-3B,跳过文本提取。但提供的原文在 patch 表示的说明处截断,后续参数和实验没有给全,不能补写结论。

我的判断

我认同先检查入库材料。表格已经丢掉列名时,换 embedding 模型很难补回原始对应关系。不过,结构切分并不总比递归切分划算:干净文章可以先用简单方案,复杂 PDF 才更需要布局恢复。

作者只测试了自行生成的单页 PDF。约 34 秒的 CPU 首次运行包含权重下载和两次转换,是冷启动记录,不是性能基准。父子检索用了假 embedding,Agent 用了 stub,结构切分相对普通切分也没有统一评测。因此,它提供的是可复现的机制示例和工程经验,尚不能证明业务效果必然提升。

父块越大,上下文成本也越高;摘要树又增加索引成本。选型应围绕真实问题比较,而不是把所有策略叠起来。

能拿来做什么

  • 给 PDF 知识库建立一组困难页面样本,先检查多栏顺序、标题归属和表格,再调检索模型。
  • 在现有检索接口中保留章节、页码和文件来源,让前端答案可以展示可回查的引用。
  • 对「命中正确但上下文不足」的问题试验父子检索,并同时记录检索效果与上下文用量。
  • 接入文档 Agent 时,让工具返回来源信息,并限制工具权限;不要把提示词中的防注入要求当成完整保障。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
16GB笔记本搭建本地大模型服务平台
下一篇
英伟达开源语义层库,为智能体SQL提供依据

资讯速览

dev.to · AI · 2026-11-02 15:54

AI 评分 8.0 / 10

相关标签

#RAG#文档解析#Agent

继续阅读

  • Agent上下文未满,工具结果为何仍被截断
  • 16GB笔记本搭建本地大模型服务平台
  • 英伟达开源语义层库,为智能体SQL提供依据
  • 代理安全不能只依赖用户点击批准
  • qwenGPU用模型内置层模拟GPU执行