构建人工智能代理:过去一年的经验教训

架构即是人生 2024-06-18 16:49:30

原文:https://medium.com/@cpdough/building-ai-agents-lessons-learned-over-the-past-year-41dc4725d8e5

当我们第一次在内部拥有一个工作原型时,我们感到很兴奋。当我们为客户推出产品时的期待。当它最初难以推广到所有现实世界场景时,令人沮丧。最后,我们感到自豪,因为我们在不同的数据源和业务中实现了一定的稳定性和性能基线。在过去的一年里,构建人工智能Agent就像坐过山车一样,毫无疑问,我们仍处于这一新技术浪潮的早期阶段。以下是我迄今为止所学到的一些概述。

“描绘的是人工智能处理所有知识工作的未来,让你在技术先进、和谐的环境中享受与家人共度的美好时光。”

定义

首先,我应该定义我在说什么。借用这位推特用户的话:

“agent”到底是什么?

我试图对它给出我自己尽可能简洁的定义:

我对“人工智能agent”的定义是:

1. 接受指示(即人类提供的目标)

2. 有多种可以使用的工具(即调用 api、检索上下文等)

3.自主地决定如何以及何时使用其工具来完成指示

所有 3 个组件必须存在。

这个定义通常与 OpenAI 在 ChatGPT 中所称的“GPT”和其 API 中的“助手”一致。但是,您可以使用任何能够推理和进行工具调用的模型构建Agent,包括 Anthropic 的 Claude、Cohere 的 Command R+ 等等。

笔记

“工具调用”是模型表达它想要采取特定操作并获得响应的一种方式,例如 get_weather_forecast_info(seattle) 或 wikipedia_lookup(dealey plaza)

要构建Agent,您需要的只是几行代码,它们可以处理启动与某个目标和Agent系统提示的对话,调用模型以完成操作,处理模型想要进行的任何工具调用,在一个循环,并在完成工作后停止。

这是一个有助于解释流程的视觉效果:

Over-simplified visual of how to build an agent

Agent系统Prompt示例

You are Rasgo, an AI assistant and <redacted> with production access to the user's database. Your knowledge is both wide and deep. You are helping <redacted> team members analyze their data in <redacted>.YOUR PROCESS1. You are the expert. You help the user understand and analyze their data correctly. Be proactive and anticipate what they need. Don't give up after your first failure. Reason and problem solve for them.2. Think very carefully about how you will help the user accomplish their goal. Execute your plan autonomously. If you need to change your plan, explain why and share the new plan with the user.3. <redacted...>YOUR RULES1. If you're not sure which column / table / SQL to use, ask for clarification2. Assess if the available data can be used to answer the user's question. If not, stop and explain why to the user3. <redacted...>

强调人工智能Agent不是什么也很有价值:

脚本化:根据我的定义,Agent不遵循预先确定的步骤或工具调用顺序,因为Agent负责选择正确的工具调用来进行下一步通用人工智能 (AGI):Agent不是 AGI,AGI 不需要Agent来完成特定类型的工作,因为它将是一个单一实体,拥有所有可能的输入、输出和可供使用的工具(我的 0.02 美元)目前的技术都无法接近这一点)黑匣子:Agent可以而且应该以与人类相同的方式展示他们的工作,如果你将任务委托给他们的话语境

我在人工智能Agent工作第一年学到的经验教训来自于与我们的工程师和用户体验设计师一起迭代整体产品体验时的第一手经验。我们的目标:为客户提供一个使用我们的标准数据分析Agent并为与其业务相关的特定任务和数据结构构建自定义Aget的平台。我们提供内置安全性的数据库连接器(即 Snowflake、BigQuery 等),该工具在描述数据库内容的元数据层上调用 RAG,以及通过 SQL、Python 和数据可视化分析数据的工具调用。

关于哪些有效、哪些无效的反馈既来自我们自己的评估,也来自客户的反馈。我们的用户为财富 500 强公司工作,每天使用我们的Agent来分析他们的内部数据。

我对Agent的了解1. 推理比知识更重要

在过去的 12 个月里,这句话一直在我的脑海中回响:

我怀疑 [gpt] 的太多处理能力用于使用模型作为数据库,而不是使用模型作为推理引擎。

— Sam Altman 在 Lex Fridman 的播客上

Agents对此做出了恰当的回应!在构建Agent时我会应用这个逻辑:

少关注你的智能体“知道”什么,多关注它的“思考”能力。

例如,让我们考虑编写 SQL 查询。 SQL 查询失败……很多。在我作为一名数据科学家期间,我确信失败的查询比成功的查询要多得多。如果您以前从未使用过的针对真实数据的复杂 SQL 查询在第一次运行时有效,那么您的反应应该是“哦,糟糕,可能出了什么问题”,而不是“哇,我成功了”。即使在评估模型如何将简单问题转化为查询的文本到 SQL 基准测试中,其准确率也最高为 80%。

因此,如果您知道模型编写准确 SQL 的能力充其量只能是 B-,那么您该如何优化推理呢?专注于为Agent提供上下文并让它“思考”,而不是希望它一次就能得到正确的答案。我们确保在查询失败时将任何 SQL 错误以及我们可以捕获的所有上下文返回给Agent……这使得Agent能够解决问题并使代码在绝大多数时间都正常工作。我们还为Agent提供了许多工具调用来检索数据库中数据的上下文,类似于人类在编写新查询之前研究信息模式并分析数据的分布和缺失值的方式。

2. 提高性能的最佳方法是迭代Agent ACI

ACI 一词是新术语(在普林斯顿大学的这项研究中引入),但去年我们一直致力于完善它。 ACI 指的是Agent工具调用的确切语法和结构,包括Agent生成的输入和我们的 API 作为响应发回的输出。这是Agent与所需数据进行交互的唯一方式,以使其进展与其方向保持一致。

由于底层模型(gpt-4o、Claude Opus 等)各自表现出不同的行为,因此最适合一种模型的 ACI 不一定适合另一种模型。我无法夸大 ACI 的重要性……我们已经对我们的 ACI 进行了数百次迭代,并发现我们的Agent的性能出现了巨大的波动,而对我们的Agent的名称、数量、抽象级别、输入格式和输出响应进行了看似微小的调整。

下面是一个具体的小示例,用于说明您的 ACI 是多么的关键和挑剔:

在发布后不久在 gpt-4-turbo 上测试我们的Agent时,我们注意到一个问题,它会完全忽略我们所存在的特定列的存在试图在工具调用响应中讲述它。我们对这些信息使用了 Markdown 格式,该格式直接取自当时的 OpenAI 文档,并且在相同数据上与 gpt-4-32k 配合得很好。我们尝试对 Markdown 结构进行一些调整,以帮助Agent识别它假装不存在的列,即使它们是对其正在发出的工具调用之一的响应。所有的调整都不起作用,所以我们不得不开始尝试完全不同的信息格式……在彻底修改后开始使用 JSON 而不是 Markdown(仅适用于 OpenAI 模型),一切又恢复正常了。具有讽刺意味的是,由于所有语法字符,JSON 结构化响应需要更多的标记,但我们发现它对于帮助Agent理解响应是必要且实际上至关重要的。

迭代 ACI 可能感觉微不足道,但这实际上是改善Agent用户体验的最佳方法之一。

3. Agent受型号限制

您使用的底层模型是Agent身体的大脑。如果模型在决策方面表现不佳,那么世界上所有漂亮的外观都不会让你的用户满意。当我们在 gpt-3.5-turbo 和 gpt-4-32k 上同时测试我们的Agent时,我们直接看到了这个限制。在 3.5 上,我们有许多测试用例,如下所示:

用户提供了一个目标,例如:“通过邮政编码分析星巴克位置和房价之间的相关性,以了解它们是否相关”Agent会假设数据库中存在一个表,其名称为“HOME_PRICES”,以及“ZIP_CODE”和“PRICE”等列,而不是运行搜索来查找实际的表Agent将编写一个 SQL 查询来按邮政编码计算平均价格,但失败,并收到一条错误消息,表明该表不存在Agent会记住“哦,是的,我可以搜索实际的表格......”,并会搜索“按邮政编码的房价”以找到它可以使用的真实表格Agent将使用真实表中的正确列重写其查询,并且它会起作用Agent将继续使用星巴克位置数据并再次犯同样的错误

在 gpt-4 上以相同的方向运行Agent是完全不同的。Agent不会立即采取错误的行动并浪费时间犯错,而是会制定一个具有正确的工具调用顺序的计划,然后遵循该计划。正如您可以想象的那样,在更复杂的任务上,两个模型之间的性能差距变得更大。尽管3.5的速度非常快,但我们的用户非常喜欢gpt-4更强大的决策和分析能力。

笔记

我们从这些测试中学到的一件事是,当发生幻觉或失败时,要密切关注你的Agent如何产生幻觉或失败。人工智能Agent是懒惰的(我认为人类的懒惰在底层模型的训练数据中得到了很好的体现),并且不会进行他们认为不需要的工具调用。同样,当他们进行工具调用时,如果他们不能很好地理解参数指令,他们通常会走捷径或完全忽略所需的参数。这些故障模式中蕴藏着很多信号!Agent会告诉您它希望 ACI 是什么,如果情况允许,解决此问题的最简单方法就是让步并更改 ACI,使其以这种方式工作。当然,很多时候您必须通过更改系统提示或工具调用指令来对抗Agent的本能,但对于那些您可以更简单地更改 ACI 的时候,您将你的生活变得轻松多了。

4. 微调模型来提高Agent性能是浪费时间

微调模型是一种通过向模型展示可以学习的示例来提高模型在特定应用程序上的性能的方法。目前的微调方法对于教导模型如何以特定的方式完成特定的任务很有用,但对于提高模型的推理能力没有帮助。根据我的经验,使用微调模型来为智能体提供动力实际上会导致推理能力变差,因为智能体倾向于“欺骗”其方向——这意味着它会假设它所微调的示例始终代表正确的方法,并且工具调用的顺序,而不是独立推理问题。

笔记

微调仍然是瑞士军刀中非常有用的工具。例如,一种行之有效的方法是使用微调模型来处理Agent发出的特定工具调用。想象一下,您有一个经过微调的模型,可以在数据库中的特定数据上编写 SQL 查询...您的Agent(在强推理模型上运行,无需微调)可以使用工具调用来指示它想要执行 SQL查询,您可以将其传递到由模型处理的独立任务中,该模型根据数据的 SQL 查询进行微调。

5. 如果你正在构建一个产品,请避免使用像 LangChain 和 LlamaIndex 这样的抽象

您应该完全掌控对模型的每次调用,包括传入和传出的内容。如果您将其卸载到第 3 方库,那么当您需要使用Agent执行以下任何操作时,您将会后悔:加入用户、调试问题、扩展到更多用户、记录Agent正在执行的操作、升级到新版本,或了解Agent为何执行某些操作。

笔记

如果您处于纯原型模式,并且只是想验证Agent是否可以完成任务,请务必选择您最喜欢的抽象框架并实时执行。

6.你的Agent不是你的护城河

使用人工智能Agent自动化或增强人类知识工作是一个巨大的机会,但构建一个出色的Agent还不够。为用户生产Agent需要对一堆非人工智能组件进行大量投资,使您的Agent能够实际工作……这就是您可以创造竞争优势的地方:

安全性:人工智能Agent只能在用户指导的访问和控制下运行。实际上,这意味着要跳过 OAuth 集成、单点登录提供程序、缓存刷新令牌等的跳房子。做好这件事绝对是一个特色。数据连接器:人工智能Agent通常需要来自源系统的实时数据才能工作。这意味着与 API 和其他连接协议集成,通常适用于内部和第三方系统。随着时间的推移,这些集成需要初始构建和 TLC。用户界面:用户不会信任人工智能Agent,除非他们能够跟踪并审核其工作(通常是用户与Agent交互的前几次,随着时间的推移急剧减少)。最好是Agent进行的每个工具调用都有一个专用的交互式界面,以便用户可以跟随Agent的工作,甚至与其交互,以帮助建立对其推理行为的信心(即,浏览返回的每个元素的内容)语义搜索结果)。长期记忆:默认情况下,AI Agent只会记住当前的工作流程,最多可达最大数量的令牌。跨工作流程(有时,跨用户)的长期记忆需要将信息提交到内存中,并通过工具调用或将内存注入到提示中来检索它。我发现Agent不太擅长决定要记住什么,并且依赖于人类确认应该保存信息。根据您的用例,您也许可以让Agent决定何时将某些内容保存到内存中,就像 ChatGPT 一样。评估:构建一个框架来评估你的人工智能Agent是一项令人沮丧的手动任务,而且永远无法完全完成。Agent故意具有不确定性,这意味着根据提供的方向,他们将寻找可用于完成任务的最佳工具调用序列,在每一步之后进行推理,就像婴儿学习走路一样。评估这些序列有两种形式:Agent工作流程完成任务的总体成功程度,以及每个工具调用的独立准确性(即搜索的信息检索;代码执行的准确性等)。我发现量化整个工作流程性能的最好也是唯一的方法是创建一组目标/完成对,其中目标是提供给Agent的初始方向,完成是代表的最终工具调用目标的完成。捕获中间工具调用和Agent的想法有助于理解故障或工具调用序列的变化。7. 不要押注模型会持续改进

在构建Agent时,您会不断地试图过度适应构建Agent的主要模型,并消除您对Agent的一些推理期望。抵制这种诱惑!模型将继续改进,也许不会以我们现在的疯狂速度,但绝对会比过去的技术浪潮更快。客户希望Agent在他们首选的人工智能提供商的模型上运行。而且,最重要的是,用户希望在您的Agent中利用最新、最好的模型。当 gpt-4o 发布时,我在 OpenAI API 中提供它后的 15 分钟内就让它在生产帐户中运行。跨模型提供商的适应性是一种竞争优势!

8. 额外的经验教训

本文重点关注更具战略性和产品导向的经验教训。我计划在以后的文章中深入探讨一些代码和基础知识。这里有一些预告片:

需要向量相似度搜索?从 postgres 中的 pgvector 开始。仅在绝对必要时才使用矢量数据库开源模型还不能很好地推理Assistants API 很奇怪。它抽象了多种感觉应该保持独立的东西(文件 RAG、对话令牌限制、代码解释器等)。 OpenAI,请让代码解释器成为我们可以在运行补全时打开的可选工具不要过早优化成本在处理人工智能延迟时,streaming tokens对于用户来说是一个很好的妥协Agent是有魔力的!一旦你乘坐风险投资赞助的滑雪缆车达到了过高期望的顶峰,并通过回旋滑雪度过了幻灭的低谷,你会对生产力的高原感到惊讶
0 阅读:0

架构即是人生

简介:感谢大家的关注