Agent代理
在大型语言模型(LLM, Large Language Model
)中,Agent代理通常指的是一个能够执行特定任务或操作的软件实体。这些任务可能包括但不限于信息检索、数据分析、文本生成、对话管理等。在不同的应用场景下,Agent的功能和设计会有所不同,但它们共同的目标是提高自动化水平、增强用户体验和效率。
Agent的主要特点
- 自主性:Agent能够在一定程度上独立运作,根据环境变化做出决策。
- 交互性:与用户或其他系统进行有效沟通,提供或请求必要的信息。
- 适应性:能够学习和适应新情况,改进自己的表现。
- 目标导向:每个Agent都有明确的任务或目标,围绕这些目标进行工作。
应用场景
- 客户服务:作为虚拟助手回答常见问题,提供产品信息,处理客户投诉等。
- 个人助理:帮助用户管理日程、提醒重要事项、搜索网络信息等。
- 教育辅助:为学生提供个性化学习建议,辅导作业等。
- 医疗健康:提供初步的健康咨询,帮助患者记录健康状况等。
- 娱乐互动:开发游戏中的非玩家角色(NPC),增加游戏的真实感和趣味性。
技术实现
在技术层面,Agent的设计通常涉及到自然语言处理(NLP)、机器学习(ML)、知识表示与推理等多个领域。通过这些技术,Agent能够理解用户的意图,处理复杂的任务,并以人类可理解的方式交流反馈。
例如,在客服场景中,一个基于LLM的Agent需要能够准确地理解客户的查询或投诉,利用预先训练好的模型来分析问题,然后从数据库中检索相关信息或直接生成适当的响应。这一过程不仅要求模型具备强大的语言理解和生成能力,还需要有良好的逻辑推理能力和数据处理能力。
随着人工智能技术的发展,Agent代理的应用将更加广泛,功能也会越来越强大,为用户提供更加智能、便捷的服务。
入门
代理由一组工具初始化。以下是从一组工具实例化 ReAct
代理的示例。
from llama_index.core.tools import FunctionTool
from llama_index.llms.openai import OpenAI
from llama_index.core.agent import ReActAgent
# define sample Tool
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("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="提供Lyft 2021年的财务信息。 "
"使用一个详细的纯文本问题作为工具的输入。",
),
return_direct=False,
),
QueryEngineTool(
query_engine=uber_engine,
metadata=ToolMetadata(
name="uber_10k",
description="提供Uber 2021年的财务信息。 "
"使用一个详细的纯文本问题作为工具的输入。",
),
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)
这也是定制代理的首选格式。
请查看下级代理指南以了解更多详细信息。
自定义您的代理
如果您希望定义自定义代理,最简单的方法就是定义一个状态函数FnAgentWorker
并用 包装它。
传入和传出函数的变量state
可以包含任何您想要的内容,无论是工具还是任意变量。它还包含任务和输出对象。
## 这个例子展示了一个简单的函数,每次将输入的数字乘以2。
## 把这个交给代理人
def multiply_agent_fn(state: dict) -> Tuple[Dict[str, Any], bool]:
"""Mock agent input function."""
if "max_count" not in state:
raise ValueError("max_count must be specified.")
# __output__ is 是一个特殊的键表示代理的最终输出
# __task__ 是一个特殊的键,表示代理传递给函数的Task对象。
# `task.input` 是传递的输入字符串
if "__output__" not in state:
state["__output__"] = int(state["__task__"].input)
state["count"] = 0
else:
state["__output__"] = state["__output__"] * 2
state["count"] += 1
is_done = state["count"] >= state["max_count"]
# 这个函数的输出应该是状态变量和is_done的元组
return state, is_done
from llama_index.core.agent import FnAgentWorker
agent = FnAgentWorker(
fn=multiply_agent_fn, initial_state={
"max_count": 5}
).as_agent()
agent.query("5")
请参阅我们的“定制代理笔记本指南”以了解更多详细信息。
高级概念(针对OpenAIAgent,测试版)
您还可以在更高级的设置中使用代理。例如,能够在查询时从索引中检索工具,并能够对现有的一组工具执行查询规划。
OpenAIAgent
这些主要通过我们的类(依赖于 OpenAI 函数 API
)实现。ReActAgent
我们正在积极研究对更通用的支持。
注意:这些概念大部分仍处于测试阶段。随着时间的推移,抽象概念可能会发生变化,并变得更加通用。
功能检索代理
如果工具集非常大,您可以创建一个ObjectIndex
来索引工具,然后ObjectRetriever
在查询时将一个传递给代理,首先动态检索相关工具,然后让代理从候选工具中进行选择。
我们首先构建一套ObjectIndex
现有的工具。
# define an "object" index over these tools
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 = [
"Abbreviation: X = Revenue",
"Abbreviation: YZ = Risk Factors",
"Abbreviation: Z = Costs",
]
docs = [Document(text=t) for t in texts]
context_index = VectorStoreIndex.from_documents(docs)
# add context agent
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
模式,该模式表示一组子工具上的查询计划。
# define query plan tool
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,
)
# initialize agent
agent = OpenAIAgent.from_tools(
[query_plan_tool],
max_function_calls=10,
llm=OpenAI(temperature=0, model="gpt-4-0613"),
verbose=True,
)
# 是否应该输出查询计划来调用3月、6月和9月的工具
response = agent.query(
"分析Uber在3月、6月和9月的收入增长情况"
)