AI 学习资料 · AI 智能体入门(精选 9 课)
第 4 课 工具使用设计模式
工具很有意思,因为它让 AI 智能体拥有更广的能力范围。智能体原本只能执行有限的几种动作,加上工具之后,就能做各种各样的事。本课介绍工具使用设计模式,它描述了 AI 智能体如何借助特定工具来实现目标。
编者注:本课原文含较多 Python 代码。本库删去了代码,每段代码处用一句话说明它做了什么;完整代码见文末链接的英文原版。
引言
本课要回答以下问题:
- 什么是工具使用设计模式?
- 它适用于哪些场景?
- 实现这一设计模式需要哪些要素或构建模块?
- 用工具使用设计模式构建可信的 AI 智能体时,有哪些需要特别注意的地方?
学习目标
学完本课,你将能够:
- 说明工具使用设计模式是什么、用来做什么。
- 识别适合使用工具使用设计模式的场景。
- 理解实现这一设计模式所需的关键要素。
- 认识到使用这一设计模式时,为保证 AI 智能体可信需要考虑哪些因素。
什么是工具使用设计模式?
工具使用设计模式的重点,是让大语言模型(LLM)能够与外部工具交互,以实现特定目标。工具是智能体可以执行的代码,用来完成某个动作。工具可以是简单的函数,比如计算器;也可以是对第三方服务的 API 调用,比如查询股价或天气预报。在 AI 智能体的语境下,工具是供智能体执行的,用来响应模型生成的函数调用。
它适用于哪些场景?
AI 智能体可以借助工具完成复杂任务、获取信息或做出决策。工具使用设计模式常用于需要与外部系统动态交互的场景,例如数据库、Web 服务或代码解释器。这种能力适用于许多场景,包括:
- 动态获取信息:智能体可以查询外部 API 或数据库,获取最新数据(例如查询 SQLite 数据库做数据分析、获取股价或天气信息)。
- 执行和解释代码:智能体可以执行代码或脚本,用来解数学题、生成报告或做模拟。
- 工作流自动化:接入任务调度器、邮件服务或数据管道等工具,把重复的或多步骤的工作流程自动化。
- 客户支持:智能体可以与 CRM 系统、工单平台或知识库交互,解决用户的问题。
- 内容生成与编辑:智能体可以借助语法检查、文本摘要或内容安全评估等工具,协助完成内容创作。
实现工具使用设计模式需要哪些要素或构建模块?
这些构建模块让 AI 智能体能执行各种任务。下面来看实现工具使用设计模式所需的关键要素:
-
函数/工具的 Schema(结构定义):对可用工具的详细定义,包括函数名、用途、必填参数和预期输出。有了这些 Schema,LLM 才知道有哪些工具可用、怎样构造有效的请求。
-
函数执行逻辑:根据用户意图和对话上下文,决定何时、如何调用工具。其中可能包括规划模块、路由机制,或者动态决定用哪个工具的条件流程。
-
消息处理系统:管理用户输入、LLM 回复、工具调用和工具输出之间对话流转的组件。
-
工具集成框架:把智能体连接到各种工具的基础设施,无论工具是简单函数还是复杂的外部服务。
-
错误处理与校验:处理工具执行失败、校验参数、应对意外响应的机制。
-
状态管理:跟踪对话上下文、之前的工具交互和需要长期保存的数据,保证多轮交互前后一致。
接下来,我们详细看看函数/工具调用。
函数/工具调用
函数调用是让大语言模型(LLM)与工具交互的主要方式。你会经常看到“函数”和“工具”混用,因为“函数”(可重复使用的代码块)就是智能体用来完成任务的“工具”。要调用某个函数的代码,LLM 必须把用户的请求与函数描述进行比对。为此,需要把一份包含所有可用函数描述的 Schema 发给 LLM。LLM 从中选出最适合这项任务的函数,返回函数名和参数。随后调用选中的函数,把函数的返回结果发回给 LLM,LLM 再据此回答用户的请求。
开发者要为智能体实现函数调用,需要:
- 一个支持函数调用的大语言模型
- 一份包含函数描述的 Schema
- 每个被描述函数的代码
下面用“获取某个城市的当前时间”这个例子来说明:
-
初始化一个支持函数调用的 LLM:
并非所有模型都支持函数调用,所以要先确认你用的 LLM 是否支持。Azure OpenAI 支持函数调用。我们可以先创建一个 OpenAI 客户端,连接 Azure OpenAI 的 Responses API(稳定的
/openai/v1/端点,不需要指定api_version)。代码略:从环境变量读取 Azure OpenAI 的端点、密钥和部署名,创建一个 OpenAI 客户端。
-
创建函数 Schema:
接下来定义一份 JSON Schema,写明函数名、函数用途的描述,以及各个参数的名称和说明。然后把这份 Schema 和用户的请求(询问旧金山现在几点)一起传给前面创建的客户端。要注意的是,返回的是一次工具调用,而不是问题的最终答案。前面说过,LLM 返回的是它为这项任务选中的函数名,以及要传给这个函数的参数。
代码略:用 JSON 定义一个名为
get_current_time的工具,说明它按城市名查询当前时间,唯一的必填参数是location。代码略:把用户问题“旧金山现在几点”和工具定义一起发给模型,并把模型返回的工具调用追加到对话记录里,再打印出来。
代码略:打印结果显示,模型没有直接回答,而是返回了一次对
get_current_time的调用,参数是{"location": "San Francisco"}。 -
完成任务所需的函数代码:
LLM 已经选好了要运行的函数,接下来就要实现并执行真正完成任务的代码。我们可以用 Python 实现获取当前时间的代码,还需要编写代码,从模型的回复中取出函数名和参数,得到最终结果。
代码略:用 Python 实现
get_current_time,在内置的城市与时区对照表里查找该城市,返回当地当前时间,查不到就返回“unknown”。代码略:逐个处理模型返回的工具调用,用模型给出的参数运行
get_current_time,把结果作为工具输出加进对话,再第二次调用模型,拿到给用户的最终回答。代码略:运行日志显示函数以“San Francisco”为参数被调用、找到了对应时区,最后模型回答“旧金山现在是上午 09:24”。
函数调用是大多数(甚至可以说所有)智能体工具使用设计的核心,但从零实现有时并不容易。正如我们在第 2 课中学到的,智能体框架提供了现成的构建模块,可以用来实现工具使用。
用智能体框架实现工具使用的示例
下面是用不同智能体框架实现工具使用设计模式的一些示例:
Microsoft Agent Framework
Microsoft Agent Framework 是一个用于构建 AI 智能体的开源框架。它让你可以用 @tool 装饰器把 Python 函数定义为工具,从而简化函数调用的过程。模型和你的代码之间来回的通信由框架处理。它还通过 FoundryChatClient 提供文件搜索、代码解释器等现成工具。
原文此处有一张图,说明 Microsoft Agent Framework 中函数调用的流程:
图略:函数调用的循环流程。用户发出请求,框架把函数序列化成描述发给模型;模型处理输入后返回要调用的函数名和参数;框架调用函数,把结果交回模型;模型据此生成回复,回应用户。原图含第三方商标标识,且图中步骤编号的机器翻译有误,本库未收录(来源:functioncalling-diagram)
在 Microsoft Agent Framework 中,工具就是加了装饰器的函数。用 @tool 装饰器,就能把前面看到的 get_current_time 函数变成一个工具。框架会自动把函数及其参数序列化,生成要发给 LLM 的 Schema。
代码略:用
@tool装饰器把get_current_time声明为工具,创建一个连接 Microsoft Foundry 项目的客户端,再创建一个名为 TimeAgent 的智能体并把这个工具交给它,最后问它“现在几点”。
来自 MCP 服务器的工具
译注:这一小节只见于同一提交的英文原版,中文机器翻译版缺失,由本库译出,代码略去。
工具不一定是你自己代码里的函数。遵循模型上下文协议(MCP,见第 11 课)的服务器,会把自己的工具连同 Schema 一起发布出来,框架可以像序列化加了装饰器的函数那样加载它们。MCPStreamableHTTPTool 通过 HTTP 连接这样的服务器,读取工具的 Schema,再把这些工具和本地工具一起提供给模型。
原文的示例使用 Keenable 托管的网页搜索服务器。它无需账号或 API 密钥即可免费使用(按 IP 限制请求频率),所以你只需要准备模型本身的凭据。和所有远程工具一样,模型写出的查询内容会被发送到这台服务器。
代码略:用
MCPStreamableHTTPTool连接这台网页搜索 MCP 服务器,创建一个名为 ResearchAgent 的智能体并交给它这个工具,然后问它“最新的 Python 版本有什么新变化”。
这台服务器发布了两个工具:search_web_pages 和 fetch_page_content。遇到需要最新信息的问题时,模型会调用 search_web_pages,拿到标题、网址和文字摘要,再据此写出回答。这和上面 get_current_time 示例中的循环是一样的。
Microsoft Foundry Agent Service
Microsoft Foundry Agent Service 是一个较新的智能体框架,帮助开发者安全地构建、部署和扩容高质量、易于扩展的 AI 智能体,而不必自己管理底层的计算和存储资源。它是全托管服务,具备企业级安全性,因此特别适合企业应用。
与直接调用 LLM API 开发相比,Microsoft Foundry Agent Service 有以下优势:
- 自动调用工具:不需要自己解析工具调用、执行工具、处理返回结果,这些都在服务端完成。
- 安全地管理数据:不必自己维护对话状态,可以靠线程(thread)保存所需的全部信息。
- 开箱即用的工具:可直接用来连接数据源的工具,例如 Bing、Azure AI Search 和 Azure Functions。
Microsoft Foundry Agent Service 中的工具可分为两类:
-
知识类工具:
-
操作类工具:
Agent Service 允许我们把这些工具组成一个工具集(toolset)一起使用。它还用线程(threads)记录某一段对话的消息历史。
假设你是 Contoso 公司的销售人员,想开发一个对话式智能体,回答与公司销售数据有关的问题。
原文此处有一张图,演示如何用 Microsoft Foundry Agent Service 分析销售数据:
图略:创建一个“Contoso 销售智能体”,给它写好说明、选择模型,并按需接入数据和工具;然后创建线程、运行智能体。第一次运行时,用户问“按地区告诉我总销售额”,智能体用函数调用工具查询 SQLite 数据库,回答欧洲 15478 美元、美洲 78792 美元;第二次运行时,用户要求“画成饼图”,智能体用代码解释器生成饼图。原图含多家公司的商标标识,本库未收录(来源:agent-service-in-action)
要在这个服务里使用任何工具,我们可以创建一个客户端,再定义单个工具或一个工具集。下面这段 Python 代码演示了具体做法。LLM 能看到工具集,并根据用户的请求,决定是用用户自己编写的函数 fetch_sales_data_using_sqlite_query,还是用现成的代码解释器。
代码略:连接 Microsoft Foundry 项目,新建一个工具集,把自定义的销售数据查询函数和代码解释器都加进去,再用这个工具集创建一个智能体。
用工具使用设计模式构建可信 AI 智能体时要特别注意什么?
对 LLM 动态生成的 SQL,常见的顾虑是安全问题,尤其是 SQL 注入或恶意操作的风险,比如删除或篡改数据库。这些顾虑是合理的,但只要正确配置数据库访问权限,就能有效防范。对大多数数据库来说,这意味着把数据库配置为只读。对于 PostgreSQL 或 Azure SQL 这类数据库服务,应给应用分配只读(SELECT)角色。
在安全的环境中运行应用,能进一步加强防护。在企业场景里,数据通常会从业务系统中抽取、转换,存入一个只读的数据库或数据仓库,并采用易于理解的 Schema。这样既保证了数据安全,又兼顾了性能和易用性,而且应用只有受限的只读权限。
补充资源
免责声明:本课中文最初由 AI 翻译工具 Co-op Translator 自动翻译,本库对照英文原文做了校订和删节。译文仍可能有错漏,与英文原版不一致之处,以英文原版为准。