我们听到的最常见的请求之一是为创建自定义代理提供更好的功能和文档。这一直有点棘手——因为在我们看来,实际上仍然非常不清楚“代理”到底是什么,因此,适合它们的“正确”抽象可能是什么。最近,我们感到一些抽象开始融合在一起,因此我们在 Python 和 TypeScript 模块中都进行了大力推动,以更好地加强和记录这些抽象。请参阅下面的链接,查看这些技术文档,然后查看我们引入的抽象以及未来的方向的描述。
TL;DR: 我们引入了 BaseSingleActionAgent
作为代理的最高级别抽象,可在我们当前的 AgentExecutor
中使用。我们添加了一个更实用的 LLMSingleActionAgent
,它以简单且可扩展的方式(PromptTemplate + LLM + OutputParser)实现了此接口。
BaseSingleActionAgent
我们引入的最基本的抽象是 BaseSingleActionAgent
。正如您从名称中可以看出,我们不认为这是所有代理的基本抽象。相反,我们认为这是每次预测单个动作的一系列代理的基本抽象。
SingleActionAgent
在我们当前的 AgentExecutor
中使用。此 AgentExecutor
在很大程度上可以被认为是以下循环:
- 将用户输入和任何先前的步骤传递给代理
- 如果代理返回
AgentFinish
,则直接将其返回给用户 - 如果代理返回
AgentAction
,则使用它来调用工具并获取Observation
- 重复,将
AgentAction
和Observation
传递回代理,直到发出AgentFinish
。
AgentAction
是一个响应,由 action
和 action_input
组成。action
指的是要使用的工具,action_input
指的是该工具的输入。
AgentFinish
是一个响应,其中包含要发送回用户的最终消息。这应该用于结束代理运行。
如果您对此级别的可定制性感兴趣,请查看此演练。但是,对于大多数用例,我们建议使用下面的抽象。
LLMSingleActionAgent
我们引入的另一个类是 LLMSingleActionAgent
。这是 BaseSingleActionAgent
的具体实现,但高度模块化,因此也高度可定制。
LLMSingleActionAgent
由四个部分组成:
PromptTemplate
:这是提示模板,可用于指导语言模型执行什么操作LLM
:这是为代理提供支持的语言模型stop
序列:指示LLM
在找到此字符串后立即停止生成OutputParser
:这决定了如何将LLM
的输出解析为AgentAction
或AgentFinish
对象
组合这些的逻辑是:
- 使用
PromptTemplate
将输入变量(包括用户输入和任何先前的AgentAction
、Observation
对)转换为提示 - 将提示传递给
LLM
,并带有特定的stop
序列 - 将
LLM
的输出解析为AgentAction
或AgentFinish
对象
这些抽象可以用于以多种方式自定义您的代理。例如:
- 想给你的代理一些个性?使用
PromptTemplate
! - 想要以特定方式格式化先前的
AgentAction
、Observation
对?使用PromptTemplate
! - 想要使用自定义或本地模型?编写一个自定义 LLM 包装器并将其作为 LLM 传入!
- 输出解析是否过于脆弱,或者您想以不同的方式处理错误?使用自定义 OutputParser!
(最后一个用粗体表示,因为这可能是我们听到最多的)
我们认为这是最实用的抽象。请参阅博客开头的文档链接,获取有关 Python/TypeScript 入门的具体指南的链接。
未来方向
我们希望这些抽象能够阐明我们对代理的一些思考,并开放我们希望社区可以做出贡献的地方。特别是:
我们对 SingleActionAgents
的其他示例感到非常兴奋,例如:
- 在调用
LLM
之前使用嵌入进行工具选择 - 使用
ConstitutionalChain
而不是LLMChain
来提高可靠性
我们还对其他类型的代理(这将需要新的 AgentExecutors
)感到兴奋,例如:
- 多动作代理
- 计划-执行代理
如果其中任何一个听起来很有趣,我们总是愿意与大家合作来实现他们的想法!最好的方法可能是先做一些初步工作,打开一个 RFC 拉取请求,我们很乐意从那里开始:)