前言

本文将详细介绍RAG技术的基础流程及其多种改进方法,探讨如何通过这些改进方法进一步提升RAG的性能,为实际应用提供更高效、可靠的解决方案。

基础RAG

小白学RAG:17种改进生成的落地方法_RAG

  • 文档预处理:加载PDF并将其文本分割成块。
  • 文本清理:应用自定义函数replace_t_with_space来清理文本块,可能解决了PDF中的特定格式问题。
  • 向量存储创建:使用OpenAI嵌入向量创建文本块的向量表示,并从这些嵌入向量创建FAISS向量存储。
  • 检索器设置:配置检索器以获取给定查询的最相关的2个块。
def encode_pdf(path, chunk_size=1000, chunk_overlap=200):

    # Load PDF documents
    loader = PyPDFLoader(path)
    documents = loader.load()

    # Split documents into chunks
    text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=chunk_size, chunk_overlap=chunk_overlap, length_function=len
    )
    texts = text_splitter.split_documents(documents)
    cleaned_texts = replace_t_with_space(texts)

    # Create embeddings (Tested with OpenAI and Amazon Bedrock)
    embeddings = get_langchain_embedding_provider(EmbeddingProvider.OPENAI)
    #embeddings = get_langchain_embedding_provider(EmbeddingProvider.AMAZON_BEDROCK)

    # Create vector store
    vectorstore = FAISS.from_documents(cleaned_texts, embeddings)

    return vectorstore

改进方法:重排(Reranking)

小白学RAG:17种改进生成的落地方法_人工智能_02

重排的主要动机是克服初始检索方法的局限性,这些方法通常依赖于简单的相似性度量。重排允许进行更复杂的相关性评估,能够捕捉到传统检索技术可能遗漏的查询和文档之间的细微关系。

  1. 初始检索:检索一组可能相关的文档。
  2. 配对创建:为每个检索到的文档创建查询-文档对。
  3. 重排序评分:
  • LLM方法:使用提示让LLM对文档相关性进行评分。
  • 交叉编码器方法:将查询-文档对直接输入模型。
  1. 分数解释:解析和标准化相关性分数。
  2. 重新排序:根据新的相关性分数对文档进行排序。
  3. 选择:从重新排序的列表中选择前K个文档。

改进方法:多路召回合并

小白学RAG:17种改进生成的落地方法_人工智能_03

传统的检索方法通常依赖于语义理解(基于向量)或关键词匹配(BM25)。每种方法都有其优势和劣势。融合检索旨在将这些方法结合起来,创建一个更强大、更准确的检索系统,能够有效处理更广泛的查询。

  • PDF处理和文本分块:将PDF文档分割成可管理的块,以便进行分析。
  • 向量存储创建:使用FAISS和OpenAI嵌入为文本块创建向量表示。
  • BM25索引创建:从用于向量存储的相同文本块创建BM25索引。
  • 自定义融合检索函数:结合两种方法的检索功能。

改进方法:语义分块

小白学RAG:17种改进生成的落地方法_人工智能_04

传统文本分割方法通常在任意点分割文档,可能会破坏信息和上下文的连贯性。语义分块通过尝试在更自然的断点处分割文本,解决了这一问题,从而在每个块内保持语义连贯性。

  • 文档预处理:读取PDF并将其转换为字符串。
  • 语义分块 :利用LangChain的SemanticChunker和OpenAI嵌入向量。提供了三种断点类型:
  • ‘percentile’:在大于X百分位数的差异处分割。
  • ‘standard_deviation’:在大于X标准差的差异处分割。
  • ‘interquartile’:使用四分位数距离来确定分割点。在此实现中,使用了’percentile’方法,阈值为90。
  • 向量存储创建:使用OpenAI嵌入向量创建语义块的向量表示,并从这些嵌入向量创建FAISS向量存储。
  • 检索器设置:配置检索器以获取给定查询的最相关的2个块。
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai.embeddings import OpenAIEmbeddings

改进方法:命题分块

小白学RAG:17种改进生成的落地方法_RAG_05

命题分块的方法将输入文本分解为原子的、事实性的、自包含的且简洁的命题,并将这些命题编码到向量存储中,以便后续检索使用。

命题分块方法的动机是构建一个系统,将文本文档分解为简洁的事实性命题,以便进行更细致和精确的信息检索。使用命题可以更好地处理特定查询,尤其是在从详细或复杂的文本中提取知识时。

  • 文档分块:使用RecursiveCharacterTextSplitter将输入文档分割成较小的块,以便LLM处理。
  • 命题生成:使用LLM(例如"llama-3.1-70b-versatile")从每个块中生成命题。输出为一系列事实性、自包含的陈述,无需额外上下文即可理解。
  • 质量检查:使用第二个LLM根据准确性、清晰性、完整性和简洁性对命题进行评分。满足所有类别所需阈值的命题将被保留。
  • 嵌入命题:通过OllamaEmbeddings模型将通过质量检查的命题嵌入到向量存储中,以便在查询时进行基于相似性的检索。
  • 检索和比较:构建两个检索系统:一个使用基于命题的块,另一个使用较大的文档块。两者都通过多个查询进行测试,以比较它们的性能和返回结果的精确度。

改进方法:改写提问

小白学RAG:17种改进生成的落地方法_agi_06

RAG系统在检索最相关信息时常常面临挑战,尤其是在处理复杂或模糊的查询时。这些查询转换技术通过重新制定查询来更好地匹配相关文档或检索更全面的信息,从而解决了这一问题。

  • 查询重写:目的是使查询更具体和详细,从而提高检索相关信息的可能性。实现上使用GPT-4模型和自定义提示模板,将原始查询重新制定得更具体和详细。
  • 退步提示:目的是生成更广泛、更一般的查询,以便检索相关的背景信息。实现上使用GPT-4模型和自定义提示模板,将原始查询生成为更一般的“退步”查询。
  • 子查询分解:目的是将复杂查询分解为更简单的子查询,以便更全面地检索信息。实现上使用GPT-4模型和自定义提示模板,将原始查询分解为2-4个更简单的子查询。

改进方法:提问增强

生成相关问题通过为每个文本片段生成各种相关问题,并将这些问题纳入向量数据库中,从而增强了标准的检索过程,提高了找到可作为生成式问答上下文的相关文档的可能性。

  • PDF处理和文本分块:处理PDF文档并将其分割成可管理的文本片段。
  • 问题增强:使用OpenAI的语言模型在文档和片段级别生成相关问题。
  • 向量存储创建:使用OpenAI的嵌入模型计算文档嵌入,并创建FAISS向量存储。
  • 检索和答案生成:使用FAISS找到最相关的文档,并基于提供的上下文生成答案。

改进方法:RAPTOR

RAPTOR(Recursive Abstractive Processing and Thematic Organization for Retrieval)结合了层次化文档摘要、基于嵌入的检索和上下文答案生成。RAPTOR旨在通过创建摘要的多层次树结构,高效地处理大型文档集合,从而实现从宽泛到详细的信息检索。

小白学RAG:17种改进生成的落地方法_agi_07

  • 树构建:从原始文档开始,逐层嵌入文本,使用高斯混合模型等聚类算法对嵌入进行聚类,并为每个聚类生成摘要,直到达到单个摘要或最大层数。
  • 嵌入和检索:将所有文档和摘要的嵌入存储在向量存储中(如FAISS),以便进行高效的相似性搜索。对于给定查询,嵌入查询并检索最相似的文档/摘要。
  • 上下文压缩:使用语言模型从检索到的文档/摘要中提取与给定查询最相关的部分。
  • 答案生成:将相关部分组合成上下文,并使用语言模型基于此上下文和原始查询生成答案。

改进方法:层次索引

传统的平面索引方法在处理大型文档或文档集时可能会遇到困难,可能会遗漏上下文或返回无关信息。文档检索的层次索引系统通过创建一个两级搜索系统来解决这个问题,使得检索更加高效且具有上下文感知能力。

小白学RAG:17种改进生成的落地方法_ai_08

  • 加载PDF并将其分割为文档(可能按页)。
  • 使用GPT-4异步生成每个文档的摘要。
  • 将原始文档分割为较小的详细块。
  • 创建两个独立的向量存储:一个用于文档级摘要,另一个用于详细块。

改进方法:HyDE

假设文档嵌入(Hypothetical Document Embedding,简称HyDE)将查询问题转换为包含答案的假设文档,旨在弥合查询和文档在向量空间中的分布差距。

小白学RAG:17种改进生成的落地方法_人工智能_09

  • 文档预处理和向量存储创建:将PDF处理并分割成块,并使用OpenAI嵌入创建FAISS向量存储。
  • 假设文档生成:使用语言模型(GPT-4)生成一个假设文档,该文档回答给定的查询。生成过程由一个提示模板引导,确保假设文档详细且与向量存储中使用的块大小匹配。

改进方法:Self-RAG

Self-RAG动态决定是否使用检索到的信息以及如何在生成响应时最好地利用这些信息,旨在产生更准确、相关且有用的输出。

小白学RAG:17种改进生成的落地方法_语言模型_10

  • 检索决策:算法首先决定是否需要对给定查询进行检索。这一步可以防止对可以直接回答的查询进行不必要的检索。
  • 文档检索:如果认为需要检索,则算法从向量存储中获取最相似的前k个文档。
  • 相关性评估:对每个检索到的文档评估其与查询的相关性。这一步可以过滤掉不相关的信息,确保只使用相关上下文进行生成。
  • 响应生成:算法使用相关上下文生成响应。如果没有找到相关上下文,则不进行检索而生成响应。
class RetrievalResponse(BaseModel):
    response: str = Field(..., title="Determines if retrieval is necessary", description="Output only 'Yes' or 'No'.")
retrieval_prompt = PromptTemplate(
    input_variables=["query"],
    template="Given the query '{query}', determine if retrieval is necessary. Output only 'Yes' or 'No'."
)

class SupportResponse(BaseModel):
    response: str = Field(..., title="Determines if response is supported", description="Output 'Fully supported', 'Partially supported', or 'No support'.")
support_prompt = PromptTemplate(
    input_variables=["response", "context"],
    template="Given the response '{response}' and the context '{context}', determine if the response is supported by the context. Output 'Fully supported', 'Partially supported', or 'No support'."
)

改进方法:Feedback Loop

传统的RAG系统有时会因检索过程或底层知识库的局限性而产生不一致或不相关的响应。通过实现反馈循环,可以持续提高检索文档的质量,增强生成响应的相关性,使系统随着时间的推移适应用户的偏好和需求。

小白学RAG:17种改进生成的落地方法_agi_11

  1. 查询处理:用户提交查询时,检索器检索相关文档,语言模型基于这些文档生成响应。
  2. 反馈收集:系统收集用户对响应相关性和质量的反馈,并将其存储在JSON文件中。
  3. 相关性评分调整:对于后续查询,系统加载之前的反馈,使用语言模型评估过去反馈与当前查询的相关性,并根据此评估调整文档的相关性评分。
  4. 检索器更新:使用调整后的文档评分更新检索器,确保未来的检索能够从过去的反馈中受益。
  5. 定期索引微调:定期对索引进行微调,使用高质量的反馈创建额外的文档,并将这些新文档更新到向量存储中,从而提高整体检索质量。

改进方法:Reliable RAG

Reliable-RAG方法的开发旨在解决传统RAG系统中常见的挑战,如检索不相关文档、生成的答案没有事实依据以及答案生成所用来源缺乏透明度。通过增加多层验证,该方法确保提供的答案既准确又可靠。

  • 文档相关性过滤:通过使用语言模型生成的二进制相关性分数,只有最相关的文档才会传递到答案生成阶段,减少噪声并提高最终答案的质量。
  • 幻觉检查:在最终确定答案之前,系统通过验证生成的内容是否完全由检索到的文档支持来检查幻觉。
  • 片段突出显示:此功能通过显示对最终答案有贡献的确切检索文档片段来增强透明度。

改进方法:相关片段提取(Relevant Segment Extraction)

相关片段提取用于从检索到的文本块中重建连续文本的多块片段。这一过程发生在向量搜索(可选地包括重排)之后,但在将检索到的上下文呈现给大型语言模型(LLM)之前。

  • 文档分块:可以使用标准的文档分块方法。这里唯一的特殊要求是文档分块时不能有重叠。这使我们可以通过连接块来重建文档的部分(即片段)。
  • RSE优化:在完成标准的块检索过程后(理想情况下包括重排步骤),可以开始RSE过程。
  • 第一步是结合绝对相关性值(即相似性分数)和相关性排名。这比单独使用相似性分数或排名提供了更稳健的起点。
  • 然后我们从每个块的值中减去一个常数阈值(比如说0.2),使得不相关块的值为负数(低至-0.2),而相关块的值为正数(高达0.8)。

改进方法:Corrective RAG

Corrective RAG扩展了标准的RAG方法,通过动态评估和纠正检索过程,结合向量数据库、网络搜索和语言模型的力量,为用户提供准确且具有上下文意识的响应。

小白学RAG:17种改进生成的落地方法_RAG_12

  • 文档检索:在FAISS索引中执行相似性搜索以找到相关文档,并检索前k个文档(默认k=3)。
  • 文档评估:为每个检索到的文档计算相关性分数,并根据最高相关性分数确定最佳行动方案。
  • 纠正性知识获取
  • 如果相关性高(分数>0.7):直接使用最相关的文档。
  • 如果相关性低(分数<0.3):通过执行网络搜索并重写查询来进行纠正。
  • 如果不明确(0.3≤分数≤0.7):通过结合最相关的文档和网络搜索结果进行纠正。
  • 自适应知识处理:对于网络搜索结果,精炼知识以提取关键点;对于不明确的情况,结合原始文档内容和精炼的网络搜索结果。
  • 响应生成:使用语言模型基于查询和获取的知识生成类似人类的响应,并在响应中包含来源信息以提高透明度。

改进方法:Contextual Chunk Headers

上下文块头(Contextual Chunk Headers,简称CCH)通过创建包含更高层次上下文(如文档级或节级上下文)的块头,并在嵌入之前将这些块头添加到块的前面。这使得嵌入能够更准确和完整地表示文本的内容和含义。在测试中,该功能显著提高了检索质量。除了提高正确信息检索的速率外,CCH还降低了搜索结果中不相关结果出现的速率。

通过在块头前面添加更高层次的上下文来增强块。这个块头可以简单到只是文档标题,也可以使用文档标题、简洁的文档摘要以及节和子节标题的完整层次结构的组合。

改进方法:Adaptive RAG

自适应的检索增强生成根据查询类型调整其检索策略。通过在各个阶段利用语言模型(LLMs),它旨在为用户提供更准确、相关且具有上下文意识的响应。

小白学RAG:17种改进生成的落地方法_ai_13

  • 事实策略:使用LLM增强原始查询以提高精确度,基于增强的查询检索文档,并使用LLM按相关性对文档进行排名。
  • 分析策略:使用LLM生成多个子查询以涵盖主查询的不同方面,为每个子查询检索文档,并使用LLM确保最终文档选择的多样性。
  • 观点策略:使用LLM识别主题的不同观点,检索代表每个观点的文档,并使用LLM从检索到的文档中选择多样化的观点。
  • 上下文策略:使用LLM将用户特定的上下文纳入查询,基于上下文化查询进行检索,并在考虑相关性和用户上下文的情况下对文档进行排名。

改进方法:GraphRAG

GraphRAG能够提供对复杂语义概念的全面理解,使其成为需要快速准确查找信息的任何人的宝贵工具。

小白学RAG:17种改进生成的落地方法_ai_14

与标准RAG模型不同,GraphRAG擅长识别不同信息片段之间的联系并从中提取见解。这使其成为需要从大型数据集或难以总结的文档中提取见解的用户的理想选择。

- 索引阶段
  - **文本分块**:将源文本分割成可管理的块。
  - **元素提取**:使用LLMs识别实体和关系。
  - **图构建**:从提取的元素构建图。
  - **社区检测**:应用Leiden等算法查找社区。
  - **社区摘要**:为每个社区创建摘要。
- 查询阶段
  - **本地答案生成**:使用社区摘要生成初步答案。
  - **全局答案综合**:结合本地答案形成全面响应。