跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI

大模型工具函数调用(Function Calling)实战指南

大模型工具函数调用(Function Calling)通过预定义外部函数接口,使 LLM 能够获取实时数据或执行特定操作。核心机制是模型输出结构化 JSON 指令,由外部程序执行并回传结果。本文涵盖客户端与服务端两种工具模式,结合 OpenAI 与 Claude 的 SDK 示例,解析了 Schema 定义、参数约束及多轮交互流程,帮助开发者构建具备行动能力的智能代理。

292440837发布于 2026/4/8更新于 2026/9/451 浏览
大模型工具函数调用(Function Calling)实战指南

大模型工具函数调用(Function Calling)详解

1. 概述

1.1 什么是工具函数调用

大语言模型(LLM)本质上是基于概率的文本生成系统,其能力边界受限于训练数据。当用户询问'今天北京天气如何'或'帮我查一下订单状态'这类需要实时信息的问题时,模型无法直接给出准确答案。工具函数调用(Tool Use / Function Calling)正是为突破这一限制而设计的能力,它在 LLM 与外部系统之间建立了一条可靠的交互通道。

从技术实现上看,Function Calling 并非让模型直接执行代码,而是让模型在理解用户意图后,输出一段结构化的 JSON 数据,其中包含需要调用的函数名称及对应的参数。经过微调的 LLM 能够准确判断当前对话是否需要借助外部工具,并严格按照预定义的函数签名(function schema)生成符合格式要求的调用请求。整个过程中,模型扮演的是'决策者'角色,而实际的函数执行则由外部程序完成。

这种机制带来了极大的灵活性。开发者可以在单次请求中定义多个工具函数,例如同时提供天气查询、数据库检索、日程管理等不同功能。模型会根据用户的具体意图,自行选择合适的函数进行调用,甚至在复杂场景下进行多次连续调用以完成一个完整的任务链。

以下是一个工具定义的基本结构示意:

{
  "name": "get_weather",
  "description": "获取指定城市的当前天气信息",
  "parameters": {
    "type": "object",
    "properties": {
      "city": {"type": "string", "description": "城市名称,例如:北京"}
    },
    "required": ["city"]
  }
}

上述 JSON 结构定义了一个名为 get_weather 的工具函数。模型在接收到用户关于天气的提问后,会解析意图并输出类似 {"name": "get_weather", "arguments": {"city": "北京"}} 的结构化调用指令,由客户端或服务端程序负责实际执行并将结果回传给模型,最终模型基于返回结果生成自然语言回复。

目前,主流的 LLM 服务商均已支持 Function Calling 能力,包括 OpenAI、Anthropic(Claude)、Google(Gemini)等。尽管各平台在 API 设计和参数格式上存在差异,但核心思路一致:通过预定义工具描述,让模型具备调用外部能力的'接口意识'。

1.2 为什么需要工具函数调用

LLM 本质上是一个基于概率的文本生成模型,其知识来源于训练语料的静态快照。这意味着模型无法感知训练截止日期之后发生的事件,也无法直接访问私有数据库、调用第三方服务或执行任何具有副作用的操作。在构建 LLM 驱动的聊天机器人或智能代理(Agent)时,这一局限尤为突出——用户的实际需求往往涉及实时数据查询、业务流程触发等模型自身无法完成的任务。

从功能定位来看,函数调用主要解决两类问题:

  • 数据获取:即获取模型自身不具备的实时信息,例如当前天气、数据库记录、知识库文档等,弥补训练数据时效性不足的缺陷。
  • 执行行动:即触发具有实际效果的外部操作,例如发送邮件、创建工单、提交表单、调用第三方 API 等,使模型从'被动回答'升级为'主动行动'。

借助这两类能力,开发者可以构建出多种形态的应用,如能够调用外部工具回答问题的对话代理、用于从非结构化文本中提取数据的 LLM 驱动方案、将自然语言转换为有效 API 调用的中间层应用等。

下表对几个代表性平台进行了简要对比:

平台能力名称工具定义格式并行调用强制调用
OpenAI(GPT-4o)Function CallingJSON Schema支持支持(tool_choice)
Anthropic(Claude)Tool UseJSON Schema支持支持(tool_choice)
Google(Gemini)Function CallingOpenAPI Schema支持支持(function_calling_config)

各平台的核心工作流程基本一致:开发者通过 JSON Schema 定义工具函数的名称、描述和参数约束,模型根据用户输入和系统提示自主决定是否调用以及调用哪些函数,最终在获取函数执行结果后整合生成自然语言响应。

在具体实现层面,工具通常被划分为客户端工具和服务端工具两类:

  • 客户端工具的执行发生在调用方(即开发者的应用程序)一侧,由应用程序接收模型输出的调用指令后自行完成函数执行并回传结果;
  • 服务端工具则由模型服务商在其基础设施上直接执行,开发者无需处理中间的调用与回传过程。两种模式适用于不同的场景,后续章节将以 Claude 为例分别进行详细实践。

2. 函数实例 (获取天气)

以一个典型的天气查询场景为例,展示函数调用的完整实现过程。下面的代码基于 OpenAI 的 Python SDK,定义了一个名为 get_weather 的工具函数,用于获取指定地点的当前温度,位置参数需要以'城市 + 国家'的格式传入。开发者通过 tools 参数将函数的 schema 描述提交给模型,模型在理解用户意图后自主决定是否触发调用:

from openai import OpenAI

# 配置 API 中转站端点
client = OpenAI(
    base_url="https://api.aaaaapi.com/v1",
    api_key="your-api-key" # 替换为你的 API 密钥
)

# 定义工具(函数)
tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "获取指定地点的当前温度。",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "城市和国家,例如:波哥大,哥伦比亚"
                }
            },
            "required": ["location"],
            "additionalProperties": False
        }
    }
]

# 调用模型,触发函数调用
response = client.responses.create(
    model="gpt-4.1",
    input=[{"role": "user", "content": "今天巴黎的天气怎么样?"}],
    tools=tools
)
print(response.output)

在上述代码中,tools 列表内的每个元素对应一个工具定义,其中 type 固定为 "function",name 和 description 分别描述函数名称与用途,parameters 则使用标准的 JSON Schema 格式约束参数类型和必填项。当用户输入'今天巴黎的天气怎么样'时,模型会解析出意图与天气查询相关,并从对话内容中提取出地点信息,随后生成一条结构化的函数调用指令,而非直接返回文本回复。

模型返回的 response.output 中会包含一个 function_call 类型的输出项,其内容类似于 {"name": "get_weather", "arguments": "{\"location\": \"巴黎,法国\"}"}。可以看到,模型不仅识别了用户提到的'巴黎',还自动补全了国家信息以符合参数描述中的格式要求。这一结果本身并不包含天气数据,而是一条等待执行的调用指令。

函数调用的完整交互流程可以概括为五个步骤:

  1. 开发者通过 tools 参数传入函数 schema,告知模型可用工具的用途和参数格式。
  2. 模型根据用户输入判断是否需要调用工具,若需要则生成包含函数名和参数的调用指令。
  3. 应用程序解析模型输出,调用对应的自定义代码(如请求天气 API 获取实时数据)。
  4. 将函数执行的返回值以 tool result 的形式回传给模型。
  5. 模型基于原始问题和函数返回结果,生成一段完整的自然语言回答呈现给用户。

需要注意的是,整个流程中模型本身并不执行任何函数代码,它的职责仅限于意图识别、参数提取和结果整合。实际的 API 调用、数据库查询等操作均由开发者的应用程序负责完成。

3. 函数调用工作流

函数调用的起点是向模型提供准确且完整的函数 schema 定义。这份 schema 是模型理解工具能力边界的唯一依据——模型并不知道函数的实际实现逻辑,它完全依赖 schema 中的描述信息来判断何时调用、如何构造参数。因此,schema 的质量直接决定了函数调用的准确率。一个标准的函数 schema 需要包含以下核心字段:

字段说明
type固定为 "function",标识工具类型
name函数名称,如 get_weather,应简洁且语义明确
description函数用途和适用场景的自然语言描述,需详细清晰
parameters函数参数的 JSON Schema 定义,包含类型、描述、约束等
strict是否启用严格模式,推荐设为 true 以确保输出严格符合 schema

其中 description 字段的撰写尤为关键。模糊的描述会导致模型在不恰当的时机触发调用,或者在应该调用时选择了错误的函数。例如,将天气查询函数的描述写为'获取天气'远不如'获取指定城市当前的实时气温和天气状况,适用于用户询问某地天气的场景'来得准确。当系统中同时存在多个功能相近的工具时,清晰的 description 能够帮助模型做出正确的路由决策。

在参数定义层面,遵循一些最佳实践能够显著提升调用的可靠性。首先,应为每个参数添加详细的 description 说明,明确格式要求和示例值,例如 location 参数注明'城市和国家,例如:巴黎,法国'。其次,必须通过 type 字段指定参数的数据类型(string、number、object 等),避免类型歧义。对于有限取值的参数,应使用 enum 进行约束,如温度单位限定为 ["celsius", "fahrenheit"]。最后,通过 required 数组显式声明必填参数,确保模型不会遗漏关键信息。

当模型决定调用函数后,应用程序需要按照规范的流程处理调用指令并完成结果回传。首先从 response.output 中解析出函数调用信息,提取 name(函数名)、arguments(参数 JSON 字符串)和 call_id(调用标识符)三个关键字段。然后根据函数名路由到对应的实现代码,将 arguments 反序列化为实际参数并执行。函数执行完成后,将返回值格式化为字符串(支持纯文本或 JSON 格式),通过 function_call_output 类型的消息回传给模型,其中必须携带对应的 call_id 以便模型正确关联请求与结果。

在实际工程中,还需要对异常情况进行处理。函数执行可能因网络超时、参数非法、服务不可用等原因失败,此时应将错误信息以结构化的方式回传给模型,而非直接抛出异常。模型在接收到错误描述后,通常能够生成合理的兜底回复,从而保证对话体验的连贯性。

4. 客户端工具实践

客户端工具(Client Tools)是 Claude 工具调用体系中最常用的模式。其核心特征在于:工具的实际执行发生在开发者的应用程序一侧,Claude 仅负责理解用户意图、决定是否调用工具并生成结构化的调用指令,而具体的函数逻辑、API 请求、数据处理等工作均由客户端代码完成。这种设计赋予开发者对工具执行过程的完全控制权,适用于需要访问本地资源、私有数据库或自定义业务逻辑的场景。

客户端工具的完整交互流程分为四个阶段。首先,开发者在 API 请求中通过 tools 参数定义可用工具的名称、描述和输入参数的 JSON Schema,同时传入用户的自然语言消息。随后,Claude 评估当前对话是否需要借助工具来完成回答,若判断需要,则构造一条格式规范的工具调用请求,此时 API 响应中的 stop_reason 字段值为 tool_use,明确表示模型希望执行工具调用而非直接生成文本回复。

以下是一个基于 Claude API 的客户端工具调用完整示例,实现了天气查询功能:

import os
import anthropic
import json

API_KEY = os.getenv("CLAUDE_API_KEY")
API_BASE = os.getenv("CLAUDE_API_BASE")

client = anthropic.Anthropic(
    api_key=API_KEY,
    base_url=API_BASE,
)

TOOLS = [
    {
        "name": "get_weather",
        "description": "获取指定城市的当前天气信息,当用户询问某地天气时使用。",
        "input_schema": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "城市名称,例如:San Francisco, CA"
                }
            },
            "required": ["location"]
        }
    }
]

# 第一步:定义工具并发送用户消息
response = client.messages.create(
    model="claude-sonnet-4.6",
    max_tokens=10000,
    tools=TOOLS,
    messages=[{"role": "user", "content": "What's the weather in San Francisco?"}]
)

# 第二步:检查模型是否请求工具调用
if response.stop_reason == "tool_use":
    # 提取工具调用信息
    tool_block = next(b for b in response.content if b.type == "tool_use")
    tool_name = tool_block.name
    tool_input = tool_block.input
    tool_use_id = tool_block.id

    # 第三步:执行本地工具函数
    def get_weather(location: str) -> dict:
        # 实际场景中此处调用天气 API
        return {"temperature": "15°C", "condition": "partly cloudy"}

    result = get_weather(tool_input["location"])

    # 第四步:将结果回传给 Claude
    final_response = client.messages.create(
        model="claude-sonnet-4.6",
        max_tokens=10000,
        tools=TOOLS,
        messages=[
            {"role": "user", "content": "What's the weather in San Francisco?"},
            {"role": "assistant", "content": response.content},
            {
                "role": "user",
                "content": [{"type": "tool_result", "tool_use_id": tool_use_id, "content": json.dumps(result)}]
            }
        ]
    )
    print(final_response.content[0].text)

这段代码有几个关键点需要留意。Claude 的工具定义使用 input_schema 字段(而非 OpenAI 的 parameters),这是两个平台在 API 设计上的主要差异之一。当 stop_reason 为 tool_use 时,response.content 中会包含一个 type 为 tool_use 的内容块,其中的 id 字段是调用标识符,在回传结果时必须通过 tool_use_id 进行关联,否则 Claude 无法正确匹配调用请求与返回结果。

在结果回传阶段,需要构造完整的对话历史传入第二次 API 调用,包括原始用户消息、Claude 的工具调用响应(作为 assistant 消息)以及工具执行结果(作为 user 消息中的 tool_result 内容块)。Claude 在接收到工具返回的数据后,会将其与原始问题结合分析,生成一段完整的自然语言回答。整个过程中,模型始终不直接执行任何代码,所有工具逻辑的安全性和正确性由开发者自行保障。

5. 服务端工具实践

与客户端工具不同,服务端工具(Server Tools)的执行完全发生在 Anthropic 的基础设施上,开发者无需编写任何工具实现代码,也无需处理调用指令的解析与结果回传。Claude 在判断需要使用服务端工具后,会在服务端自动完成工具执行,并将结果直接整合到最终响应中。这种模式极大地简化了开发流程,尤其适用于 Anthropic 已经内置支持的通用能力场景。

目前 Claude 提供的服务端工具主要包括 web_search(网页搜索)和 web_fetch(网页内容获取)两种。前者允许模型在对话过程中主动检索互联网上的实时信息,后者则可以抓取指定 URL 的页面内容进行分析。开发者只需在 tools 参数中声明这些工具,无需定义 input_schema,因为服务端工具的参数结构由 Anthropic 预先规定。

import os
import anthropic

API_KEY = os.getenv("CLAUDE_API_KEY")
API_BASE = os.getenv("CLAUDE_API_BASE")

client = anthropic.Anthropic(api_key=API_KEY, base_url=API_BASE)

# 使用服务端工具 - web_search
response = client.messages.create(
    model="claude-sonnet-4.6",
    max_tokens=10240,
    tools=[{"type": "web_search_20260209", "name": "web_search", "max_uses": 5}],
    messages=[{"role": "user", "content": "搜索一下 2026 年 3 月 13 日 GitHub 热门项目,简要介绍它们。"}]
)
print(response.content)

上述代码的结构相比客户端工具明显更为简洁。服务端工具通过特定的 type 标识(如 web_search_20260209)进行声明,而非使用通用的 "function" 类型。max_uses 参数用于控制工具在单次对话中的调用上限,防止模型过度依赖搜索而消耗过多资源。整个过程中,开发者只需发起一次 API 调用即可获得最终结果,不存在客户端工具中'接收调用指令—执行函数—回传结果'的多轮交互。

服务端工具的一个重要特性是支持内部采样循环(sampling loop)。当一个问题需要多步检索才能获得完整答案时,Claude 可以在服务端连续执行多次工具调用——例如先搜索关键词获取相关链接,再抓取特定页面提取详细内容——整个过程对开发者完全透明,最终返回的响应已经是经过多轮工具调用后综合整理的结果。

下表对客户端工具与服务端工具的核心差异进行了对比:

特性客户端工具服务端工具
执行位置开发者应用程序Anthropic 服务端
需要回传结果是,需构造 tool_result否,自动整合
自定义逻辑完全自定义仅限预置工具能力
多轮调用处理开发者手动编排服务端自动循环
典型场景数据库查询、业务 API、本地计算网页搜索、URL 内容分析

在实际项目中,客户端工具与服务端工具通常会混合使用。例如一个智能客服系统可以同时配置 web_search 用于检索公开信息,以及自定义的 query_order 客户端工具用于查询内部订单数据库。Claude 会根据用户的具体问题自主选择合适的工具组合,开发者只需确保客户端工具的调用链路正确处理即可。

目录

  1. 大模型工具函数调用(Function Calling)详解
  2. 1. 概述
  3. 1.1 什么是工具函数调用
  4. 1.2 为什么需要工具函数调用
  5. 2. 函数实例 (获取天气)
  6. 配置 API 中转站端点
  7. 定义工具(函数)
  8. 调用模型,触发函数调用
  9. 3. 函数调用工作流
  10. 4. 客户端工具实践
  11. 第一步:定义工具并发送用户消息
  12. 第二步:检查模型是否请求工具调用
  13. 5. 服务端工具实践
  14. 使用服务端工具 - web_search

更多推荐文章

查看全部
  • 宇树开源 UnifoLM-VLA-0 模型实现具身智能通用操作
  • 机器人阻抗控制器与导纳控制器原理及实现
  • 微信小程序从 0 到 1 开发部署全流程指南
  • 基于 Llama.cpp 本地部署大语言模型实战
  • Qwen3-4B-Instruct 本地部署与 AI 写作实战指南
  • Retinaface+CurricularFace 基于 Kubernetes StatefulSet 部署方案
  • 鸿蒙金融理财全栈项目:基础架构、数据安全与用户体验
  • 7 款高颜值 Linux 发行版推荐
  • Mac Mini M4 本地部署大模型:Ollama 与 Llama 环境配置指南
  • Web JS 逆向全体系详解
  • Python3.8 环境下 Stable Diffusion 轻量化部署
  • 基于宝塔面板的 OpenClaw 生产环境部署与安全优化
  • Adoptium Temurin JDK 安装与配置指南
  • OpenClaw 龙虾机器人免费部署与进阶配置指南
  • AI 辅助编程工具实战:提升开发效率的最佳实践
  • 阿里开源 Page-Agent:一行 JS 代码实现大模型前端 DOM 操控
  • 数据库索引类型与结构详解
  • Quartus Prime FPGA 开发入门:从安装到工程落地
  • 冷启动数据与多阶段训练在 DeepSeek 模型中的作用
  • Qwen-Image-2512 在 ComfyUI 中搭建 AI 绘画工作流指南

相关免费在线工具

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online