更好的 RAG 3:文本是你的朋友
这是关于构建更好的生产 RAG 系统以回答复杂问题系列文章的第 3 部分。第 1 部分涵盖了系统设计的基础知识和关键问题,第 2 部分涵盖了多轮检索或“漫游”。
在本部分中,我们将讨论可以应用于源数据和问题以改进检索的转换。
今天我希望说服你,在可能的情况下,尽可能地利用整个(AI)大脑。
许多 RAG 管道都体现了其创建者发现嵌入的路径——包括我的——我们许多人都陷入了相同的陷阱。
首先,你找到了嵌入并抛弃了模糊搜索的世界。也许你听说过 BM25,或者 Elastic 或 Postgres 是你最接近的选择——但嵌入很棒!第一次实现真正的语义搜索!就像任何令人上瘾的新工具一样,你开始使用它,然后过度使用它。
不知不觉中,你已经嵌入了所有能找到的东西,并且检索过多。有时它能奏效,有时则一无所获。你搜索的每样东西都有数千个匹配项,再多的上下文也无法容纳所有你能检索到的内容。增加无实际组织的分层嵌入会让你回到模糊搜索的领域,只是模型更智能了。
你停下来环顾四周——你有很多嵌入(有人会说太多了——我就是其中之一)。下一步的逻辑步骤可能是一个重排器,或者某种偏置矩阵来组织嵌入和搜索结果。
这些本身不是坏事——重排器和嵌入转换在你的检索管道中是非常有用的*最后*一步。只是它们放错了位置,顺序也错了。
如果我们从头开始呢?
纯文本是你的朋友
源语料库——这可以是你的文档存储、图像、PDF 等——是你管道中拥有的最有用的信息。一旦我们开始嵌入,我们就会丢失信息——通常是以不可控的方式。
你认为哪一列包含更多有用的信息来指导搜索?
一旦我们开始分块/嵌入/应用矩阵,我们就会在每个阶段失去控制和信息。任何处理管道的第一个阶段都应该尝试从源文档中转换和发现信息,主要目标有两个。
元数据提取
第一个目标是在进行语义搜索之前,尽可能地提取可以帮助缩小搜索范围的元数据。即使是对你的分块应用一个二进制标签,也可以将你的搜索、内存和计算复杂度减半,同时将检索速度(并希望能提高准确性)加倍。
这是一个 GPT 演示了朴素的结构检索,它通过构建实时类型规范并用信息填充它。
事实上,这里有一个HF 助手运行在 Mixtral 上,它应该能证明即使是小得多的模型也能做到这一点。
让我们把系列文章中的第一篇扔进去,看看我们能得到什么
我们在这里所做的只是让模型创建一个动态类型规范并填充它。即使采用这种朴素的方法,我们也可以获得更多可以使用的东西
- 关键词可用于简单分类。
- 隐含结构可以与查询转换相关联。
- 摘要标题和摘要可以作为更好的嵌入表面积,以匹配您的问题。
你在这里也获得了可控性——结构化搜索的修改、调整和修复远比在 n 维嵌入空间中瞎搞容易得多。
缩小问题与答案之间的距离
第二个目标是缩小查询与数据中相关信息之间的距离。有时你可能会很幸运——你的问题可能来自与你的文档相同的作者,并且他们可能正在寻找简单的、单事实检索。
在大多数情况下,你会发现你的问题看起来和听起来都与相关答案截然不同。对双方进行转换有助于将它们拉近。
永远记住,嵌入寻找的是*简单*的含义和关系。SemanticFinder是测试嵌入极限的好地方。较小的嵌入模型是学习和巩固语义搜索直觉的好地方,通过及早指出问题。这里有一个问题可以尝试:“那里最后住了多少人?”
在理想情况下,您应该同时转换您的问题和您的语料库,使它们在嵌入空间中彼此更接近。
这并不是一个新概念——最成功的 RAG 技术之一是 HyDE——假设文档嵌入,它试图为问题生成潜在的(虚构的)答案,希望这些答案的嵌入能够更接近真实的答案。
你也可以做相反的事情。在 WalkingRAG 中,我们在摄取时执行的一个额外步骤是生成每个文档部分回答的假设问题。这些问题的嵌入与实际用户问题之间的距离比源数据更近——这也是一个有用的多模态步骤,可以从纯视觉信息生成文本问题。关于这个以后再说,但这里有一个例子。
这里是另一个 GPT 示例,用于演示一些转换。您可以尝试自己的文档,甚至可能绘制转换的嵌入图,看看它们之间的距离有多近。
让我们试一试
很快,我们就能看到从我们简单问题中提取的假设子问题。回答(或嵌入)其中每一个都可以找到隐藏在我们数据集中不同信息。另一方面,我们可以看到与所提问题更相关的提取事实和摘要。
还有很多事要做
一旦你开始将大型语言模型(LLM)用作其他步骤之前的转换工具,你就可以做更多的事情。例如,你可以
生成回答问题的推理步骤(不含任何分块或文档上下文)。生成的步骤数量可以作为判断问题复杂度的有用指标,而这些步骤本身可以作为有用的检索器来查找相关分块。
注释文档中的歧义。对于每个块,生成潜在的网络搜索以检索更多信息。即使您从不运行这些搜索,它们也会成为模型可能缺少的信息的有用指针。您还可以对整个文档运行最常见的搜索,并将结果添加到您的数据集中作为补充信息。
RAPTOR 和其他方法指出,递归摘要是提高跨数据集回答的有用工具。长距离摘要可以连接广泛的块信息,并有助于回答复杂问题。
结论
我希望这可以成为一个开放式的系列。还有很多概念尚未涵盖——从结构化提取、引导输出,到有效使用超过一百万个令牌的 LLM 上下文。随着语言模型和我们对嵌入的理解不断发展,我们将找到改进知识组织和检索的新方法。
同时,这里有一些对我很有帮助的经验法则
- 保持简单可以非常有帮助,尤其从模型的角度来看。使用多种模型架构和复杂的提示优化管道可能很有吸引力——它们通常可以为您带来额外的百分之几的准确性。但是,请注意您在复杂性和可维护性方面可能做出的权衡。添加到管道中的黑盒机器学习越多,升级、维护和控制就越困难。
- 在构建新系统时,请从查询入手。了解您的系统需要回答的问题类别,并与客户、用户和您自己保持一致。构建通用系统可能很诱人——现代 AI 系统感觉它们“几乎可以”处理任何事情。但是,缺乏对问题空间的定义通常意味着您没有意识到正在做出的权衡。
- 将查询时完成的工作与摄取时完成的工作分开。在理想系统中,您应该在两个地方都进行操作——并且意识到您的信息集在摄取和查询之间会发生变化,这会带来很大的不同。
我希望这能有所帮助。一如既往,这都是基于许多人的工作——如果我漏掉了某人,或者您认为我应该添加什么,请告诉我!你通常可以在 Twitter 上找到我。