跳转到内容

使用UpTrain对LlamaIndex执行评估

概述:在本示例中,我们将了解如何将 UpTrain 与 LlamaIndex 结合使用。UpTrain(GitHub || 官网 || 文档)是一个用于评估和改进生成式AI应用的开源平台。它提供20多项预配置检查的评分(涵盖语言、代码、嵌入用例),对失败案例进行根本原因分析,并提供解决方案的见解。有关UpTrain评估的更多详细信息可在此查看

问题: 随着越来越多的公司将他们的LLM原型升级为生产就绪的应用程序,他们的RAG流水线也变得越来越复杂。开发者正在利用查询重写、上下文重排等模块来提高RAG系统的准确性。

随着复杂性的增加,故障点也随之增多。

  1. 需要高级评估来衡量这些新模块的质量,并确定它们是否真正提升了系统的准确性。
  2. 需要一个稳健的实验框架来系统性地测试不同模块并做出数据驱动的决策。

解决方案: UpTrain 有助于解决这两个问题:

  1. UpTrain 提供一系列检查来评估生成响应、检索上下文以及所有中间步骤的质量。相关检查包括 ContextRelevance、SubQueryCompleteness、ContextReranking、ContextConciseness、FactualAccuracy、ContextUtilization、ResponseCompleteness、ResponseConciseness 等。
  2. UpTrain 还允许您尝试不同的嵌入模型,并提供一个“evaluate_experiments”方法来比较不同的 RAG 配置。

有两种方式可以将 UpTrain 与 LlamaIndex 结合使用:

  1. 使用UpTrain回调处理器:此方法使您能够将UpTrain与LlamaIndex无缝集成。您只需将UpTrainCallbackHandler添加到现有的LlamaIndex流水线中,它就会评估您RAG流水线的所有组件。这是推荐的方法,因为它最易于使用,并能以最小工作量为您提供仪表盘和洞察。

  2. 使用 UpTrain 的 EvalLlamaIndex:该方法允许您使用 UpTrain 对生成的响应执行评估。您可以使用 EvalLlamaIndex 对象为查询生成响应,然后对这些响应执行评估。您可以在下方找到关于如何执行此操作的详细教程。该方法在评估方面提供更大的灵活性和控制力,但需要更多的设置和使用工作。

以下三个演示说明如何使用 UpTrain 回调处理器来评估 RAG 管道的不同组件。

RAG查询引擎在检索上下文和生成响应方面扮演着关键角色。为确保其性能和响应质量,我们进行以下评估:

  • 上下文相关性: 判断检索到的上下文是否包含足够信息来回答用户查询。
  • 事实准确性: 评估LLM的响应是否可以通过检索到的上下文进行验证。
  • 响应完整性: 检查响应是否包含全面回答用户查询所需的所有信息。

SubQuestionQueryGeneration 操作符将问题分解为子问题,并使用 RAG 查询引擎为每个子问题生成响应。为了衡量其准确性,我们使用:

重排序涉及根据与查询的相关性重新排列节点并选择顶部节点。根据重排序后返回的节点数量执行不同的评估。

a. 相同节点数

  • 上下文重排序: 检查重新排序后的节点顺序是否比原始顺序与查询更相关。

b. 不同节点数量:

这些评估共同确保了LlamaIndex流程中RAG查询引擎、子问题查询生成算子以及重排序过程的鲁棒性和有效性。

  • 我们已使用基础RAG查询引擎进行了评估;同样可以使用高级RAG查询引擎执行这些评估。
  • 对于重排序评估同样如此,我们已使用 SentenceTransformerRerank 执行了评估,相同的评估也可以使用其他重排序器来执行。

安装笔记本依赖项。

Terminal window
%pip install llama-index-readers-web
%pip install llama-index-callbacks-uptrain
%pip install -q html2text llama-index pandas tqdm uptrain torch sentence-transformers

导入库。

from getpass import getpass
from llama_index.core import Settings, VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter
from llama_index.readers.web import SimpleWebPageReader
from llama_index.core.callbacks import CallbackManager
from llama_index.callbacks.uptrain.base import UpTrainCallbackHandler
from llama_index.core.query_engine import SubQuestionQueryEngine
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.postprocessor import SentenceTransformerRerank
from llama_index.llms.openai import OpenAI
import os

UpTrain 为您提供:

  1. 具有高级钻取和筛选选项的仪表板
  2. 失败案例中的洞察与常见主题
  3. 生产数据的可观测性与实时监控
  4. 通过与您的CI/CD流水线无缝集成进行回归测试

您可以选择以下选项来使用 UpTrain 进行评估:

您可以使用开源评估服务来评估您的模型。在这种情况下,您需要提供一个OpenAI API密钥。您可以在此处获取您的密钥。

为了在UpTrain仪表板中查看您的评估结果,您需要通过终端运行以下命令进行设置:

Terminal window
git clone https://github.com/uptrain-ai/uptrain
cd uptrain
bash run_uptrain.sh

这将在您的本地机器上启动 UpTrain 仪表板。您可以通过 http://localhost:3000/dashboard 访问它。

参数:

  • key_type=“openai”
  • api_key=“OPENAI_API_KEY”
  • project_name=“PROJECT_NAME”

或者,您可以使用 UpTrain 的托管服务来评估您的模型。您可以在此处创建一个免费的 UpTrain 账户并获得免费试用积分。如果您需要更多试用积分,请在此处与 UpTrain 的维护者预约通话

使用托管服务的优势包括:

  1. 无需在本地机器上设置 UpTrain 仪表板。
  2. 无需其API密钥即可访问众多大型语言模型。

执行评估后,您可以在UpTrain仪表板的https://dashboard.uptrain.ai/dashboard处查看它们

参数:

  • key_type=“uptrain”
  • api_key=“UPTRAIN_API_KEY”
  • project_name=“PROJECT_NAME”

注意: project_name 将作为项目名称,在该项目下执行的评估将显示在 UpTrain 仪表板中。

os.environ["OPENAI_API_KEY"] = getpass()
callback_handler = UpTrainCallbackHandler(
key_type="openai",
api_key=os.environ["OPENAI_API_KEY"],
project_name="uptrain_llamaindex",
)
Settings.callback_manager = CallbackManager([callback_handler])

从保罗·格雷厄姆的文章《我的工作历程》中加载文档。

documents = SimpleWebPageReader().load_data(
[
"https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt"
]
)

将文档解析为节点。

parser = SentenceSplitter()
nodes = parser.get_nodes_from_documents(documents)

UpTrain 回调处理器将在生成后自动捕获查询、上下文和响应,并对响应运行以下三项评估(评分范围从0到1)

  • 上下文相关性: Determines if the retrieved context has sufficient information to answer the user query or not.
  • 事实准确性: Assesses if the LLM’s response can be verified via the retrieved context.
  • 响应完整性: Checks if the response contains all the information required to answer the user query comprehensively.
index = VectorStoreIndex.from_documents(
documents,
)
query_engine = index.as_query_engine()
max_characters_per_line = 80
queries = [
"What did Paul Graham do growing up?",
"When and how did Paul Graham's mother die?",
"What, in Paul Graham's opinion, is the most distinctive thing about YC?",
"When and how did Paul Graham meet Jessica Livingston?",
"What is Bel, and when and where was it written?",
]
for query in queries:
response = query_engine.query(query)
Question: What did Paul Graham do growing up?
Response: Paul Graham wrote short stories and started programming on the IBM 1401 in 9th grade using an early version of Fortran. Later, he convinced his father to buy a TRS-80, where he wrote simple games, a program to predict rocket heights, and a word processor.
Context Relevance Score: 0.0
Factual Accuracy Score: 1.0
Response Completeness Score: 1.0
Question: When and how did Paul Graham's mother die?
Response: Paul Graham's mother died when he was 18 years old, from a brain tumor.
Context Relevance Score: 0.0
Factual Accuracy Score: 0.0
Response Completeness Score: 1.0
Question: What, in Paul Graham's opinion, is the most distinctive thing about YC?
Response: The most distinctive thing about Y Combinator, according to Paul Graham, is that instead of deciding for himself what to work on, the problems come to him. Every 6 months, a new batch of startups brings their problems, which then become the focus of YC's work.
Context Relevance Score: 0.0
Factual Accuracy Score: 0.5
Response Completeness Score: 1.0
Question: When and how did Paul Graham meet Jessica Livingston?
Response: Paul Graham met Jessica Livingston at a big party at his house in October 2003.
Context Relevance Score: 1.0
Factual Accuracy Score: 0.5
Response Completeness Score: 1.0
Question: What is Bel, and when and where was it written?
Response: Bel is a new Lisp that was written in Arc. It was developed over a period of 4 years, from March 26, 2015 to October 12, 2019. Most of the work on Bel was done in England, where the author had moved to in the summer of 2016.
Context Relevance Score: 1.0
Factual Accuracy Score: 1.0
Response Completeness Score: 1.0

以下是仪表板示例,展示如何筛选并深入查看失败案例,获取关于失败案例的洞察: image-2.png

子问题查询引擎用于解决使用多个数据源回答复杂查询的问题。它首先将复杂查询分解为针对每个相关数据源的子问题,然后收集所有中间响应并综合生成最终响应。

UpTrain 回调处理器将在每个子问题及其响应生成后自动捕获,并对响应运行以下三项评估(评分范围从0到1)

  • 上下文相关性: Determines if the retrieved context has sufficient information to answer the user query or not.
  • 事实准确性: Assesses if the LLM’s response can be verified via the retrieved context.
  • 响应完整性: Checks if the response contains all the information required to answer the user query comprehensively.

除了上述评估外,回调处理器还将运行以下评估:

  • 子查询完整性: Assures that the sub-questions accurately and comprehensively cover the original query.
# build index and query engine
vector_query_engine = VectorStoreIndex.from_documents(
documents=documents,
use_async=True,
).as_query_engine()
query_engine_tools = [
QueryEngineTool(
query_engine=vector_query_engine,
metadata=ToolMetadata(
name="documents",
description="Paul Graham essay on What I Worked On",
),
),
]
query_engine = SubQuestionQueryEngine.from_defaults(
query_engine_tools=query_engine_tools,
use_async=True,
)
response = query_engine.query(
"How was Paul Grahams life different before, during, and after YC?"
)
Generated 3 sub questions.
[documents] Q: What did Paul Graham work on before Y Combinator?
[documents] Q: What did Paul Graham work on during Y Combinator?
[documents] Q: What did Paul Graham work on after Y Combinator?
[documents] A: Paul Graham worked on a project with Robert and Trevor after Y Combinator.
[documents] A: Paul Graham worked on projects with his colleagues Robert and Trevor before Y Combinator.
[documents] A: Paul Graham worked on writing essays and working on Y Combinator during his time at Y Combinator.

Question: What did Paul Graham work on after Y Combinator?
Response: Paul Graham worked on a project with Robert and Trevor after Y Combinator.
Context Relevance Score: 0.0
Factual Accuracy Score: 1.0
Response Completeness Score: 0.5
Question: What did Paul Graham work on before Y Combinator?
Response: Paul Graham worked on projects with his colleagues Robert and Trevor before Y Combinator.
Context Relevance Score: 0.0
Factual Accuracy Score: 1.0
Response Completeness Score: 0.5
Question: What did Paul Graham work on during Y Combinator?
Response: Paul Graham worked on writing essays and working on Y Combinator during his time at Y Combinator.
Context Relevance Score: 0.0
Factual Accuracy Score: 0.5
Response Completeness Score: 0.5
Question: How was Paul Grahams life different before, during, and after YC?
Sub Query Completeness Score: 1.0

以下是一个以条形图形式展示子问题分数的仪表板示例:

image.png

重排序是根据节点与查询的相关性重新排列节点的过程。Llamaindex 提供了多类重排序算法。在本示例中,我们使用了 LLMRerank。

重新排序器允许您输入重新排序后返回的前n个节点数量。如果该值与原始节点数量保持一致,重新排序器将仅对节点进行重新排序而不改变节点数量。否则,它将重新排序节点并返回前n个节点。

我们将根据重新排序后返回的节点数量执行不同的评估。

如果重排序后返回的节点数量与原始节点数量相同,将执行以下评估:

  • 上下文重排序: Checks if the order of re-ranked nodes is more relevant to the query than the original order.
callback_handler = UpTrainCallbackHandler(
key_type="openai",
api_key=os.environ["OPENAI_API_KEY"],
project_name_prefix="llama",
)
Settings.callback_manager = CallbackManager([callback_handler])
rerank_postprocessor = SentenceTransformerRerank(
top_n=3, # number of nodes after reranking
keep_retrieval_score=True,
)
index = VectorStoreIndex.from_documents(
documents=documents,
)
query_engine = index.as_query_engine(
similarity_top_k=3, # number of nodes before reranking
node_postprocessors=[rerank_postprocessor],
)
response = query_engine.query(
"What did Sam Altman do in this essay?",
)
Question: What did Sam Altman do in this essay?
Context Reranking Score: 0.0
Question: What did Sam Altman do in this essay?
Response: Sam Altman was asked to become the president of Y Combinator after the original founders decided to step back and reorganize the company for long-term sustainability.
Context Relevance Score: 1.0
Factual Accuracy Score: 1.0
Response Completeness Score: 0.5

如果重排序后返回的节点数量少于原始节点数量,将执行以下评估:

callback_handler = UpTrainCallbackHandler(
key_type="openai",
api_key=os.environ["OPENAI_API_KEY"],
project_name_prefix="llama",
)
Settings.callback_manager = CallbackManager([callback_handler])
rerank_postprocessor = SentenceTransformerRerank(
top_n=2, # Number of nodes after re-ranking
keep_retrieval_score=True,
)
index = VectorStoreIndex.from_documents(
documents=documents,
)
query_engine = index.as_query_engine(
similarity_top_k=5, # Number of nodes before re-ranking
node_postprocessors=[rerank_postprocessor],
)
# Use your advanced RAG
response = query_engine.query(
"What did Sam Altman do in this essay?",
)
Question: What did Sam Altman do in this essay?
Context Conciseness Score: 0.0
Question: What did Sam Altman do in this essay?
Response: Sam Altman offered unsolicited advice to the author during a visit to California for interviews.
Context Relevance Score: 1.0
Factual Accuracy Score: 1.0
Response Completeness Score: 0.5

要通过UpTrain的回调处理器使用UpTrain的托管服务,唯一需要更改的是设置key_typeapi_key参数。其余代码保持不变。

callback_handler = UpTrainCallbackHandler(
key_type="uptrain",
api_key="up-******************************",
project_name_prefix="llama",
)

以下是一个简短的GIF,展示了仪表板以及您可以从UpTrain托管服务中获取的洞察信息:

output.gif

Terminal window
pip install uptrain llama_index
import httpx
import os
import openai
import pandas as pd
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from uptrain import Evals, EvalLlamaIndex, Settings as UpTrainSettings

您可以使用任何您拥有的文档来完成此操作。在本教程中,我们将使用从维基百科提取的纽约市数据。我们只会向文件夹添加一个文档,但您可以根据需要添加任意数量的文档。

url = "https://uptrain-assets.s3.ap-south-1.amazonaws.com/data/nyc_text.txt"
if not os.path.exists("nyc_wikipedia"):
os.makedirs("nyc_wikipedia")
dataset_path = os.path.join("./nyc_wikipedia", "nyc_text.txt")
if not os.path.exists(dataset_path):
r = httpx.get(url)
with open(dataset_path, "wb") as f:
f.write(r.content)

在生成回复之前,我们需要创建一个查询列表。由于查询引擎是基于纽约市训练的,我们将创建一个与纽约市相关的查询列表。

data = [
{"question": "What is the population of New York City?"},
{"question": "What is the area of New York City?"},
{"question": "What is the largest borough in New York City?"},
{"question": "What is the average temperature in New York City?"},
{"question": "What is the main airport in New York City?"},
{"question": "What is the famous landmark in New York City?"},
{"question": "What is the official language of New York City?"},
{"question": "What is the currency used in New York City?"},
{"question": "What is the time zone of New York City?"},
{"question": "What is the famous sports team in New York City?"},
]

本笔记本使用 OpenAI API 为提示生成文本,并创建向量存储索引。因此,请将 openai.api_key 设置为您的 OpenAI API 密钥。

openai.api_key = "sk-************************" # your OpenAI API key

让我们使用LLamaIndex创建一个向量存储索引,然后将其用作查询引擎从文档中检索相关部分。

Settings.chunk_size = 512
documents = SimpleDirectoryReader("./nyc_wikipedia/").load_data()
vector_index = VectorStoreIndex.from_documents(
documents,
)
query_engine = vector_index.as_query_engine()

UpTrain 为您提供:

  1. 带有高级钻取和筛选选项的仪表板
  2. 失败案例中的洞察与常见主题
  3. 生产数据的可观测性与实时监控
  4. 通过与您的CI/CD流水线无缝集成进行回归测试

您可以选择以下两种替代方案之一来使用 UpTrain 进行评估:

替代方案1:使用UpTrain的开源软件(OSS)进行评估

Section titled “Alternative 1: Evaluate using UpTrain’s Open-Source Software (OSS)”

您可以使用开源评估服务来评估您的模型。在这种情况下,您需要提供一个OpenAI API密钥。您可以在此处获取您的密钥。

为了在UpTrain仪表板中查看您的评估结果,您需要通过终端运行以下命令进行设置:

Terminal window
git clone https://github.com/uptrain-ai/uptrain
cd uptrain
bash run_uptrain.sh

这将在您的本地机器上启动 UpTrain 仪表板。您可以通过 http://localhost:3000/dashboard 访问它。

注意: project_name 将作为项目名称,在该项目下进行的评估将显示在 UpTrain 仪表板中。

settings = UpTrainSettings(
openai_api_key=openai.api_key,
)

现在我们已经创建了查询引擎,可以使用它来创建一个EvalLlamaIndex对象。该对象将用于生成查询的响应。

llamaindex_object = EvalLlamaIndex(
settings=settings, query_engine=query_engine
)

现在我们有了查询列表,就可以使用 EvalLlamaIndex 对象为查询生成响应,然后对这些响应执行评估。您可以在此处找到 UpTrain 提供的完整评估列表。我们选择了两个在本教程中最相关的评估:

  1. 上下文相关性:此评估检查检索到的上下文是否与查询相关。这一点很重要,因为检索到的上下文用于生成响应。如果检索到的上下文与查询不相关,那么响应也将与查询不相关。

  2. 响应简洁性:此评估检查响应是否简洁。这一点很重要,因为响应应当简洁明了,不应包含任何不必要的信息。

results = llamaindex_object.evaluate(
project_name="uptrain-llama-index",
evaluation_name="nyc_wikipedia", # adding project and evaluation names allow you to track the results in the UpTrain dashboard
data=data,
checks=[Evals.CONTEXT_RELEVANCE, Evals.RESPONSE_CONCISENESS],
)
pd.DataFrame(results)

替代方案2:使用UpTrain托管服务和仪表板进行评估

Section titled “Alternative 2: Evaluate using UpTrain’s Managed Service and Dashboards”

或者,您可以使用 UpTrain 的托管服务来评估您的模型。您可以在此处创建一个免费的 UpTrain 账户并获得免费试用积分。如果您需要更多试用积分,请在此处与 UpTrain 的维护者预约通话

使用托管服务的优势包括:

  1. 无需在本地机器上设置 UpTrain 仪表板。
  2. 无需其API密钥即可访问多种大型语言模型。

执行评估后,您可以在UpTrain仪表板的https://dashboard.uptrain.ai/dashboard处查看它们https://dashboard.uptrain.ai/dashboard

注意: project_name 将作为项目名称,在该项目下执行的评估将显示在 UpTrain 仪表板中。

UPTRAIN_API_KEY = "up-**********************" # your UpTrain API key
# We use `uptrain_access_token` parameter instead of 'openai_api_key' in settings in this case
settings = UpTrainSettings(
uptrain_access_token=UPTRAIN_API_KEY,
)

现在我们已经创建了查询引擎,可以使用它来创建一个EvalLlamaIndex对象。该对象将用于生成查询的响应。

llamaindex_object = EvalLlamaIndex(
settings=settings, query_engine=query_engine
)

现在我们有了查询列表,我们可以使用 EvalLlamaIndex 对象为查询生成响应,然后对响应执行评估。您可以在此处找到 UpTrain 提供的完整评估列表。我们选择了两个在本教程中最相关的评估:

  1. 上下文相关性:此评估检查检索到的上下文是否与查询相关。这一点很重要,因为检索到的上下文用于生成响应。如果检索到的上下文与查询不相关,那么响应也将与查询不相关。

  2. 响应简洁性:此评估检查响应是否简洁。这一点很重要,因为响应应当简明扼要,不应包含任何不必要的信息。

results = llamaindex_object.evaluate(
project_name="uptrain-llama-index",
evaluation_name="nyc_wikipedia", # adding project and evaluation names allow you to track the results in the UpTrain dashboard
data=data,
checks=[Evals.CONTEXT_RELEVANCE, Evals.RESPONSE_CONCISENESS],
)
pd.DataFrame(results)

得分与对应得分案例数量的直方图

nyc_dashboard.png

您可以筛选失败案例并生成其中的共同主题。这有助于识别核心问题并帮助修复它

nyc_insights.png

  1. 关于 UpTrainCallbackHandler 的 Colab 笔记本
  2. 关于UpTrain与LlamaIndex集成的Colab笔记本
  3. UpTrain GitHub 代码库
  4. UpTrain 文档