微信扫码
与创始人交个朋友
我要投稿
本指南通过使用我们的OpenAIAssistantAgent
基准测试OpenAI Assistant API中的检索工具。我们对Llama 2论文进行测试,并与简单的RAG管道的生成质量进行比较。
%pip install llama-index-readers-file pymupdf
%pip install llama-index-agent-openai
%pip install llama-index-llms-openai
!pip install llama-index
import nest_asyncio
nest_asyncio.apply()
这里我们加载 Llama 2 论文并将其分块。
!mkdir -p 'data/'
!wget --user-agent "Mozilla" "https://arxiv.org/pdf/2307.09288.pdf" -O "data/llama2.pdf"
--2023-11-08 21:53:52--https://arxiv.org/pdf/2307.09288.pdf
正在解析 arxiv.org (arxiv.org)... 128.84.21.199
正在连接 arxiv.org (arxiv.org)|128.84.21.199|:443... 已连接。
已发送 HTTP 请求,正在等待响应... 200 OK
长度:13661300 (13M) [application/pdf]
正在保存至: ‘data/llama2.pdf’
data/llama2.pdf 100%[===================>]13.03M 141KB/s用时 1m 48s
2023-11-08 21:55:42 (123 KB/s) - ‘data/llama2.pdf’ 已保存 [13661300/13661300]
from pathlib import Path
from llama_index.core import Document, VectorStoreIndex
from llama_index.readers.file import PyMuPDFReader
from llama_index.core.node_parser import SimpleNodeParser
from llama_index.llms.openai import OpenAI
loader = PyMuPDFReader()
docs0 = loader.load(file_path=Path("./data/llama2.pdf"))
doc_text = "\n\n".join([d.get_content() for d in docs0])
docs = [Document(text=doc_text)]
node_parser = SimpleNodeParser.from_defaults()
nodes = node_parser.get_nodes_from_documents(docs)
len(nodes)
89
我们设置评估模块,包括数据集和评估器。
这里我们加载一个“黄金”数据集。
注意:我们从Dropbox中拉取。有关如何生成数据集的详细信息,请参阅我们的DatasetGenerator
模块。
!wget "https://www.dropbox.com/scl/fi/fh9vsmmm8vu0j50l3ss38/llama2_eval_qr_dataset.json?rlkey=kkoaez7aqeb4z25gzc06ak6kb&dl=1" -O data/llama2_eval_qr_dataset.json
from llama_index.core.evaluation import QueryResponseDataset
# 可选
eval_dataset = QueryResponseDataset.from_json(
"data/llama2_eval_qr_dataset.json"
)
如果您选择此选项,您可以从头开始生成新数据集。这使您可以调整DatasetGenerator
设置,以确保满足您的需求。
from llama_index.core.evaluation import DatasetGenerator, QueryResponseDataset
from llama_index.llms.openai import OpenAI
# 注意:如果数据集尚未保存,请运行此代码
# 注意:我们仅从前20个节点生成,因为其余节点是引用
llm = OpenAI(model="gpt-4-1106-preview")
dataset_generator = DatasetGenerator(
nodes[:20],
llm=llm,
show_progress=True,
num_questions_per_chunk=3,
)
eval_dataset = await dataset_generator.agenerate_dataset_from_nodes(num=60)
eval_dataset.save_json("data/llama2_eval_qr_dataset.json")
# 可选
eval_dataset = QueryResponseDataset.from_json(
"data/llama2_eval_qr_dataset.json"
)
我们定义了两个评估模块:正确性和语义相似性 - 两者都比较预测响应与实际响应的质量。
from llama_index.core.evaluation.eval_utils import (
get_responses,
get_results_df,
)
from llama_index.core.evaluation import (
CorrectnessEvaluator,
SemanticSimilarityEvaluator,
BatchEvalRunner,
)
from llama_index.llms.openai import OpenAI
eval_llm = OpenAI(model="gpt-4-1106-preview")
evaluator_c = CorrectnessEvaluator(llm=eval_llm)
evaluator_s = SemanticSimilarityEvaluator(llm=eval_llm)
evaluator_dict = {
"correctness": evaluator_c,
"semantic_similarity": evaluator_s,
}
batch_runner = BatchEvalRunner(evaluator_dict, workers=2, show_progress=True)
import numpy as np
import time
import os
import pickle
from tqdm import tqdm
def get_responses_sync(
eval_qs, query_engine, show_progress=True, save_path=None
):
if show_progress:
eval_qs_iter = tqdm(eval_qs)
else:
eval_qs_iter = eval_qs
pred_responses = []
start_time = time.time()
for eval_q in eval_qs_iter:
print(f"eval q: {eval_q}")
pred_response = agent.query(eval_q)
print(f"predicted response: {pred_response}")
pred_responses.append(pred_response)
if save_path is not None:
# 保存中间响应(作为缓存,以防出现异常)
avg_time = (time.time() - start_time) / len(pred_responses)
pickle.dump(
{"pred_responses": pred_responses, "avg_time": avg_time},
open(save_path, "wb"),
)
return pred_responses
async def run_evals(
query_engine,
eval_qa_pairs,
batch_runner,
disable_async_for_preds=False,
save_path=None,
):
# 然后进行评估
# TODO: 评估生成结果的样本
eval_qs = [q for q, _ in eval_qa_pairs]
eval_answers = [a for _, a in eval_qa_pairs]
if save_path is not None:
if not os.path.exists(save_path):
start_time = time.time()
if disable_async_for_preds:
pred_responses = get_responses_sync(
eval_qs,
query_engine,
show_progress=True,
save_path=save_path,
)
else:
pred_responses = get_responses(
eval_qs, query_engine, show_progress=True
)
avg_time = (time.time() - start_time) / len(eval_qs)
pickle.dump(
{"pred_responses": pred_responses, "avg_time": avg_time},
open(save_path, "wb"),
)
else:
# [可选] 加载
pickled_dict = pickle.load(open(save_path, "rb"))
pred_responses = pickled_dict["pred_responses"]
avg_time = pickled_dict["avg_time"]
else:
start_time = time.time()
pred_responses = get_responses(
eval_qs, query_engine, show_progress=True
)
avg_time = (time.time() - start_time) / len(eval_qs)
eval_results = await batch_runner.aevaluate_responses(
eval_qs, responses=pred_responses, reference=eval_answers
)
return eval_results, {"avg_time": avg_time}
我们将通过传递内置的OpenAI检索工具来构建助手。
在这里,我们上传并在创建助手时传入文件。
from llama_index.agent.openai import OpenAIAssistantAgent
agent = OpenAIAssistantAgent.from_new(
name="SEC 分析师",
instructions="你是一个设计用来分析SEC文件的QA助手。",
openai_tools=[{"type": "retrieval"}],
instructions_prefix="请以Jerry称呼用户。",
files=["data/llama2.pdf"],
verbose=True,
)
response = agent.query(
"Llama 2 和 Llama 2-Chat 的主要区别是什么?"
)
print(str(response))
根据文档,Llama 2 和 Llama 2-Chat 的主要区别在于它们在安全评估中的表现,特别是在对抗性提示测试中。Llama 2-Chat 的安全评估部分突出显示了以下一些差异:
...
我们在评估数据集上运行代理。我们使用标准的 top-k RAG 管道(k=2)与 gpt-4-turbo 进行基准对比。
注意:在我们测试的时期(2023年11月),助手API的速率限制非常严格,对60个数据点生成响应可能需要约1-2小时。
llm = OpenAI(model="gpt-4-1106-preview")
base_index = VectorStoreIndex(nodes)
base_query_engine = base_index.as_query_engine(similarity_top_k=2, llm=llm)
base_eval_results, base_extra_info = await run_evals(
base_query_engine,
eval_dataset.qr_pairs,
batch_runner,
save_path="data/llama2_preds_base.pkl",
)
results_df = get_results_df(
[base_eval_results],
["基线查询引擎"],
["正确性", "语义相似度"],
)
display(results_df)
names | correctness | semantic_similarity | |
---|---|---|---|
0 | 基线查询引擎 | 4.05 | 0.964245 |
assistant_eval_results, assistant_extra_info = await run_evals(
agent,
eval_dataset.qr_pairs[:55],
batch_runner,
save_path="data/llama2_preds_assistant.pkl",
disable_async_for_preds=True,
)
我们看到...我们的基本 RAG 管道表现更好。
对这些数字持保留态度。这里的目标是提供一个脚本,以便您可以在自己的数据上运行。
尽管如此,检索API没有立即提供开箱即用的更好性能,这还是令人惊讶的。
results_df = get_results_df(
[assistant_eval_results, base_eval_results],
["检索API", "基线查询引擎"],
["正确性", "语义相似度"],
)
display(results_df)
print(f"基线平均时间: {base_extra_info['avg_time']}")
print(f"助手平均时间: {assistant_extra_info['avg_time']}")
names | correctness | semantic_similarity | |
---|---|---|---|
0 | 检索API | 3.536364 | 0.952647 |
1 | 基线查询引擎 | 4.050000 | 0.964245 |
基线平均时间: 0.25683316787083943
助手平均时间: 75.43605598536405
53AI,企业落地应用大模型首选服务商
产品:大模型应用平台+智能体定制开发+落地咨询服务
承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2024-12-17
llamaindex实战-ChatEngine-Context(上下文)模式
2024-12-01
LlamaIndex,让AI唤醒你的数据
2024-11-29
llamaindex实战-Agent-自定义工具函数
2024-11-22
llamaindex实战-Agent-让Agent调用多个工具函数(本地部署)
2024-11-19
llamaindex实战-Workflow:工作流入门(本地部署断网运行)
2024-11-15
llamaindex实战-Agent-在Agent中使用RAG查询(本地部署)
2024-11-07
深度解析 REAcT Agent 的实现:利用 LlamaIndex 和 Gemini 提升智能代理工作流
2024-11-04
手把手教你用Coze零代码搭建一个智能搜索智能体,高时效性、保姆级!
2024-07-09
2024-04-20
2024-06-05
2024-04-25
2024-04-28
2024-05-09
2024-07-20
2024-04-26
2024-06-19
2024-04-08