如何使用 RAGAs 框架评估您的 RAG

如何使用 RAGAs 框架评估您的 RAG

Barry Lv6

LLM 双胞胎课程:构建生产就绪的AI复制品

如何使用RAGAs框架评估你的RAG

学习使用 RAGAs 框架,遵循行业最佳实践评估您的 RAG 模型。了解检索与生成特定指标,以及利用 CometML LLM 进行高级 RAG 链监控。

LLM Twin 免费课程的第 10 课,共 11 课

什么是你的 LLM Twin? 它是一个 AI 角色,通过融入你的风格、个性和声音,使其写作风格与你相似。

为何本课程与众不同?

通过完成“LLM Twin: 构建你的生产就绪型AI复制品免费课程,你将学会如何设计、训练并部署一个由LLMs、向量数据库及LLMOps最佳实践驱动的生产就绪型个人LLM双胞胎系统

为何你应该关注?🫵

→ 不再局限于孤立的脚本或Notebook! 通过构建并部署一个端到端的生产级LLM系统,学习生产级机器学习。

本课程结束时,你将学会构建什么?

你将学习如何从头到尾设计和构建一个真实的LLM系统——从数据收集部署

你还将学习利用MLOps最佳实践,例如实验跟踪器、模型注册表、提示监控和版本控制。

最终目标是什么? 构建并部署你自己的LLM双胞胎。

什么是LLM双胞胎? 它是一个AI角色,通过将某人的风格和个性融入LLM中,学会像某人一样写作。

LLM双胞胎的架构分为4个Python微服务

  1. 数据收集管道: 从各种社交媒体平台抓取你的数字数据。通过一系列ETL管道清理、标准化并加载数据到NoSQL数据库。使用CDC模式将数据库更改发送到队列。(部署在AWS上)
  2. 特征管道: 通过Bytewax流管道从队列中消费消息。每条消息将被实时清理、分块、嵌入(使用Superlinked)并加载到Qdrant向量数据库中。(部署在AWS上)
  3. 训练管道: 基于你的数字数据创建自定义数据集。使用QLoRA对LLM进行微调。使用Comet ML的实验跟踪器监控实验。评估并将最佳模型保存到Comet的模型注册表中。(部署在Qwak上)
  4. 推理管道: 从Comet的模型注册表加载并量化微调后的LLM。将其部署为REST API。使用RAG增强提示。使用你的LLM双胞胎生成内容。使用Comet的提示监控仪表板监控LLM。(部署在Qwak上)

在这4个微服务中,你将学习集成3个无服务器工具:

  • Comet ML 作为你的ML平台;
  • Qdrant 作为你的向量数据库;
  • Qwak 作为你的ML基础设施;

适用对象

受众: 希望学习使用LLMOps稳健原则构建生产就绪型LLM系统的MLE、DE、DS或SWE。级别: 中级先决条件: 具备Python、机器学习和云计算的基础知识

你将如何学习?

本课程包含11个实践性书面课程以及你可以在GitHub上访问的开源代码

你可以按照自己的节奏阅读所有内容。→ 为了最大限度地从本课程中获益,我们鼓励你在学习课程的同时克隆并运行该仓库。

费用问题?

文章代码均为完全免费。它们将始终保持免费。

但如果你计划在阅读的同时运行代码,你必须知道我们使用了几种云工具,这可能会产生额外费用。

云计算平台(AWS Qwak )采用按使用付费的定价计划。Qwak提供数小时的免费计算时间。因此,我们尽力将成本降至最低。

对于其他无服务器工具(Qdrant Comet ),我们将坚持使用它们的免费增值版本,该版本不收取费用。

认识你的老师们!

本课程由解码机器学习 团队创建,成员包括:

🔗 查看 GitHub上的代码 [1] 并给我们一个⭐️以示支持

课程内容

本课程分为11个课时。每篇Medium文章即为一个课时。

  1. 构建生产就绪型LLM系统的端到端框架:打造你的LLM双胞胎
  2. 生成式AI时代数据管道的重要性
  3. 变更数据捕获:实现事件驱动架构
  4. 实时微调LLM和RAG的SOTA Python流式管道
  5. 你必须了解的4种高级RAG算法
  6. 特征存储在微调LLM中的作用
  7. 如何使用Qwak和Comet ML在自定义数据集上大规模微调LLM
  8. 评估微调LLM模型的最佳实践
  9. 构建可扩展且成本效益高的LLM & RAG推理管道
  10. 如何使用RAGAs框架评估你的RAG管道
  11. 总结。我们学到了什么?[模块6] …待更新

为了更好地理解课程目标、技术细节及系统设计 → 查看第1课

让我们从第10课开始↓↓↓

第10课:如何使用RAGAs框架评估您的RAG管道

在进入课程之前,让我们快速回顾一下,了解我们是如何走到这一步的

第8课中,我们专注于LLM在各种任务中的常见评估方法,特别是在内容生成方面,我们通过API使用了一个更大的模型(GPT3.5-Turbo)来评估连贯性并量化其他LLM生成指标。

第9课中,我们展示了如何在Qwak [2] 上实现和部署LLM双系统推理管道。我们迭代了基于微服务的设计,将ML和业务逻辑分离为两个层次。

第10课我们将重点放在RAG评估逻辑上。

在这里,我们将展示我们执行的评估步骤,以及我们如何逐步构建评估负载。我们将介绍最佳的RAG评估框架之一(RAGAs [5] ),并讨论其提供的指标、实现和其他优秀功能。

最终,我们将学习如何通过单独设计每个链步骤、附加元数据并记录到CometML-LLM来监控复杂的链。

本课我们将学习的内容

  • RAG应用的评估技术。
  • 如何使用RAGAs评估RAG应用。
  • 如何构建元数据链并将其记录到CometML-LLM。
  • LLM-Twin RAG评估工作流程。

目录

  1. 什么是RAG评估?
  2. RAGAs框架
  3. 如何评估我们的RAG应用
  4. 高级提示链监控
  5. 结论

什么是RAG评估?

RAG评估涉及评估模型如何将检索到的信息整合到其响应中。这不仅需要评估生成文本的质量,还需要评估检索信息的准确性和相关性,以及它如何有效地增强最终输出。

构建RAG流水线相当简单。您只需要一个向量数据库知识库、一个LLM来处理您的提示,以及这些模块之间交互的额外逻辑。

由于RAG流水线的“独立”组件,达到令人满意的性能水平带来了挑战:

  • 检索器 — 负责查询知识数据库并检索与用户查询匹配的额外上下文。
  • 生成器 — 包含LLM模块,基于上下文增强的提示生成答案。

在评估RAG流水线时,我们必须分别和共同评估这两个组件,以了解RAG流水线是否以及在哪些方面仍需改进,这将帮助我们识别其“质量”。此外,为了了解其性能是否在提升,我们需要进行定量评估。

RAGAs框架

Ragas是一个帮助您评估检索增强生成(RAG)管道的框架。已有工具和框架(例如LLamaIndex)帮助您构建这些管道,但评估和量化管道性能可能很困难。这就是Ragas(RAG评估)的用武之地。

RAGAs [5] 框架(5.3k ⭐️)是开源的,属于explodinggradients团队,并附带一篇论文提交:RAGAs论文 [6]

RAGAs的核心概念之一是基于指标的开发(MDD),这是一种依赖数据做出明智决策的产品开发方法。重点是利用强大的LLM在后台进行有针对性的评估过程,而不是依赖HITL(人在回路中)进行地面真实标注。

RAGAs 指标

让我们逐一了解 RAGAs 指标 [4] 所提供的各项指标:

检索阶段 🔽 指标:

  1. 上下文精确度:评估用于生成答案的上下文的精确度,确保从上下文中选择了相关信息。
  2. 上下文相关性:衡量所选上下文与问题的相关程度,有助于改进上下文选择以提高答案准确性。
  3. 上下文召回率:衡量是否检索到了回答问题所需的所有相关信息。
  4. 上下文实体召回率:评估上下文中实体的召回情况,确保在上下文检索中没有遗漏重要实体。

生成阶段 🔽 指标:

  1. 忠实度:衡量生成的答案在多大程度上准确反映了源内容,确保生成的内容真实可靠。
  2. 答案相关性:评估答案与所提问题的相关程度,验证回复是否直接针对用户的查询。
  3. 答案语义相似度:量化生成的答案与预期的“理想”答案之间的语义相似度,表明生成的内容在语义上与预期回复一致。
  4. 答案正确性:侧重于事实核查,评估生成答案的事实准确性。

在评估设置中可以使用这些指标的子集或全部。在我们的 LLM-Twin RAG 应用场景中,我们将使用针对检索和生成模块的 6 项指标:

  • 上下文精确度、召回率、相关性和实体召回率 — 用于 检索
  • 答案相关性和答案语义相似度 — 用于 生成

RAGAs 评估格式

为了评估 RAG 管道,RAGAs 期望以下数据集格式:

1
2
3
4
5
6
question       : 用户查询,这是我们 RAG 的输入。
answer : 根据查询 + 上下文提示从 RAG 管道生成的答案。
contexts : 从知识库(向量数据库)检索的上下文。
ground_truths : 问题的真实答案。

[注意] : 仅在使用 ContextRecall 指标时需要 `ground_truths` 字段。

📓 所有列出的 RAGAs 指标都使用 questionanswercontexts 字段。需要注意的是,唯一需要 ground_truths 字段的指标是 上下文召回率。因为它衡量的是回答问题所需的所有相关信息是否都从向量数据库中检索到了。

以下是一个为 RAGAs 设置数据集的快速示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from datasets import Dataset

questions= ["埃菲尔铁塔是什么时候建造的,它有多高?"],
answers= ["截至我上次更新,即2023年4月,埃菲尔铁塔建于1889年,高324米"]
contexts= [
"埃菲尔铁塔是访问法国巴黎时最吸引人的纪念碑之一。它于1889年作为1889年世界博览会的入口拱门建造,高达324米。"
]
ground_truths=[
["埃菲尔铁塔建于1889年,高达324米。"]
]

sample = {
"question": questions,
"answer": answers,
"contexts": contexts,
"ground_truths": ground_truths
}

eval_dataset = Dataset.from_dict(sample)

数据集看起来是这样的:

1
2
3
4
5
#> print(eval_dataset)
Dataset({
features: ['question', 'answer', 'contexts', 'ground_truths'],
num_rows: 1
})

创建数据集后,RAGAs 需要一组指标传递给评估方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from ragas import evaluate
from ragas.metrics import (
answer_similarity,
context_relevancy,
)

scores = evaluate(
dataset=eval_dataset,
metrics=[context_recall, answer_similarity]
)

# 分数将是一个这种格式的字典
# scores = {
# "context_recall": 0.95,
# "answer_similarity": 0.98
# }

现在我们已经了解了使用 RAGAs 所需的前提条件,让我们看看该框架如何应用于我们的 LLM-Twin RAG 评估用例。

如何评估我们的RAG应用?

在这一评估阶段,我们将重点关注LLM Twin系统设计的这一部分:

工作流程概览:

  1. 定义评估提示模板
  2. 定义用户查询
  3. 从向量数据库中检索与用户查询相关的上下文
  4. 格式化提示并传递给LLM模型
  5. 捕获回答,并使用查询/上下文准备评估数据样本
  6. 使用RAGAs进行评估
  7. 构建评估链,附加元数据,并记录到CometML

🗒 在深入实现之前,一个有趣的细节是,我们的目标是使LLM-Twin模仿我们的写作风格。

对于这个特定的用例,我们可以利用从向量数据库中检索的上下文作为评估时的真实依据。

为什么❓

由于我们已经将我们的写作(帖子/文章/代码)存储在向量数据库中,它们可能扮演双重角色,既是传递给LLM用于生成的上下文,同时也是我们在评估过程中与RAG响应进行比较的真实依据

考虑到这一细节,现在让我们按照这个蓝图进行实现:

  1. 我们将回顾提示模板
  2. 我们将准备用于评估的查询/响应/上下文负载
  3. 使用RAGAs进行评估
  4. 在CometML上监控一切

生成提示模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class InferenceTemplate(BasePromptTemplate):
simple_prompt: str = """You are an AI language model assistant. Your task is to generate a cohesive and concise response to the user question.
Question: {question}
"""

rag_prompt: str = """ You are a specialist in technical content writing. Your task is to create technical content based on a user query given a specific context
with additional information consisting of the user's previous writings and his knowledge.

Here is a list of steps that you need to follow in order to solve this task:
Step 1: You need to analyze the user provided query : {question}
Step 2: You need to analyze the provided context and how the information in it relates to the user question: {context}
Step 3: Generate the content keeping in mind that it needs to be as cohesive and concise as possible related to the subject presented in the query and similar to the users writing style and knowledge presented in the context.
"""

def create_template(self, enable_rag: bool = True) -> PromptTemplate:
if enable_rag is True:
return PromptTemplate(
template=self.rag_prompt, input_variables=["question", "context"]
)

return PromptTemplate(template=self.simple_prompt, input_variables=["question"])

解析这个模板,我们在系统提示中指定了LLM模型应该在步骤1中分析查询,在步骤2中分析检索到的上下文,并在步骤3中遵循生成指令。

准备评估负载

让我们按顺序遍历每个模块。我们已经定义了提示模板,并将问题字段分配给输入查询。接下来,我们需要从向量数据库中检索上下文样本。

检索逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
# 1. 实例化一个与向量数据库通信的VectorRetriever
retriever = VectorRetriever(query=query)
# 2. 初始获取K个条目
hits = retriever.retrieve_top_k(
k=settings.TOP_K, to_expand_to_n_queries=settings.EXPAND_N_QUERY
)
# 3. 使用后检索增强技术重新排序条目
context = retriever.rerank(hits=hits, keep_top_k=settings.KEEP_TOP_K)
# 4. 更新上下文
prompt_template_variables["context"] = context
prompt = prompt_template.format(question=query, context=context)

要深入了解上述代码中步骤3提到的重新排序技术,请确保查看📓 第5课

检索到上下文后,是时候将我们的提示传递给部署在Qwak [2] 上的推理管道,并获取LLM生成响应。

要深入了解推理管道是如何构建和部署的,请查看📓 第9课

接下来,我们有评估块代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if enable_evaluation is True:
if enable_rag:
st_time = time.time_ns()
rag_eval_scores = evaluate_w_ragas(
query=query, output=answer, context=context
)
en_time = time.time_ns()
self._timings["evaluation_rag"] = (en_time - st_time) / 1e9
st_time = time.time_ns()
llm_eval = evaluate_llm(query=query, output=answer)
en_time = time.time_ns()
self._timings["evaluation_llm"] = (en_time - st_time) / 1e9
evaluation_result = {
"llm_evaluation": "" if not llm_eval else llm_eval,
"rag_evaluation": {} if not rag_eval_scores else rag_eval_scores,
}
else:
evaluation_result = None

从这一实现中获得的关键见解:

  • 我们应用了第8课中描述的LLM评估阶段,以评估(查询,响应)对。
  • 我们应用了RAG评估阶段,以评估(查询,响应,上下文)对。
  • 我们使用_timings字典来跟踪执行持续时间,以进行性能分析。

核心RAGAs评估功能在evaluate_w_ragas方法中处理,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from ragas.metrics import (
answer_correctness,
answer_similarity,
context_entity_recall,
context_recall,
context_relevancy,
context_utilization,
)

METRICS = [
context_utilization,
context_relevancy,
context_recall,
answer_similarity,
context_entity_recall,
answer_correctness,
]

def evaluate_w_ragas(query: str, context: list[str], output: str) -> DataFrame:
"""
使用RAGAS评估RAG(查询,上下文,响应)
"""
data_sample = {
"question": [query], # 问题作为序列(str)
"answer": [output], # 回答作为序列(str)
"contexts": [context], # 上下文作为序列(str)
"ground_truth": [context], # 真实依据作为序列(str)
}

oai_model = ChatOpenAI(
model=settings.OPENAI_MODEL_ID,
api_key=settings.OPENAI_API_KEY,
)
embd_model = HuggingfaceEmbeddings(model=settings.EMBEDDING_MODEL_ID)
dataset = Dataset.from_dict(data_sample)
score = evaluate(
llm=oai_model,
embeddings=embd_model,
dataset=dataset,
metrics=METRICS,
)

return score

需要注意的事项:

  • 我们使用data_sample字典准备评估数据集。
  • 我们实例化了一个连接到OpenAI GPT模型的连接器,这将作为底层LLM在RAGAs中执行评估逻辑。模型标签来自设置 = gpt-4–1106-preview
  • 我们实例化了一个连接到HuggingFaceEmbeddings模型的连接器。我们使用与之前在QDrant向量数据库实例中存储样本时使用的相同的嵌入模型。模型标签来自设置 = sentence-transformers/all-MiniLM-L6-v2
  • 我们组合负载并将其传递给evaluate方法。

一旦执行到达这个阶段,我们可能会在控制台中看到以下日志部分:

一旦评估完成,在score变量中我们将有一个这种格式的字典:

1
2
3
4
5
6
7
8
score = {
"context_utilization": float, # 上下文对生成回答的实用性
"context_relevancy": float, # 上下文对给定查询的相关性
"context_recall": float, # 相关检索上下文的比例
"answer_similarity": float, # 语义相似度
"answer_correctness": float, # 事实正确性
"context_entity_recall": float,# 上下文中相关实体的召回率
}

在下一部分,让我们以逐步方式组合完整的评估链,并将其记录到Comet ML LLM [3] 进行监控。

高级提示链监控

在基于LLM的应用中,提示监控至关重要,原因有几点。它有助于确保响应的质量和相关性,保持用户交互的准确性和连贯性,同时允许维护项目的ML工程师及早发现并缓解偏见或幻觉,并着手修复它们。

📓 在第8课 中,我们更详细地描述了提示监控的优势。

在本节中,我们将重点介绍如何构建端到端的链并将它们记录到Comet ML LLM [3] 。让我们深入代码,描述链由哪些组件组成。

步骤1:定义链的开始 这里我们指定要从CometML记录此链的project, workspace,并将其inputs设置为标记开始。

1
2
3
4
5
6
7
8
9
import comet_llm

comet_llm.init([project])
comet_llm.start_chain(
inputs={'user_query' : [our query]},
project=[comet-llm-project],
api_key=[comet-llm-api-key],
workspace=[comet-llm-ws]
)

步骤2:定义链的阶段 我们使用多个Span (comet_llm.Span)对象来定义链的阶段。在Span对象内部,我们必须定义:

  • category — 作为组键。
  • name — 当前链步骤的名称(将出现在CometML UI中)
  • inputs — 作为字典,用于与之前的链步骤(Span)关联
  • outputs — 作为字典,定义此链步骤的输出。
1
2
3
4
5
6
with comet_llm.Span(
"category"="RAG Evaluation",
"name"="ragas_eval",
"inputs"={"query": [our_query], "context": [our_context], "answers": [llm_answers]}
) as span:
span.set_outputs(outputs={"rag-eval-scores" : [ragas_scores]})

步骤3:定义链的结束 最后一步,在启动链并附加链阶段之后,是标记链的结束并返回响应。

1
comet_llm.end_chain(outputs={"response": [our-rag-response]})

现在我们已经理解了Comet ML LLM [3] 链监控背后的逻辑,让我们看看实际的实现是什么样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# == 启动链 ==
comet_llm.init(project=f"{settings.COMET_PROJECT}-monitoring")
comet_llm.start_chain(
inputs={"user_query": query},
project=f"{settings.COMET_PROJECT}-monitoring",
api_key=settings.COMET_API_KEY,
workspace=settings.COMET_WORKSPACE,
)

# == 链步骤 ==
with comet_llm.Span(
category="Vector Retrieval",
name="retrieval_step",
inputs={"user_query": query},
) as span:
span.set_outputs(outputs={"retrieved_context": context})

with comet_llm.Span(
category="LLM Generation",
name="generation_step",
inputs={"user_query": query},
) as span:
span.set_outputs(outputs={"generation": llm_gen})

with comet_llm.Span(
category="Evaluation",
name="llm_eval_step",
inputs={"query": llm_gen, "user_query": query},
metadata={"model_used": settings.OPENAI_MODEL_ID},
) as span:
span.set_outputs(outputs={"llm_eval_result": llm_eval_output})

with comet_llm.Span(
category="Evaluation",
name="rag_eval_step",
inputs={
"user_query": query,
"retrieved_context": context,
"llm_gen": llm_gen,
},
metadata={
"model_used": settings.OPENAI_MODEL_ID,
"embd_model": settings.EMBEDDING_MODEL_ID,
"eval_framework": "RAGAS",
},
) as span:
span.set_outputs(outputs={"rag_eval_scores": rag_eval_scores})

# == 结束链 ==
comet_llm.end_chain(outputs={"response": llm_gen})

📓 完整的链监控实现,请查看PromptMonitoringManager 类。

您可能已经注意到,Span还有一个metadata字段,我们使用它来记录仅对当前链步骤重要的额外数据。

例如,在rag_eval_step中,我们添加了使用的评估框架和模型类型。在CometML UI中,我们可以看到附加的元数据。

一旦评估过程完成,并且链成功记录到Comet ML LLM [3] ,这就是我们期望看到的内容:

如果您想回顾我们如何仅评估LLM模型,请确保查看📓第8课,我们在其中进行了详细描述。

如果我们想查看RAG评估分数:

结论

至此,我们完成了LLM Twin 免费课程第10课

我们介绍了如何使用名为RAGAs的强大框架来描述LLM-Twin RAG评估工作流程。我们解释了所使用的指标、如何实现评估功能以及如何构建评估数据集。

此外,我们还展示了如何在Comet ML LLM [3] 上有效监控具有多个执行步骤的链,如何附加元数据,如何分组链步骤等。

通过完成第10课,您已经对如何使用RAGAs构建完整的RAG评估管道有了很好的理解。您学习了可用的检索与生成特定指标以及将大型LLM链记录到Comet ML LLM [3] 所需的所有细节。

第11课中,我们将回顾并复习LLM-Twin课程的整个工作流程,描述每个模块并提及您跟进并免费构建一个生产就绪的RAG应用程序所需的所有资源,利用我们从经验中获得的最好见解。期待在那里与您相见!

🔗 查看 GitHub上的代码 [1] 并给我们一个⭐️支持

喜欢这篇文章吗?

加入解码ML通讯,获取关于设计、编码及部署生产级ML与MLOps系统实战经验分享。每周更新,完全免费

参考文献

[1] LLM Twin Github 仓库 ,2024,Decoding ML GitHub 组织

[2] Qwak ,2024,The Qwak.ai 平台登录页面

[3] Comet ML LLM ,The Comet ML LLM 平台

[4] RAGAs 指标 ,The RAGAs 框架指标文档

[5] RAGAs ,The RAGAs 框架 Github 仓库

[6] RAGAs 论文 ,2023,The RAGAs Arxiv 论文

  • 标题: 如何使用 RAGAs 框架评估您的 RAG
  • 作者: Barry
  • 创建于 : 2024-06-10 15:02:39
  • 更新于 : 2024-08-31 06:59:45
  • 链接: https://wx.role.fun/2024/06/10/7e1984198e9844b698f30e087b6e3bc1/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。