RAG 是 Retrieval-Augmented Generation 的缩写,即检索增强生成。这是一种自然语言处理技术,结合了检索式模型和生成式模型的优点,目的是提高生成文本的质量、一致性和信息丰富度。在RAG模型中,系统首先根据输入查询从大量的文档或知识库中检索相关信息,然后利用这些检索到的信息来辅助生成更准确、上下文相关的输出文本。这种方法特别适用于需要精确信息和长文本生成的任务,如问答系统、对话系统和文本摘要等。
一个令人满意的LLM输出完全取决于检索器和生成器的质量,因此RAG评估专注于RAG管道中的检索器和生成器的评估。这还可以使调试更加容易,并能够在组件级别定位问题。
RAG中的常见误区
RAG 管道包括检索和生成两个步骤,这些步骤会受到你选择的超参数的影响。超参数包括用于检索的嵌入模型、检索的节点数(从现在起,我们将它简称为“top-K”)、LLM 温度、提示模板等。
检索器负责检索步骤,而生成器负责生成步骤。检索器检索的上下文(即一组文本片段),而生成器生成的是LLM(大型语言模型)的输出。
检索
检索步骤通常包括:
将初始输入转换为嵌入向量,使用选择的嵌入模型(例如OpenAI的 text-embedding-3-large 模型)。
使用之前嵌入的输入对包含矢量化知识库的向量存储进行向量搜索,以检索存储中与之“最相似”的前K个矢量化文本片段。
对检索到的节点进行重新排序。矢量搜索提供的初始排序可能并不总是与特定用例的具体相关性完全匹配。
提示
所谓的“向量存储”可以是专门的向量数据库(例如Pinecone),也可以是现有数据库(例如PostgreSQL)的向量扩展(例如pgvector)。在
如你所见,需要调整的超参数有很多,比如选择嵌入模型、K值等。在检索步骤中,RAG评估旨在解决以下问题:
你使用的嵌入模型是否捕捉到了特定领域的细微差别?(如果正在处理医疗用例,OpenAI提供的通用嵌入模型可能无法提供预期的向量搜索结果。)
你的重排序模型是否能按照“正确的”顺序对检索到的节点进行排序?
你正在获取正确的信息量吗?这受到超参数“文本分块大小”和“前K个”的影响。
我们将在展示如何评估RAG之前,探讨RAG管道生成步骤中需要考虑的其他超参数。
生成
检索步骤之后通常是生成步骤,该步骤主要包括:
基于上一次的向量检索上下文构建提示。
将此提示提供给的LLM。这将产生最终的增强输出。
归因评估在生成步骤中通常更加简单,这是因为LLMs的标准化。同样,RAG评估可以在生成步骤中回答以下问题:
你能使用更小、更快、更便宜的LLM吗?这通常需要探索一些开源替代品,比如LLaMA-2、Mistral 7B,并对它们进行微调以适应你的需求。
温度升高是否会带来更好的效果呢?
改变提示模板如何影响输出质量?这是大多数LLM从业者花费大量时间的地方。
通常情况下,你通常会从像 gpt-4-turbo 和 claude-3-opus 这样的最先进的模型开始,然后尽可能地切换到较小的甚至经过微调的模型。正是这些不同的提示模板版本让LLM从业者失去了控制。
检索评估
提供了三种LLM(大型语言模型)评估指标来评估检索结果:
ContextualPrecisionMetric :评估的检索器中的重排序器是否能够将检索上下文中更相关的节点比不相关的节点排名更高。
ContextualRecallMetric :评估所使用的检索器中的嵌入模型是否能够根据输入的上下文准确地捕获和检索相关信息。
ContextualRelevancyMetric :评估的检索器是否能够在不包含太多无关信息的情况下检索到所需信息,包括文本块大小和前K值。
注意
巧合的是,这三种度量标准恰好涵盖了所有可能影响检索上下文质量的主要超参数。应该尝试同时使用这三种度量标准,以获得全面的评估结果。
这些三个指标的组合是必需的,因为你希望确保检索器能够正确地检索到适量的信息,并且按照正确的顺序进行检索。在检索步骤中的RAG评估可以确保你向生成器提供的是干净的数据。
在《 deepeval 》中,你可以通过以下三个指标轻松评估你的检索器:
from deepeval.metrics import (
ContextualPrecisionMetric,
ContextualRecallMetric,
ContextualRelevancyMetric
)
contextual_precision = ContextualPrecisionMetric()
contextual_recall = ContextualRecallMetric()
contextual_relevancy = ContextualRelevancyMetric()
TIPS
在 deepeval 中,可以设置通过的阈值、打开开关以及使用任何LLM进行评估。可以在每个指标的单独文档页面上详细了解每个指标,包括计算它们的算法:
ContextualPrecisionMetric
ContextualRecallMetric
ContextualRelevancyMetric
然后,定义一个测试用例。请注意, deepeval 可以让灵活地选择是使用完整的数据集开始评估,还是在评估时进行检索和生成。
from deepeval.test_case import LLMTestCase
...
test_case = LLMTestCase(
input="I'm on an F-1 visa, gow long can I stay in the US after graduation?",
actual_output="You can stay up to 30 days after completing your degree.",
expected_output="You can stay up to 60 days after completing your degree.",
retrieval_context=[
"""If you are in the U.S. on an F-1 visa, you are allowed to stay for 60 days after completing
your degree, unless you have applied for and been approved to participate in OPT."""
]
)
input 是用户输入, actual_output 是的 RAG 管道的最终生成结果, expected_output 是期望的理想 actual_output ,而 retrieval_context 是在检索步骤中检索到的文本片段。expected_output 是必需的,因为它为 retrieval_context 应该包含哪些信息提供了基准。
你不应该将整个提示模板作为输入,而应该只将原始用户输入作为输入。这是因为提示模板是我们试图优化的独立变量。请访问测试用例部分以了解更多信息。
最后,你可以通过单独使用每个指标来衡量你的检索器的表现:
...
contextual_precision.measure(test_case)
print("Score: ", contextual_precision.score)
print("Reason: ", contextual_precision.reason)
contextual_recall.measure(test_case)
print("Score: ", contextual_recall.score)
print("Reason: ", contextual_recall.reason)
contextual_relevancy.measure(test_case)
print("Score: ", contextual_relevancy.score)
print("Reason: ", contextual_relevancy.reason)
或者批量导入,如果有大量测试用例,这将非常有用:
from deepeval import evaluate
...
evaluate(
test_cases=[test_case],
metrics=[contextual_precision, contextual_recall, contextual_relevancy]
)
使用这些指标,可以轻松地查看对不同超参数所做的更改如何影响不同的指标得分。
生成评估
它提供了两种LLM(大型语言模型)评估指标来评估通用生成能力:
它会评估你的生成器中的提示模板是否能够指导你的LLM根据 retrieval_context 输出相关且有用的输出。
评估所使用的生成器中使用的LLM是否能够输出不产生幻觉且不与 retrieval_context 中提供的任何事实信息相矛盾的信息。
请注意
实际上,生成器的超参数不像检索器中的超参数那样明确。
(要根据自定义标准评估生成结果,应该使用“GEval”度量标准,它涵盖了所有自定义用例。)
与检索指标类似,将这些分数结合使用将最符合人们对于优秀LLM输出的期望。
首先,定义你的指标:
from deepeval.metrics import AnswerRelevancyMetric, FaithfulnessMetric
answer_relevancy = AnswerRelevancyMetric()
faithfulness = FaithfulnessMetric()
然后,创建一个测试用例(我们将在前面的章节中重用相同的测试用例):
from deepeval.test_case import LLMTestCase
..
test_case = LLMTestCase(
input="I'm on an F-1 visa, gow long can I stay in the US after graduation?",
actual_output="You can stay up to 30 days after completing your degree.",
expected_output="You can stay up to 60 days after completing your degree.",
retrieval_context=[
"""If you are in the U.S. on an F-1 visa, you are allowed to stay for 60 days after completing
your degree, unless you have applied for and been approved to participate in OPT."""
]
)
:
answer_relevancy.measure(test_case)
print("Score: ", answer_relevancy.score)
print("Reason: ", answer_relevancy.reason)
faithfulness.measure(test_case)
print("Score: ", faithfulness.score)
print("Reason: ", faithfulness.reason)
或者作为更大数据集的一部分:
from deepeval import evaluate
...
evaluate(
test_cases=[test_case],
metrics=[answer_relevancy, faithfulness]
)
你会注意到在示例测试用例中, actual_output 实际上与 retrieval_context 中的信息相矛盾。运行评估以查看 FaithfulnessMetric 的输出!
正如上面所提到的,这些RAG指标虽然有用,但非常通用。例如,如果我想让我基于RAG的聊天机器人使用黑色幽默回答问题,我该如何评估这一点呢?
这里你可以利用 deepeval 的 GEval 指标,它能够根据任何标准评估LLM的输出。
from deepeval.metrics import GEval
from deepeval.test_case import LLMTestCaseParams
...
dark_humor = GEval(
name="Dark Humor",
criteria="Determine how funny the dark humor in the actual output is",
evaluation_params=[LLMTestCaseParams.ACTUAL_OUTPUT],
)
dark_humor.measure(test_case)
print("Score: ", dark_humor.score)
print("Reason: ", dark_humor.reason)
可以访问“ GEval ”页面了解更多关于此指标的信息。
E2E RAG评估
你可以将检索和生成指标结合起来,对整个RAG管道进行端到端的评估。
evaluate(
test_cases=test_cases,
metrics=[
contextual_precision,
contextual_recall,
contextual_relevancy,
answer_relevancy,
faithfulness,
# Optionally include any custom metrics
dark_humor
]
)
在CI/CD中对RAG系统进行单元测试
使用 deepeval ,可以在CI环境中轻松地对RAG应用程序进行单元测试。在这里,我们将以GitHub Actions和GitHub Workflow为例进行说明。首先,创建一个测试文件:
test_rag.py
from deepeval import assert_test
from deepeval.test_case import LLMTestCase
from deepeval.metrics import AnswerRelevancyMetric
dataset = EvaluationDataset(test_cases=[...])
"test_case",
dataset,
)
def test_rag(test_case: LLMTestCase):
# metrics is the list of RAG metrics as shown in previous sections
assert_test(test_case, metrics)
然后,在命令行中直接执行 ` deepeval test run `:
deepeval test run test_rag.py
请注意
你可以在这里了解所有有关 deepeval test run 的内容(包括并行化、缓存、错误处理等)。
一旦你将所有指标都添加完毕,请将其包含在你的GitHub工作流文件中:
`.github/workflows/rag-testing.yml` .
name: RAG Testing
on:
push:
pull:
jobs:
test:
ubuntu-latest :
steps:
# Some extra steps to setup and install dependencies,
name: Run deepeval tests
run: poetry run deepeval test run test_rag.py
大功告成!现在已经成功地在CI/CD中设置了一个自动化单元测试RAG应用程序的工作流程。
对于那些感兴趣的人,这里还有一篇关于在持续集成/持续交付(CI/CD)中单元测试RAG应用程序的不错的文章。
优化超参数
在 deepeval 中,可以将文本分块大小、前K个、嵌入模型、LLM等超参数与每个测试运行相关联,当与“confident-ai”一起使用时,这将使能够轻松地查看更改不同的超参数如何导致不同的评估结果。
自信AI是一个基于Web的LLM评估平台,所有使用 deepeval 的用户都可以自动访问该平台。要开始使用,请通过CLI登录:
deepeval login
按照说明创建一个账户,将API密钥复制并粘贴到CLI中,然后在测试文件中添加以下几行代码,以便在每次运行测试时记录超参数:
test_rag.py
import deepeval
...
@deepeval.log_hyperparameters(model="gpt-4", prompt_template="...")
def custom_parameters():
return {
"embedding model": "text-embedding-3-large",
"chunk size": 1000,
"k": 5,
"temperature": 0
}