重磅干货|企业级 AI Agent智能体大白话解读 |2025 Google 全新发布(全42页白皮书,附下载)

duke 的头像

·

·

是不是感觉 AI Agent 智能体很难懂?别担心,今天给大家分享一篇通俗易懂的文章——《谷歌“智能体” 2025白皮书》。本文会用大白话告诉你,智能体和大模型的区别,智能体中常用的工具有哪几种? 

引言

人类非常擅长处理复杂的模式识别任务。然而,在得出结论之前,他们往往依赖工具,如书籍、谷歌搜索或计算器,来补充先验知识。与人类一样,生成式人工智能模型也可以经过训练使用工具,来获取实时信息或提出实际行动建议。例如,模型可以利用数据库检索工具获取特定信息,如客户的购买历史,从而生成个性化的购物推荐。或者,根据用户的查询,模型可以进行各种 API 调用,代表用户向同事发送电子邮件回复,或完成一笔金融交易。要做到这一点,模型不仅必须能够使用一系列外部工具,还需要具备以自主方式规划和执行任何任务的能力。这种与生成式人工智能模型相关联的推理、逻辑以及对外部信息的访问能力的结合,引出了智能体的概念,或者说是一个扩展了生成式人工智能模型独立能力范围的程序。本白皮书将更详细地深入探讨所有这些方面及相关内容。  

专注于核心功能,智能体的认知架构中有三个基本组件,如图 1 所示。 

图 1 通用智能体架构和组件 

什么是智能体?

从最基本的形式来看,生成式人工智能智能体可定义为一种应用程序,它试图通过观察周围环境,并利用自身可支配的工具对环境采取行动,以实现某个目标。智能体具有自主性,能够在无需人类干预的情况下行动,特别是在被赋予明确要达成的目标时。智能体在追求目标的过程中也能主动行事。即便没有人类给出的明确指令集,智能体也能思考下一步该做什么以实现其最终目标。虽然人工智能中智能体的概念相当宽泛且强大,但本白皮书聚焦于在发布之时生成式人工智能模型能够构建的特定类型的智能体。 

为了理解智能体的内部运作机制,我们首先介绍驱动智能体行为、行动和决策的基础组件。这些组件的组合可被描述为一种认知架构,通过对这些组件进行混合与匹配,可以实现多种这样的架构。着眼于核心功能,如图 1 所示,智能体的认知架构中有三个基本组件。  

模型

在智能体范畴内,模型指的是语言模型(LM),它将作为智能体运行过程中的核心决策组件。智能体使用的模型可以是一个或多个任意规模(小型/大型)的语言模型,这些模型需能够遵循基于指令的推理和逻辑框架,如 ReAct、思维链(Chain-of-Thought)或思维树(Tree-of-Thoughts)。模型可以是通用型、多模态的,也可根据特定智能体架构的需求进行微调。为了在实际应用中取得最佳效果,你应选用最适合目标终端应用的模型,理想情况下,该模型应在与你计划在认知架构中使用的工具相关的数据特征上进行过训练。需要注意的是,模型通常不会依据智能体的特定配置设置(如工具选择、编排/推理设置)进行训练。不过,通过向模型提供展示智能体能力的示例,包括智能体在各种场景下使用特定工具或推理步骤的实例,可为智能体的任务对模型做进一步优化。  

简单来说,模型就像是智能体的“大脑”,负责做出决策。这个“大脑”可以根据不同的需求进行选择和调整,以便更好地适应智能体的工作。虽然模型本身不能直接和外界交互,但它可以通过学习相关的数据和工具,来帮助智能体更好地完成任务。 

工具

尽管基础模型在文本和图像生成方面表现出色,但仍受限于无法与外部世界交互。工具则弥补了这一不足,使智能体能够与外部数据和服务互动,并且开启了诸多仅靠基础模型无法完成的行动。 

工具可以有多种形式,复杂程度也各不相同,但通常与常见的网络 API 方法(如 GET、POST、PATCH 和 DELETE )一致。例如,一个工具可以在数据库中更新客户信息,或者获取天气数据,从而影响智能体向用户提供的旅行建议。借助工具,智能体能够访问和处理现实世界中的信息。这使它们能够支持诸如检索增强生成(RAG)等更专业的系统,显著扩展了智能体的能力,使其超越基础模型的独自所能。我们将在下文更详细地讨论工具,但最重要的是要明白,工具弥合了智能体内部能力与外部世界之间的差距,开启了更广泛的可能性。  

编排层(The orchestration layer)

编排层描述了一个循环过程,该过程控制智能体如何接收信息、进行内部推理,并依据推理结果决定下一步行动或决策。一般来说,这个循环会持续进行,直至智能体达成目标或到达某个停止点。

 

编排层的复杂程度会因智能体及其执行的任务而有很大差异。有些循环可能只是基于决策规则的简单计算,而其他循环可能包含链式逻辑,涉及额外的机器学习算法,或者采用其他概率推理技术。在认知架构部分,我们将更深入地探讨智能体编排层的详细实现方式。 

简单来说,编排层就像是智能体的“指挥中心”,负责管理智能体的记忆、状态、推理和计划。它使用提示工程和相关框架来指导智能体的推理和计划,使智能体能够更有效地与环境互动并完成任务。  

智能体与模型的对比

为了更清楚地理解智能体和模型之间的区别,可以考虑下面的图表: 

模型 (Models) 智能体 (Agents)
知识仅限于他们所掌握的内容训练数据。 知识通过连接而扩展
通过工具与外部系统连接
基于用户查询的单次推理/预测。除非模型明确实现,否则不会管理会话历史记录或持续性上下文(即聊天历史) 管理会话历史(即聊天历史)以实现基于用户查询和编排层决策的多轮推理/预测。
在此上下文中,”轮次”被定义为交互系统与智能体之间的一次交互。(即1个传入事件/查询和1个智能体响应)
无原生工具支持 工具已集成在智能体架构中
未实施原生逻辑层。用户可以将提示构建为简单问题,或使用推理框架(如思维链、ReAct等)来构建复杂提示,以引导模型进行预测 原生认知架构,它使用像思维链(CoT)、反应(ReAct)这样的推理框架,或其他像 LangChain 这样的预构建智能体框架

简单来说,模型就像是一个擅长处理信息的“大脑”,但它不能直接与外界互动。而智能体则像是一个有手有脚的“小活人”,它不仅有自己的“大脑”(模型),还可以使用工具(如 API 调用)来与外界互动,完成各种任务。 

认知架构(Cognitive Architectures):智能体如何运作

想象一下,在一个繁忙的厨房里,厨师的目标是为餐厅的顾客制作美味的菜肴,这个过程涉及到规划、执行和调整的循环。 

  • 厨师收集信息,比如顾客的订单,以及食品储藏室和冰箱里有哪些食材。
  • 根据刚收集到的信息,厨师在脑海中思考能做出哪些菜肴、搭配出何种风味。
  • 厨师开始动手做菜:切菜、调配香料、煎肉。

在整个过程的每个阶段,厨师会根据需要进行调整,随着食材的消耗或收到顾客反馈来完善计划,并依据之前的一系列结果决定下一步行动方案。这种信息收集、规划、执行和调整的循环,描述了厨师为实现目标所采用的独特认知架构。 

就像厨师一样,智能体可以通过迭代处理信息、做出明智决策,并根据先前的输出优化后续行动,利用认知架构来达成最终目标。智能体认知架构的核心是编排层,它负责维持记忆、状态、推理和规划。编排层借助快速发展的提示工程领域及相关框架来引导推理和规划,使智能体能够更有效地与所处环境互动并完成任务。 

简单来说,认知架构就像是智能体的“操作手册”,指导它如何收集信息、进行推理、制定计划并采取行动。通过这种循环的过程,智能体可以不断地调整自己的行为,以更好地实现目标 

针对语言模型的提示工程框架和任务规划领域的研究正在迅速发展,产生了多种前景可观的方法。以下并非完整清单,而是在本文撰写时一些最流行的框架和推理技术: 

  • ReAct 是一种提示工程框架,它为语言模型提供了一种思维过程策略,使模型能够针对用户查询进行推理并采取行动,无论是否有上下文示例。事实证明,ReAct 提示方法优于多个当前最优基准,并提升了大语言模型(LLMs)与人类的交互能力和可信度。
  • CoT(Chain-of-Thought,思维链)是一种提示工程框架,它通过中间步骤赋予推理能力。思维链有多种子技术,包括自一致性、主动提示和多模态思维链,每种技术根据具体应用场景各有优劣。
  • ToT(Tree – of – thoughts, 思维树)是一种提示工程框架,非常适合探索性任务或需要前瞻性策略的任务。它对思维链提示方法进行了扩展,允许模型探索各种思维链,这些思维链可作为借助语言模型解决一般问题的中间步骤。

智能体可以利用上述推理技术中的一种,或者许多其他技术,针对给定的用户请求选择下一个最佳行动方案。例如,假设有一个智能体被编程为使用 ReAct 框架,为用户查询选择正确的行动和工具。事件的发生顺序可能如下: 

  1. 用户向智能体发送查询。
  2. 智能体启动 ReAct 流程。
  3. 智能体向模型给出提示,要求其生成下一步 ReAct 步骤及其相应输出:
    • a. 问题:随提示一同给出的,来自用户查询的输入问题。
    • b. 思考:模型对于接下来应做之事的思考。
    • c. 行动:模型对于下一步采取何种行动的决策。
      • i. 这是选择工具的环节。
      • ii. 例如,行动可以是[航班、搜索、代码、无]其中之一,前三项代表模型可选择的已知工具,最后一项代表“不选择工具”。
    • d. 行动输入:模型对于向工具提供何种输入(若有)的决策。
    • e. 观察结果:行动/行动输入序列的结果。
      • i. 根据需要,此思考/行动/行动输入/观察结果环节可能重复 N 次。
    • f. 最终答案:模型针对原始用户查询给出的最终答案。
  4. ReAct 循环结束,最终答案返回给用户。

图 2. 在编排层采用 ReAct 推理的智能体示例 

如图 2 所示,模型、工具和智能体配置协同工作,根据用户的原始查询,向用户提供有依据且简洁的回复。虽然模型本可以凭借其先验知识猜测答案(产生幻觉),但它却选择使用一种工具(航班查询工具)来搜索实时外部信息。这些额外信息被提供给模型,使其能够基于真实数据做出更明智的决策,并将这些信息总结后反馈给用户。 

总之,智能体回复的质量,直接取决于模型针对各类任务进行推理和行动的能力,这包括选择合适工具的能力,以及工具的定义完善程度。就像厨师精心选用新鲜食材烹饪菜肴,并留意顾客反馈一样,智能体依赖合理的推理和可靠的信息来达成最佳效果。在下一节中,我们将深入探讨智能体获取最新鲜数据的各种方式。  

工具:我们通往外部世界的钥匙

虽然语言模型擅长处理信息,但它们缺乏直接感知和影响现实世界的能力。这限制了它们在与外部系统或数据交互的情况下的实用性。这意味着,从某种意义上说,语言模型的能力仅限于它从训练数据中学到的内容。但是,无论我们向模型提供多少数据,它们仍然缺乏与外部世界互动的基本能力。那么,我们如何赋予我们的模型实时、上下文感知的外部系统交互能力呢?函数、扩展、数据存储和插件都是提供这种关键能力给模型的方法。 

虽然它们有很多不同的名称,但工具是创建我们基础模型与外部世界之间联系的东西。这种与外部系统和数据的联系允许我们的智能体执行更广泛的任务,并且这样做可以更加准确和可靠。例如,工具可以使智能体调整智能家居设置、更新日历、从数据库中获取用户信息或根据特定指令发送电子邮件。 

截至本文发布之日,谷歌模型能够互动的主要工具有三种:扩展(Extensions)、函数(Functions)和数据存储(Data Stores)。通过为智能体配备这些工具,我们解锁了它们不仅理解世界,而且还能作用于世界的巨大潜力,为新的应用和可能性打开了大门。 

简单来说,工具就像是智能体的“魔法棒”,让它们能够与现实世界互动,完成各种任务。通过使用这些工具,智能体不仅可以更好地理解世界,还可以采取行动改变世界。 

扩展

理解扩展(Extensions)最简单的方式,就是将其视为以标准化方式弥合应用程序编程接口(API)与智能体之间差距的桥梁,它能让智能体无缝执行各种 API,无论这些 API 的底层实现方式如何。假设你构建了一个旨在帮助用户预订航班的智能体。你知道自己想使用谷歌航班 API 来检索航班信息,但却不确定如何让智能体调用这个 API 端点。  

图 3 展示了智能体如何与外部 API 进行交互 

一种方法是实现自定义代码,该代码会获取用户查询,解析查询中的相关信息,然后进行 API 调用。例如,在航班预订用例中,用户可能会说:“我想从奥斯汀飞往苏黎世。”在这种情况下,我们的自定义代码解决方案需要从用户查询中提取“奥斯汀”和“苏黎世”作为相关实体,然后尝试进行 API 调用。但如果用户说:“我想飞往苏黎世”,而从未提供出发城市呢?没有所需数据,API 调用将会失败,还需要实现更多代码来捕捉这种边缘和角落情况。这种方法不具备扩展性,并且在任何超出实现的自定义代码范围的场景中都容易崩溃。 

一种更有韧性的方法是使用扩展。扩展通过以下方式弥合了智能体和 API 之间的差距: 

  1. 使用示例(examples)教智能体如何使用 API endpoint
  • 这意味着可以向智能体提供一系列具体的示例,展示如何调用 API endpoint。例如,如果是一个图像识别的 API,可能会给出如 “使用 API endpoint /image/recognition,传入图像的 URL 作为参数,调用后会得到图像中物体的识别结果” 这样的示例,让智能体学习在不同情况下如何正确调用 API endpoint。通过多个这样的示例,智能体可以学习到 API endpoint 的使用规则和模式,以便在处理不同任务时能够准确调用相应的 API endpoint。
  1. 教智能体成功调用 API 端点所需的参数或参数
  • 这是为了确保智能体在调用 API 时能够提供完整的信息。例如,对于一个天气查询的 API,需要告诉智能体调用 API 端点时可能需要的参数,如城市名称、日期范围、查询类型(如当前天气、历史天气或预测天气)等。这样,智能体在准备调用 API 时,会明确需要哪些参数,并能正确组织这些参数进行调用,避免因参数缺失或错误而导致的 API 调用失败。

图 4. 扩展将智能体与外部 API 相连  

扩展可以独立于智能体进行构建,但应作为智能体配置的一部分提供。智能体在运行时使用模型和示例来决定哪个扩展(如果有的话)适合解决用户的查询。这凸显了扩展的一个关键优势,即其内置的示例类型,这些示例类型使智能体能够为任务动态选择最合适的扩展。  

图 5. 智能体、扩展与 API 之间的一对多关系 

可以这样理解,就如同软件开发人员在为用户解决问题并设计解决方案时,会决定使用哪些 API endpoint。如果用户想预订航班,开发人员可能会使用谷歌航班 API。如果用户想知道离他们位置最近的咖啡店在哪,开发人员可能会使用谷歌地图 API。同样,智能体/模型组合会利用一组已知的扩展(Extensions),来决定哪一个最适合用户的查询。如果你想看看扩展的实际运行效果,可以在 Gemini 应用程序中进行尝试,路径为:设置>扩展,然后启用任何你想测试的扩展。例如,你可以启用谷歌航班扩展,然后问 Gemini “显示下周五从奥斯汀飞往苏黎世的航班”。  

示例扩展

为了简化扩展的使用,谷歌提供了一些现成的扩展,可以快速导入到你的项目中,并且只需很少配置即可使用。 

简单来说,谷歌已经为你准备了一些“傻瓜式”的扩展工具,你可以直接拿来在你的项目中使用,不需要复杂的设置。这些扩展就像是智能体的“小助手”,帮助智能体更容易地完成特定的任务,比如调用某个 API 或者处理某种数据。这样一来,智能体就能更加专注于它的核心任务,而不需要为了一些琐碎的事情操心。 

Copied!
import vertexai
import pprint

PROJECT_ID = "YOUR_PROJECT_ID"
REGION = "us-central1"

vertexai.init(project=PROJECT_ID, location=REGION)

from vertexai.preview.extensions import Extension

extension_code_interpreter = Extension.from_hub("code_interpreter")
CODE_QUERY = """Write a python method to invert a binary tree in O(n) time."""

response = extension_code_interpreter.execute(
 operation_id = "generate_and_execute",
 operation_params = {"query": CODE_QUERY}
 )
 
print("Generated Code:")
pprint.pprint({response['generated_code']})

# The above snippet will generate the following code.
```
Generated Code:
class TreeNode:
 def __init__(self, val=0, left=None, right=None):
 self.val = val
 self.left = left
 self.right = right

def invert_binary_tree(root):
 """
 Inverts a binary tree.
 Args:
 root: The root of the binary tree.
 Returns:
 The root of the inverted binary tree.
 """
 if not root:
     return None
 
 # Swap the left and right children recursively
 root.left, root.right =
invert_binary_tree(root.right), invert_binary_tree(root.left)

return root

# Example usage:
# Construct a sample binary tree
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
root.right.left = TreeNode(6)
root.right.right = TreeNode(9)
# Invert the binary tree
inverted_root = invert_binary_tree(root)
```

代码片段 1. 代码解释器扩展可以生成并运行 Python 代码 

总而言之,扩展为智能体提供了多种方式来感知、交互以及影响外部世界。这些扩展的选择和调用是由示例引导的,所有示例均作为扩展配置的一部分进行定义。  

函数

在软件工程领域,函数被定义为独立的代码模块,它们完成特定任务,并可根据需要重复使用。软件开发人员编写程序时,通常会创建多个函数来执行各种任务。他们还会定义何时调用函数 A 而非函数 B 的逻辑,以及预期的输入和输出。 

在智能体领域,函数的工作方式非常相似,但我们可以用模型替代软件开发人员。模型可以利用一组已知函数,并根据函数的规格说明,决定何时使用每个函数以及该函数需要哪些参数。函数与扩展在几个方面有所不同,最显著的是: 

1. 模型输出一个函数及其参数,但不进行实时 API 调用。 

2. 函数在客户端执行,而扩展在智能体端执行。 

 

再次以谷歌航班为例,一个简单的函数设置可能如图 7 中的示例所示。  

图 7. 函数如何与外部 API 交互? 

请注意,这里的主要区别在于,无论是函数还是智能体,都不会直接与谷歌航班 API 进行交互。那么,API 调用实际上是如何发生的呢? 

对于函数而言,调用实际 API 端点的逻辑和执行工作从智能体转移回了客户端应用程序,如下图 8 和图 9 所示。这使开发人员能够更精细地控制应用程序中的数据流。开发人员选择使用函数而非扩展,原因有很多,以下是一些常见的用例: 

  • API 调用需要在应用程序栈的另一层进行,不在智能体的直接架构流程范围内(例如,中间件系统、前端框架等)。
  • 安全或认证限制导致智能体无法直接调用 API(例如,API 未暴露在互联网上,或者智能体基础设施无法访问)。
  • 时间安排或操作顺序的限制,使得智能体无法实时进行 API 调用(例如,批量操作、人工介入审核等)。

图 8. 划分客户端与智能体端对扩展和函数调用的控制权  

使用案例

模型可用于调用函数,以便为终端用户处理复杂的客户端执行流程。在这种情况下,智能体开发者可能不希望语言模型管理 API 执行(扩展功能的情况就是如此)。我们来看下面这个例子,一个智能体被训练为旅行礼宾,与想要预订度假行程的用户进行交互。目标是让智能体生成一份城市列表,我们可以在中间件应用程序中使用该列表,为用户的旅行规划下载图片、数据等。用户可能会这样说: 

“我想和家人一起去滑雪旅行,但不确定去哪里。” 

在向模型发出的典型提示(prompt)中,输出可能如下: 

“当然,以下是一些您可以考虑的适合家庭滑雪旅行的城市: 

  • 美国科罗拉多州克雷斯特德比特
  • 加拿大不列颠哥伦比亚省惠斯勒
  • 瑞士采尔马特”

虽然上述输出包含了我们需要的数据(城市名称),但其格式并不理想,不利于解析。通过函数调用(Function Calling),我们可以教会模型以结构化风格(如 JSON)来格式化此输出,这样更便于其他系统解析。对于用户给出的相同输入提示,函数生成的示例 JSON 输出可能如代码片段 5 所示。  

Copied!
Unset

function_call {
 name: "display_cities"
 args: {
 "cities": ["Crested Butte", "Whistler", "Zermatt"],
 "preferences": "skiing"
 }
}

代码片段 5. 用于展示城市列表和用户偏好的示例函数调用负载  

此 JSON 数据(JSON payload)由模型生成,然后发送到我们的客户端服务器,以便我们按需求进行处理。在这个特定场景中,我们会调用谷歌地图地点 API (Google Places API),使用模型提供的城市信息来查找相关图片,然后将其格式化为丰富内容反馈给用户。请参考图 9 中的序列图,它详细展示了上述交互的一步步过程。  

图 9. 展示函数调用生命周期的序列图 

图 9 中示例的结果是,利用模型来“填空”,提供客户端用户界面(UI)调用谷歌地图 API(Google Places API)所需的参数。客户端 UI 使用模型在返回的函数中提供的参数来管理实际的 API 调用。这只是函数调用的一个用例,不过还有许多其他场景值得考虑,比如: 

  • 你希望语言模型推荐一个可在代码中使用的函数,但又不想在代码中包含认证信息。由于函数调用并不运行函数,所以你无需在包含函数信息的代码中加入认证信息。
  • 你正在运行可能需要数秒以上时间的异步操作。这些场景很适合函数调用,因为它本身就是异步操作。
  • 你想在与生成函数调用及其参数的系统不同的设备上运行函数。

关于函数,需要记住的一个关键要点是,它旨在让开发者不仅能更好地控制 API 调用的执行,还能全面掌控应用程序中的整个数据流。在图 9 的示例中,开发者选择不将 API 信息返回给智能体,因为这与智能体未来可能采取的行动无关。然而,根据应用程序的架构,将外部 API 调用数据返回给智能体,以便影响其未来的推理、逻辑和行动选择,或许是有意义的。最终,还是要由应用程序开发者来选择最适合特定应用的方式。  

函数示例代码

为了在滑雪度假场景中实现上述输出,让我们构建各个组件,使其能与我们的 gemini – 1.5 – flash – 001 模型协同工作。 

首先,我们将display_cities函数定义为一个简单的 Python 方法。  

Copied!
def display_cities(cities: list[str], preferences: Optional[str] = None):
"""Provides a list of cities based on the user's search query and preferences.
Args:
 preferences (str): The user's preferences for the search, like skiing,
 beach, restaurants, bbq, etc.
 cities (list[str]): The list of cities being recommended to the user.
Returns:
 list[str]: The list of cities being recommended to the user.
"""
return cities

代码片段 6. 用于显示城市列表的函数的 Python 示例方法 

接下来,我们将实例化模型,构建工具,然后将用户查询和工具传递给模型。执行以下代码将产生代码片段底部所示的输出。  

Copied!
from vertexai.generative_models import GenerativeModel, Tool, FunctionDeclaration

model = GenerativeModel("gemini-1.5-flash-001")

display_cities_function = FunctionDeclaration.from_func(display_cities)
tool = Tool(function_declarations=[display_cities_function])

message = "I’d like to take a ski trip with my family but I’m not sure where
to go."

res = model.generate_content(message, tools=[tool])

print(f"Function Name: {res.candidates[0].content.parts[0].function_call.name}")
print(f"Function Args: {res.candidates[0].content.parts[0].function_call.args}")

> Function Name: display_cities
> Function Args: {'preferences': 'skiing', 'cities': ['Aspen', 'Vail',
'Park City']}

代码片段 7. 构建一个工具,将其与用户查询一同发送至模型,并允许进行函数调用  

总而言之,函数提供了一个简单直接的框架,使应用程序开发人员能够精细地控制数据流和系统执行,同时有效地利用智能体/模型生成关键输入。开发人员可以根据特定的应用架构需求,有选择地决定是否通过返回外部数据让智能体 “参与其中”,还是省略这一步骤。  

数据存储

可以把语言模型想象成一个庞大的图书馆,里面存放着它的训练数据。但与不断购入新书的普通图书馆不同,这个 “图书馆” 是静态的,仅包含最初训练时所用到的知识。这就带来了一个挑战,因为现实世界的知识在不断发展变化。数据存储则通过提供对更动态、更新的信息的访问,解决了这一限制,并确保模型的回答始终基于事实且具有相关性。 

设想这样一个常见场景:开发人员可能需要向模型提供少量额外数据,比如以电子表格或 PDF 文件的形式。  

图 10. 智能体如何与结构化和非结构化数据进行交互? 

数据存储使开发人员能够以原始格式向智能体提供额外数据,无需进行耗时的数据转换、模型重新训练或微调。数据存储会将传入的文档转换为一组向量数据库嵌入,智能体可以利用这些嵌入提取所需信息,为其下一步行动或对用户的回复提供补充。  

图 11. 数据存储将智能体与各类新的实时数据源连接起来 

实施与应用

在生成式人工智能智能体的情境中,数据存储通常作为向量数据库来实施,开发人员希望智能体在运行时能够访问该数据库。虽然我们在此不会深入探讨向量数据库,但关键要理解的是,它们以向量嵌入的形式存储数据,这是一种对所提供数据的高维向量或数学表示。近年来,语言模型使用数据存储最常见的示例之一,就是基于检索增强生成(RAG)的应用程序的实施。这些应用程序试图通过让模型访问各种格式的数据,来扩展模型知识的广度和深度,使其超越基础训练数据,这些数据格式包括: 

  • 网站内容
  • 诸如 PDF、Word 文档、CSV、电子表格等格式的结构化数据
  • 诸如 HTML、PDF、TXT 等格式的非结构化数据

图 12. 智能体与数据存储之间的一对多关系,数据存储可代表各类预先索引的数据  

每个用户请求与智能体响应循环的底层流程,一般如图 13 所示。 

  1. 用户查询被发送至嵌入模型,为该查询生成嵌入向量。
  2. 然后,使用诸如 SCaNN 之类的匹配算法,将查询嵌入向量与向量数据库中的内容进行匹配。
  3. 从向量数据库中以文本格式检索出匹配的内容,并将其发送回智能体。
  4. 智能体接收用户查询和检索到的内容,然后制定出响应或行动。
  5. 最终的回复被发送给用户

图 13. 基于检索增强生成(RAG)应用中用户请求与智能体响应的生命周期 

最终的成果是一个应用程序,它能让智能体通过向量搜索,将用户查询与已知的数据存储进行匹配,检索原始内容,并将其提供给编排层和模型做进一步处理。接下来的操作可能是向用户提供最终答案,或者执行额外的向量搜索以进一步优化结果。 

图 14 展示了与采用 ReAct 推理/规划实现检索增强生成(RAG)的智能体的示例交互。  

图 14. 基于检索增强生成(RAG)并结合 ReAct 推理/规划的应用示例  

工具总结

综上所述,扩展、函数和数据存储构成了几种不同类型的工具,可供智能体在运行时使用。每种工具都有其独特用途,智能体开发者可自行决定将它们组合使用或单独使用。  

扩展 函数调用 数据存储
执行位置 智能体端执行 客户端执行 智能体端执行
使用场景 开发者希望智能体控制与 API 端点的交互利用原生预构建扩展(如 Vertex Search、代码解释器等)时很有用 多步规划和 API 调用(即智能体的下一步行动取决于上一步行动/API 调用的输出)安全或认证限制阻止智能体直接调用 API 时间限制或操作顺序限制阻止智能体实时进行 API 调用(如批量操作、人工介入审核等) 未暴露在互联网上或谷歌系统无法访问的 API 开发者希望使用以下任何数据类型实现检索增强生成(RAG): 来自预索引域和 URL 的网站内容 如 PDF、Word 文档、CSV、电子表格等格式的结构化数据 关系型/非关系型数据库 如 HTML、PDF、TXT 等格式的非结构化数据

通过定向学习提升模型性能

有效使用模型的一个关键因素,在于其在生成输出时选择正确工具的能力,尤其是在生产环境中大规模使用工具的情况下。虽然常规训练有助于模型培养这项技能,但现实场景往往需要超出训练数据范围的知识。可以把这想象成基本烹饪技能与精通某一特定菜系之间的区别。两者都需要基础烹饪知识,但后者需要有针对性的学习,才能取得更精细的成果。 

为帮助模型获取这类特定知识,有几种可行的方法: 

  • 上下文内学习(In-context):这种方法在推理时向通用模型提供 prompt、tools 以及 few-shot examples,使其能够 “即时” 学习针对特定任务如何以及何时使用这些工具。自然语言处理中的 ReAct 框架就是这种方法的一个例子。
  • 基于检索的上下文内学习(Retrieval-based):该技术通过从外部存储器中检索最相关的信息、工具及相关示例,动态地填充模型提示。Vertex AI 扩展中的 “示例存储” 或前文提到的基于检索增强生成(RAG)架构的数据存储就是这类例子。
  • 基于微调的学习(Fine-tuning):此方法在推理之前,使用更大的特定示例数据集对模型进行训练。这有助于模型在收到任何用户查询之前,了解何时以及如何应用某些工具。

为了对每种定向学习方法提供更多见解,让我们再回到烹饪这个类比上来。  

  • 想象一下,一位厨师收到了顾客给出的一份特定食谱(提示词 the prompt)、几种关键食材(相关工具 relevant tools)以及一些菜品示例(少量示例 few-shot examples)。基于这些有限信息以及厨师的烹饪常识,他们需要 “即时” 想出如何烹制出最符合这份食谱以及顾客喜好的菜肴。这就是上下文内学习。
  • 现在,假设我们这位厨师身处一间食材储备丰富的厨房(外部数据存储),里面有各种各样的食材和烹饪书籍(示例和工具)。此时,厨师就能从储备中动态挑选食材和烹饪书籍,更好地契合顾客的食谱和喜好。这使得厨师能够利用已有知识和新知识,制作出更考究、更精致的菜肴。这就是基于检索的上下文内学习。
  • 最后,设想我们把厨师送回学校,让其学习一门新菜系或一系列新菜系(在更大的特定示例数据集上进行预训练)。这样一来,厨师在面对未来从未见过的顾客食谱时,就能有更深入的理解。如果我们希望厨师精通特定菜系(知识领域),这种方法就非常理想。这就是基于微调的学习。

就速度、成本和延迟而言,这些方法各有独特的优缺点。然而,通过在智能体框架中结合使用这些技术,我们可以发挥它们的各种优势并尽量减少劣势,从而得出更强大、更具适应性的解决方案。  

使用 LangChain 快速上手智能体

为了提供一个智能体实际运行的真实可执行示例,我们将使用 LangChain 和 LangGraph 库构建一个快速原型。这些广受欢迎的开源库允许用户通过将逻辑、推理和工具调用序列 “链接” 在一起,来构建自定义智能体,以回答用户的查询。我们将使用 gemini – 1.5 – flash – 001 模型以及一些简单工具,来回答用户的多阶段查询,如代码片段 8 所示。 

我们使用的工具是 SerpAPI(用于谷歌搜索)和谷歌地图地点 API。在运行代码片段 8 中的程序后,你可以在代码片段 9 中看到示例输出。  

Copied!
from langgraph.prebuilt import create_react_agent
from langchain_core.tools import tool
from langchain_community.utilities import SerpAPIWrapper
from langchain_community.tools import GooglePlacesTool

os.environ["SERPAPI_API_KEY"] = "XXXXX"
os.environ["GPLACES_API_KEY"] = "XXXXX"

@tool
def search(query: str):
"""Use the SerpAPI to run a Google Search."""
search = SerpAPIWrapper()
return search.run(query)

@tool
def places(query: str):
"""Use the Google Places API to run a Google Places Query."""
places = GooglePlacesTool()
return places.run(query)

model = ChatVertexAI(model="gemini-1.5-flash-001")
tools = [search, places]

query = "Who did the Texas Longhorns play in football last week? What is the
address of the other team's stadium?"

agent = create_react_agent(model, tools)

input = {"messages": [("human", query)]}

for s in agent.stream(input, stream_mode="values"):
message = s["messages"][-1]

if isinstance(message, tuple):
 print(message)
else:
message.pretty_print()

代码片段 8. 基于 LangChain 和 LangGraph 并使用工具的示例智能体  

Copied!
Unset
=============================== Human Message ================================
Who did the Texas Longhorns play in football last week? What is the address
of the other team's stadium?
================================= Ai Message =================================
Tool Calls: search
Args:
query: Texas Longhorns football schedule
================================ Tool Message ================================
Name: search
{...Results: "NCAA Division I Football, Georgia, Date..."}
================================= Ai Message =================================
The Texas Longhorns played the Georgia Bulldogs last week.
Tool Calls: places
Args:
query: Georgia Bulldogs stadium
================================ Tool Message ================================
Name: places
{...Sanford Stadium Address: 100 Sanford...}
================================= Ai Message =================================
The address of the Georgia Bulldogs stadium is 100 Sanford Dr, Athens, GA
30602, USA.

代码片段 9. 代码片段 8 中程序的输出 

虽然这是一个相当简单的智能体示例,但它展示了模型、编排和工具等基础组件协同工作以实现特定目标的过程。在最后一部分,我们将探讨这些组件如何在谷歌规模的托管产品(如 Vertex AI 智能体和生成式手册)中协同发挥作用。  

使用 Vertex AI 智能体构建生产应用程序

虽然本白皮书探讨了智能体的核心组件,但构建生产级应用程序需要将它们与用户界面、评估框架和持续改进机制等其他工具集成。谷歌的 Vertex AI 平台通过提供一个完全托管的环境,涵盖了前面提到的所有基本要素,简化了这一过程。借助自然语言界面,开发人员可以快速定义其智能体的关键要素,如目标、任务指令、工具、用于任务委派的子智能体以及示例,从而轻松构建出期望的系统行为。此外,该平台还配备了一套开发工具,可用于测试、评估、衡量智能体性能、调试以及提升所开发智能体的整体质量。这使得开发人员能够专注于构建和优化智能体,而基础架构、部署和维护等复杂工作则由平台自行管理。 

 

在图 15 中,我们展示了一个基于 Vertex AI 平台构建的智能体示例架构,该架构使用了 Vertex 智能体构建器、Vertex 扩展、Vertex 函数调用和 Vertex 示例存储等多种功能。此架构包含了生产就绪应用程序所需的诸多组件。  

图 15. 基于 Vertex AI 平台构建的端到端智能体示例架构 

你可以从我们的官方文档中尝试体验这种预构建智能体架构的示例。  

总结

在本白皮书中,我们探讨了生成式人工智能智能体的基础构建模块、它们的组成结构,以及以认知架构形式实现它们的有效方法。本白皮书的一些关键要点包括: 

  1. 智能体通过利用工具获取实时信息、提出现实世界中的行动建议,以及自主规划和执行复杂任务,扩展了语言模型的能力。智能体可以利用一个或多个语言模型来决定何时以及如何在不同状态间转换,并使用外部工具来完成模型自身难以或无法独自完成的众多复杂任务。
  2. 智能体运作的核心是编排层,这是一种认知架构,用于组织推理、规划、决策过程并指导其行动。诸如 ReAct、思维链(Chain-of-Thought)和思维树(Tree-of-Thoughts)等各种推理技术,为编排层提供了一个框架,使其能够接收信息、进行内部推理,并生成明智的决策或回应。
  3. 扩展、函数和数据存储等工具,是智能体通向外部世界的钥匙,使它们能够与外部系统交互,并获取超出其训练数据范围的知识。扩展在智能体与外部 API 之间架起桥梁,支持执行 API 调用和检索实时信息。函数通过分工为开发者提供更精细的控制,使智能体能够生成可在客户端执行的函数参数。数据存储使智能体能够访问结构化或非结构化数据,助力实现数据驱动的应用程序。

智能体的未来发展令人振奋,而我们目前不过是浅尝辄止,尚未充分发掘其潜力。随着工具愈发精密,推理能力不断提升,智能体将能够解决日益复杂的问题。 

此外,“智能体链式连接”这一策略将愈发受到重视。通过组合专门化的智能体——每个智能体都在特定领域或任务中表现卓越——我们可以打造一种 “专家智能体组合” 的模式,使其在各个行业和问题领域都能取得出色成果。  

需要牢记的是,构建复杂的智能体架构需要采用迭代的方法。通过不断试验和优化,才能找到契合特定商业场景和组织需求的解决方案。由于支撑智能体架构的基础模型具有生成性,没有两个完全相同的智能体。然而,利用好这些基础组件的优势,我们就能开发出有影响力的应用程序,拓展语言模型的能力,并创造实际价值。  

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注