智能代理:现代AI系统的核心技术


本文总阅读量

  • 原文链接:Agents
  • 作者:Chip Huyen
  • 日期: 2025-01-07

本文探讨了智能代理(Agents)的核心概念与工作原理。智能代理是能感知环境并对环境采取行动的AI系统,其能力主要取决于可用工具和规划能力。文章详细分析了代理的工具类型(知识增强、能力扩展和写入工具)、规划方法(包括计划生成、反思与纠错)以及常见故障模式。随着基础模型能力的提升,代理技术有望实现更高程度的自主性,在各领域发挥重要作用。


许多人认为,智能代理 (Agent) 是人工智能 (AI) 的终极目标。斯图尔特·罗素 (Stuart Russell) 和彼得·诺维格 (Peter Norvig) 的经典著作《人工智能:一种现代方法》(Prentice Hall, 1995)将 AI 研究领域定义为“对理性代理 (rational agents) 的研究与设计”。

基础模型 (foundation models) 前所未有的能力,为以往无法想象的代理应用开启了大门。这些新能力使得开发自主、智能的代理成为可能,它们可以充当我们的助手、同事和教练。它们能协助我们创建网站、收集数据、规划旅行、进行市场调研、管理客户账户、自动化数据录入、为面试做准备、面试候选人、谈判交易等。其可能性似乎无穷无尽,这些代理所蕴含的潜在经济价值也极为巨大。

本节将首先概述代理,然后探讨决定代理能力的两个核心要素:工具和规划。代理凭借其新颖的操作模式,也带来了新的故障模式。本节最后将讨论如何评估代理以发现这些故障。

本文改编自 《AI 工程》 (2025 年出版) 的 “代理” 章节,并进行了少量编辑,使其成为一篇独立的文章。

备注
  1. AI 驱动的代理是一个新兴领域,目前尚无既定的理论框架来定义、开发和评估它们。本节致力于基于现有文献构建一个初步框架,但该框架会随着领域的发展而不断演进。与本书其他章节相比,本节更具探索性。我已收到早期审阅者的宝贵反馈,也期待本博客文章的读者能提供更多意见。
  2. 就在本书出版前夕,Anthropic 发表了一篇关于构建高效代理 (Building effective agents) 的博文(2024 年 12 月)。我很高兴地看到,Anthropic 的博文与我关于代理的章节在概念上高度契合 (conceptually aligned),尽管术语略有差异。然而,Anthropic 的文章侧重于孤立的设计模式,而我的文章则更深入地探讨了其工作原理及原因,并更加关注规划、工具选择和故障模式。
  3. 本文包含大量背景信息。若感觉某些部分过于深入细节,可随时跳过。

代理概述

“代理” (agent) 一词已在众多不同的工程领域中被广泛应用,包括但不限于软件代理、智能代理、用户代理、对话代理以及强化学习代理等。那么,究竟什么是代理?

代理是任何能够感知其所处环境并能对该环境采取行动的事物。《人工智能:一种现代方法》(1995) 将代理定义为:任何可以被视为能够通过传感器感知环境,并通过执行器对环境施加影响的事物。

这意味着,代理的特性取决于其运行的环境以及它能够执行的一系列动作

代理可以操作的环境由其具体用例决定。如果一个代理是为了玩游戏(如 我的世界/Minecraft、围棋、Dota)而开发的,那么该游戏即是其环境。如果你希望代理从互联网上抓取文档,那么互联网就是其环境。自动驾驶汽车代理的环境则是道路系统及其周边区域。

AI 代理可执行的一系列动作,通过其能够访问的工具得到增强。我们日常交互的许多生成式 AI 应用,实际上都是配备了工具(尽管可能很简单)的代理。例如,ChatGPT 就是一个代理,它能够搜索网页、执行 Python 代码以及生成图像。RAG(检索增强生成)系统也是代理,其工具包括文本检索器、图像检索器和 SQL 执行器。

代理的环境与其工具集之间存在着密切的依赖关系。环境决定了代理可能使用的工具类型。例如,在国际象棋游戏中,代理唯一可能的动作就是合法的棋步。反过来,代理的工具清单(即代理可调用的各类工具的列表)也限制了其能够操作的环境。例如,如果一个机器人唯一的动作是游泳,那么它的活动范围就会被限制在水域环境中。

图 6-8 展示了 SWE-agent (Yang et al., 2024) 的可视化界面,这是一个基于 GPT-4 构建的代理。它所在的环境是包含终端和文件系统的计算机,其动作集包括导航代码仓库、搜索文件、查看文件和编辑代码行。

swe_agent.png

图 6-8. SWE-agent 是一个编程代理,其所在的环境为计算机,其具备的动作包括导航、搜索、查看文件和编辑

AI 代理旨在完成通常由用户指定的任务。在 AI 代理中,AI 扮演着“大脑”的角色,负责处理任务、规划达成任务目标的动作序列,并判断任务是否已经完成。

让我们回到前面 Kitty Vogue 示例中处理表格数据的 RAG 系统。这是一个拥有三种动作的简单代理:

对于查询 "预测 Fruity Fedora 未来三个月的销售收入",该代理可能会执行以下动作序列:

  1. 思考如何完成此任务。它可能判断,要预测未来销售额,首先需要过去五年的销售数据。代理的思考过程可以作为中间响应展示。
  2. 调用 SQL 查询生成功能,以生成获取过去五年销售数据的查询语句。
  3. 调用 SQL 查询执行功能,以执行该查询。
  4. 分析工具的输出(即 SQL 查询执行的结果),以及这些输出如何辅助销售预测。它可能发现现有数据不足以做出可靠的预测(例如,因为存在缺失值),因此决定还需要过去营销活动的相关信息。
  5. 调用 SQL 查询生成功能,以生成获取过去营销活动信息的查询语句。
  6. 调用 SQL 查询执行。
  7. 判断新获得的信息足以支持对未来销售额的预测,然后生成预测结果。
  8. 判断任务已成功完成。

与非代理应用场景相比,代理通常需要性能更强的模型,主要有两个原因:

需要多个步骤的任务可能耗时且耗费资金。一个常见的担忧是代理系统可能会消耗大量 API 配额 (credits)。然而,如果代理能够实现自主运行,它们就能节省人力时间,从而使其成本投入物超所值。

在特定环境下,代理的成功取决于其可访问的工具以及其 AI 规划器的能力。让我们首先了解模型可以使用的不同类型的工具,然后再分析 AI 的规划能力。

工具

一个系统并非必须访问外部工具才能成为代理。但是,若没有外部工具,代理的能力将受到极大限制。模型自身通常只能执行单一类型的动作——例如,大型语言模型 (LLM) 可以生成文本,图像生成器可以生成图像。外部工具则能极大地增强代理的能力。

工具辅助代理感知环境并对环境施加影响。允许代理感知环境的动作是只读动作,而允许代理对环境施加影响的动作是写入动作

代理可访问的工具集合构成了其工具清单。由于工具清单决定了代理的能力范围,因此审慎考虑赋予代理哪些工具以及工具的数量至关重要。更多的工具意味着更强的能力,但工具数量的增加也会提升理解和有效利用这些工具的难度。如后续“工具选择”部分将讨论的,必须通过实验来确定最合适的工具组合。

根据代理所处的环境,存在多种可能的工具。以下是您可能需要考虑的三类工具:知识增强(即上下文构建)、能力扩展,以及允许代理对环境施加影响的工具。

知识增强 (Knowledge augmentation)

我希望本书至此已经使您信服:拥有相关上下文对于提升模型响应质量至关重要。重要的工具类别之一是那些有助于增强代理知识的工具。其中一些已在前文讨论过:文本检索器、图像检索器和 SQL 执行器。其他潜在的工具包括内部员工搜索、返回不同产品状态的库存 API、Slack 内容检索、邮件阅读器等。

许多此类工具利用您组织内部的私有流程和信息来增强模型的能力。同时,工具也可以使模型访问公开信息,尤其是来自互联网的信息。

网页浏览是最早被整合到 ChatGPT 中且备受期待的功能之一。网页浏览可以防止模型信息过时。当模型训练所用的数据变得陈旧时,模型就会“过时”。如果模型的训练数据截止于上周,那么除非本周的信息在上下文中提供,否则它将无法回答需要这些最新信息的问题。没有网页浏览功能,模型将无法告知您天气、新闻、近期活动、股价、航班状态等信息。

我将“网页浏览”作为一个概括性术语,涵盖所有访问互联网的工具,包括网页浏览器和各类 API,如搜索 API、新闻 API、GitHub API 或社交媒体 API。

虽然网页浏览能让代理引用最新信息以生成更优的响应并减少“幻觉” (hallucinations),但它也可能将代理暴露在互联网的“污水池”中。因此,请务必谨慎选择互联网 API。

能力扩展 (Capability extension)

您可能还会考虑使用工具来弥补 AI 模型的固有局限性。这些是提升模型性能的简便方法。例如,AI 模型在数学运算方面表现不佳是众所周知的。如果您问一个模型 199,999 除以 292 是多少,它很可能会出错。但是,如果模型能够访问计算器,这个计算就变得轻而易举。与其投入大量资源训练模型使其擅长算术,不如直接为其提供计算器工具更为高效。

其他能够显著提升模型能力的简单工具包括日历、时区转换器、单位转换器(例如,磅到千克)以及翻译器(可以将文本翻译成模型不擅长的语言,或从这些语言翻译过来)。

代码解释器是更复杂但功能更强大的工具。与其训练模型理解代码,不如赋予其访问代码解释器的权限,使其能够执行代码片段、返回结果或分析代码故障。这一能力使您的代理能够胜任编程助手、数据分析师,甚至是能够编写代码运行实验并报告结果的研究助理。然而,如第 5 章“防御性提示工程”部分所述,自动化代码执行伴随着代码注入攻击的风险。采取适当的安全措施对于保护您和用户的安全至关重要。

工具可以将纯文本或纯图像模型转变为多模态模型。例如,一个只能生成文本的模型可以利用文本到图像模型作为工具,从而能够同时生成文本和图像。接收到文本请求后,代理的 AI 规划器会决定调用文本生成、图像生成,还是两者都调用。ChatGPT 正是这样同时生成文本和图像的——它使用 DALL-E 作为其图像生成器。

代理还可以使用代码解释器生成图表,使用 LaTeX 编译器渲染数学公式,或使用浏览器从 HTML 代码渲染网页。

类似地,一个只能处理文本输入的模型可以使用图像描述工具来处理图像,使用语音转文本工具来处理音频,还可以使用 OCR(光学字符识别)工具来读取 PDF 文件。

与仅使用提示或甚至微调相比,工具的使用能显著提升模型的性能Chameleon (Lu et al., 2023) 的研究表明,一个由 GPT-4 驱动、并配备了 13 种工具的代理,在多个基准测试中的表现优于单独的 GPT-4。该代理使用的工具示例包括知识检索、查询生成器、图像描述器、文本检测器和必应搜索 (Bing search)。

在科学问答基准 ScienceQA 上,Chameleon 将已发布的最佳少样本学习 (few-shot) 结果提升了 11.37%。在涉及表格数学问题的基准 TabMWP (Tabular Math Word Problems) (Lu et al., 2022) 上,Chameleon 将准确率提升了 17%。

写入动作 (Write actions)

至此,我们讨论的都是允许模型从其数据源读取信息的只读动作。但工具同样可以执行写入动作,从而更改数据源。SQL 执行器不仅可以检索数据表(读取),还可以修改或删除表(写入)。电子邮件 API 不仅可以读取邮件,还可以回复邮件。银行 API 不仅可以查询您当前的余额,还可以发起银行转账。

写入动作使系统能够完成更多任务。它们可以帮助您自动化整个客户拓展工作流程:研究潜在客户、查找联系方式、起草邮件、发送首封邮件、阅读回复、跟进、提取订单、用新订单更新数据库等等。

然而,赋予 AI 自动改变我们生活的能力,其前景也令人担忧。正如您不应授予实习生删除生产数据库的权限一样,您也不应允许一个不可靠的 AI 发起银行转账。对系统能力及其安全措施的信任至关重要。您需要确保系统得到妥善保护,以防范可能试图操纵其执行有害操作的恶意行为者。

代理与安全

每当我向一群人谈论自主 AI 代理时,常常有人会提及自动驾驶汽车。“如果有人入侵汽车来绑架你怎么办?”虽然自动驾驶汽车的例子因其物理存在而显得尤为直观,但 AI 系统即使没有物理实体,也可能造成危害。正如原书第 5 章“防御性提示工程”部分所讨论的,它可能操纵股票市场、窃取版权、侵犯隐私、强化偏见、传播虚假信息和政治宣传等。

这些都是合理的担忧,任何希望利用 AI 的组织都必须严肃对待安全问题。但这并不意味着永远不应赋予 AI 系统在现实世界中行动的能力。如果我们能够信任机器将我们送入太空,我希望有朝一日,安全措施能够足以让我们信任自主 AI 系统。此外,人类也会犯错。就我个人而言,在搭便车这件事上,我可能更信任自动驾驶汽车,而非一个普通的陌生人。

正如合适的工具能极大地提高人类的生产力——您能想象没有 Excel 如何开展业务,或者没有起重机如何建造摩天大楼吗?——工具同样使模型能够完成远超以往的任务。许多模型提供商已经为其模型提供了工具使用支持,这一特性通常被称为函数调用 (function calling)。展望未来,我预计具备广泛工具集的函数调用将成为大多数模型的标配。(译者注:就像最近大火的 MCP 协议,它就是提供了广泛工具集调用。)

规划 (Planning)

基础模型代理的核心是负责解决用户所提供任务的模型。任务由其目标和约束条件定义。例如,一项任务可能是:预算 5000 美元,安排一次从旧金山到印度的为期两周的旅行。目标是这次为期两周的旅行,约束条件则是预算。

复杂的任务需要规划。规划过程的输出是一个计划 (plan),即一份概述了完成任务所需步骤的路线图。有效的规划通常要求模型理解任务、考虑达成任务的不同选项,并选择最有希望的那个。

如果您参加过任何规划会议,就会明白规划的难度。作为一个重要的计算问题,规划领域已有深入研究,足以写满几卷书。在此我仅能进行浅尝辄止的介绍。

规划概述

对于给定的任务,存在多种可能的解决方案,但并非所有方案都能成功。在正确的解决方案中,有些方案比其他方案更有效率。考虑以下查询:"有多少家没有收入的公司融资额至少达到了 10 亿美元?",以及两种示例解决方案:

  1. 找出所有没有收入的公司,然后按融资金额筛选。
  2. 找出所有融资额至少达到 10 亿美元的公司,然后按收入筛选。

第二种方案效率更高,因为没有收入的公司数量远多于融资额达到 10 亿美元的公司。仅凭这两个选项,智能代理应选择选项 2。

您可以将规划与执行耦合在同一个提示 (prompt) 中。例如,您给模型一个提示,要求它逐步思考(例如使用思维链 (chain-of-thought) 提示),然后在同一个提示中执行这些步骤。但如果模型提出了一个包含 1000 个步骤却无法达成目标的计划,那该怎么办?缺乏监督的情况下,代理可能会运行这些步骤数小时,在 API 调用上浪费时间和金钱,而您却在很久之后才意识到它毫无进展。

为避免无效执行,规划应与执行解耦。您首先要求代理生成一个计划,只有在该计划经过验证后才予以执行。计划的验证可以采用启发式方法。例如,一个简单的启发式规则是排除包含无效动作的计划。如果生成的计划需要进行谷歌搜索,而代理没有谷歌搜索的权限,则该计划无效。另一个简单的启发式规则可能是排除所有超过 X 个步骤的计划。

计划也可以通过 AI 评审员 (AI judges) 进行验证。您可以要求一个模型评估计划是否合理,或如何改进计划。

如果生成的计划被评估为不佳,您可以要求规划器生成另一个计划。如果生成的计划良好,则执行它。

如果计划包含了外部工具的调用,那么函数调用将被触发。执行此计划产生的输出随后也需要再次评估。请注意,生成的计划不必是针对整个任务的端到端计划,它可以是针对某个子任务的小型计划。整个过程如图 6-9 所示。

planning_execution.png

图 6-9. 解耦规划与执行,确保仅执行经过验证的计划

您的系统现在包含三个组件:一个用于生成计划,一个用于验证计划,另一个用于执行计划。如果将每个组件都视为一个代理,那么这可以被认为是一个多代理系统 (multi-agent system)。由于大多数代理工作流程都相当复杂,需要多个组件协同工作,因此大多数代理实际上都是多代理系统。

为了加快进程,您可以并行生成多个计划,然后让评估器选择最有希望的一个,而不是按顺序生成。这是另一种延迟与成本之间的权衡,因为同时生成多个计划会产生额外的成本。

规划需要理解任务背后的意图:用户试图通过此查询实现什么目标?意图分类器通常用于辅助代理进行规划。如原书第 5 章“将复杂任务分解为更简单的子任务”部分所述,意图分类可以通过另一个提示或为此任务专门训练的分类模型来完成。意图分类机制可以被视为您的多代理系统中的另一个代理。

了解意图有助于代理选择正确的工具。例如,在客户支持场景下,如果查询与账单相关,代理可能需要访问工具来检索用户的近期付款记录;但如果查询是如何重置密码,代理则可能需要访问文档检索工具。

某些查询可能超出了代理的处理范围。意图分类器应能将这类请求识别并分类为 不相关 (IRRELEVANT),以便代理能够礼貌地拒绝,而不是浪费 FLOPs(浮点运算次数,衡量计算能力的指标)去尝试不可能的解决方案。

到目前为止,我们假设代理能自动完成所有三个阶段:生成计划、验证计划和执行计划。实际上,人类可以在任何阶段介入,以协助流程并降低风险。

总结来说,解决一项任务通常涉及以下过程。请注意,反思 (reflection) 并非代理的强制要求,但它能显著提升代理的性能。

  1. 计划生成:为完成任务制定一个计划。计划是一系列可管理的操作,因此这个过程也称为任务分解。
  2. 反思与纠错:评估生成的计划。如果计划不佳,则生成新计划。
  3. 执行:采取生成计划中列出的行动。这通常涉及调用特定的函数。
  4. 反思与纠错:收到行动结果后,评估这些结果并确定目标是否已达成。识别并纠正错误。如果目标未完成,则生成新计划。

您在本书中已经接触过一些计划生成和反思的技术。当您要求模型“逐步思考 (think step by step)”时,就是在要求它分解任务。当您要求模型“验证您的答案是否正确”时,就是在要求它进行反思。

基础模型作为规划器

一个悬而未决的问题是:基础模型在规划方面的能力究竟如何?许多研究人员认为,基础模型,至少是那些基于自回归语言模型构建的模型,不具备规划能力。Meta 的首席 AI 科学家杨立昆 (Yann LeCun) 明确指出,自回归 LLM 无法进行规划 (2023)。

尽管有大量坊间证据表明 LLM 是糟糕的规划者,但尚不清楚这究竟是因为我们尚未掌握正确使用 LLM 的方法,还是因为 LLM 从根本上就不具备规划能力。

规划的核心在于搜索问题 (search problem)。您需要在通往目标的不同路径中进行搜索,预测每条路径的结果(奖励),然后选择结果最有希望的路径。通常,您可能会发现不存在任何能够将您引向目标的路径。

搜索通常需要回溯 (backtracking)。例如,假设您处于某个步骤,有两个可能的动作:A 和 B。执行动作 A 后,您进入了一个不理想的状态,因此需要回溯到之前的状态以执行动作 B。

有些人认为自回归模型只能生成前向动作,无法回溯以生成替代动作。因此,他们得出结论:自回归模型无法进行规划。然而,这并非必然正确。在执行了包含动作 A 的路径后,如果模型判断该路径不合理,它可以转而使用动作 B 来修正路径,从而实现有效的回溯。模型也可以随时重新开始并选择另一条路径。

LLM 之所以规划能力欠佳,也可能是因为缺乏必要的规划辅助工具。要进行规划,不仅需要了解可用的动作,还需要了解每个动作的潜在结果。举个简单的例子,假设您想登山。您可能的动作是右转、左转、转身或直行。但是,如果右转会导致您坠崖,您可能就不会考虑这个动作。用技术术语来说,一个动作会将您从一个状态带到另一个状态,因此有必要了解结果状态才能决定是否采取某个动作。

这意味着,仅仅提示模型生成一系列动作(如流行的思维链提示技术那样)是不够的。论文《语言模型推理即世界模型规划 (Reasoning with Language Model is Planning with World Model)》(Hao et al., 2023) 认为,LLM 由于包含了大量关于世界的信息,因此能够预测每个动作的结果。这样的 LLM 可以将这种结果预测能力整合进来,以生成连贯的计划。

即使 AI 本身不能直接进行规划,它仍然可以成为规划器的一部分。或许可以通过为 LLM 配备搜索工具和状态跟踪系统来辅助其进行规划。

基础模型 (fm) 与强化学习 (rl) 规划器

代理 是强化学习 (RL) 中的一个核心概念。维基百科将强化学习定义为一个领域,它研究“智能代理应如何在动态环境中采取行动以最大化累积奖励”。
RL 代理和 FM 代理在许多方面都很相似。它们的特性都取决于其环境和可能的动作。主要区别在于它们规划器的工作方式。

  • 在 RL 代理中,规划器通过 RL 算法进行训练。训练此 RL 规划器可能需要大量的时间和资源。
  • 在 FM 代理中,模型本身就是规划器。可以通过提示或微调来改进此模型的规划能力,并且通常需要更少的时间和资源。

然而,并没有什么能阻止 FM 代理融合 RL 算法以提升其性能。我推测,从长远来看,FM 代理和 RL 代理将会趋于统一。

生成计划

将模型转变为规划器的最简单方法是运用提示工程 (prompt engineering)。假设您想创建一个代理来帮助顾客了解 Kitty Vogue 的产品。您为该代理提供了访问三个外部工具的权限:按价格检索产品、检索热门产品以及检索产品信息。以下是一个计划生成提示的示例。此提示仅作说明之用,实际生产环境中的提示可能会复杂得多。

系统提示 (SYSTEM PROMPT)

为解决该任务提出一个计划。您可以使用以下 5 个动作:

* get_today_date()
* fetch_top_products(start_date, end_date, num_products)
* fetch_product_info(product_name)
* generate_query(task_history, tool_output)
* generate_response(query)

该计划必须是一系列有效的动作。

示例
任务:“告诉我关于 Fruity Fedora 的信息”
计划:[fetch_product_info, generate_query, generate_response]

任务:“上周最畅销的产品是什么?”
计划:[fetch_top_products, generate_query, generate_response]

任务:{用户输入}
计划:

关于此示例,有两点需要注意:

对于用户输入“上周最畅销产品的价格是多少”,生成的计划可能如下所示:

  1. get_today_date()
  2. fetch_top_products()
  3. fetch_product_info()
  4. generate_query()
  5. generate_response()

您可能会疑惑:“每个函数所需的参数呢?” 由于确切的参数通常是从先前的工具输出中提取的,因此很难提前预测。如果第一步 get_today_date() 输出“2030-09-13”,代理可以推断出下一步 fetch_top_products 应该使用以下参数调用:

fetch_top_products(
    start_date="2030-09-07",
    end_date="2030-09-13",
    num_products=1
)

通常,信息不足以确定函数的精确参数值。例如,如果用户询问“畅销产品的平均价格是多少?”,以下问题的答案并不明确:

这意味着模型经常需要进行猜测,而猜测可能是错误的。

由于动作序列和相关参数都是由 AI 模型生成的,它们可能会产生幻觉。幻觉可能导致模型调用无效函数,或者调用有效函数但使用了错误的参数。通常用于提升模型整体性能的技术,同样可以用来提高模型的规划能力。

提升代理规划能力的技巧
  • 编写更好的系统提示,并提供更多示例。
  • 提供更清晰的工具及其参数描述,以便模型更好地理解它们。
  • 重写函数本身使其更简单,例如将一个复杂函数重构为两个更简单的函数。
  • 使用更强大的模型。通常,能力更强的模型在规划方面表现更好。
  • 针对计划生成任务对模型进行微调。

函数调用 (Function calling)

许多模型提供商为其模型提供工具使用功能,从而有效地将其模型转化为代理。工具即函数,因此工具调用也通常被称为函数调用。不同的模型 API 工作方式各异,但总的来说,函数调用的工作流程如下:

  1. 创建工具清单。声明所有您希望模型可能使用的工具。每个工具都通过其执行入口点(例如函数名)、参数及其文档(例如函数的功能和所需参数)进行描述。
  2. 为查询指定代理可用的工具
    由于不同的查询可能需要不同的工具,许多 API 允许您为每个查询指定一个已声明的工具列表。有些 API 还允许您通过以下设置进一步控制工具的使用:
    • required:模型必须至少使用一个工具。
    • none:模型不应使用任何工具。
    • auto:模型自行决定使用哪些工具。

函数调用过程如图 6-10 所示。该图以伪代码形式编写,以便代表多种 API 的通用流程。要使用特定的 API,请参考其官方文档。

function_calling.png

图 6-10. 一个模型使用两个简单工具的示例

对于给定的查询,如图 6-10 中定义的代理将自动生成要使用的工具及其参数。一些函数调用 API 会确保只生成有效的函数,但它们无法保证参数值的正确性。

例如,对于用户查询“40 磅等于多少公斤?”,代理可能会决定需要 lbs_to_kg_tool 工具,并带有一个值为 40 的参数。代理的响应可能如下所示:

{
  "response": {
    "finish_reason": "tool_calls",
    "message": {
      "content": null,
      "role": "assistant",
      "tool_calls": [
        {
          "function": {
            "arguments": "{\"lbs\":40}",
            "name": "lbs_to_kg"
          },
          "type": "function"
        }
      ]
    }
  }
}

根据此响应,您可以调用函数 lbs_to_kg(lbs=40),并使用其输出来生成对用户的答复。

提示:在使用代理时,务必让系统报告其为每个函数调用所使用的参数值。检查这些值以确保其正确性。

计划粒度 (Planning granularity)

计划是概述完成任务所需步骤的路线图。路线图可以具有不同级别的粒度。对于年度规划,季度计划比月度计划的粒度更粗(层级更高),而月度计划又比周计划的粒度更粗。

这里存在规划与执行之间的权衡。详细的计划更难生成,但更易于执行。层级更高的计划更易于生成,但更难执行。一种规避这种权衡的方法是进行分层规划。首先,使用一个规划器生成一个高层计划,例如季度计划。然后,对于每个季度,使用相同或不同的规划器生成月度计划。

到目前为止,所有生成的计划示例都使用了精确的函数名,这属于非常细致的粒度。这种方法的一个问题是,代理的工具清单可能会随时间而变化。例如,获取当前日期的函数 get_today_date() 可能会被重命名为 get_current_time()。当工具发生变化时,您需要更新提示和所有示例。使用精确的函数名也使得在具有不同工具 API 的不同用例之间重用规划器变得更加困难。

如果您之前已经基于旧的工具清单微调了一个模型来生成计划,那么您将需要针对新的工具清单重新微调该模型。

为了避免这个问题,计划也可以使用更自然的语言来生成,这种方式比领域特定的函数名层级更高。例如,对于查询“上周最畅销产品的价格是多少”,可以指示代理输出如下所示的计划:

1. `获取当前日期`
2. `检索上周最畅销的产品`
3. `检索产品信息`
4. `生成查询`
5. `生成响应`

使用更自然的语言有助于您的规划器对工具 API 的变化保持鲁棒性。如果您的模型主要是在自然语言上训练的,那么它可能更擅长理解和生成自然语言的计划,并且产生幻觉的可能性也更小。

这种方法的缺点是您需要一个转换器 (translator) 将每个自然语言动作转换为可执行的命令。Chameleon (Lu et al., 2023) 将此转换器称为程序生成器 (program generator)。然而,转换是一项比规划简单得多的任务,可以由能力要求较低的模型完成,产生幻觉的风险也更低。

复杂计划 (Complex plans)

到目前为止的计划示例都是顺序性的:计划中的下一个动作总是在上一个动作完成后执行。动作可以执行的顺序称为控制流 (control flow)。顺序形式只是控制流的一种类型。其他类型的控制流包括并行 (parallel)、if 语句 (if statement) 和 for 循环 (for loop)。以下列表概述了每种控制流,并包含顺序控制流以供比较:

这些不同的控制流如图 6-11 所示。

complex_plans.png

图 6-11. 计划可以执行的不同顺序示例

在传统的软件工程中,控制流的条件是精确的。而在 AI 驱动的代理中,则由 AI 模型来决定控制流。包含非顺序控制流的计划更难生成,也更难转换为可执行的命令。

在评估一个代理框架时,请检查它支持哪些控制流。例如,如果系统需要浏览十个网站,它能否同时进行?并行执行可以显著减少用户感知的延迟。

反思与纠错 (Reflection and error correction)

即使是最好的计划也需要不断评估和调整,以最大限度地提高其成功的机会。虽然反思对于代理的运行并非绝对必要,但对于代理的成功却是必不可少的。

在任务处理过程中,有许多环节可以运用反思:

反思和纠错是两种相辅相成、紧密协作的机制。反思产生洞察,帮助发现需要纠正的错误。

反思可以通过同一个代理使用自我批判 (self-critique) 提示来完成,也可以通过一个独立的组件来完成,例如一个专门的评分器——一个为每个结果输出具体分数的模型。

ReAct (Yao et al., 2022) 首次提出的交错进行推理 (reasoning) 和行动 (action) 的模式,已成为代理的常见范式。Yao 等人使用“推理”一词来涵盖规划和反思。在每个步骤中,代理都被要求解释其思考过程(规划),采取行动,然后分析观察结果(反思),直到代理认为任务完成。通常会通过示例来提示代理生成以下格式的输出:

思考 1:…
行动 1:…
观察 1:…

… [持续进行,直到反思判断任务已完成] …

思考 N:…
行动 N:完成 [对查询的响应]

图 6-12 展示了一个遵循 ReAct 框架的代理响应 HotpotQA (Yang et al., 2018) 基准(一个多跳问答基准)中问题的示例。

react_agent.png

图 6-12. 一个运行中的 ReAct 代理

您可以在多代理设置中实现反思:一个代理负责规划和采取行动,另一个代理在每个步骤之后或若干步骤之后评估结果。

如果代理的响应未能完成任务,您可以提示代理反思其失败的原因以及如何改进。基于此建议,代理会生成一个新的计划。这使得代理能够从错误中学习。

例如,给定一个代码生成任务,评估器可能会发现生成的代码未能通过三分之一的测试用例。然后,代理反思其失败是因为没有考虑到所有数字均为负数的数组情况。接着,行动者 (actor) 会生成新的代码,并考虑到全负数数组的情况。

Reflexion (Shinn et al., 2023) 框架采用了这种方法。在该框架中,反思被分为两个模块:一个评估结果的评估器和一个分析出错原因的自我反思模块。图 6-13 展示了 Reflexion 代理的工作示例。作者使用“轨迹 (trajectory)”一词来指代计划。在每个步骤中,经过评估和自我反思后,代理会提出一个新的轨迹。

reflexion_agent.png

图 6-13. Reflexion 代理工作方式示例

与计划生成相比,反思的实现相对容易,并且能带来出乎意料的显著性能提升。这种方法的缺点在于延迟和成本。思考、观察,有时甚至是行动,都可能需要生成大量的 token,这会增加成本和用户感知的延迟,特别是对于包含许多中间步骤的任务。为了引导其代理遵循特定格式,ReAct 和 Reflexion 的作者都在提示中使用了大量示例。这增加了计算输入 token 的成本,并减少了可用于其他信息的上下文空间。

工具选择 (Tool selection)

由于工具在任务成功中通常扮演着至关重要的角色,因此工具选择需要仔细斟酌。为代理选择何种工具,不仅取决于环境和任务,还取决于驱动代理的 AI 模型。

关于如何选择最佳工具集,并没有万无一失的指南。代理相关的文献中包含了各式各样的工具清单。例如:

更多的工具赋予代理更强的能力。然而,工具越多,高效使用它们的难度也越大。这与人类难以精通大量工具的情况类似。增加工具也意味着需要增加工具描述,而这些描述可能无法完全容纳在模型的上下文中。

与构建 AI 应用时的许多其他决策一样,工具选择需要实验和分析。以下是一些有助于您做出决定的方法:

tool_usage.png

图 6-14. 不同的模型和任务表现出不同的工具使用模式

Chameleon (Lu et al., 2023) 的实验也揭示了两点:

  1. 不同的任务需要不同的工具。例如,科学问答任务 ScienceQA 比表格数学问题解决任务 TabMWP 更依赖知识检索工具。
  2. 不同的模型有不同的工具偏好。例如,GPT-4 似乎比 ChatGPT 更倾向于选择更多样化的工具集。ChatGPT 似乎偏爱图像描述功能,而 GPT-4 则似乎更偏爱知识检索功能。

在评估一个代理框架时,请评估其支持哪些规划器和工具。不同的框架可能专注于不同类别的工具。例如,AutoGPT 专注于社交媒体 API(如 Reddit、X 和 Wikipedia),而 Composio 则专注于企业级 API(如 Google Apps、GitHub 和 Slack)。

由于您的需求可能会随时间变化,因此评估扩展代理以集成新工具的便捷性非常重要。

作为人类,我们提高生产力不仅依赖于使用现有的工具,还依赖于基于简单工具创造出功能日益强大的新工具。那么,AI 能否基于其初始工具集创造出新的工具呢?

Chameleon (Lu et al., 2023) 提出了对工具转换 (tool transition) 的研究:在使用工具 X 之后,代理调用工具 Y 的可能性有多大?图 6-15 展示了一个工具转换的示例。如果两个工具经常一起使用,它们可以被组合成一个更大的工具。如果代理意识到这一信息,它自身就可以组合初始工具,从而持续构建更复杂的工具。

tool_transition.png

图 6-15. 由 Chameleon (Lu et al., 2023) 提出的工具转换树

Voyager (Wang et al., 2023) 提出了一个技能管理器 (skill manager),用于跟踪代理获取的新技能(工具),以便后续重用。每个技能都是一个编码程序。当技能管理器判断一个新创建的技能有用时(例如,因为它成功帮助代理完成了某项任务),它会将该技能添加到技能库(概念上类似于工具清单)。该技能后续可以被检索并用于其他任务。

在本节前面,我们提到代理在特定环境中的成功取决于其工具清单和规划能力。这两个方面中的任何一个出现故障都可能导致代理失败。下一节将讨论代理的不同故障模式以及如何评估它们。

代理故障模式与评估

评估的核心在于检测故障。代理执行的任务越复杂,潜在的故障点就越多。除了第 3 章和第 4 章中讨论的所有 AI 应用所共有的故障模式外,代理还存在因规划、工具执行和效率问题而导致的特有故障。其中一些故障比其他故障更容易被发现。

要评估一个代理,首先要识别其故障模式,然后衡量每种故障模式发生的频率。

规划失败 (Planning failures)

规划本身就很困难,并且可能因多种方式失败。最常见的规划失败模式是工具使用失败。代理生成的计划可能包含以下一种或多种错误:

另一种规划失败模式是目标失败 (goal failure):代理未能达成预设目标。这可能是因为计划本身无法解决任务,或者计划虽然解决了任务但没有遵守约束条件。举例来说,假设您要求模型规划一次预算为 5000 美元、从旧金山到印度的为期两周的旅行。代理可能会规划成一次从旧金山到越南的旅行,或者规划的旧金山到印度的两周旅行费用远超预算。

在代理评估中,时间是一个经常被忽视的重要约束。在许多情况下,代理花费的时间可能不那么重要,因为您可以将任务分配给代理,只需在其完成后检查即可。然而,在很多情况下,随着时间的推移,代理的效用会降低。例如,如果您要求代理准备一份拨款申请,而代理在截止日期之后才完成,那么这个代理就没什么帮助了。

一个有趣的规划失败模式是由反思中的错误引起的。即代理确信已经完成了任务,但实际上并没有。例如,您要求代理将 50 个人分配到 30 间酒店客房。代理可能只分配了 40 个人,却坚称任务已经完成。

要评估代理的规划失败,一种方法是创建一个规划数据集,其中每个样本都是一个元组 (任务, 工具清单)。对于每个任务,让代理生成 K 个计划。然后计算以下指标:

  1. 在所有生成的计划中,有多少是有效的?
  2. 对于给定的任务,代理需要生成多少个计划才能得到一个有效的计划?
  3. 在所有工具调用中,有多少是有效的?
  4. 调用无效工具的频率如何?
  5. 以无效参数调用有效工具的频率如何?
  6. 以不正确的参数值调用有效工具的频率如何?

分析代理的输出以发现模式。代理在哪些类型的任务上更容易失败?您对此有什么假设吗?模型经常在哪些工具上出错?某些工具可能对代理来说更难使用。您可以通过改进提示、提供更多示例或进行微调来提升代理使用有挑战性工具的能力。如果所有方法都失败,您可能需要考虑将该工具替换为更易于使用的工具。

工具失败 (Tool failures)

工具失败是指虽然使用了正确的工具,但工具的输出是错误的。一种失败模式是工具直接给出了错误的输出。例如,图像描述器返回了错误的描述,或者 SQL 查询生成器返回了错误的 SQL 查询。

如果代理仅生成高层级的计划,并且涉及到将每个计划动作转换为可执行命令的翻译模块,那么失败也可能由翻译错误引起。

工具失败是工具相关的,每个工具都需要独立测试。务必打印出每次工具调用及其输出,以便进行检查和评估。如果您使用了翻译器,请创建基准来评估其性能。

检测缺失工具导致的失败,需要理解在特定情境下应该使用哪些工具。如果您的代理经常在特定领域失败,这可能意味着它缺乏该领域的适用工具。与人类领域专家合作,观察他们会使用哪些工具,可以为您的代理补充合适的工具。

效率 (Efficiency)

代理可能生成了一个使用正确工具来完成任务的有效计划,但其过程可能效率低下。以下是一些您可能需要跟踪以评估代理效率的指标:

您可以将这些指标与您的基准进行比较,基准可以是另一个代理或人类操作员。在比较 AI 代理和人类代理时,请记住,人类和 AI 的操作模式截然不同,因此对人类而言高效的方式,对 AI 而言可能效率低下,反之亦然。例如,访问 100 个网页对于一次只能访问一个页面的人类代理而言可能效率低下,但对于可以同时访问所有网页的 AI 代理而言则可能轻而易举。

结论

从本质上讲,代理的概念相当简单。代理的特性由其运行的环境和可访问的工具集决定。在 AI 驱动的代理中,AI 模型扮演着“大脑”的角色,它利用其工具和来自环境的反馈来规划如何最好地完成任务。工具的赋能极大地扩展了模型的能力,因此代理模式的应用势必会成为常态。

尽管“代理”的概念听起来新颖,但它们建立在许多自 LLM 早期就已应用的概念之上,包括自我批判、思维链和结构化输出等。

本文从概念上阐述了代理的工作方式以及代理的不同组成部分。在未来的文章中,我将讨论如何评估不同的代理框架。

代理模式通常需要处理超出模型上下文限制的信息。一个能够辅助模型上下文处理信息的记忆系统,可以显著增强代理的能力。由于本文篇幅已长,我将在未来的博客文章中探讨记忆系统的工作原理。


本站总访问量