多代理礼宾系统
该存储库包含两种实现下述多代理礼宾系统的方法。第一种是 demo.py
,使用原生 Python 构建。第二种是 workflows.py
,使用 LlamaIndex 的 Workflows 抽象来控制流程。
生成的工作流使用内置的 draw_all_possible_flows()
自动渲染,如下所示:
这段代码的 Workflows 版本的讲解视频可在 YouTube 上观看。
为什么要构建这个系统?
交互式聊天机器人作为客户服务的解决方案已经很常见,而代理通常是聊天机器人实现的一个组成部分。它们提供记忆、自省、工具使用等功能,这些都是一个称职的机器人所必需的。
我们对更大规模的聊天机器人产生了兴趣:那些能够完成数十项任务、有些任务相互依赖、使用数百种工具的机器人。这样的代理会是什么样子?它会有一个庞大的系统提示和大量可供选择的工具,这对代理来说可能会造成困扰。
想象一下,一家银行实施了一个系统,可以:
- 查找特定股票的价格
- 验证用户身份
- 查看账户余额
- 这需要用户先进行身份验证
- 在账户之间转账
- 这需要用户先进行身份验证
- 还需要用户先查看账户余额
这些顶级任务中的每一个都有子任务,例如:
- 股票价格查询可能需要先查找股票代码
- 用户身份验证需要收集用户名和密码
- 账户余额查询需要知道要查看用户的哪个账户
为所有这些任务和子任务设计一个单一的主要提示会非常复杂。因此,我们设计了一个多代理系统,每个顶级任务都有负责的代理,再加上一个能够引导用户到正确代理的"礼宾"代理。
我们构建的内容
我们构建了一个代理系统来完成上述任务。有四个基本的"任务"代理:
- 股票查询代理(负责处理查找股票代码等子任务)
- 身份验证代理(要求输入用户名和密码)
- 账户余额代理(负责处理选择账户等子任务)
- 转账代理(负责处理询问转账目标账户、金额等任务)
还有三个"元"代理:
-
礼宾代理:该代理负责与首次到达的用户互动,告知他们可用的任务类型,并在任务完成时提供反馈。
-
编排代理:该代理从不直接向用户提供输出。相反,它会查看用户当前尝试完成的任务,并以纯文本形式回复应该处理该任务的代理名称。然后代码将路由到该代理。
-
连续性代理:有时需要将代理链接在一起以完成任务。例如,要查看账户余额,你需要先进行身份验证。身份验证代理不知道你是否只是想验证身份还是作为链式操作的一部分,它也不需要知道。当身份验证代理完成时,连续性代理会检查聊天历史以了解原始任务是什么,如果还有更多要做的,它会向编排代理提出新的请求,无需用户进一步输入就能完成任务。
全局状态在所有代理之间共享,用于跟踪用户及其当前状态。
系统的流程大致如下:
系统运行实例
为了了解这个系统在实践中如何运作,这里有一个包含有用调试信息的样本输出。通常显示给用户的输出以洋红色显示,用户输入显示为固定文本
。
在对话开始时,还没有发生任何事情,所以你会被引导到礼宾代理:
当前没有发言者,请求编排代理做出决定"转账"任务需要身份验证。编排代理在决定如何路由您时会检查您是否已通过身份验证(出于某种原因,它会检查两次,这只是一个演示!):已选择礼宾代理
您好!今天我能为您提供什么帮助?以下是我可以协助您的一些事项:
- 查询股票价格
- 验证您的身份
- 查看账户余额(需要先进行身份验证)
- 在账户之间转账(需要先进行身份验证和查看账户余额)
您想做什么?
> 转账
当前没有发言者,请求编排代理决定编排器正在检查是否已通过身份验证
编排器正在检查是否已通过身份验证
已选择身份验证代理
它正确地确定您尚未通过身份验证,因此将您路由到身份验证代理:
要转账,我需要先对您进行身份验证。请提供您的用户名和密码。> seldo
这是一个有趣的部分:您已经提供了输入,但还不足以完成任务(您没有提供密码)。因此,当流程返回到编排代理时,全局状态表明"身份验证"代理已经在运行但尚未完成,所以它会再次路由回身份验证代理,然后再次要求输入密码:
已经有一个发言者:authenticate已选择身份验证代理
记录用户名
谢谢!现在,请提供您的密码。
> monkey
已经有一个发言者:authenticate
已选择身份验证代理
正在登录seldo
检查是否已通过身份验证
身份验证已完成
现在身份验证代理已调用done()
函数,向全局状态表明它已完成任务。因此,流程现在转到延续代理,它查看聊天历史并发现用户试图转账。于是它生成一个提示,就像用户说的一样,并将其发送给编排代理:
您已成功通过身份验证。另一个代理将协助您进行转账。请求延续代理决定下一步该做什么
延续代理说"我想转账。"
当前没有发言者,请求编排代理决定
编排器正在检查账户是否有余额
编排器正在检查账户是否有余额
已选择账户余额代理
现在您已通过身份验证,但还没有查看您的余额,编排代理知道这是转账所必需的。因此,它将您路由到账户余额代理(出于某种原因,它会检查两次):
在您转账之前,需要先查看您的账户余额。让我们先查看您的账户余额。请提供您感兴趣的账户名称。
> Checking
已经有一个发言者:account_balance
已选择账户余额代理
正在查找Checking账户的ID
正在查找账户1234567890的余额
账户余额查询已完成
您的Checking账户余额为1000美元。另一个代理将协助您进行转账。
请求延续代理决定下一步该做什么
延续代理说"我想转账。"
当前没有发言者,请求编排代理决定
已选择转账代理
账户余额代理询问您哪个账户,使用工具获取该账户的ID,然后标记自己已完成。延续代理再次介入,发现您仍未完成最初的转账任务,因此再次提示编排代理。不幸的是,编排代理有点困惑,循环了两次才最终将您路由到转账代理:
转账已完成另一个代理将协助您进行转账。
请求延续代理决定下一步该做什么
延续代理说"我想转账。"
当前没有发言者,请求编排代理决定
已选择转账代理
转账已完成
另一个代理将协助您进行转账。
请求延续代理决定下一步该做什么
延续代理说"我想转账。"
当前没有发言者,请求编排代理决定
编排器正在检查账户是否有余额
已选择转账代理
您已经查看了账户余额。请提供以下详细信息以继续转账:
1. 您想转账的目标账户ID。
2. 您想转账的金额。
> To account ID 1234324
已经有一个发言者:transfer_money
已选择转账代理
您想向账户ID 1234324转账多少金额?
> 500
已经有一个发言者:transfer_money 已选择转账代理
正在检查余额是否充足
正在从账户1234567890向账户1234324转账500元
转账已完成
已成功向账户ID 1234324转账500美元。如果您需要任何进一步的帮助,请随时询问!
正在请求续作代理决定下一步行动
续作代理表示无further_tasks
我们已经完成了任务!续作代理发现没有进一步的任务,并将您引导回礼宾服务。
接下来
我们认为这里有一些新颖的内容:协调多个代理同时"交谈",通过自然语言指令创建隐式代理"链",使用"续作"代理管理这些链,以及以这种方式使用全局状态。我们很期待看到您如何运用我们在这里展示的模式。