Phoenix (Arize)
1. 简介
为 RAG pipeline 建立基线通常并不难,但要把它提升到适合生产、并确保回复质量,几乎总是很难。当可选方案很多时,为 RAG 选择合适的工具和参数本身就很有挑战。本教程分享一套稳健工作流,帮助你在构建 RAG 时做出正确选择并保证质量。
本文介绍如何结合开源库来评测、可视化并分析你的 RAG。我们将使用:
- Ragas 做合成测试数据生成与评测
- Arize AI 的 Phoenix 做 tracing、可视化与聚类分析
- LlamaIndex 构建 RAG pipelines
本文将使用 arXiv 上关于 prompt-engineering 的论文数据来构建 RAG pipeline。
ℹ️ 本 notebook 需要 OpenAI API key。
2. 安装依赖并导入库
运行下面的 cell 安装 Git LFS,我们用它下载数据集。
!git lfs install
安装并导入 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 Key
若尚未作为环境变量设置,请设置你的 OpenAI API key。
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. 生成合成测试数据集
为评测整理一份黄金测试集往往漫长、繁琐且昂贵,并不 pragmatic——尤其是起步阶段或数据源不断变化时。这个问题可以通过合成高质量数据点再由开发者核验来解决,可把整理测试数据的时间精力降低 90%。
运行下面的 cell,从 arXiv 下载一份 PDF 格式的 prompt engineering 论文数据集,并用 LlamaIndex 读取这些文档。
!git clone https://huggingface.co/datasets/vibrantlabsai/prompt-engineering-papers
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 pipeline。
5. 用 LlamaIndex 构建 RAG 应用
LlamaIndex 是一个易用且灵活的 RAG 应用构建框架。为简单起见,我们使用默认 LLM(gpt-3.5-turbo)和 embedding 模型(openai-ada-2)。
在后台启动 Phoenix,并为 LlamaIndex 应用做 instrumentation,使 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")
构建 query engine。
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,应能看到语料索引时产生的 embedding spans。导出这些 embeddings 并保存到 DataFrame,供 notebook 后续可视化使用。
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。
px.close_app()
session = px.launch_app()
6. 评测你的 LLM 应用
Ragas 提供一份全面的指标列表,可用于按组件以及端到端评测 RAG pipelines。
要使用 Ragas,我们先组成一份评测数据集,包含问题、生成答案、检索上下文,以及 ground-truth 答案(该问题实际期望的答案)。
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。
print(session.url)
我们保存几个 DataFrame:一个包含稍后要可视化的 embedding 数据,另一个包含我们计划用 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 做 instrumentation,以便在评测 LLM 应用时看到底层发生了什么。
from openinference.instrumentation.langchain import LangChainInstrumentor
LangChainInstrumentor().instrument()
评测 LLM traces,并以 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,这样它们会作为 annotations 显示在 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 评测作为 annotations 出现在应用 spans 上。
print(session.url)
7. 可视化并分析 Embeddings
Embeddings 编码了检索文档和用户查询的含义。它们不仅是 RAG 系统的必要部分,对理解和调试 LLM 应用表现也极为有用。
Phoenix 会取出 RAG 应用中的高维 embeddings,降低维度,并聚类成语义上有意义的数据组。然后你可以选择感兴趣的指标(例如 Ragas 计算的 faithfulness 或 answer correctness),可视化检查应用表现并找出有问题的聚类。这种方法的优势在于:它能在细粒度但有意义的数据子集上提供指标,帮助你分析数据集上的局部表现,而不仅仅是全局表现。它也有助于建立直觉:你的 LLM 应用在哪类查询上难以回答。
我们将把 Phoenix 重新启动为 embedding 可视化器,以检查应用在测试集上的表现。
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 后,可按以下步骤用所选指标可视化数据:
- 选择
vectorembedding, - 选择
Color By > dimension,再选你感兴趣的维度,按某个字段给数据上色,例如按 Ragas 评测分数如 faithfulness 或 answer correctness, - 从
metric下拉框选择感兴趣的指标,按聚类查看聚合指标。
8. 回顾
恭喜!你用 Ragas 和 Phoenix 构建并评测了一个 LlamaIndex query engine。我们学到了:
- 借助 Ragas,你引导生成了测试集,并计算了 faithfulness、answer correctness 等指标来评测 LlamaIndex query engine。
- 借助 OpenInference,你为 query engine 做了 instrumentation,从而可以观察 LlamaIndex 和 Ragas 的内部工作。
- 借助 Phoenix,你收集了 spans 和 traces,导入评测以便检查,并可视化嵌入的查询与检索文档,找出表现较差的局部区域。
本 notebook 只是 Ragas 与 Phoenix 能力的入门。要了解更多,请参阅 Ragas 和 Phoenix 文档。
若觉得本教程有帮助,请在 GitHub 上留下 ⭐: