深度解析RAG:你必须要了解的RAG优化方法

1,157 阅读7分钟

RAG(Retrieval-Augmented Generation)是一种结合检索和生成能力的技术框架,旨在通过从外部知识库中检索相关信息来增强生成模型的输出。其基本思想是利用大型语言模型(LLM)的生成能力,同时通过检索机制获取更准确和相关的信息,从而提高生成内容的质量和准确性。RAG的应用场景广泛,尤其适用于需要结合外部知识或实时信息的任务,如问答系统、信息摘要和聊天机器人等。

传统模型通常被视为黑盒,因为它们的内部机制和决策过程对用户而言是不透明的。这种不透明性使得用户难以理解和解释模型的输出,尤其是在复杂任务或大量数据处理的情况下。正是在这样的背景下,检索增强生成技术(Retrieval-Augmented Generation,RAG)应时而生,成为LLM时代的一大趋势。

NVIDIA-RAG-diagram-scaled.jpg

下边我们将从RAG的每个环节来探讨如何优化RAG的效果。

文本预处理

  • 实体解析:消除实体术语的歧义,实现实体和术语的一致性。例如:RAG、检索增强生成等。
  • 文档划分:合理的区分不同主题文档。如果人类无法区分,那么检索系统也不行。例如:上课安排相关、售卖相关等。
  • 数据增强:简单的理解就是数据够多。扩充检索系统使其可以理解同义词、词汇意思的解释等;
  • 数据过期机制:多变的数据要能过期或者更新。
  • 增加周边数据:例如摘要、时间、问题的附加信息等。

文本分割

因为文本长度通常非常长,可能回超过LLM所能承受的上限,所以要对文本进行分割。理想的情况是在不超过LLM输入长度上限的基础上,每个分割的块(trunking)内部是一致的,块之间是有差异的。这样的好处是可以尽量的提供给LLM有效信息,而不会分散其注意力。常用的分割方法有以下几种:

  • 根据长度分割。例如设定每个块512个token,然后分割的每个块保证不超过512个token。可以通过OpenAI的相关库来计算token。还有一种方法也是比较常用的,就是后一个块包含前一个块的部分内容。
  • 按照句子进行分割。这部分可以通过NLTK等库来做。
  • 基于段落分割,然后在基于行分割。在dify中就有类似的分割方式实现。例如线根据\n\n进行按段分割。如果超长度,再根据\n分割。
  • 自定义分割。自己可以根据数据类型进行分割。例如word、excel或者JSON这样的数据可能就会根据其自身需要进行分割。
  • 基于语义分割。这种方法的目的还是要保证块内部信息的一致性。我们可以简单的理解就是先对文本分成句子,然后根据前后句子的相关度来进行合并。具体方法有可以依据嵌入的方法(在langchain有实现)、基于模型的方法以及基于LLM的方法(实际就是让模型帮我们分段)。详细信息可以阅读:**本地AI知识库RAG(5):探索语义分块。**

Embedding(嵌入)

  • 尽可能使用动态嵌入。一开始看到这个词可能会比较蒙。实际非常好理解,他和静态嵌入的区别就在于是否可以捕获上下文信息,然后根据上下文信息使得每个词有不同的含义。例如:打飞机可能在不通的语境中含义是不一样的。bert就是动态嵌入,因为它引入了多头自注意力机制(self-attention)。Word2Vec就是静态嵌入。详细信息可以阅读:为什么说bert是动态embedding?
  • 微调嵌入。这个上手较高,主要是对垂类数据来说的。大多数模型都是基于通用语料库进行训练,为了让嵌入有更好的效果可以对垂类数据的训练。增加模型对垂类领域数据的理解。
  • 混合嵌入。对不同问题或者不同的知识库使用不同的嵌入模型。

查询优化

  • 利用LLM从不同的视角根据用户提出的问题生成多个问题。然后根据生成的问题进行查询。最后把所有的问题并集。理论上这对于解决复杂问题非常有用。

  • **HyDE&QueryDoc。**使用假设文档嵌入 (HyDE) 改进检索增强生成。参考下边的两张图:

1_sbBnisuzLw72-YpQMWhQDw1.webp 传统检索和HyDE的区别

1_vPX3TZXE5NQ0wHjrpI_muw2.webp

实现原理

我们来解释一下这张图。

1.  根据用户的问题使用类似于ChatGPT这样的模型进行寻找答案。
1.  根据ChatGPT生成的答案去嵌入。
1.  然后使用向量相似性去查询文档。注意原始问题不做查询。
1.  用检索到的结果来生成最终结果。

详细信息可以阅读:

[**Advanced RAG: Improving Retrieval-Augmented Generation with Hypothetical Document Embeddings (HyDE)**](https://www.pondhouse-data.com/blog/advanced-rag-hypothetical-document-embeddings/)

这总方法也并非总是有效,如果模型对知识了解较少则问题较大。
  • Back Prompting。后退提示法指导 LLM 首先从给定的细节中提取高级概念和原则,然后使用这些概念引导其推理得到正确的解决方案。这种提示法基于以下事实:“在关键决策中,人类发现抽象很有帮助,因为它提供了对环境的更广阔的视野”。例如:我想知道汉武帝某个时间段的成就,就可以想让模型给出汉武帝的所有经历,然后再给出答案。

    详细内容可以阅读:Step Back Prompting

sb-prompt3.png

检索

检索的目的是确保最终的答案出现在候选列表中。

  • 句子窗口搜索。这个本质不是一种检索优化。核心原理是就是检索到相应结果后,把周边数据一并提交给LLM,增加LLM对问答案的理解。
  • 使用Agent。这个方法就是使用Agent决定应该采用什么样的索引的方法。例如:根据问题选择不同的专注于不同领域的索引。
  • 混合检索。为了提高查询的**召回率,**可以采用向量索引和关键词检索的方法来组合RAG的检索功能。因为在RAG的搜索方法中大部分的场景的主要目的还是确保结果出现在候选列表中。

检索后处理

检索后处理比较典型的方法就是Rerank。核心思想是利用专有模型对结果进行重新排序。这些模型会对结果进行更深入的相关度的理解然后重新排序。确保相关对最高的答案排在最前面,以便于LLM更好的输出答案。

生成

生成这部分重点要考虑的是体验。比较简单的方式就是根据检索后的结果进行润色、整理然后输出给用户,但也可能存在无法找到答案的场景,这时候就要引导用户进行多轮对话来进行问题以及上下文的理解。涉及到一下基本部分。

  • 如果问题不够清晰,进行多轮用户对话引导,对问题进行追问或者采用其它策略结束会话。
  • 建立科学的用户反馈录入机制。根据用户反馈的答案进行知识库更新。

参考文档