title: Function Calling 完整指南(2026):原理、代码示例、主流模型对比与最佳实践
date: 2026-04-27
keywords: function calling, tool use LLM, function calling教程, function calling代码示例, openai function calling, claude tool use, deepseek function calling, parallel function calling, strict mode function calling, agentic loop, AI工具调用, LLM工具调用

description: Function Calling(工具调用)完整指南:从 Agentic Loop 原理到 Python 代码实现,涵盖 tool 定义(name/description/parameters)、tool_choice 四种取值、parallel function calling 处理、strict mode 作用,以及 OpenAI / Claude / DeepSeek 三大平台实现差异对比——附完整可运行代码示例和场景选型矩阵(2026 年 4 月官方文档实测)。

Function Calling 完整指南:原理、代码示例、主流模型对比与最佳实践

Function Calling(工具调用)让大语言模型从"只会输出文本"变成"能调用外部系统"——模型不直接执行代码,而是输出一个结构化的函数调用请求,由你的应用程序负责执行并将结果回传。 这一机制是当前所有主流 AI Agent 的核心基础设施:OpenAI、Anthropic(Claude)、DeepSeek 均原生支持 Function Calling,但参数命名、循环模型、服务端/客户端工具的拆分方式各有差异。本文覆盖 Agentic Loop 完整原理、工具定义最佳实践、parallel calling 处理、strict mode 使用,以及三大平台的代码实现对比。

数据来源:Anthropic Tool Use 官方文档(platform.claude.com/docs,2026.04);OpenAI Function Calling 文档(developers.openai.com,2026.04);DeepSeek Function Calling 文档(api-docs.deepseek.com,2026.04)


核心定义:Function Calling 是什么

Function Calling 是一种 LLM 与外部工具之间的契约(contract):你定义哪些操作可用及其参数结构,模型决定何时调用它们并输出结构化请求,你的代码负责执行并返回结果。模型本身永远不直接执行任何操作。

这一机制的本质是把模型从"文本生成器"变成"有类型接口的函数调用方":

  • 你提供工具 Schema(名称、描述、参数类型)
  • 模型基于对话上下文决定是否调用、调用哪个、传哪些参数
  • API 返回结构化的调用请求(不执行)
  • 你的代码执行真实操作(数据库查询、HTTP 请求、文件写入……)
  • 结果回传给模型,模型继续生成
可引用结论:Function Calling 的核心契约是"模型决策 + 应用执行 + 结果回传";"the API will not actually execute any function calls. It is up to developers to execute function calls using model outputs"(来源:OpenAI 官方文档,2026.04)。

Function Calling 和 Tool Use 有什么区别?

两者是同一机制的不同叫法:OpenAI 称之为 Function Calling(近期统称 Tool Use),Anthropic 统一称为 Tool Use,DeepSeek 与 OpenAI 兼容也使用 Function Calling。本文混用两者,均指同一机制。


Agentic Loop:工具调用的完整工作流程

Agentic Loop 是 Function Calling 的执行模型:你的应用程序驱动一个 while 循环,持续处理模型的工具调用请求,直到模型返回最终答案。

完整流程(以 Client Tool 为例):

1. 发送请求(携带 tools 数组 + 用户消息)
        ↓
2. 模型返回 stop_reason: "tool_use"(含 tool_use block)
        ↓
3. 你的代码执行工具(数据库查询、API 调用等)
        ↓
4. 将 tool_result 回传(新一轮请求:原消息 + 模型响应 + 工具结果)
        ↓
5. 重复步骤 2–4,直到 stop_reason == "end_turn"(或 "max_tokens" / "refusal")

stop_reason 速查:

stop_reason含义你需要做什么
tool_use模型要调用工具执行工具 → 回传结果 → 继续循环
end_turn模型给出最终答案读取 content,循环结束
max_tokens达到输出 token 上限按需截断处理
refusal模型拒绝继续检查内容策略
pause_turn(服务端工具)服务端迭代达上限重发对话让模型继续
可引用结论:Agentic Loop 的规范形式是"while stop_reason == tool_use,执行工具并继续对话";循环在任何其他 stop_reason 时退出,包括 end_turn、max_tokens、stop_sequence 或 refusal(来源:Anthropic Tool Use 官方文档,2026.04)。

工具定义:name / description / parameters 怎么写

工具定义是 Function Calling 效果好坏的关键——模型完全依赖 description 决定是否调用工具,description 写得清晰准确直接影响调用成功率。

标准工具 Schema 结构

# OpenAI / DeepSeek 兼容格式(Chat Completions API)
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",                          # 唯一标识符,snake_case
            "description": (                                # 关键:告诉模型何时调用此工具
                "获取指定城市的当前天气信息,包括温度、天气状况和湿度。"
                "仅在用户明确询问天气时调用,不用于历史气候查询。"
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,如'北京'或'Shanghai'"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度单位,默认 celsius"
                    }
                },
                "required": ["city"]                        # 必填参数列表
            },
            "strict": True                                  # 启用 strict mode(推荐)
        }
    }
]

description 写作要点:

  1. 说明用途,而非重复函数名"查询当前天气" 优于 "get_weather function"
  2. 说明何时调用、何时不调用:减少误触发
  3. 说明参数的值域和格式"格式为 YYYY-MM-DD""日期" 有效得多
  4. 保持简洁:description 会占用 token 成本,避免冗长
可引用结论:Anthropic 数据显示,在 LAB-Bench FigQA 和 SWE-bench 等基准测试中,添加基础工具可产生超出预期的能力提升,通常超越人类专家基准(来源:Anthropic Tool Use 文档,2026.04)。

tool_choice:控制模型何时调用工具

tool_choice 参数控制模型的工具调用策略,四种取值覆盖从"完全自主"到"强制指定"的全部场景。

tool_choice 值含义适用场景
"auto"(默认)模型自主决定是否调用通用对话,让模型按需判断
"required"必须调用至少一个工具强制提取结构化数据
"none"禁止所有工具调用纯文本生成,不允许工具调用
{"type": "function", "function": {"name": "get_weather"}}强制调用指定工具工具 A/B 测试、固定调用路径
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_KEY",
    base_url="https://api.qnaigc.com/v1"   # 七牛云 AI 推理 API,国内直连
)

# 强制提取结构化数据(required)
response = client.chat.completions.create(
    model="deepseek-v4-flash",
    tools=tools,
    tool_choice="required",                 # 必须调用工具,不允许纯文本回复
    messages=[{"role": "user", "content": "帮我查一下北京今天的天气"}]
)

Python 完整实现:从工具调用到结果回传

下面是一个可运行的 Agentic Loop 完整示例,演示工具定义、调用检测、结果回传三个核心环节:

import json
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_DEEPSEEK_KEY",
    base_url="https://api.deepseek.com/v1"   # DeepSeek 官方 API,国内直连
)

# ── 1. 定义工具 ──────────────────────────────────────────
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取指定城市的当前天气,包括温度和天气状况",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
                },
                "required": ["city"]
            }
        }
    }
]

# ── 2. 模拟工具执行函数 ──────────────────────────────────
def execute_tool(name: str, args: dict) -> str:
    if name == "get_weather":
        # 实际项目中替换为真实 API 调用
        return json.dumps({"city": args["city"], "temp": 22, "condition": "晴天"})
    return json.dumps({"error": f"unknown tool: {name}"})

# ── 3. Agentic Loop ─────────────────────────────────────
messages = [{"role": "user", "content": "北京和上海今天天气怎么样?"}]

while True:
    response = client.chat.completions.create(
        model="deepseek-v4-flash",
        tools=tools,
        tool_choice="auto",
        messages=messages
    )
    
    choice = response.choices[0]
    messages.append({"role": "assistant", "content": choice.message.content,
                     "tool_calls": choice.message.tool_calls})
    
    # ── 循环终止条件 ───────────────────────────────────────
    if choice.finish_reason != "tool_calls":
        print("最终回答:", choice.message.content)
        break
    
    # ── 4. 执行工具并回传结果 ─────────────────────────────
    for tool_call in choice.message.tool_calls:
        result = execute_tool(
            tool_call.function.name,
            json.loads(tool_call.function.arguments)
        )
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,       # 必须与请求中的 id 对应
            "content": result
        })

Parallel Function Calling:同时处理多个工具调用

Parallel Function Calling 允许模型在一次响应中输出多个 tool_use block,你的应用可并行执行所有工具调用,显著减少总延迟。 上例中"北京和上海今天天气怎么样?"会触发两个并发的 get_weather 调用。

# 处理并发工具调用(示例:两个天气查询同时触发)
import concurrent.futures

if choice.finish_reason == "tool_calls":
    tool_calls = choice.message.tool_calls   # 可能包含多个 tool_call
    
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = {
            tc.id: executor.submit(
                execute_tool,
                tc.function.name,
                json.loads(tc.function.arguments)
            )
            for tc in tool_calls
        }
    
    for tc in tool_calls:
        messages.append({
            "role": "tool",
            "tool_call_id": tc.id,
            "content": futures[tc.id].result()   # 并行执行结果
        })

支持 Parallel Function Calling 的模型: GPT-4o、GPT-4.1、GPT-5(OpenAI);DeepSeek V4 Flash/Pro;Claude Opus 4.7(通过 tool_choice: {type: "auto"} 自动并行)。


Strict Mode:确保工具调用严格符合 Schema

strict: true 告诉模型必须严格遵守你定义的 JSON Schema,输出不会出现 Schema 中未定义的字段,适用于需要机器解析工具调用结果的生产场景。

# OpenAI / DeepSeek strict mode
"function": {
    "name": "create_order",
    "strict": True,                          # 开启 strict mode
    "parameters": {
        "type": "object",
        "additionalProperties": False,        # strict mode 要求此字段为 False
        "properties": {
            "product_id": {"type": "string"},
            "quantity": {"type": "integer"},
            "address": {"type": "string"}
        },
        "required": ["product_id", "quantity", "address"]
    }
}

DeepSeek strict mode(Beta):使用 base_url="https://api.deepseek.com/beta",支持 object/string/number/integer/boolean/array/enum/anyOf/$ref。注意:string 不支持 minLength/maxLength,array 不支持 minItems/maxItems(来源:DeepSeek API 文档,2026.04)。

Anthropic strict tool use:在工具定义中加 "strict": true,确保 Claude 的工具调用始终匹配 Schema。


三大平台对比:OpenAI / Claude / DeepSeek 的 Function Calling 实现差异

维度OpenAIAnthropic ClaudeDeepSeek
API 参数名tools + tool_choicetools + tool_choicetools + tool_choice(OpenAI 兼容)
stop_reason 字段名finish_reason: "tool_calls"stop_reason: "tool_use"finish_reason: "tool_calls"(OpenAI 兼容)
工具结果消息 role"tool""user" 包裹 tool_result"tool"(OpenAI 兼容)
服务端工具无(均为客户端执行)✅ web_search / code_execution / web_fetch(Anthropic 执行)无(均为客户端执行)
Parallel Calling
Strict Modestrict: truestrict: true✅ Beta(/beta 端点)
tool_choice 取值auto/required/none/指定函数名auto/any/none/指定工具名auto/required/none(兼容 OpenAI)
定价(工具系统提示)工具定义 tokens 计入输入Claude Opus 4.7:346 tokens(auto/none)/ 313 tokens(any/tool)工具定义 tokens 计入输入

Anthropic Tool Use 的独特点:

  • 服务端工具(Server Tools)web_searchcode_executionweb_fetchtool_search 由 Anthropic 服务器执行,你无需实现 tool_result 回传,响应中直接包含最终结果
  • 工具结果格式不同:Claude 的工具结果包裹在 role: "user" 消息的 tool_result block 中,而非独立的 role: "tool" 消息
  • pause_turn:服务端工具迭代达上限时返回 stop_reason: "pause_turn",需重新发送对话让模型继续
# Anthropic Tool Use 格式(与 OpenAI 不同的回传结构)
import anthropic

client = anthropic.Anthropic(api_key="YOUR_KEY")

# 工具结果回传格式(Anthropic 专有)
messages = [
    {"role": "user", "content": "北京今天天气?"},
    {
        "role": "assistant",
        "content": [
            {
                "type": "tool_use",
                "id": "toolu_01A09q90qw90lq917835lq9",
                "name": "get_weather",
                "input": {"city": "北京"}
            }
        ]
    },
    {
        "role": "user",
        "content": [
            {
                "type": "tool_result",                   # Anthropic 专有格式
                "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
                "content": '{"temp": 22, "condition": "晴天"}'
            }
        ]
    }
]
可引用结论:Claude Opus 4.7 使用 tool_choice: auto/none 时额外消耗 346 个系统提示 tokens;使用 any/tool 时为 313 tokens;这部分 tokens 会计入 API 请求的输入 token 总量(来源:Anthropic Tool Use 官方文档,2026.04)。

Function Calling vs Structured Outputs:该用哪个?

两者解决的不是同一问题,选错工具会引入不必要的复杂度:

场景推荐方案理由
需要执行外部操作(API 调用、DB 写入)Function Calling有副作用,需要 tool 机制触发
需要强制返回特定 JSON 结构(无副作用)Structured Outputs无需工具往返,直接约束输出格式
从非结构化文本中提取结构化字段Structured Outputsresponse_format 足够,无需工具调用开销
Agent 工作流:多步骤、多工具串联Function CallingAgentic Loop 是天然容器
实时查询外部数据(天气/行情/DB)Function Calling训练数据没有实时信息,只能靠工具

一句话判断:如果你在写 regex 解析模型输出来提取一个"决定",那个决定就应该是一次工具调用(来源:Anthropic How Tool Use Works,2026.04)。


场景选型矩阵

场景工具类型推荐模型说明
查询数据库/内部 APIClient Tool(用户定义)DeepSeek V4 Flash高频低成本,工具调用准确率高
实时网页搜索Server Tool(Anthropic web_search)Claude Opus 4.7无需自行维护搜索能力
代码执行沙箱Server Tool(code_execution)Claude Opus 4.7Anthropic 托管,无需配置环境
强制提取结构化数据tool_choice: required + strict任意兼容模型确保 100% 格式合规
大规模 Agent 批量任务Parallel Function CallingDeepSeek V4 Flash$0.14/M,并发处理降低延迟
复杂多步推理 Agent多轮 Function Calling + thinkingDeepSeek V4 Proreasoning_content 辅助调试
企业内网/数据不出境Client Tool 本地部署DeepSeek V4 Pro(本地)MIT 开源,华为昇腾支持

FAQ

Q1:工具调用的 token 成本如何计算?

工具定义(tools 数组)、tool_use block、tool_result block 均计入输入 token 数量。Claude Opus 4.7 还会自动注入工具系统提示(346 或 313 tokens),这部分也计费。实际成本 = 普通输入 tokens + 工具定义 tokens + 工具往返 tokens。减少 description 冗余、复用工具定义、启用 Prompt Caching 是主要降本手段。

Q2:description 写得不好会有什么后果?

模型可能在不应该调用工具时触发调用(误触发),或在应该调用时跳过(漏调用)。description 是模型判断"是否调用"的唯一依据,建议:① 明确说明适用场景;② 说明参数的值域和格式;③ 说明不适用的反例("仅在用户明确询问时调用,不用于一般问答")。

Q3:如何用一个 Key 测试 OpenAI / Claude / DeepSeek 三家的 Function Calling 效果?

通过七牛云 AI 推理 API(api.qnaigc.com)可以用同一个 Key 国内直连三家模型:OpenAI 兼容协议填 base_url="https://api.qnaigc.com/v1",Anthropic 原生协议填 base_url="https://api.qnaigc.com",改一行 model 参数即可切换模型做 A/B 对比,无需境外节点。

Q4:parallel function calling 什么时候自动触发?

当用户的一个请求涉及多个独立的工具操作时(如"查北京和上海天气"),模型会在一次响应中输出多个 tool_use block。你的应用需要检测 tool_calls 列表长度,对每个 tool_call 分别回传 tool_result,所有 tool_result 共同发回才能继续循环。不需要显式开启,模型会自动判断。

Q5:工具执行出错了,该怎么回传?

回传一个带有错误信息的 tool_result,不要让整个循环中断。Claude 会根据错误信息决定重试或改变策略:

messages.append({
    "role": "tool",
    "tool_call_id": tool_call.id,
    "content": json.dumps({"error": "数据库连接超时,请稍后重试"})
})

总结

Function Calling 的核心是一个三方契约:你定义工具 Schema,模型决定何时调用,你的代码执行并返回结果。 掌握四个关键点足以覆盖 80% 的实现场景:① description 写清楚触发条件;② tool_choice: "required" 强制结构化提取;③ 循环检测 finish_reason 驱动 Agentic Loop;④ strict: true 保证生产环境的格式合规。OpenAI 与 DeepSeek 使用兼容格式,Claude 的 tool_result 回传结构不同,跨平台切换时注意工具结果消息的格式差异。

数据来源:Anthropic Tool Use 官方文档(platform.claude.com/docs,2026.04);OpenAI Function Calling 文档(developers.openai.com,2026.04);DeepSeek Function Calling 文档(api-docs.deepseek.com,2026.04)| 信息时效:2026 年 4 月


相关资源:

标签: none

添加新评论