智能体21种设计模式之(5)工具调用
本文探讨了智能体工具使用模式的核心机制与应用场景。通过函数调用技术,智能体能够突破大语言模型的静态知识局限,实现与外部系统的交互。文章详细阐述了工具使用的工作流程:从工具定义、模型决策到函数执行和结果处理,并介绍了在LangChain框架中的具体实现方法。重点分析了该模式在实时数据获取、数据库交互、复杂计算等场景下的应用价值,指出工具使用是将语言模型转化为实用智能体的关键技术。通过代码示例展示了如
工具使用模式概述
到目前为止,我们讨论的智能体模式侧重于在大语言模型之间协调交互和管理智能体内部的信息流(如提示链、路由、并行化和反思模式)。但如果要让智能体真正有用、能与现实世界或外部系统交互,就必须赋予它们使用工具的能力。
工具使用模式通常通过函数调用(Function Calling)机制实现,使智能体能够与外部 API、数据库、服务交互,甚至直接执行代码。它允许作为智能体核心的大语言模型根据用户请求或当前任务状态,来决定何时以及如何使用特定的外部函数。
这个过程通常包括以下几个步骤:
-
工具定义:向大语言模型描述外部函数或功能,包括函数的用途、名称,以及所接受参数的类型和说明。
-
大语言模型决策:大语言模型接收用户的请求和可用的工具定义,并根据对两者的理解判断是否需要调用一个或多个工具来完成请求。
-
生成函数调用:如果大语言模型决定使用工具,它会生成结构化输出(通常是 JSON 对象),指明要调用的工具名称以及从用户请求中提取的参数。
-
工具执行:智能体框架或编排层捕获这个结构化输出,识别要调用的工具,并根据给定参数执行相应的外部函数。
-
观察/结果:工具执行的输出或结果返回给智能体。
-
大语言模型处理(可选,但很常见):大语言模型接收工具的输出作为上下文,并用它来生成对用户的最终回复,或决定工作流的下一步(可能涉及调用另一个工具、进行反思或提供最终答案)。
这种模式很关键,因为它突破了大语言模型训练数据的局限,使其能够获取最新信息、执行内部无法处理的计算、访问用户特定的数据,或触发现实世界的动作。函数调用是连接大语言模型推理能力与外部功能的技术桥梁。
虽然「函数调用」这个说法确实能准确描述调用预定义代码函数的过程,但从更广阔的视角理解「工具调用」这一概念更为有益。通过这个更广义的术语,我们看到智能体的能力可以远远超出简单的函数执行。工具可以是传统函数、复杂的 API 接口、数据库请求,甚至是发给另一个智能体的指令。这种视角让我们能够构想更复杂的系统,例如,主智能体可以将复杂的数据分析任务委托给专门的「分析智能体」,或通过 API 查询外部知识库。「工具调用」的思维方式能更好地捕捉智能体作为编排者的全部潜力,使其能够在多样化的数字资源和其他智能生态系统中发挥作用。
LangChain、LangGraph 等框架可以很方便地定义工具并将它们集成到智能体工作流中,通常会利用 Gemini 或 OpenAI 等现代大语言模型的原生函数调用功能。在这些框架中,你可以定义工具,并通过设置让智能体识别和使用这些工具。
工具使用是构建强大、可交互且能感知和利用外部资源的智能体的关键模式。
实际应用场景
当智能体需要的不只是文本生成,而是执行操作或检索动态信息的时候,工具使用模式几乎都能派上用场。
1、从外部来源获取信息:
获取大语言模型训练数据中未包含的实时数据或信息。
-
用例:天气信息智能体。
-
工具:天气查询接口,可输入地点并返回该地的实时天气。
-
智能体流程:用户提问「伦敦天气怎么样?」,大语言模型识别出需要使用天气工具,并使用「伦敦」作为参数调用该工具,工具返回数据后,大语言模型将这些信息整理并以易懂的方式输出给用户。
2、与数据库和接口交互:
对结构化数据执行查询、更新或其他操作。
-
用例:电商平台智能体。
-
工具:通过接口来检查产品库存、查询订单状态或处理支付。
-
智能体流程:用户提问「产品 X 有货吗?」,大语言模型先调用库存接口,工具返回库存数量后,大语言模型向用户反馈该产品库存情况。
3、执行计算和数据分析:
使用计算器、数据分析库或统计工具。
-
用例:金融领域智能体。
-
工具:计算器函数、股票行情接口、电子表格工具。
-
智能体流程:用户提问「苹果公司当前股价是多少?如果我以 150 美元买入 100 股,可能会赚多少钱?」,大语言模型会先调用股票行情接口获取最新价格,然后调用计算器工具计算收益,最后把结果整理并返回给用户。
4、发送通知:
发送电子邮件、消息或调用外部通信服务的接口。
-
用例:个人助理智能体。
-
工具:邮件发送接口。
-
智能体流程:用户说「给约翰发一封关于明天会议的邮件」,大语言模型会从请求中提取收件人、主题和正文,并调用邮件接口发送邮件。
5、执行代码:
在受控且安全的环境中运行代码片段以完成特定任务。
-
用例:编程助理智能体。
-
工具:代码解释器。
-
智能体流程:用户提供一段 Python 代码并问「这段代码是做什么的?」,大语言模型会先使用代码解释器运行代码,并据此进行分析和解释。
6、控制其他系统或设备:
与智能家居设备、物联网平台或其他联网系统交互。
-
用例:智能家居智能体。
-
工具:控制智能灯的接口。
-
智能体流程:用户说「关掉客厅的灯」,大语言模型将带有命令和目标设备信息的请求发送给智能家居工具以执行操作。
工具使用模式将语言模型从文本生成器变成能够在数字或现实世界中感知、推理和行动的智能体(见图 1)。

图 1:智能体使用工具的一些示例
实战代码:使用 LangChain
在 LangChain 框架中,使用工具分两个步骤。首先,定义一个或多个工具,通常通过封装现有的 Python 函数或其他可执行组件来完成。随后,将这些工具和大语言模型绑定,这样当大语言模型判断需要调用外部函数来完成用户请求时,就能生成结构化的调用请求并执行相应操作。
以下代码将演示这一原理。首先定义一个简单函数来模拟信息检索工具,然后构建并配置智能体,使其能够利用该工具响应用户输入。运行此示例需要先安装 LangChain 的核心库和相应的模型接入包,并在本地环境中配置好 API 密钥。
import os, getpass
import asyncio
import nest_asyncio
from typing import List
from dotenv import load_dotenv
import logging
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool as langchain_tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
# UNCOMMENT
# Prompt the user securely and set API keys as an environment variables
# 安全地提示用户设置 API 密钥作为环境变量
os.environ["GOOGLE_API_KEY"] = getpass.getpass("Enter your Google API key: ")
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
try:
# A model with function/tool calling capabilities is required.
# 需要一个具有函数调用能力的模型,这里使用 Gemini 2.0 Flash。
llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0)
print(f"✅ Language model initialized: {llm.model}")
except Exception as e:
print(f"🛑 Error initializing language model: {e}")
llm = None
# --- Define a Tool ---
# --- 定义模拟的搜索工具 ---
@langchain_tool
def search_information(query: str) -> str:
"""
Provides factual information on a given topic. Use this tool to find answers to phrases
like 'capital of France' or 'weather in London?'.
# 模拟提供关于特定查询的输出。使用此工具查找类似「法国的首都是哪里?」或「伦敦的天气如何?」这类问题的答案。
"""
print(f"\n--- 🛠️ Tool Called: search_information with query: '{query}' ---")
# Simulate a search tool with a dictionary of predefined results.
# 通过一个字典预定义的结果来模拟搜索工具。
simulated_results = {
"weather in london": "The weather in London is currently cloudy with a temperature of 15°C.",
"capital of france": "The capital of France is Paris.",
"population of earth": "The estimated population of Earth is around 8 billion people.",
"tallest mountain": "Mount Everest is the tallest mountain above sea level.",
"default": f"Simulated search result for '{query}': No specific information found, but the topic seems interesting."
}
result = simulated_results.get(query.lower(), simulated_results["default"])
print(f"--- TOOL RESULT: {result} ---")
return result
tools = [search_information]
# --- Create a Tool-Calling Agent ---
# --- 创建一个使用工具的智能体 ---
if llm:
# This prompt template requires an `agent_scratchpad` placeholder for the agent's internal steps.
# 这个提示模板需要一个 `agent_scratchpad` 占位符,用于记录智能体的内部步骤。
agent_prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant."),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
# Create the agent, binding the LLM, tools, and prompt together.
# 使用定义好的大语言模型、工具和提示词模板构建智能体。
agent = create_tool_calling_agent(llm, tools, agent_prompt)
# AgentExecutor is the runtime that invokes the agent and executes the chosen tools.
# The 'tools' argument is not needed here as they are already bound to the agent.
# AgentExecutor 负责调用智能体并运行其选择工具的运行时组件。
# 这里的 'tools' 参数可以不需要了,因为它们已经绑定到智能体上了。
agent_executor = AgentExecutor(agent=agent, verbose=True, tools=tools)
async def run_agent_with_tool(query: str):
"""
Invokes the agent executor with a query and prints the final response.
执行智能体并打印最终输出信息。
"""
print(f"\n--- 🏃 Running Agent with Query: '{query}' ---")
try:
response = await agent_executor.ainvoke({"input": query})
print("\n--- ✅ Final Agent Response ---")
print(response["output"])
except Exception as e:
print(f"\n🛑 An error occurred during agent execution: {e}")
async def main():
"""
Runs all agent queries concurrently.
并发运行所有智能体查询任务。
"""
tasks = [
run_agent_with_tool("What is the capital of France?"),
run_agent_with_tool("What's the weather like in London?"),
run_agent_with_tool("Tell me something about dogs.") # Should trigger the default tool response
]
await asyncio.gather(*tasks)
nest_asyncio.apply()
asyncio.run(main())
以上代码使用了 LangChain 库和 Google Gemini 模型构建了一个使用工具的智能体。
首先定义了 search_information 工具,用于模拟检索特定问题的事实答案,比如「伦敦天气怎么样?」、「法国的首都是哪里?」和「地球的人口是多少?」,如果是其他问题就返回一个兜底回复。
接着初始化了一个具备工具调用能力的 ChatGoogleGenerativeAI 模型,并创建了用于引导对话的 ChatPromptTemplate。通过 create_tool_calling_agent 将上述定义的模型、工具和提示组合成智能体,并用 AgentExecutor 负责具体的执行与工具调用任务。
代码中还用异步函数 run_agent_with_tool,用于用指定输入调用智能体,并打印最终输出结果。主异步函数 main 则准备了多条查询,以测试工具 search_information 的输出情况,包括预定义的查询和兜底回复。
执行前代码会检查模型是否成功初始化,最后通过 asyncio.run(main()) 启动所有任务
要点概述
问题所在:大语言模型是强大的文本生成器,但它们本质上与外部世界脱节。它们的知识是静态的,仅限于训练时所用的数据,并且缺乏执行操作或检索实时信息的能力。这种固有的局限性使它们无法完成需要与外部接口、数据库、服务进行交互的任务。如果没有连接这些外部系统的桥梁,它们在解决实际问题的能力将大打折扣。
解决之道:工具使用模式(通常通过函数调用机制实现)为这个问题提供了标准化解决方案。它的工作原理是,以大语言模型能理解的方式向其描述可用的外部函数或工具。基于用户请求,具有智能能力的模型可以判断是否需要使用工具,并生成结构化数据对象(如 JSON),指明要调用哪个函数以及使用什么参数。编排层负责执行此函数调用,获取结果,并将其反馈给模型。这使得大语言模型能够将最新的外部信息或操作结果整合到最终响应中,从而有效地赋予了它行动的能力。
经验法则:当智能体需要突破大语言模型内部知识局限并与外部世界互动时,就应该使用工具使用模式。这对于需要实时数据(如查询天气、股票价格)、访问私有或专有信息(如查询公司数据库)、执行精确计算、执行代码或在其他系统中触发操作(如发送邮件、控制智能设备)的任务至关重要。
可视化总结:

图 2:工具使用模式
核心要点
-
工具使用(函数调用)模式使智能体能够与外部系统交互并获取动态信息。
-
这包括为工具定义清晰的描述和参数,以便大语言模型能正确使用这些工具。
-
大语言模型会决定何时使用工具,并生成结构化的数据以执行这些操作。
-
智能体框架负责执行实际的工具调用,并将结果返回给大语言模型。
-
工具使用模式对于构建能够执行现实任务并提供最新信息的智能体来说至关重要。
-
LangChain 使用
@tool装饰器简化工具定义,并提供create_tool_calling_agent和AgentExecutor来构建能够使用工具的智能体。
结语
工具使用模式是一种重要的架构原则,用于把大型语言模型的能力扩展到纯文本生成之外。通过让模型能够与外部软件和数据源对接,这一模式使得智能体可以执行操作、完成计算以及从其他系统获取信息。当模型判断需要调用外部工具来满足用户请求时,它会生成一个结构化的调用请求。
像 LangChain、Langgraph 这样的框架提供了便于集成外部工具的抽象层和组件,负责向模型暴露工具的定义并解析模型返回的工具调用请求。总体而言,这大大简化了能够在外部数字环境中感知、交互和行动的复杂智能体系统的开发。
更多推荐


所有评论(0)