为了账号安全,请及时绑定邮箱和手机立即绑定

从零开始解析增强检索生成(RAG)系统

我在做机器学习工程师的工作时,经常使用Claude或ChatGPT帮我写代码。然而,在某些情况下,模型会开始重复或产生幻觉,特别是在执行复杂或长的任务时。这种情况通常是由于模型上下文窗口大小的限制或提示性质引起的。“上下文窗口”指的是模型在单个输入中可以处理的最大文本量(以token计算)。超出这个限制会导致信息丢失或在长任务中出现混淆等问题。我会在提示中加入伪代码来指导模型,这在大多数情况下效果都很好。

观看这个视频 Youtube

在某些情况下,当我感觉模型开始“忘记”我给它的信息时,我会使用一个小技巧:将必要的信息分块提供,以避免超出上下文窗口的限制。这种策略可以帮助模型在互动过程中记住重要的细节。这实际上是所谓的 Retrieval-Augmented Generation (RAG) 系统的核心思想,稍作调整后,我们将在接下来的章节中详细讲解。

作者提供图片

创建索引

这是作者提供的一张图片

  • 资料:这是我们开始收集信息来源的起点,比如书籍、文章或其他任何基于文本的知识。
  • 分块:在这一步骤中,我们将大型文档分解为更易处理的小块。这样可以更方便地处理和查找特定信息。
  • 嵌入:在这里,我们将每一块文本转换成一种数值表示形式,以捕捉文本的意义。让计算机可以高效地理解和比较这些文本。
  • 索引:最后,我们将这些数值表示存储在一个特殊结构中,以便快速高效地搜索。
分段

我相信所有步骤都明白了,除了文档拆分的部分,我们应该怎样拆分文档呢?

为此,已经提出了许多方法。其中一些是静态的,例如固定长度切分,它涉及将文本切成固定数量的令牌或字符。其他方法则更具语义。

对于更详细的解释,请参阅以下文章:RAG中的五级分块策略

检索

作者提供的图片

将文档拆分成块、嵌入并索引之后,我们不会将所有块和查询一起输入到大规模语言模型中。相反,我们会挑选出最相关的k个块。比如说,我们会把查询或问题嵌入进去,并与之前嵌入的块进行对比,来找出最相关的k个块。

生成
创造

作者提供的照片。

这是我们RAG管道中的倒数第二步。我们现在将包含最相关文档的查询作为提示传递给大模型,它会给出最终答案。

这是最基础的RAG流程,这一点在推文中都有提到:RAG用于根据私有数据回答用户的问题,前提是查询本身不能有歧义。我的意思是,查询的表述可能与文档差异很大。所以可能的问题是模型无法理解任务或问题,这意味着我们需要翻译查询。

推特,查看推特上的帖子。

查找翻译

LangChain (LangChain官网)

多查询功能

我们从一个原始问题出发,将其重新表述为几个不同的问题。接下来,我们会针对每个问题查找相关信息。最后,我们可以用不同的方式把这些问题和它们的结果结合起来,和原始问题一起发送给模型。

RAG融合技术

RAG-fusion技术采用了一种叫做互反排名融合(Reciprocal Rank Fusion,RRF)的技术。理解这一点至关重要,特别是当我们稍后讨论重排序时,会再次提到RRF。

当我们使用多查询策略时,我们会生成多个查询请求并收集每个查询的相关信息片段。收集完这些信息片段后,我们会检查并删除任何重复项,确保我们只使用唯一的条目信息。

现在,让我们考虑这种情况,即两个查询返回评分相同(如0.55)的片段。例如,如果两个查询都产生一个评分0.55的片段,在合并这些片段时,就需要确定它们的顺序。这时,RRF就能派上用场了。

RRF 帮助我们根据每个查询的相关性对这些片段进行排序,让我们能够决定哪个片段应在最终列表中优先显示。通过应用 RRF,我们可以有效地合并结果,同时优先考虑最相关的片段,从而更高效、更准确地展示我们需要的信息。

要了解这个公式并看看一些例子,可以看看这些文章。

RAG融合革命来了——生成式AI的范式转变随着自然语言处理(NLP)和生成式AI的最新进展,引入的RAG(检索增强生成)……medium.com
互逆排名融合(RRF)4分钟内解释清楚。解锁RRF在检索增强生成中的潜力
分解过程

分解查询法是一种方法,我们将查询中的复杂任务拆分成更小、更简单且更容易解决的子任务。之后,我们可以通过递归解决这些子任务,或者逐一处理它们,然后将答案合并起来。

作者图片

递归地回答

这种方法涉及将一个复杂的查询分解为一系列更简单、更小的问题。当大型语言模型回答第一个问题时,将问题和答案作为后续问题的背景信息。我们继续这个过程,依次处理下一个问题,直到所有较小的问题都被回答完。(在某些情况下,我们可以在这里结束。)在其他情况下,我们将所有这些问题及其答案作为上下文来回答原始查询。如果进行这最后一步,则称为逐个回答的方法。

作者供图

路由

构建大型RAG应用通常不会只专注于单一任务或仅处理一个文件。例如,如果你有一个高中生正在为考试做准备,你可能会创建一个RAG应用来帮助他们在所有科目上学习,而不仅仅是某一门。然而,该应用需要一个路由来确定每个查询的科目。例如,如果学生询问一个物理问题,路由会将物理问题导向学生上传的物理教材中搜索,忽略其他科目。根据用户的查询,应用会挑选最合适的路径或链路来获取最佳答案。

接下来,我们来谈谈可以使用的路由方法:

使用自定义函数时:

只需为每个科目创建自定义链。例如,如果科目是数学,你可以让模型认为它是一个数学老师,并应依据其数学知识来回答相关问题。同样的,你也会为物理等其他科目创建另一个链。一个简单的函数会检查查询中是否包含特定的单词(例如,“数学”),并选择对应的链来处理相关问题。

机器学习分类

如果你有很多关于不同学科的问题,比如物理、数学等,并且你希望系统能够判断出问题是哪个学科的,你可以训练一个分类模型。这个分类模型会将查询归类到正确的学科领域,分类完成后,系统就可以将查询导向相关教科书或与该学科相关的资源。

语义相似度指的是:

更高级的功能不仅限于简单的关键词匹配。例如,你可以为每个链创建一个嵌入向量(一种数值表示)。当接收到一个查询时,其嵌入向量与每个链的嵌入向量进行比较,选择与之最接近的链。

混合式方法:

正如名字所暗示的,你可以使用结合上述多种方法的混合方法,从而实现更优和更精确的路由。

路由的重要性在于确保提供给大型语言模型的上下文真正与所问的问题相关。这可以防止模型使用来自其他主题的无关上下文。有效的路由还能通过确保我们在正确的块中进行搜索,来改进索引过程,从而节省时间并获得更好的结果。

作者提供的图片

查询

注:原文中的“Construction”保留未翻译,因为它在特定语境中可能有特定含义。

当我们构建查询时,我们使用的大多数文件应该包含元数据。那么什么是元数据呢?元数据就是关于数据的信息。

例如,如果我们有一个视频,数据 就是视频里的具体内容。例如,元数据 可以是视频的 出处、制作日期、时长多长等等。

现在,如果我们有一个这样的问题:

A和B这两段视频,哪一段更长?

第一个方法可能是模型查看第一个视频的文字稿中的单词数量,然后将其与第二个视频的文字稿中的单词数量进行比较。字数多的那个视频就比较长,对吧?

其实不是这样。一个视频可能比另一个更安静,所以即使它的词数更少,也可能更长。但即使词数多的视频更长,最快得到答案的方法是?是让模型分析整个视频,还是直接从元数据中获取时长进行比较?

所以,你觉得用元数据来改进分段处理怎么样?用户写的查询可能直接通过元数据得到回答,这样我们就可以更轻松地给出答案。

这张图片来自作者。

这就是这篇文章的全部内容了!接下来这几天里,我可能会分享一些更复杂的内容。

这里有些资源:
基于检索增强的生成(RAG)从入门到高级
LangChain的产品套件支持开发人员在每个开发阶段。
freeCodeCamp.org 学编程 - www.freecodecamp.org
高级RAG技术:解锁下一个层次medium.com
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消