Phoenix (Arize)
1. 简介
为 RAG 管道构建基线通常不难,但要将其增强以适用于生产环境并确保响应质量几乎总是很困难。当有大量选项可用时,为 RAG 选择正确的工具和参数本身就可能具有挑战性。本教程分享了一个稳健的工作流程,用于在构建 RAG 并确保其质量时做出正确的选择。
本文介绍了如何结合使用开源库来评估、可视化和分析您的 RAG。我们将使用
- Ragas 用于生成合成测试数据和评估
- Arize AI 的 Phoenix 用于追踪、可视化和聚类分析
- LlamaIndex 用于构建 RAG 管道
为方便本文演示,我们将使用 arXiv 上关于提示工程 (prompt-engineering) 的论文数据来构建 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 应用程序进行插桩 (instrument),以便您的 OpenInference 跨度 (span) 和追踪 (trace) 数据能够发送到 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,您应该能看到在索引语料库数据时产生的嵌入跨度。导出这些嵌入并将其保存到 DataFrame 中,以便稍后在本笔记本中进行可视化。
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 以清除累积的追踪数据。
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 应用程序追踪。
我们保存了几个 DataFrame,一个包含我们将稍后可视化的嵌入数据,另一个包含我们计划使用 Ragas 评估的导出追踪和跨度数据。
# 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 追踪数据,并以 DataFrame 格式查看评估分数。
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,以便它们作为注释在您的跨度上可见。
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 评估结果作为注释显示在您的应用程序跨度上。
7. 可视化和分析您的嵌入
嵌入 (Embeddings) 对检索到的文档和用户查询的含义进行编码。它们不仅是 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嵌入, - 选择
Color By > dimension,然后选择您想要的维度,以按特定字段为您的数据着色,例如,按 Ragas 评估分数(如忠实度或答案正确性)着色, - 从
metric下拉菜单中选择您想要的指标,以查看每个聚类的聚合指标。
8. 总结
恭喜!您已经使用 Ragas 和 Phoenix 构建并评估了一个 LlamaIndex 查询引擎。让我们回顾一下我们学到的内容:
- 通过 Ragas,您快速构建了一个测试数据集,并计算了如忠实度和答案正确性等指标,以评估您的 LlamaIndex 查询引擎。
- 通过 OpenInference,您对查询引擎进行了插桩,从而可以观察 LlamaIndex 和 Ragas 的内部工作原理。
- 通过 Phoenix,您收集了跨度和追踪数据,导入了您的评估结果以便于检查,并可视化了您的嵌入查询和检索到的文档,以识别性能不佳的区域。
本笔记本只是对 Ragas 和 Phoenix 功能的入门介绍。要了解更多信息,请参阅 Ragas 和 Phoenix 文档。
如果您喜欢本教程,请在 GitHub 上留下一颗 ⭐


