Phoenix (Arize)
1. 介绍
构建 RAG 管道的基线通常不难,但要增强它使其适合生产并确保响应质量几乎总是困难的。在有大量选项可用时,为 RAG 选择合适的工具和参数本身就可能具有挑战性。本教程分享了一个可靠的工作流程,用于在构建 RAG 时做出正确选择并确保其质量。
本文介绍如何结合使用开源库来评估、可视化和分析您的 RAG。我们将使用
- 用于合成测试数据生成和评估的 Ragas
- Arize AI 的 Phoenix 用于追踪、可视化和聚类分析
- 用于构建 RAG 管道的 LlamaIndex
出于本文的目的,我们将使用来自 arXiv 上关于提示工程的论文数据来构建 RAG 管道。
ℹ️ 本笔记本需要一个 OpenAI API 密钥。
2. 安装依赖项并导入库
运行下面的单元格以安装 Git LFS,我们用它来下载数据集。
安装并导入 Python 依赖项。
!pip install "ragas<0.1.1" pypdf arize-phoenix "openinference-instrumentation-llama-index<1.0.0" "llama-index<0.10.0" pandas
import pandas as pd
# Display the complete contents of dataframe cells.
pd.set_option("display.max_colwidth", None)
3. 配置您的 OpenAI API 密钥
如果您的 OpenAI API 密钥尚未设置为环境变量,请进行设置。
import os
from getpass import getpass
import openai
if not (openai_api_key := os.getenv("OPENAI_API_KEY")):
openai_api_key = getpass("🔑 Enter your OpenAI API key: ")
openai.api_key = openai_api_key
os.environ["OPENAI_API_KEY"] = openai_api_key
4. 生成您的合成测试数据集
策划用于评估的黄金测试数据集可能是一个漫长、繁琐且昂贵的过程,不切实际——尤其是在刚开始或数据源不断变化时。这可以通过合成生成高质量数据点来解决,这些数据点随后可以由开发人员验证。这可以将策划测试数据的时间和精力减少 90%。
运行下面的单元格,从 arXiv 下载提示工程论文的 PDF 数据集,并使用 LlamaIndex 读取这些文档。
from llama_index import SimpleDirectoryReader
dir_path = "./prompt-engineering-papers"
reader = SimpleDirectoryReader(dir_path, num_files_limit=2)
documents = reader.load_data()
理想的测试数据集应包含高质量且具有多样性、分布与生产环境中观察到的相似的数据点。Ragas 使用一种独特的基于演化的合成数据生成范式来生成最高质量的问题,这也确保了生成问题的多样性。Ragas 默认在底层使用 OpenAI 模型,但您可以自由选择使用任何您喜欢的模型。让我们使用 Ragas 生成 100 个数据点。
from ragas.testset import TestsetGenerator
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
TEST_SIZE = 25
# generator with openai models
generator_llm = ChatOpenAI(model="gpt-4o-mini")
critic_llm = ChatOpenAI(model="gpt-4o")
embeddings = OpenAIEmbeddings()
generator = TestsetGenerator.from_langchain(generator_llm, critic_llm, embeddings)
# generate testset
testset = generator.generate_with_llamaindex_docs(documents, test_size=TEST_SIZE)
test_df = testset.to_pandas()
test_df.head()
您可以根据需要自由更改问题类型的分布。既然我们的测试数据集已经准备就绪,让我们继续使用 LlamaIndex 构建一个简单的 RAG 管道。
5. 使用 LlamaIndex 构建您的 RAG 应用
LlamaIndex 是一个易于使用且灵活的框架,用于构建 RAG 应用。为了简单起见,我们使用默认的 LLM (gpt-3.5-turbo) 和嵌入模型 (openai-ada-2)。
在后台启动 Phoenix,并为您的 LlamaIndex 应用添加检测,以便您的 OpenInference spans 和 traces 发送并由 Phoenix 收集。OpenInference 是一个基于 OpenTelemetry 构建的开放标准,用于捕获和存储 LLM 应用的执行。它被设计为一种遥测数据类别,用于理解 LLM 的执行以及周围的应用上下文,例如从向量存储中检索以及使用搜索引擎或 API 等外部工具。
import phoenix as px
from llama_index import set_global_handler
session = px.launch_app()
set_global_handler("arize_phoenix")
构建您的查询引擎。
from llama_index.core import VectorStoreIndex, ServiceContext
from llama_index.embeddings.openai import OpenAIEmbedding
def build_query_engine(documents):
vector_index = VectorStoreIndex.from_documents(
documents,
service_context=ServiceContext.from_defaults(chunk_size=512),
embed_model=OpenAIEmbedding(),
)
query_engine = vector_index.as_query_engine(similarity_top_k=2)
return query_engine
query_engine = build_query_engine(documents)
如果您查看 Phoenix,您应该会看到语料库数据索引时产生的嵌入 spans。导出并保存这些嵌入到数据框中,以便稍后在本笔记本中进行可视化。
from phoenix.trace.dsl import SpanQuery
client = px.Client()
corpus_df = px.Client().query_spans(
SpanQuery().explode(
"embedding.embeddings",
text="embedding.text",
vector="embedding.vector",
)
)
corpus_df.head()
重新启动 Phoenix 以清除累积的 traces。
6. 评估您的 LLM 应用
Ragas 提供了全面的度量列表,可用于对 RAG 管道进行组件级别和端到端的评估。
要使用 Ragas,我们首先构建一个评估数据集,其中包含问题、生成的答案、检索到的上下文和真实答案(给定问题的实际预期答案)。
from datasets import Dataset
from tqdm.auto import tqdm
import pandas as pd
def generate_response(query_engine, question):
response = query_engine.query(question)
return {
"answer": response.response,
"contexts": [c.node.get_content() for c in response.source_nodes],
}
def generate_ragas_dataset(query_engine, test_df):
test_questions = test_df["question"].values
responses = [generate_response(query_engine, q) for q in tqdm(test_questions)]
dataset_dict = {
"question": test_questions,
"answer": [response["answer"] for response in responses],
"contexts": [response["contexts"] for response in responses],
"ground_truth": test_df["ground_truth"].values.tolist(),
}
ds = Dataset.from_dict(dataset_dict)
return ds
ragas_eval_dataset = generate_ragas_dataset(query_engine, test_df)
ragas_evals_df = pd.DataFrame(ragas_eval_dataset)
ragas_evals_df.head()
查看 Phoenix 以查看您的 LlamaIndex 应用 traces。
我们保存了几个数据框,一个包含稍后将可视化的嵌入数据,另一个包含我们计划使用 Ragas 评估的导出 traces 和 spans。
# dataset containing embeddings for visualization
query_embeddings_df = px.Client().query_spans(
SpanQuery().explode(
"embedding.embeddings", text="embedding.text", vector="embedding.vector"
)
)
query_embeddings_df.head()
from phoenix.session.evaluation import get_qa_with_reference
# dataset containing span data for evaluation with Ragas
spans_dataframe = get_qa_with_reference(client)
spans_dataframe.head()
Ragas 使用 LangChain 评估您的 LLM 应用数据。让我们使用 OpenInference 为 LangChain 添加检测,以便在评估 LLM 应用时查看内部情况。
from openinference.instrumentation.langchain import LangChainInstrumentor
LangChainInstrumentor().instrument()
评估您的 LLM traces 并以数据框格式查看评估分数。
from ragas import evaluate
from ragas.metrics import (
faithfulness,
answer_correctness,
context_recall,
context_precision,
)
evaluation_result = evaluate(
dataset=ragas_eval_dataset,
metrics=[faithfulness, answer_correctness, context_recall, context_precision],
)
eval_scores_df = pd.DataFrame(evaluation_result.scores)
将您的评估提交到 Phoenix,以便它们作为 spans 上的注释可见。
from phoenix.trace import SpanEvaluations
# Assign span ids to your ragas evaluation scores (needed so Phoenix knows where to attach the spans).
eval_data_df = pd.DataFrame(evaluation_result.dataset)
assert eval_data_df.question.to_list() == list(
reversed(spans_dataframe.input.to_list()) # The spans are in reverse order.
), "Phoenix spans are in an unexpected order. Re-start the notebook and try again."
eval_scores_df.index = pd.Index(
list(reversed(spans_dataframe.index.to_list())), name=spans_dataframe.index.name
)
# Log the evaluations to Phoenix.
for eval_name in eval_scores_df.columns:
evals_df = eval_scores_df[[eval_name]].rename(columns={eval_name: "score"})
evals = SpanEvaluations(eval_name, evals_df)
px.Client().log_evaluations(evals)
如果您查看 Phoenix,您会看到您的 Ragas 评估作为应用 spans 上的注释。
7. 可视化并分析您的嵌入
嵌入编码了检索到的文档和用户查询的含义。它们不仅是 RAG 系统的重要组成部分,而且对于理解和调试 LLM 应用性能也极为有用。
Phoenix 获取您的 RAG 应用中的高维嵌入,降低它们的维度,并将其聚类成具有语义意义的数据组。然后,您可以选择您选择的度量(例如,Ragas 计算的忠实度或答案正确性)来直观检查您的应用的性能,并发现存在问题的聚类。这种方法的优势在于它提供了对数据进行细粒度且有意义的子集度量,帮助您分析数据集上的局部性能,而不仅仅是全局性能。它也有助于直观了解您的 LLM 应用在回答哪种类型的查询时遇到了困难。
我们将重新启动 Phoenix 作为嵌入可视化工具,以检查我们的应用在测试数据集上的性能。
query_embeddings_df = query_embeddings_df.iloc[::-1]
assert ragas_evals_df.question.tolist() == query_embeddings_df.text.tolist()
assert test_df.question.tolist() == ragas_evals_df.question.tolist()
query_df = pd.concat(
[
ragas_evals_df[["question", "answer", "ground_truth"]].reset_index(drop=True),
query_embeddings_df[["vector"]].reset_index(drop=True),
test_df[["evolution_type"]],
eval_scores_df.reset_index(drop=True),
],
axis=1,
)
query_df.head()
query_schema = px.Schema(
prompt_column_names=px.EmbeddingColumnNames(
raw_data_column_name="question", vector_column_name="vector"
),
response_column_names="answer",
)
corpus_schema = px.Schema(
prompt_column_names=px.EmbeddingColumnNames(
raw_data_column_name="text", vector_column_name="vector"
)
)
# relaunch phoenix with a primary and corpus dataset to view embeddings
px.close_app()
session = px.launch_app(
primary=px.Dataset(query_df, query_schema, "query"),
corpus=px.Dataset(corpus_df.reset_index(drop=True), corpus_schema, "corpus"),
)
启动 Phoenix 后,您可以按照以下步骤使用您选择的度量来可视化您的数据
- 选择
vector
嵌入, - 选择
按颜色分类 > 维度
,然后选择您想要的维度,以便根据特定字段对数据进行颜色编码,例如根据 Ragas 评估分数(如忠实度或答案正确性), - 从
metric
下拉菜单中选择您想要的度量,以按聚类查看聚合度量。
8. 回顾
恭喜!您使用 Ragas 和 Phoenix 构建并评估了一个 LlamaIndex 查询引擎。让我们回顾一下学到了什么
- 使用 Ragas,您启动了一个测试数据集,并计算了诸如忠实度和答案正确性等度量来评估您的 LlamaIndex 查询引擎。
- 使用 OpenInference,您为查询引擎添加了检测,从而可以观察 LlamaIndex 和 Ragas 的内部工作原理。
- 使用 Phoenix,您收集了 spans 和 traces,导入了您的评估以便轻松检查,并可视化了嵌入式查询和检索到的文档,以识别性能不佳的区域。
本笔记本仅介绍了 Ragas 和 Phoenix 的功能。要了解更多信息,请参阅 Ragas 和 Phoenix 文档。
如果您喜欢本教程,请在 GitHub 上留一个 ⭐