#!/usr/bin/env python # coding: utf-8 # 在 Colab 中打开 # # # 答案相关性和上下文相关性评估 # # 在这个笔记本中,我们演示了如何利用`AnswerRelevancyEvaluator`和`ContextRelevancyEvaluator`类来衡量生成的答案和检索到的上下文与给定用户查询的相关性。这两个评估器都会返回一个介于0和1之间的`score`,以及一个解释分数的生成`feedback`。需要注意的是,得分越高表示相关性越高。特别地,我们要求评判LLM以逐步的方式提供相关性评分,要求它回答以下两个关于查询答案相关性的问题(对于上下文相关性,这些问题会稍作调整): # # 1. 提供的回应是否与用户查询的主题相关? # 2. 提供的回应是否试图解决用户查询所采用的主题的焦点或观点? # # 每个问题值1分,因此完美的评估将得到2/2分。 # # In[ ]: get_ipython().run_line_magic('pip', 'install llama-index-llms-openai') # In[ ]: import nest_asyncio from tqdm.asyncio import tqdm_asyncio nest_asyncio.apply() # In[ ]: def displayify_df(df): """在笔记本中漂亮地显示DataFrame。""" display_df = df.style.set_properties( **{ "inline-size": "300px", "overflow-wrap": "break-word", } ) display(display_df) # ### 下载数据集(`LabelledRagDataset`) # # 对于这个演示,我们将使用通过我们的[llama-hub](https://llamahub.ai)提供的羊驼数据集。 # # In[ ]: from llama_index.core.llama_dataset import download_llama_datasetfrom llama_index.core.llama_pack import download_llama_packfrom llama_index.core import VectorStoreIndex# 下载并安装基准数据集的依赖项rag_dataset, documents = download_llama_dataset( "EvaluatingLlmSurveyPaperDataset", "./data") # In[ ]: rag_dataset.to_pandas()[:5] # 接下来,我们将在与创建`rag_dataset`时使用的相同源文档上构建一个RAG。 # # In[ ]: index = VectorStoreIndex.from_documents(documents=documents) query_engine = index.as_query_engine() # 有了我们定义的RAG(即`query_engine`),我们可以利用它在`rag_dataset`上进行预测(即生成对查询的响应)。 # # In[ ]: prediction_dataset = await rag_dataset.amake_predictions_with( predictor=query_engine, batch_size=100, show_progress=True ) # ### 分别评估答案和上下文相关性 # # 在问答系统中,评估答案的质量是非常重要的。通常情况下,我们需要分别评估答案的准确性以及答案与上下文的相关性。这两个方面的评估可以帮助我们确定一个答案是否是正确的,以及它是否与提出的问题和上下文相关。 # # 在实际应用中,我们可以使用不同的指标和技术来分别评估答案的准确性和上下文的相关性。这些指标可能包括词向量相似度、语义匹配模型、逻辑推理等。通过综合考虑这些指标,我们可以更全面地评估答案的质量。 # # 因此,在设计问答系统时,我们需要考虑如何分别评估答案的准确性和上下文的相关性,以提供更准确和相关的答案。 # # 我们首先需要定义我们的评估器(即`AnswerRelevancyEvaluator`和`ContextRelevancyEvaluator`): # # In[ ]: # 实例化gpt-4评估器from llama_index.llms.openai import OpenAIfrom llama_index.core.evaluation import ( AnswerRelevancyEvaluator, ContextRelevancyEvaluator,)judges = {}judges["answer_relevancy"] = AnswerRelevancyEvaluator( llm=OpenAI(temperature=0, model="gpt-3.5-turbo"),)judges["context_relevancy"] = ContextRelevancyEvaluator( llm=OpenAI(temperature=0, model="gpt-4"),) # 现在,我们可以使用我们的评估器通过循环遍历所有的<示例,预测>对来进行评估。 # # In[ ]: eval_tasks = [] for example, prediction in zip( rag_dataset.examples, prediction_dataset.predictions ): eval_tasks.append( judges["answer_relevancy"].aevaluate( query=example.query, response=prediction.response, sleep_time_in_seconds=1.0, ) ) eval_tasks.append( judges["context_relevancy"].aevaluate( query=example.query, contexts=prediction.contexts, sleep_time_in_seconds=1.0, ) ) # In[ ]: eval_results1 = await tqdm_asyncio.gather(*eval_tasks[:250]) # In[ ]: eval_results2 = await tqdm_asyncio.gather(*eval_tasks[250:]) # In[ ]: eval_results = eval_results1 + eval_results2 # In[ ]: evals = { "answer_relevancy": eval_results[::2], "context_relevancy": eval_results[1::2], } # ### 查看评估结果 # # 在这里,我们使用一个实用函数将`EvaluationResult`对象的列表转换为更适合笔记本的格式。这个实用函数将提供两个DataFrame,一个包含所有评估结果的详细信息,另一个通过对每种评估方法的所有分数取平均值来进行聚合。 # # In[ ]: from llama_index.core.evaluation.notebook_utils import get_eval_results_df import pandas as pd deep_dfs = {} mean_dfs = {} for metric in evals.keys(): deep_df, mean_df = get_eval_results_df( names=["baseline"] * len(evals[metric]), results_arr=evals[metric], metric=metric, ) deep_dfs[metric] = deep_df mean_dfs[metric] = mean_df # In[ ]: mean_scores_df = pd.concat( [mdf.reset_index() for _, mdf in mean_dfs.items()], axis=0, ignore_index=True, ) mean_scores_df = mean_scores_df.set_index("index") mean_scores_df.index = mean_scores_df.index.set_names(["metrics"]) mean_scores_df # 上述实用程序还提供了在`mean_df`中对所有评估进行平均得分。 # # 我们可以通过在`deep_df`上调用`value_counts()`来查看分数的原始分布。 # # In[ ]: deep_dfs["answer_relevancy"]["scores"].value_counts() # In[ ]: deep_dfs["context_relevancy"]["scores"].value_counts() # 似乎大部分情况下,默认的RAG在生成与查询相关的答案方面表现相当不错。通过查看任何`deep_df`的记录,可以更仔细地了解情况。 # # In[ ]: displayify_df(deep_dfs["context_relevancy"].head(2)) # 当然,您可以根据需要应用任何筛选器。例如,如果您想查看产生不完美结果的示例。 # # In[ ]: cond = deep_dfs["context_relevancy"]["scores"] < 1 displayify_df(deep_dfs["context_relevancy"][cond].head(5))