创建带有内存的代理

在这个笔记本中,我们将使用新的内存保留功能为Amazon Bedrock创建一个代理。

我们将使用一个旅行助手的例子。使用这个代理,我们可以预订新的旅行、更新行程详情和删除现有的预订。

对于这个例子,我们将使用只确认操作而不执行它们的虚拟函数。对于一个真正的实时系统,我们应该实现函数执行并与现有系统集成。

将构建以下架构:

旅行助手代理

先决条件

在开始之前,让我们更新botocore和boto3软件包以确保我们有最新版本。

接下来,我们将导入所需的支持包并设置日志记录器对象。

我们现在可以为所需的AWS服务创建boto3客户端。

接下来,我们可以设置代理和lambda函数的一些配置变量。

让我们现在创建我们的lambda函数。它实现了book_tripupdate_existing_trip_datesdelete_existing_trip_reservation的功能。

接下来,让我们创建lambda IAM角色和策略来调用Bedrock模型。

创建带有内存配置的代理

一旦创建了所需的IAM角色,我们就可以使用Bedrock Agent客户端创建一个新的代理。为此,我们使用create_agent函数。它需要一个代理名称、基础模型和说明。我们还可以提供代理描述。请注意,创建的代理尚未准备就绪。稍后,我们将准备并使用该代理。

作为create_agent过程的一部分,我们想要为代理启用长期内存。为此,我们使用memoryConfiguration参数来启用长达30天的SESSION_SUMMARY内存。我们想要存储内存的天数是通过storageDays配置定义的。

使用SESSION_SUMMARY作为内存类型,我们的代理将总结每个会话并将摘要添加到代理的长期内存中。为了控制这种行为,我们需要在代理调用时传递一个memoryId

创建代理动作组

我们现在将创建一个使用前面创建的lambda函数的代理动作组。create_agent_action_group函数提供了这个功能。我们将使用DRAFT作为代理版本,因为我们还没有创建代理版本或别名。为了告知代理动作组的功能,我们提供了一个动作组描述。

在这个例子中,我们使用functionSchema提供了动作组功能。我们也可以提供一个APISchema。笔记本02-create-agent-with-api-schema.ipynb 提供了这种方法的示例。

要使用函数模式定义函数,我们需要为每个函数提供namedescriptionparameters

允许代理调用动作组lambda

在使用动作组之前,我们需要允许代理调用与动作组关联的lambda函数。这是通过基于资源的策略完成的。让我们为创建的lambda函数添加基于资源的策略。

准备代理

让我们创建一个代理的DRAFT版本,可用于内部测试。

使用内存调用代理

我们现在将调用这个代理,传递一个memoryId,我们将看到如何处理最常见的内存API。

让我们首先创建一个帮助函数来调用我们的代理和一个帮助函数来通过代理名称获取我们的代理id。

invoke_agent_helper函数允许用户向代理发送一个query,并带有一个session_id。会话定义了用户与代理之间的一轮来回对话。代理可以记住会话内的全部上下文。一旦用户结束会话,这个上下文就会被删除。

用户然后可以决定是否使用enable_trace布尔变量启用跟踪,并通过session_state变量传递会话状态作为字典。

如果提供了新的session_id,代理将创建一个没有先前上下文的新对话。如果重复使用相同的session_id,代理就知道与该会话相关的对话上下文。

如果enable_trace设置为True,每个来自代理的响应都会附带一个跟踪,详细说明代理正在编排的步骤。这允许我们跟踪代理的推理(通过Chain of Thoughts提示),从而得到当时对话的最终响应。

要处理内存功能,使用memory_id参数。一旦会话结束,它就会将内容总结为新的会话id作为memory_id的一部分。

最后,我们也可以使用session_state参数传递会话上下文。会话状态允许我们与代理共享以下信息:

  • sessionAttributes: 在用户和代理之间的会话中持续存在的属性。所有使用相同session_id调用的invokeAgent都属于同一个会话,并将共享sessionAttributes,只要会话时间限制没有超过,用户也没有结束会话。sessionAttributes在lambda函数中可用,但不会添加到代理的提示中。因此,我们只能在lambda函数可以处理它们的情况下使用会话属性。我们可以在这里 找到使用会话属性的更多示例。使用lambda函数集成实现细粒度访问控制也是一个很好的模式。我们可以在这里 找到一个示例。
  • promptSessionAttributes: 在单个invokeAgent调用中持续存在的属性。提示属性被添加到提示和lambda函数中。我们还可以在编辑编排基础提示时使用$prompt_session_attributes$占位符。
  • invocationId: 代理在ReturnControlPayload 对象的returnControl字段中返回的id。如果传递Return of Control调用的答案,则需要此字段。我们可以在这里 找到如何使用它的示例。
  • returnControlInvocationResults: 在Amazon Bedrock Agents之外调用操作得到的结果。如果传递Return of Control调用的答案,则需要此字段。我们可以在这里 找到如何使用它的示例。

我们还将使用测试agent_alias_id设置为TSTALIASID。这是一个默认值,我们可以用它来测试正在开发的代理。我们也可以部署我们的代理 来创建代理的新版本并获得新的代理别名id。

使用空内存启动对话

让我们运行一个端到端的对话

我们现在假设代理已经预订了一个行程并为我们提供了一个预订id。然后我们感谢代理的支持。

接下来,我们将end_session设置为True以结束我们的会话。

让我们现在创建一个新的支持函数wait_memory_creation,等待内存被创建。

基于内存信息调用代理

让我们现在使用我们的内存来调用带有存储信息的代理。

这里我们假设代理从内存返回的信息是正确的,我们确认,允许代理执行更新行程预订的函数。

检索内存

现在让我们看看保存到代理的内存。我们可以使用boto3的get_agent_memory功能来实现。它将返回某个memoryId的不同会话摘要。对于这个例子,我们再次使用支持函数wait_memory_creation

删除内存

现在让我们看看保存到代理的内存。我们可以使用boto3的delete_agent_memory功能来实现。它将返回某个memoryId的不同会话摘要。

需要注意的是,通过调用delete_agent_memory功能,我们将删除memoryId中的所有会话。

清理

最后,我们可以选择清理创建的资源。

结论

我们现在已经使用boto3 SDK来创建和调用带有内存的代理进行了实验。我们还学习了如何检索和删除创建的内存。

下一步

作为下一步,我们应该在我们的应用程序中尝试使用代理的内存功能!通过为我们现有的代理启用内存开始吧。