工具使用模式概述

到目前为止,我们讨论的智能体模式主要涉及编排语言模型之间的交互,并管理代理内部工作流中的信息流(链式调用、路由、并行化、反思)。然而,要使智能体真正有用并与现实世界或外部系统交互,它们必须具备使用工具的能力。

工具使用模式通常通过一种称为“函数调用”的机制实现,使智能体能够与外部 API、数据库、服务交互,甚至执行代码。它让智能体核心的 LLM 能够根据用户请求或任务当前状态,决定何时以及如何调用特定的外部函数。

该流程通常包括以下步骤:

  1. 工具定义:将外部函数或能力定义并描述给 LLM。描述内容包括函数用途、名称、接受的参数及其类型和说明。
  2. LLM 决策:LLM 接收用户请求与可用工具定义,根据其理解判断是否需要调用一个或多个工具来完成请求。
  3. 函数调用生成:若 LLM 决定使用工具,它会生成结构化输出(通常为 JSON 对象),指定要调用的工具名称以及从用户请求中提取的参数(参数值)。
  4. 工具执行:智能体框架或编排层拦截该结构化输出,识别所请求的工具,并使用提供的参数执行实际的外部函数。
  5. 观察/结果:工具执行的输出或结果返回给智能体。
  6. LLM 处理(可选但常见):LLM 将工具输出作为上下文,用于制定对用户的最终回应,或决定工作流中的下一步(可能涉及再次调用工具、反思或给出最终答案)。

这一模式之所以至关重要,是因为它突破了 LLM 训练数据的局限,使模型能够获取最新信息、执行自身无法完成的计算、操作用户特定数据,甚至触发现实世界的行动。函数调用正是连接 LLM 推理能力与海量外部功能的技术桥梁。

虽然“函数调用”恰当地描述了调用特定的、预定义的代码函数这一行为,但考虑更广泛的“工具调用”概念会更有帮助。这个更宽泛的术语承认,智能体的能力可以远远超出简单的函数执行。一个“工具”可以是传统的函数,也可以是复杂的API端点、数据库请求,甚至是指向另一个专门智能体的指令。这种视角让我们能够设想更复杂的系统,例如,一个主智能体可能会将复杂的数据分析任务委托给专门的“分析师智能体”,或者通过API查询外部知识库。从“工具调用”的角度思考,能更好地捕捉智能体作为协调者在多样化的数字资源和其他智能实体生态系统中发挥的全部潜力。

LangChain、LangGraph 和 Google Agent Developer Kit(ADK)等框架为定义工具并将其集成到智能体工作流提供了强大支持,通常利用 Gemini 或 OpenAI 系列等现代大语言模型的原生函数调用能力。在这些框架的“画布”上,你可以定义工具,然后配置智能体(通常是 LLM 智能体)使其知晓并能够使用这些工具。
工具使用是构建强大、交互性强且具备外部感知能力的智能体的基石模式。

实际应用与用例

工具使用模式几乎适用于任何需要智能体超越文本生成、执行操作或获取特定动态信息的场景:

  1. 从外部源检索信息
    访问 LLM 训练数据中未包含的实时数据或信息。
    ● 用例:天气助手
    ○ 工具:天气 API,接收地点并返回当前天气状况。
    ○ 智能体流程:用户询问“伦敦天气如何?”,LLM 识别需要调用天气工具,传入参数“London”,工具返回数据,LLM 将数据格式化为用户友好的回答。
  2. 与数据库和 API 交互
    对结构化数据执行查询、更新或其他操作。
    ● 用例:电子商务助手
    ○ 工具:检查产品库存、获取订单状态或处理支付的 API 调用。
    ○ 智能体流程:用户询问“X 商品是否在库存中?”,LLM 调用库存 API,工具返回库存数量,LLM 告诉用户库存状态。
  3. 执行计算和数据分析
    使用外部计算器、数据分析库或统计工具。
    ● 用例:金融智能体
    ○ 工具:计算器函数、股票市场数据 API、电子表格工具。
    ○ 智能体流程:用户询问“AAPL 当前价格是多少,我如果在 $150 购买 100 股,潜在利润是多少?”,LLM 调用股票 API 获取当前价格,然后调用计算器工具计算结果,格式化响应。
  4. 发送通信
    发送电子邮件、消息或调用外部通信服务的 API。
    ● 用例:个人助手智能体
    ○ 工具:电子邮件发送 API
    ○ 智能体流程:用户说“明天给 John 发送关于会议的电子邮件”,LLM 调用电子邮件工具,传入收件人、主题和正文从请求中提取。
  5. 执行代码
    在安全环境中运行代码片段,执行特定任务。
    ● 用例:编码助手智能体
    ○ 工具:代码解释器
    ○ 智能体流程:用户提供 Python 代码片段并询问“这段代码做什么?”,LLM 使用解释器工具运行代码并分析输出。
  6. 控制其他系统或设备
    与智能家庭设备、物联网平台或其他连接系统交互。
    ● 用例:智能家庭助手
    ○ 工具:控制智能灯的 API
    ○ 智能体流程:用户说“关闭客厅灯”,LLM 调用智能家庭工具,传入命令“关闭”和目标设备“客厅灯”。
    工具使用正是将语言模型从文本生成器转变为能够在数字或物理世界中感知、推理并行动的代理的关键(见图 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.messages import HumanMessage
from langchain.agents import create_agent
from langchain.tools import tool

# 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 ---
# --- 定义模拟的搜索工具 ---
@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:
   agent = create_agent(llm, tools, system_prompt="You are a helpful assistant.")

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.ainvoke(
			{"messages": [HumanMessage(content=query)]}
		)
		print("\n--- ✅ Final Agent Response ---")
		# Get the final response from the messages list
		if "messages" in response:
			# Iterate through messages in reverse to find the last AIMessage
			for message in reversed(response["messages"]):
				if hasattr(message, "content") and message.content:
					print(f"Output: {message.content}")
					break
				else:
					print("No message with content found in response.")
		else:
			print(f"No messages key found in response. Full response: {response}")
	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 模型,通过 create_agent 将上述定义的模型、工具和提示组合成智能体。

代码中还用异步函数 run_agent_with_tool,用于用指定输入调用智能体,并打印最终输出结果。主异步函数 main 则准备了多条查询,以测试工具search_information 的输出情况,包括预定义的查询和兜底回复。

执行前代码会检查模型是否成功初始化,最后通过 asyncio.run(main()) 启动所有任务。

速览

what:大语言模型(LLM)虽然擅长生成文本,但本质上与外界隔绝。它们的知识是静态的,仅限于训练数据,无法主动获取实时信息或执行操作。这一固有限制使其难以完成需要调用外部 API、数据库或服务的任务。若无连接外部系统的桥梁,其解决实际问题的能力将严重受限。

why:工具使用模式(通常通过函数调用实现)为这个问题提供了标准化的解决方案。它的工作原理是将可用的外部函数(或称为"工具")以LLM能够理解的方式描述给它。基于用户的请求,智能体化的LLM可以决定是否需要使用工具,并生成一个结构化数据对象(如JSON),指定要调用的函数及其参数。编排层执行此函数调用,检索结果,并将其反馈给LLM。这使LLM能够将最新的外部信息或操作结果整合到其最终响应中,从而有效地赋予其行动能力。

经验法则:只要智能体需要突破大语言模型的内部知识边界并与外部世界交互,就应采用工具使用模式。这对于需要实时数据(如查询天气、股票价格)、访问私有或专有信息(如查询公司数据库)、执行精确计算、运行代码或触发其他系统操作(如发送邮件、控制智能设备)等任务至关重要。

视觉摘要:

在这里插入图片描述

图.2: 工具使用的设计模式

核心要点
● 工具使用(函数调用)让智能体得以与外部系统交互并获取动态信息。
● 需为工具提供清晰的描述与参数,以便大语言模型理解。
● 大语言模型自主判断何时调用工具,并生成结构化的函数调用请求。
● 智能体框架负责实际执行工具调用,并将结果返回给模型。
● 工具使用是构建可执行现实动作、提供实时信息的智能体的基石模式。
● LangChain 通过 @tool 装饰器简化工具定义,并提供 create_tool_calling_agent 与 AgentExecutor 来构建使用工具的智能体。
● Google ADK 内置多款实用工具,如 Google 搜索、代码执行与 Vertex AI 搜索工具。

结论

工具使用(Tool Use)模式是扩展大型语言模型功能范围的关键架构原则,使其超越固有的文本生成能力。通过赋予模型与外部软件和数据源交互的能力,这种范式允许智能体执行操作、进行计算并从其他系统检索信息。这一过程涉及当模型确定需要调用外部工具来满足用户查询时,生成结构化请求以调用外部工具。LangChain、Google ADK和Crew AI等框架提供了结构化抽象和组件,促进了这些外部工具的集成。这些框架管理向模型公开工具规范并解析其后续工具使用请求的过程。这简化了能够与外部数字环境交互并在其中采取行动的复杂智能体系统的开发。

引用

  1. LangChain 文档 (Tools):
    https://python.langchain.com/docs/integrations/tools/
  2. Google Agent Developer Kit (ADK) 文档 (Tools):
    https://google.github.io/adk-docs/tools/
  3. OpenAI Function Calling 文档:
    https://platform.openai.com/docs/guides/function-calling
  4. CrewAI 文档 (Tools): https://docs.crewai.com/concepts/tools
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐