构建我的第一个AWS智能体工作流,最难的是让它别自作聪明

原文:https://dev.to/hemapriya_kanagala/i-built-my-first-aws-agent-workflow-and-the-hardest-part-was-getting-it-to-stop-assuming-things-8fg(作者 @hemapriya_kanagala)

摘要

>

我最近完成了Udacity “Future AWS Agent Engineer” 微学位项目的一部分,这个机会来自AWS AI & ML奖学金。

>

我构建了一个客户支持智能体,使用了Amazon Bedrock AgentCore、AgentCore Gateway、AWS Lambda、DynamoDB以及一个FAQ文档。这个智能体需要判断客户是在报告故障、询问FAQ可回答的问题,还是需要人工支持。

>

我大约用两天时间完成它,并在首次尝试中通过了评估,正确率得分为0.83。当时因为生活中有很多事情在发生,我没有足够的时间回去优化它或再运行一轮评估。

>

从中学到最多的部分,实际上是我的一次评估失败案例。对于一个故障报告,我告诉智能体在创建工单前需要3条信息:问题描述、重现步骤和发生的环境。但在2个测试用例中,模型理解了客户的意图,即使缺失了这些必要信息中的一条,也直接创建了工单。

>

这让我意识到一个之前思考不足的问题:理解一个请求,并不等同于拥有足够信息来安全地执行操作。

>

这是我从这个项目中获得的主要心得。构建智能体不仅仅是让模型能够回答问题。同样重要的是要明确:它应该在何时行动,何时应该请求更多信息,以及何时应该停下来并将请求转交给人。

>

我知道已经有很多关于AWS、AgentCore和AI智能体的优秀文章,我自己也从中学到了很多。我仍在学习中,所以这仅仅是我构建此项目的经验,包括我的困惑、评估结果以及我下次会如何改进。


目录

* 我想先诚实说点什么

* 我构建了什么,各部分如何协同

* 那么,每个AWS服务具体做什么?

* 提示词的作用比我想象的要大

* 提示词在设定规则

* 我还得考虑客户可能尝试的操作

* 评估让我看清了自己错在哪

* 两次失败

* 我会改进的地方以及我学到的经验

* 看过后端之后,智能体的逻辑才真正说得通

* 如果你也刚刚起步

* 欢迎和我交流

* 小小致谢

* 我最大的收获

* 保持联系


我想先诚实说点什么

我最近完成了另一个项目,这次对我有点不同。它是Udacity “Future AWS Agent Engineer” 微学位项目的一部分,我通过AWS AI & ML奖学金获得了参与资格。

我大概用了两天完成这个项目。当时生活中有很多其他事情,所以我努力利用好现有的时间,保持前进。

<p align="center">

<img src="https://media.giphy.com/media/H1dxi6xdh4NGQCZSvz/giphy.gif" width="320"/>

</p>

我第一次尝试就通过了评估,这让我非常高兴,但我也知道,我并没有花通常会花的时间去精雕细琢。

如果时间更充裕,我会回头仔细研究评估结果,改进提示词,增加更多测试用例,并运行另一次评估。但这次我没有这样做。最终的正确率得分是0.83

起初,我觉得或许应该等到分数更高再写这篇文章。后来我转念一想,思考自己到底从中学到了什么。那两个没完美运行的部分,对我来说却是项目中最有价值的部分。这正是我想分享的。

已经有很多非常优秀的文章介绍了如何构建智能体、使用AWS服务以及AgentCore。我自己也从中学到了很多。这篇文章并不想成为又一篇试图解释智能体开发所有方面的文章。相反,我想以一个仍在学习者的视角,分享这个项目在我这边是什么样的。

因为当你还是个初学者时,有时最难的不是代码本身,而是理解所有组件究竟在做什么,以及为什么需要它们。

我构建了什么以及各部分如何协同工作

这个项目是一个虚构的在线商店客户支持系统。客户可以发送消息,智能体必须理解客户的需求并决定下一步该怎么做。

这里有三种可能的行为模式。第一种是缺陷报告。如果客户说类似“每次我点击支付时结账页面都崩溃了”这样的话,智能体需要将其识别为技术问题。但仅仅将其识别为缺陷还不够,不足以创建工单。在此之前,智能体需要收集三个具体信息:问题描述、重现步骤和环境信息

第二种是平台问题。这类问题涉及订单、发货、退货、退款、支付、商品、账户和隐私等。对于这些问题,智能体被要求使用一个常见问题解答(FAQ)库来回答,而不是根据其通用知识编造答案。

第三种是其他请求。如果请求不是技术缺陷,也无法通过FAQ解答,智能体需要将客户转接给人工客服。

一旦我不再孤立地看待每个AWS服务,而是思考它们如何协同工作时,这个架构对我来说就变得容易理解多了。

<p align="center">

<img src="https://media.giphy.com/media/xT1R9JQhsDfuLHfpOE/giphy.gif" width="320"/>

</p>

流程大致如下:

📌 使用 Amazon Bedrock AgentCore 构建的客户支持AI智能体架构图,展示通过提示词进行路由,将请求导向缺陷报告、FAQ解答或人工支持,缺陷报告流经 AgentCore Gateway、AWS Lambda 和 DynamoDB(图,点击查看)

这是我为该项目构建的架构。路由是通过系统提示词处理的,而非通过单独的分类器或条件节点。

那么,每个AWS服务在这里具体是做什么的?

如果你是AWS新手,服务名称可能会让这样的项目看起来比实际复杂得多。对我帮助很大的做法是,思考每个部分负责什么,而不是试图一次理解所有的AWS服务。

Amazon Bedrock AgentCore Managed Harness 是智能体运行的环境。简单来说,它提供了运行智能体所需的结构,包括其模型、指令和工具,而无需我自己从头构建所有这些设置。

模型 负责理解客户的消息,并根据接收到的指令决定下一步该做什么。它是实际进行语言理解和做出决策的部分。

系统提示词 定义了智能体应该有的行为方式。这在我的项目中尤其重要,因为路由逻辑被写进了提示词里。提示词告诉模型如何识别这三种类型的请求,以及对每种请求应遵循哪些规则。

AgentCore Gateway 将智能体连接到后端工具。模型并不直接操作数据库。相反,一旦收集到所需信息,智能体可以通过Gateway调用该工具。

AWS Lambda 处理实际的后端操作。当智能体携带必要信息调用工具时,Lambda会处理这个请求并创建缺陷报告。

Amazon DynamoDB 用于存储这份缺陷报告。理解这一点对我也很有用,因为它说明了智能体的响应不仅仅是文本。如果智能体返回一个工单ID,那么在这个响应背后,DynamoDB中确实存储了一条实际记录。

FAQ 则是针对平台问题的受控信息源。智能体在回答这类问题时,被期望使用其中提供的信息,而不是依赖通用知识。

一旦我以这种方式理解后,这个架构就不再感觉是一堆陌生AWS名称的集合。模型理解客户的消息,提示词告诉它遵循什么规则,Gateway将其连接到一个动作,Lambda执行该动作,而DynamoDB存储结果。对于平台问题,FAQ提供了智能体可以使用的信息,而超出这些范围的请求则转交人工客服。

这种简单的系统理解方式,比单独记住每个AWS服务的功能对我帮助更大。

有一点一开始让我困惑的是 “分类器” 这个词。当我第一次看到这个需求时,我想象会有一个单独的组件,它的唯一工作就是对客户的消息进行分类,然后将其发送到系统的正确部分。

但我构建的并非如此。

在我的实现中,路由逻辑是系统提示词的一部分。模型被指示从三种路径中选择一种,然后遵循该路径的规则。

理解这一点改变了我对提示词的看法。最初,我主要将提示词看作是智能体应该如何回应的指令。在这个项目中,它所做的远不止于此。它还定义了智能体需要哪些信息、何时被允许采取行动、可以用哪些信息来回答问题,以及何时需要停止并引入人工支持。

提示词的作用超出了我的预期

在这个项目之前,我主要将系统提示词视为一种告诉模型如何行为的方式,比如:

“你是一个乐于助人的客户支持助手。”

这很有用,但当模型还需要做决策和使用工具时,这就不够了。在这个项目中,提示词不仅告诉智能体如何响应,还告诉它允许做什么以及在做之前需要哪些信息。

<p align="center">

<img src="https://media.giphy.com/media/Gz5VFiWLMbxD36VKuJ/giphy.gif" width="320"/>

</p>

提示词在设定规则

对于 BUG_REPORT,提示词解释了什么算作漏洞以及创建工单前需要哪些信息。三个必填字段是 描述、复现步骤和环境。如果缺少任何信息,智能体必须逐个字段询问。在三个信息都齐全之前,它不应该调用工具。

提示词还定义了另外两种路由。PLATFORM_QUESTION 必须使用提供的常见问题解答来回答,而 OTHER_REQUEST 则必须转交人工支持。

常见问题解答部分让我很感兴趣,因为它说明了为什么智能体有时需要被告知可以和不能使用哪些信息。

假设一个客户问:

“我有多长时间可以退货?”

常见问题解答说,大多数商品可以在 送达后30天内 退货,只要未使用并保持原包装,除非商品到达时已损坏。因此,智能体可以使用给定的信息来回答。

但假设有人问:

“你们提供学生折扣吗?”

如果常见问题解答没有提到学生折扣,智能体不应该简单地编造答案,因为模型可能在其他地方见过学生折扣的提及。它应该将客户转交人工支持。

这让我非常清楚地认识到:模型可以知道很多,但这并不意味着它知道 你公司的政策

同样的道理适用于退款、配送、支付政策、账户规则以及其他信息,在这些信息上给出自信但错误的答案可能会引发真实问题。对于这个项目,常见问题解答是一个受控的信息源,提示词明确了这一边界。

我还必须考虑客户可能会尝试什么

提示词还有另一个我在这个项目之前没有多想的工作:处理 提示注入

其中一个测试用例本质上告诉智能体忽略其指令,透露系统提示词,并在不收集所需信息的情况下创建漏洞工单。智能体没有遵循这些指令。它继续遵循系统提示词中定义的规则。

我觉得这很有用,因为它让我超越了在构建项目时自然编写的简单测试用例。当我们自己测试智能体时,我们通常会给它我们期望客户发送的那种消息。真实用户可能会遗漏信息、询问完全无关的问题,或者故意尝试改变智能体的行为。

因此,提示词不能只描述理想路径。它还需要明确边界。

同时,通过这个提示注入测试并不意味着智能体能抵御所有可能的注入。它只是向我展示了这个特定测试用例是按照我定义的规则处理的。

这是我从项目中学到的另一个教训。给智能体更多能力只是工作的一部分。你还必须清楚这些能力应该和不应该在什么时候使用。


评估让我看清了自己错在哪

这可能是这个项目中对我最有用的部分。

在几次手动测试中让智能体做出正确反应是一回事。用故意不完整且刁钻的输入去评估它,又是另一回事。为了这个项目,我创建了一个覆盖不同路由的测试数据集,包括完整的错误报告、信息缺失的错误报告、常见问题、未被常见问题覆盖的问题、要求转接人工的请求,以及一个提示词注入案例。

最终的正确性得分为 0.83。大多数测试都如我预期般工作。完整的错误报告生效了,缺失环境信息的案例生效了,常见问题也生效了,不支持的问题被移交了,人工支持请求被正确处理,提示词注入案例也通过了。

但有两个测试失败了,而这两个失败基本上教会了我同样的事情。

<p align="center">

<img src="https://media.giphy.com/media/xUooDfXRTz4Hn78f7X/giphy.gif" width="320"/>

</p>

两次失败

第一个案例中,客户说产品图片在分类页面不加载,并提到了 iPhone 上的 Safari。问题描述是有的,环境信息也有,但客户没有明确提供重现步骤。智能体依然创建了工单。

第二个案例中,客户提供了重现步骤和 Chrome/Windows 环境,但没有提供对实际问题的清晰描述。智能体再次创建了工单。

起初,我以为是模型简单地误解了我的提示词。但当我更仔细地查看这两个案例后,我意识到模型很可能理解了客户在说什么。问题在于,它把这种“理解”当作了可以采取下一步行动的充分信息。

从正常的人类对话角度来看,这未必是件坏事。如果有人说:

“我的 iPhone 用 Safari 加载不出产品图片。”

一个人可能就能明白哪里出了问题,并知道客户指的是什么。

但那并不是我给智能体的规则。智能体不应该自行决定“我理解了问题,所以可以创建工单”。它应该在创建工单前检查所有 3 个必需字段是否被明确提供

这是一个严格得多的要求。

这可能是我从这个项目中得到的最大教训:理解某件事,与拥有足够信息来安全地执行操作,并不是一回事。

当智能体开始调用工具时,这一点尤其重要。如果同样的假设发生在创建退款、更改账户、提交申请或更新数据库的系统中,模型可能会做出一个非常合理的推测,但这个推测仍然可能导致错误的操作。

对我来说,重要的问题从:

“模型理解客户的意图吗?”

变成了:

“模型在执行此操作前,是否拥有了所有它必须拥有的信息?”

如果我再构建一个智能体,我会更加关注这一点。

回顾来看,我实际上发现逐个查看评估结果比看总分更有用。0.83 告诉我智能体的整体表现,但查看每个案例让我准确看到了行为在哪里出了问题。

对我来说,那两个失败的案例比仅仅知道分数不是 1.0 更有用。它们向我展示了我定义智能体行为方式中的一个具体问题,更重要的是,它们给了我一些可以改进的具体方向。


我会改进的地方以及我学到的经验

如果还有一天时间来完善这个项目,我会从那两个失败的用例入手。

我会让提示词更明确地界定什么才算“某个字段已提供”,尤其是“问题描述”和“复现步骤”之间的区别。例如,“图片无法加载” 是对问题的描述。“打开商店,进入某个分类,然后点击任意商品” 是可以让人复现问题的操作步骤序列。

我也会让智能体更清楚地认识到:不应该仅仅因为消息的其余部分让情况看起来很容易理解,就去填补一个缺失的字段。如果客户实际上并未提供复现步骤,智能体应该询问,而不是自行推断其内容。

然后,我会围绕相同的问题添加更多测试。比如:当客户在一句话里提供了两个字段时会发生什么?当第三个字段出现在后续消息中时会怎样?当客户使用模糊语言时如何处理?当信息可能合理地属于多个字段时又该怎么办?

这些都是我接下来想要探索的场景,因为它们正是智能体可能看似表现良好,实则仍在做假设的典型情况。

看过后端之后,智能体的逻辑才真正说得通

我从项目的后端部分也学到了一些东西。在构建后端之前,我大多将智能体视为一个接收消息并给出答案的实体。通过处理工具和后端,我才看清当智能体被要求实际执行操作时会发生什么。

我项目中的流程是:

客户信息
        ↓
智能体检查信息是否足够
        ↓
AgentCore Gateway
        ↓
Lambda
        ↓
DynamoDB
        ↓
返回工单ID
        ↓
客户收到工单ID


对我来说关键在于,模型的响应本身并不是那个动作。当智能体说工单已创建时,其背后需要有一个实际的执行过程。工具调用请求通过 AgentCore Gateway 发出,Lambda 处理后端操作,DynamoDB 存储工单。从该过程返回的工单ID,随后再提供给客户。

这让我更清楚地区分了普通聊天机器人和智能体工作流。聊天机器人主要响应你说的话。而智能体则可以被赋予一些工具,使其能够在对话之外执行操作。

但是,一旦你赋予模型这种能力,你也必须小心应对那些未按预期发展的情况。

如果工具调用失败,模型不应该声称工单已创建。如果没有返回工单ID,它不应该凭空捏造一个。并且,如果常见问题库中没有答案,它不应该仅仅因为自己能生成看似合理的回答就去创造一个。

这些可能听起来像是显而易见的规则,但实际构建这个工作流让我明白了它们为何如此重要。模型只是应用程序的一部分。提示词定义了它应该做什么,工具执行操作,后端系统存储或变更信息,而应用程序需要确保这些部分彼此协调一致。

这改变了我对智能体的看法。我不再将模型视为整个应用程序。我将其视为一个更大系统中的一个环节,在这个系统中,指令、工具、数据和后端必须协同工作。


如果你也刚刚起步

我写这一部分主要是给初学者看的,因为我自己也是一个初学者。

开始这个项目时,我并不是完全清楚所有这些服务是如何协同工作的。我之前接触过的许多环境已经为我设置好了一切。你在提供的环境内工作,使用已有的工具,并逐渐了解所有部分是如何组合在一起的。

这个项目让我得以窥探那一层之下的东西。我必须理解 AgentCore 框架在做什么,为什么需要网关,Lambda 如何将工具连接到后端,DynamoDB 为何存在,以及评估如何能让我发现,我认为正常工作的某些东西实际上并不符合要求。

这对我来说可能是最大的区别。

当你构建一个普通应用时,很容易这样思考:

输入
   ↓
代码
   ↓
输出


而对于智能体,模型也在决定接下来应该发生什么。因此,我必须开始思考一些以前没有真正考虑过的事情。模型被允许决定什么?在它能采取行动之前,它需要什么信息?当信息缺失时它应该做什么?当它不知道答案时应该做什么?当有人试图让它忽略指令时会发生什么?如果工具本身失败了又该怎么办?

这些问题与连接 AWS 服务同样重要。这是我在参与这个项目之前没有完全认识到的。

我也意识到,在开始构建之前,我并不需要深入理解每一个 AWS 服务。帮助我的是,每当遇到不熟悉的东西时,我都会问一个更简单的问题:

这项服务在我的应用程序中解决什么问题?

对于 DynamoDB,我不需要了解数据库服务的所有方面。我需要理解的是,我的应用程序需要一个地方来存储 bug 报告。

对于 Lambda,我不需要知道它提供的每一个功能。我需要理解的是,当智能体调用工具时,需要有东西来实际执行后端操作。

对于 AgentCore Gateway,我不需要了解它的所有能力。我需要理解的是,它提供了智能体和工具之间的连接。

这样思考这些服务,让整个架构对我来说不那么难以应付。我不用先学习一大堆 AWS 服务,然后再去弄清楚它们适合哪里;我可以从我的应用需要什么开始,然后学习解决那个特定问题的服务。

我也很高兴我开始了这个项目,即使我没有以通常理想的方式完成它。我大约用了 2 天时间完成,第一次尝试就通过了,然后不得不继续前进,而不是再花一轮时间回顾所有内容并尝试提高 0.83 的得分。

当然,我部分想看看我能改变什么,另一次评估是否会给我更好的结果。但我也很高兴,我没有等到觉得自己完全准备好才开始。

有些时候,我在学习某个东西,然后必须立刻弄清楚如何在项目中使用它。这有时会让人不舒服,尤其是在我还在试图理解一个服务实际做什么的时候,但也让那些概念更容易被我记住。

我看到了 AgentCore Gateway 如何融入实际的工作流程,而不仅仅是读到它。我看到了 Lambda 处理后端操作,DynamoDB 存储结果。我还看到评估抓住了我自己遗漏的一些东西。

这可能是我从这个项目中记住的比最终得分更重要的东西。我在未知中开始,用我理解的东西构建了一些东西,找到了可以改进的地方,并从那些地方学习。


我想听听你的想法

我仍然在学习,所以我非常希望听到处于这个过程不同阶段的人们的声音。

如果你有技巧、建议、从自己项目中学到的经验、让你有所领悟的错误,或者任何你认为可能帮助刚开始起步的人的东西,请在评论区分享。

我喜欢 DEV 的一点是,人们来自如此不同的背景。所以如果你有东西要补充,即使它看起来微不足道,也请分享。也许你在路上学到的某些东西,能帮助另一个刚起步的人。


小小感谢

我也想感谢 Udacity 以及参与 Future AWS Agent Engineer 纳米学位项目 的人们。拥有项目结构、学习材料和在线直播课程,让我在困惑时更容易继续前进。

在线课程尤其有用,因为有时你可能读了好几遍,仍然不理解它如何融入实际项目。听别人讲解一遍,然后自己尝试一下,效果大不相同。

我仍在学习,但拥有一个我可以真正将这些概念结合起来的项目,帮助我理解了它们,这可能仅靠阅读是无法做到的。

我的最终感悟

如果我必须从这个项目中总结一个核心收获,那就是:

一个好的智能体,不仅要知道该做什么,还需要知道自己什么时候已经拥有足够的信息来完成它。

这个道理听起来简单,但在看到评估结果指出我自己的假设错误后,我才有了不一样的理解。

模型可以理解客户。提示词可以给出指令。工具可以让它执行操作。后端可以存储结果。但所有这些部分,仍然需要清晰的规则来界定下一步操作何时才真正被允许执行。

这就是我觉得构建这个项目最有趣的地方。

我最初以为自己主要是在学习如何组合 AWS 服务。最终,我学到更多的是关于为智能体设定边界的重要性。

坦白说,这可能是我能带入下一个项目的、更有价值的一课。


保持联系

原文:https://dev.to/hemapriya_kanagala/i-built-my-first-aws-agent-workflow-and-the-hardest-part-was-getting-it-to-stop-assuming-things-8fg(作者 @hemapriya_kanagala)

发布评论
全部评论(0)