假设你给模型一份200页的年度报告,并问它一个具体问题,比如“今年的收入确认政策有什么变化?”以及报告在哪里解释了原因。这是一个很平常的问题。了解这份文件的人大约两分钟就能回答,他们会翻到正确的章节并阅读相关内容。但请看看机器是如何回答同样问题的,因为通常的做法会丢弃我们用来简化问题的唯一关键要素。

处理此类问题的常规方法是检索增强生成(RAG)。你将文档切成块,可能是每500字一块,或按段落划分。然后将每个文本块转化为向量并存储起来。当问题出现时,也将该问题转化为向量,从中检索出最相似的少数几个文本块。这些内容进入模型的上下文窗口,模型据此作答。这种方法有用、成本低廉,对于许多问题来说确实足够。

然而,当面对一份大型结构化文档时,其局限性便显现出来。一旦将其切块,你就丢弃了它的构建方式:标题与其介绍的段落分离,表格与解释其含义的句子断开。如果答案分散在多个不同章节中,相似度搜索无法得知这些章节属于同一整体,因为它仅在小段文本间进行比较。你得到的是碎片,模型不得不猜测它们之间的关系。

但这份文档起初就不是一堆杂乱的文字,而是有人以结构化的方式撰写的:有标题、章节、子章节、段落、表格和图片,它们都存在于这棵层级树结构中。作者已经为你组织好了信息。“分块”操作将这棵树压平,以便进行相似度搜索,但这最终破坏了结构,导致我们需要花费更多精力去恢复那些原本就存在的关联。

让我们思考另一种寻找合适材料的方法:不要压平文档,保留树状结构;让模型通过推理找到正确部分,而不是依靠相似度匹配。想想你如何亲自回答那个关于收入的问题?你不会读完200页文档,而是打开目录,找到会计政策章节并阅读。如果指向脚注,你会跟随引用导航文档——智能体也能做到这一点。

它从树状大纲开始,每个章节附带简短摘要,使其无需阅读全文即可了解文档结构。它推理出最可能包含答案的章节并打开阅读;若信息足够便作答,否则选择下一节继续。这一过程分几步进行直到获取所需内容。由此产生两个仅靠扁平化文本块难以获得的优势:首先是上下文免费附带,智能体在阅读段落时仍知晓其所属章节及子章节。

其次是能够回答贯穿全文的问题:若政策定义在一处,推理在几章之后,智能体仍可保持位置并读取其他分支后返回。它是在地图中移动,而相似度搜索只是 handing 给你看似与查询相似的部分。此外还有另一个好处:智能体并非减少总工作量,遍历树状结构意味着多次往返并累积开销。

关键在于最终呈现在模型面前的内容发生变化:不再是整份文档或失去位置的少数文本块,而是带有标题的相关章节。模型在正确的材料和结构上进行推理,往往能产生更清晰的答案,减少因不相关碎片而产生的幻觉。这一切都依赖于实际拥有这棵树状结构,而这正是难点所在:大多数文档以PDF形式呈现。

PDF本质上只是将字符和图形放置到页面上的指令,内部没有清晰的结构可供遍历。这正是Docling的工作:你给它一个PDF文件,它返回一份结构化的树状文档对象——保留真实的章节、标题和阅读顺序,表格依然是表格。PDF格式埋没了作者构建的层级,而Docling将其重构出来。

一旦拥有该对象和Docling智能体,它可以直接在结构上工作:写入、编辑、提取字段并丰富章节内容。其中包含的智能体执行了我刚才描述的导航功能。项目称此为“无分块RAG”(Chunkless RAG),这是一个很好的描述:目标与普通检索相同,即找到合适材料并以此为基础生成答案。

但它通过推理文档结构而非将其切碎并进行相似度匹配来实现这一目标。这仍然是检索,只是在执行过程中保持文档的完整性。但这并非没有代价:在一切生效之前需要良好的树状结构,而将现实世界的文档解析为清晰的结构是一个难题,这也是大部分工程工作所在。

通过结构进行推理也比单次向量查找需要更多的来回交互模型调用,因此延迟更高、请求更多。基于分块的检索在很多时候仍是合适的工具:如果你拥有数百万份文档,且问题是模糊的“关于X的任何内容”,相似度搜索很难被击败。

结构方法在长篇幅、组织良好的文档中证明其价值,特别是在精度至关重要且你关注各部分之间联系的场景下。在许多现实世界的系统中,你会结合使用两者:用相似度搜索找到正确的文档,再用结构在内部进行导航。这就是真正的选择点。

这两者都是检索方式。问题在于:你是将文档切碎并通过相似度匹配,还是保持其完整性并推理其结构?作者已经绘制了地图,文档将其交还给你,智能体现在可以跟随它前行。