首页 > 其他分享 >《Advanced RAG》-10-Corrective Retrieval Augmented Generation (CRAG)

《Advanced RAG》-10-Corrective Retrieval Augmented Generation (CRAG)

时间:2024-08-09 19:54:30浏览次数:19  
标签:检索 RAG Corrective 10 index CRAG 文档 llama query

摘要

CRAG 设计了一个轻量级检索评估器,用于评估针对特定查询检索到的文档的整体质量,并使用网络搜索作为改进检索结果的辅助工具。CRAG 可与基于 RAG 的各种方法无缝集成,并提供了一个插件式的解决方案。

CRAG 的主要思想是引入一个检索评估器,用于评估检索文档与查询之间的关系,并根据评估结果分为三种情况:正确、不正确和模棱两可。

  • 对于正确的情况,使用知识细化算法重写检索文档;
  • 对于不正确的情况,使用网络搜索引擎检索外部知识;
  • 对于模棱两可的情况,使用知识细化算法和搜索引擎进行处理。

文章要点

  1. CRAG 是一种改进传统 RAG 方法的技术,可以避免引入不相关信息,提高模型获取准确知识的能力。
  2. CRAG 设计了一个轻量级检索评估器,用于评估检索文档的质量,并使用网络搜索作为辅助工具。
  3. CRAG 可与基于 RAG 的各种方法无缝集成,并提供了一个插件式的解决方案。
  4. CRAG 的主要思想是引入一个检索评估器,用于评估检索文档与查询之间的关系,并根据评估结果分为三种情况:正确、不正确和模棱两可。
  5. CRAG 的代码已开源,并提供了 Langchain 和 LlamaIndex 的实现。

本文从一个常见的场景开始:参加开卷考试。

通常,我们有三种策略:

  • 方法 1:快速回答熟悉的题目。对于不熟悉的题目,可参考参考书。快速找到相关章节,在头脑中进行整理和归纳,然后将答案写在试卷上。
  • 方法 2:针对每个题目,参考书目。找出相关章节,在脑海中进行总结,然后将答案写在试卷上。
  • 方法 3:针对每个主题,查阅本书并确定相关章节。在形成观点之前,将收集到的信息分为三类:正确、不正确和模糊。分别处理每一类信息。然后,根据这些处理过的信息,在头脑中进行梳理和总结。在试卷上写下你的答案。

方法 1 涉及Self-RAG,而方法 2 则是传统的 RAG 流程。

最后,本文将介绍方法 3,即修正检索增强生成(CRAG)。

CRAG 的动机

在这里插入图片描述

图 1 显示,大多数传统的 RAG 方法并不考虑文档与问题的相关性,而只是简单地合并检索到的文档。这可能会引入不相关的信息,从而阻碍模型获取准确的知识,并可能误导模型,导致幻觉问题。

此外,大多数传统的 RAG 方法将整个检索文档作为输入。然而,在这些检索文档中,有很大一部分文本往往不是生成所必需的,也不应该同样参与到 RAG 中。

CRAG 的主要理念

CRAG 设计了一个轻量级检索评估器,用于评估针对特定查询检索到的文档的整体质量。它还将网络搜索作为改进检索结果的辅助工具。

CRAG 即插即用,可与基于 RAG 的各种方法无缝集成。整体架构如图 2 所示。

在这里插入图片描述

如图 2 所示,CRAG 通过引入检索评估器来评估检索文档与查询之间的关系,从而增强了传统的 RAG。

有 3 种可能的判断结果。

  1. 如果它是正确的,这意味着检索到的文档包含查询所需的必要内容,然后采用知识细化算法重写检索到的文档
  2. 如果检索到的文档不正确,这就意味着查询和检索到的文档不相关。因此,我们不能将文档发送给 LLM。在 CRAG 中,我们使用网络搜索引擎来检索外部知识。
  3. 对于模棱两可的情况,这意味着检索到的文件可能很接近,但不足以提供答案。在这种情况下,就需要通过网络搜索来获取更多信息。因此,需要同时使用知识提炼算法和搜索引擎。

最后,经过处理的信息被转发到 LLM,以生成响应。图 3 正式描述了这一过程。

在这里插入图片描述

请注意,网络搜索并不直接使用用户的输入查询进行搜索。相反,它会构建一个提示,并以少量样本的方式呈现给GPT-3.5 Turbo,以获取搜索的查询。

在对该方法有了总体了解之后,让我们逐一讨论 CRAG 的两个关键组成部分:检索评价器和知识完善算法。

检索评估(Retrieval Evaluator)

如图 4 所示,检索评价器对后续程序的结果有重大影响,是决定整个系统性能的关键。

在这里插入图片描述

CRAG 采用轻量级的 T5-large 模型作为检索评估器,并对其进行微调。值得注意的是,在大型语言模型时代,T5-large 也被认为是轻量级的。

对于每个查询,通常会检索到十个文档。然后,将查询与每个文档单独连接起来,作为预测文档相关性的输入。在微调过程中,为正样本赋予 1 的标签,为负样本赋予 -1 的标签。在推理过程中,评价器会给每个文档分配一个相关性分数,范围从 -1 到 1 不等。

这些分数将根据阈值分为三个等级。显然,这种分类需要两个阈值。在 CRAG 中,阈值的设置可能会根据实验数据的不同而有所变化:

触发三项行动之一的两个置信度阈值是根据经验设定的。具体来说,

  • 在 PopQA 中,它们被设定为(0.59, -0.99);
  • 在 PubQA 和 ArcChallenge 中,它们被设定为(0.5, -0.91);
  • 在 Biography 中,它们被设定为(0.95, -0.91)。

知识提炼算法

对于检索到的相关文档,CRAG 设计了一种分解–再分解的知识提取方法,以进一步提取最关键的知识语句,如图 4 所示。

首先,采用启发式规则将每篇文档分解成细粒度的知识条,以获得细粒度的结果。如果检索到的文档仅由一两个句子组成,则将其视为一个独立单元。否则,文档会被分割成更小的单元,通常由几个句子组成,具体取决于总长度。每个单元都应包含一条独立的信息。

接下来,检索评价器会计算每个知识条的相关性得分。相关性得分低的知识条带会被过滤掉。然后将剩余的相关知识条重新组合,形成内部知识。

代码解释

CRAG 是开源的,Langchain 和 LlamaIndex 都提供了自己的实现。我们将以 LlamaIndex 的实现 作为解释的参考。

环境配置

(base) Florian:~ Florian$ conda create -n crag python=3.11
(base) Florian:~ Florian$ conda activate crag
(crag) Florian:~ Florian$ pip install llama-index llama-index-tools-tavily-research
(crag) Florian:~ Florian$ mkdir "YOUR_DOWNLOAD_DIR"

安装完成后,LlamaIndex 和 Tavily 的相应版本如下:

(crag) Florian:~ Florian$ pip list | grep llama
llama-index                             0.10.29
llama-index-agent-openai                0.2.2
llama-index-cli                         0.1.11
llama-index-core                        0.10.29
llama-index-embeddings-openai           0.1.7
llama-index-indices-managed-llama-cloud 0.1.5
llama-index-legacy                      0.9.48
llama-index-llms-openai                 0.1.15
llama-index-multi-modal-llms-openai     0.1.5
llama-index-packs-corrective-rag        0.1.1
llama-index-program-openai              0.1.5
llama-index-question-gen-openai         0.1.3
llama-index-readers-file                0.1.19
llama-index-readers-llama-parse         0.1.4
llama-index-tools-tavily-research       0.1.3
llama-parse                             0.4.1
llamaindex-py-client                    0.1.18

(crag) Florian:~ Florian$ pip list | grep tavily
llama-index-tools-tavily-research       0.1.3

测试代码

测试代码如下。第一次执行需要下载 CorrectiveRAGPack。

import os
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"

from llama_index.core import Document


# Option: Download CorrectiveRAGPack
# The first execution requires the download of CorrectiveRAGPack
# Subsequent executions can comment this out.
from llama_index.core.llama_pack import download_llama_pack
CorrectiveRAGPack = download_llama_pack(
    "CorrectiveRAGPack", "YOUR_DOWNLOAD_DIR"
)


# Create testing documents
documents = [
    Document(
        text="A group of penguins, known as a 'waddle' on land, shuffled across the Antarctic ice, their tuxedo-like plumage standing out against the snow."
    ),
    Document(
        text="Emperor penguins, the tallest of all penguin species, can dive deeper than any other bird, reaching depths of over 500 meters."
    ),
    Document(
        text="Penguins' black and white coloring is a form of camouflage called countershading; from above, their black back blends with the ocean depths, and from below, their white belly matches the bright surface."
    ),
    Document(
        text="Despite their upright stance, penguins are birds that cannot fly; their wings have evolved into flippers, making them expert swimmers."
    ),
    Document(
        text="The fastest species, the Gentoo penguin, can swim up to 36 kilometers per hour, using their flippers and streamlined bodies to slice through the water."
    ),
    Document(
        text="Penguins are social birds; many species form large colonies for breeding, which can number in the tens of thousands."
    ),
    Document(
        text="Intriguingly, penguins have excellent hearing and rely on distinct calls to identify their mates and chicks amidst the noisy colonies."
    ),
    Document(
        text="The smallest penguin species, the Little Blue Penguin, stands just about 40 cm tall and is found along the coastlines of southern Australia and New Zealand."
    ),
    Document(
        text="During the breeding season, male Emperor penguins endure the harsh Antarctic winter for months, fasting and incubating their eggs, while females hunt at sea."
    ),
    Document(
        text="Penguins consume a variety of seafood; their diet mainly consists of fish, squid, and krill, which they catch on their diving expeditions."
    ),
]


from llama_index.packs.corrective_rag import CorrectiveRAGPack
corrective_rag = CorrectiveRAGPack(documents, "YOUR_TAVILYAI_API_KEY")


# From here, you can use the pack, or inspect and modify the pack in ./corrective_rag_pack.
# The run() function contains around logic behind Corrective Retrieval Augmented Generation - CRAG paper.
query = "How tall is the smallest penguins?"
print('-' * 100)
print("The response of the query " + query + " is:")
response = corrective_rag.run(query, similarity_top_k=2)
print(response)

其中 YOUR_TAVILYAI_API_KEY 可通过tavilyai网站申请。

测试代码产生了以下结果(大部分调试信息已被删除):

(crag) Florian:~ Florian$ python /Users/Florian/Documents/crag.py
--------------------------------------------------------------------------------------
The response of the query How tall is the smallest penguins? is:
--------------------------------------------------------------------------------------
The smallest penguins are about 40 cm (16 inches) tall.

理解测试代码的关键在于 corrective_rag.run() 的实现,让我们深入了解一下。

类 CorrectiveRAGPack 的构造函数

首先,我们来看看构造函数,其源代码如下:

class CorrectiveRAGPack(BaseLlamaPack):
    def __init__(self, documents: List[Document], tavily_ai_apikey: str) -> None:
        """Init params."""
        llm = OpenAI(model="gpt-4")
        self.relevancy_pipeline = QueryPipeline(
            chain=[DEFAULT_RELEVANCY_PROMPT_TEMPLATE, llm]
        )
        self.transform_query_pipeline = QueryPipeline(
            chain=[DEFAULT_TRANSFORM_QUERY_TEMPLATE, llm]
        )

        self.llm = llm
        self.index = VectorStoreIndex.from_documents(documents)
        self.tavily_tool = TavilyToolSpec(api_key=tavily_ai_apikey)

请注意,默认设置为 gpt-4。如果没有权限使用 gpt-4,可以手动将其切换为 gpt-3.5-turbo。

类 CorrectiveRAGPack:: run()

函数 run() 的源代码如下:

class CorrectiveRAGPack(BaseLlamaPack):
    ...
    ...
    def run(self, query_str: str, **kwargs: Any) -> Any:
        """Run the pipeline."""
        # Retrieve nodes based on the input query string.
        retrieved_nodes = self.retrieve_nodes(query_str, **kwargs)

        # Evaluate the relevancy of each retrieved document in relation to the query string.
        relevancy_results = self.evaluate_relevancy(retrieved_nodes, query_str)
        # Extract texts from documents that are deemed relevant based on the evaluation.
        relevant_text = self.extract_relevant_texts(retrieved_nodes, relevancy_results)

        # Initialize search_text variable to handle cases where it might not get defined.
        search_text = ""

        # If any document is found irrelevant, transform the query string for better search results.
        if "no" in relevancy_results:
            transformed_query_str = self.transform_query_pipeline.run(
                query_str=query_str
            ).message.content
            # Conduct a search with the transformed query string and collect the results.
            search_text = self.search_with_transformed_query(transformed_query_str)

        # Compile the final result. If there's additional search text from the transformed query,
        # it's included; otherwise, only the relevant text from the initial retrieval is returned.
        if search_text:
            return self.get_result(relevant_text, search_text, query_str)
        else:
            return self.get_result(relevant_text, "", query_str)

上述代码与标准 CRAG 流程有三个主要区别:

  1. 无需判断或处理模棱两可的文件。
  2. 它不使用训练有素的 T5 大模型,而是利用 LLM 来评估检索到的信息。
  3. 跳过了知识提炼的过程。

尽管存在这些差异,但 LlamaIndex 提供了另一种思维方式(langchain 也是如此)。

使用 LLM 评估检索到的信息

代码如下

class CorrectiveRAGPack(BaseLlamaPack):
    ...
    ...
    def evaluate_relevancy(
        self, retrieved_nodes: List[Document], query_str: str
    ) -> List[str]:
        """Evaluate relevancy of retrieved documents with the query."""
        relevancy_results = []
        for node in retrieved_nodes:
            relevancy = self.relevancy_pipeline.run(
                context_str=node.text, query_str=query_str
            )
            relevancy_results.append(relevancy.message.content.lower().strip())
        return relevancy_results

调用 LLM 的提示如下所示:

DEFAULT_RELEVANCY_PROMPT_TEMPLATE = PromptTemplate(
    template="""As a grader, your task is to evaluate the relevance of a document retrieved in response to a user's question.

    Retrieved Document:
    -------------------
    {context_str}

    User Question:
    --------------
    {query_str}

    Evaluation Criteria:
    - Consider whether the document contains keywords or topics related to the user's question.
    - The evaluation should not be overly stringent; the primary objective is to identify and filter out clearly irrelevant retrievals.

    Decision:
    - Assign a binary score to indicate the document's relevance.
    - Use 'yes' if the document is relevant to the question, or 'no' if it is not.

    Please provide your binary score ('yes' or 'no') below to indicate the document's relevance to the user question."""
)

CRAG 论文显示,ChatGPT 在识别检索相关性方面的性能不如 T5-Large 高。

此外,在实际项目中,我们当然可以使用原始的知识提炼算法。你可以在这里找到相关代码。

重写搜索查询

如前所述,网络搜索并不直接使用用户的输入查询。取而代之的是,它构建了一个提示,并将其呈现给 GPT-3.5 Turbo,使用少量的方法来获取搜索查询。提示如下

DEFAULT_TRANSFORM_QUERY_TEMPLATE = PromptTemplate(
    template="""Your task is to refine a query to ensure it is highly effective for retrieving relevant search results. \n
    Analyze the given input to grasp the core semantic intent or meaning. \n
    Original Query:
    \n ------- \n
    {query_str}
    \n ------- \n
    Your goal is to rephrase or enhance this query to improve its search performance. Ensure the revised query is concise and directly aligned with the intended search objective. \n
    Respond with the optimized query only:"""
)

我对 CRAG 的见解和想法

CRAG 与 Self-RAG的区别

  1. 从流程的角度来看,self-RAG 可以使用 LLM 直接提供响应而无需检索,而 CRAG 则必须在添加评估层之前进行检索。
  2. 从结构上看,self-RAG 比 CRAG 更复杂,它需要更复杂的训练过程,并且在生成阶段需要生成和评估多个标签,这不可避免地增加了推理成本。因此,CRAG 比 selfRAG 更轻便。
  3. 从性能上看,如图 5 所示,在大多数情况下,CRAG 通常优于Self-RAG。

在这里插入图片描述

改进检索评估器

检索评估器可以看作是一个评分分类模型。该模型用于确定查询和文档的相关性,类似于 RAG 中的重新排序模型

这种相关性判断模型可以通过整合更多符合现实世界场景的特征来加以改进。例如,科学论文问题解答 RAG 包含许多专业术语,而旅游领域的 RAG 则往往包含更多口语化的用户查询。

通过在检索评估器的训练数据中添加场景特征,它可以更好地评估检索文档的相关性。如图 6 所示,还可以加入用户意图和编辑距离等其他特征:

在这里插入图片描述

此外,考虑到 T5-Large 所取得的成果,轻量级模型似乎也能取得良好的成果。这为 CRAG 在小规模团队或公司中的应用带来了希望。

检索评价器的分数和阈值

如前所述,不同类型数据的阈值是不同的。此外,我们还可以发现,模棱两可和不正确的阈值基本上都在-0.9 左右,这表明大部分检索到的知识都与查询相关。完全摒弃这些检索到的知识而完全依赖网络搜索可能并不可取。

在实际应用中,我们需要根据实际问题和需求进行调整。

结论

本文从一个直观的例子入手,概述了 CRAG 的基本流程,并辅以代码解释。其中还包括我的见解和想法。

总之,CRAG 作为一个即插即用的插件,可以显著提高 RAG 的性能。它为改进 RAG 提供了一个轻量级解决方案。

本文为翻译,原文地址:https://ai.gopubby.com/advanced-rag-10-corrective-retrieval-augmented-generation-crag-3f5a140796f9

标签:检索,RAG,Corrective,10,index,CRAG,文档,llama,query
From: https://blog.csdn.net/JingYu_365/article/details/140938598

相关文章

  • 《Advanced RAG》-04-深度研究RAG技术Re-ranking
    摘要文章首先介绍了重新排序在RAG中的重要性,它允许对检索到的文档进行重新排序和过滤,以确保最相关的文档能够被优先考虑,从而提高RAG的效率和准确性。接着,文章详细描述了两种主流的重新排序方法:一种是使用重新排序模型,如bge-reranker-base和bge-reranker-large等,这些模型......
  • 代码随想录Day10
    232.用栈实现队列请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):实现MyQueue类:voidpush(intx)将元素x推到队列的末尾intpop()从队列的开头移除并返回元素intpeek()返回队列开头的元素booleanempty()如果队列为......
  • 如何在 Windows 10 环境下安装和配置 MySQL:初学者指南
    如何在Windows10环境下安装和配置MySQL:初学者指南MySQL是一个流行的开源数据库管理系统,广泛应用于各种应用程序中。对于初学者来说,了解如何在Windows10环境下安装和配置MySQL是一个重要的第一步。本篇博客将详细介绍如何完成这些步骤,确保你能顺利地启动和使用MySQL......
  • 总有坏人想爬我网站的数据,看我用这 10 招干他!
    大家好,我是程序员鱼皮。前两天模拟面试一位社招两年的老哥,由于他的表现不错,我就临时起意,跟他交流一下我们最近遇到的业务场景问题。问题如下:最近我们不是做了个程序员刷题网站-面试鸭嘛,有很多坏人盯上了我们网站,想把我们4,000多道面试题、100多个面试题库的数据都......
  • 本地化部署GraphRAG+Ollama,实现基于知识图谱的智能问答
    citingfromhttps://medium.com/@vamshirvk/unlocking-cost-effective-local-model-inference-with-graphrag-and-ollama-d9812cc60466之前写过一篇使用deepseek和智谱AI实现《红楼梦》中人物关系智能问答的随笔但deepseek提供的免费tokens只有500万个,GraphRAG构建图谱的索引和......
  • 给定一个10GB大小的文件,存储的都是数字,如何对文件中的数字进行排序,并输出新文件?限制内
    背景这是一道面试题,可考察的点也不少。总结几个关键词去解决这个问题,1,文件拆分;2、排序算法;3、缓冲buffer性能优化。啊,乍一看,这绝对不是一个初级程序员能够答出来,且能答得很好的问题,这个题目可以考察到我们的算法能力,性能优化经验。可万万不能马虎对待!开始讲思路。第一步,文件拆......
  • 泛微E-office 10 schema_mysql接口敏感信息泄露漏洞复现 [附POC]
    文章目录泛微E-office10schema_mysql接口敏感信息泄露漏洞复现[附POC]0x01前言0x02漏洞描述0x03影响版本0x04漏洞环境0x05漏洞复现1.访问漏洞环境2.构造POC3.复现泛微E-office10schema_mysql接口敏感信息泄露漏洞复现[附POC]0x01前言......
  • 创新的HR管理工具:大型企业的10款新选择
    本篇文章介绍了以下几个工具:Moka、北森iTalentX、宏景HJSOFT、红海eHR、Bullhorn、智思云、金蝶K/3Cloud、Lever、BreezyHR、KAYANG嘉扬。在寻找适合大型企业的人力资源管理系统时,许多HR管理者都面临着如何在众多选项中做出最佳选择的难题,这不仅关系到企业的运营效率,还直接影......
  • coca saw vs seen 时态搭配对比 1000句
    基于https://www.cnblogs.com/hhdom/p/18351105seen@@the:@@442@@have:@@281@@i:@@270@@in:@@219@@a:@@207ive:205@@and:@@183@@of:@@181@@you:@@170@@#:@@136@@as:@@127@@that:@@127@@to:@@123@@is:@@113@@it:@@112@@be:@@111@@never:@@109@@this:@@107@@&......
  • AP5101C 6-100V 2A LED降压恒流型的线性调光驱动器 台灯手电筒与汽车灯方案
    产品描述AP5101C是一款高压线性LED恒流芯片,外围简单、内置功率管,适用于6-100V输入的高精度降压LED恒流驱动芯片。最大电流2.0A。AP5101C可实现内置MOS做2.0A,外置MOS可做3.0A的。AP5101C内置温度保护功能,温度保护点为130度,温度达到130度时,输出电流慢慢减小,达到保护芯片电路......