用法模式#
入门指南#
代理程序是从一组工具初始化的。以下是一个从一组工具实例化 ReAct 代理程序的示例。
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
from llama_index.core.agent import ReActAgent
# 定义示例工具
def multiply(a: int, b: int) -> int:
"""将两个整数相乘并返回结果整数"""
return a * b
multiply_tool = FunctionTool.from_defaults(fn=multiply)
# 初始化 llm
llm = OpenAI(model="gpt-3.5-turbo-0613")
# 初始化 ReAct 代理程序
agent = ReActAgent.from_tools([multiply_tool], llm=llm, verbose=True)
代理程序支持 chat
和 query
两种端点,分别继承自我们的 ChatEngine
和 QueryEngine
。
示例用法:
agent.chat("What is 2123 * 215123")
要根据 LLM 自动选择最佳代理程序,可以使用 from_llm
方法生成代理程序。
from llama_index.core.agent import AgentRunner
agent = AgentRunner.from_llm([multiply_tool], llm=llm, verbose=True)
定义工具#
查询引擎工具#
将查询引擎包装为代理程序工具也很容易。只需按照以下步骤操作:
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import QueryEngineTool
# 注意:lyft_index 和 uber_index 都是 SimpleVectorIndex 实例
lyft_engine = lyft_index.as_query_engine(similarity_top_k=3)
uber_engine = uber_index.as_query_engine(similarity_top_k=3)
query_engine_tools = [
QueryEngineTool(
query_engine=lyft_engine,
metadata=ToolMetadata(
name="lyft_10k",
description="提供 2021 年 Lyft 财务信息。"
"使用详细的纯文本问题作为工具的输入。",
),
return_direct=False,
),
QueryEngineTool(
query_engine=uber_engine,
metadata=ToolMetadata(
name="uber_10k",
description="提供 2021 年 Uber 财务信息。"
"使用详细的纯文本问题作为工具的输入。",
),
return_direct=False,
),
]
# 初始化 ReAct 代理程序
agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
使用其他代理程序作为工具#
我们代理程序的一个巧妙特性是,由于它们继承自 BaseQueryEngine
,所以可以通过我们的 QueryEngineTool
轻松地将其他代理程序定义为工具。
from llama_index.core.tools import QueryEngineTool
query_engine_tools = [
QueryEngineTool(
query_engine=sql_agent,
metadata=ToolMetadata(
name="sql_agent", description="可以执行 SQL 查询的代理程序。"
),
),
QueryEngineTool(
query_engine=gmail_agent,
metadata=ToolMetadata(
name="gmail_agent",
description="可以在 Gmail 上发送电子邮件的工具。",
),
),
]
outer_agent = ReActAgent.from_tools(query_engine_tools, llm=llm, verbose=True)
具有规划的代理程序#
将初始任务分解为更易理解的子任务是一种强大的模式。
LlamaIndex 提供了一个代理程序规划模块,正是做到了这一点:
from llama_index.agent.openai import OpenAIAgentWorker
from llama_index.core.agent import (
StructuredPlannerAgent,
FunctionCallingAgentWorker,
)
worker = FunctionCallingAgentWorker.from_tools(tools, llm=llm)
agent = StructuredPlannerAgent(worker)
一般来说,与基本的 AgentRunner
类相比,这种代理程序可能需要更长时间来响应,但输出通常会更完整。另一个要考虑的权衡是,规划通常需要一个非常有能力的 LLM(例如,gpt-3.5-turbo
有时对规划不太稳定,而 gpt-4-turbo
做得更好)。
在 完整指南 中了解更多信息。
低级 API#
OpenAIAgent 和 ReActAgent 只是与与 AgentRunner
交互的 AgentWorker
的简单包装。
所有代理程序都可以用这种方式定义。例如,对于 OpenAIAgent:
from llama_index.core.agent import AgentRunner
from llama_index.agent.openai import OpenAIAgentWorker
# 从工具构建 OpenAIAgent
openai_step_engine = OpenAIAgentWorker.from_tools(tools, llm=llm, verbose=True)
agent = AgentRunner(openai_step_engine)
这也是自定义代理程序的首选格式。
查看 低级代理程序指南 以获取更多详细信息。
自定义您的代理程序#
如果您希望自定义您的代理程序,可以选择对 CustomSimpleAgentWorker
进行子类化,并将其插入到 AgentRunner 中(参见上文)。
from llama_index.core.agent import CustomSimpleAgentWorker
class MyAgentWorker(CustomSimpleAgentWorker):
"""自定义代理程序工作者。"""
# 在此定义类
pass
# 将工作者包装到 AgentRunner 中
agent = MyAgentWorker(...).as_agent()
高级概念(适用于 OpenAIAgent
,处于测试版)#
您还可以在更高级的设置中使用代理。例如,在查询时能够从索引中检索工具,并且能够在现有工具集上执行查询规划。
这些功能主要是使用我们的 OpenAIAgent
类实现的(依赖于 OpenAI 函数 API)。我们正在积极研究对更通用的 ReActAgent
的支持。
注意:这些功能主要仍处于测试版。抽象化可能会随时间变化并变得更通用。
功能检索代理#
如果工具集非常庞大,您可以创建一个 ObjectIndex
来索引这些工具,然后在查询时向代理传递一个 ObjectRetriever
,以便在代理从候选工具中选择之前,首先动态检索相关工具。
首先,我们在现有工具集上构建一个 ObjectIndex
。
# 在这些工具上定义一个“对象”索引
from llama_index.core import VectorStoreIndex
from llama_index.core.objects import ObjectIndex
obj_index = ObjectIndex.from_objects(
all_tools,
index_cls=VectorStoreIndex,
)
然后我们定义我们的 OpenAIAgent
:
from llama_index.agent.openai import OpenAIAgent
agent = OpenAIAgent.from_tools(
tool_retriever=obj_index.as_retriever(similarity_top_k=2), verbose=True
)
您可以在完整指南中找到有关对象索引的更多详细信息。
上下文检索代理#
我们的上下文增强的 OpenAI 代理在调用任何工具之前总是执行检索。
这有助于提供额外的上下文,可以帮助代理更好地选择工具,而不仅仅是在没有任何上下文的情况下做出决定。
from llama_index.core import Document
from llama_index.agent.openai_legacy import ContextRetrieverOpenAIAgent
# 玩具索引 - 存储缩写列表
texts = [
"缩写:X = 收入",
"缩写:YZ = 风险因素",
"缩写:Z = 成本",
]
docs = [Document(text=t) for t in texts]
context_index = VectorStoreIndex.from_documents(docs)
# 添加上下文代理
context_agent = ContextRetrieverOpenAIAgent.from_tools_and_retriever(
query_engine_tools,
context_index.as_retriever(similarity_top_k=1),
verbose=True,
)
response = context_agent.chat("2022年3月的 YZ 是什么?")
查询规划#
OpenAI 函数代理可以实现高级查询规划。关键是为代理提供一个 QueryPlanTool
- 如果代理调用 QueryPlanTool,则必须推断出代表一组子工具的查询计划的完整 Pydantic 模式。
# 定义查询计划工具
from llama_index.core.tools import QueryPlanTool
from llama_index.core import get_response_synthesizer
response_synthesizer = get_response_synthesizer(
service_context=service_context
)
query_plan_tool = QueryPlanTool.from_defaults(
query_engine_tools=[query_tool_sept, query_tool_june, query_tool_march],
response_synthesizer=response_synthesizer,
)
# 初始化代理
agent = OpenAIAgent.from_tools(
[query_plan_tool],
max_function_calls=10,
llm=OpenAI(temperature=0, model="gpt-4-0613"),
verbose=True,
)
# 应输出一个查询计划,以调用三月、六月和九月的工具
response = agent.query(
"分析 Uber 在三月、六月和九月的收入增长"
)