Function Calling 深度实测:Claude 4.6 vs GPT-5.4 vs Gemini 2.5,谁的工具调用最靠谱?AILLM

3 阅读7分钟

Function Calling 是 AI Agent 的心脏——模型再聪明,工具调不好就是废的。

上周生产环境出了个诡异的 bug:同一套 Tool Schema,GPT-5.4 调得好好的,Claude 4.6 偶尔漏参数,Gemini 2.5 直接把返回的 JSON 搞坏了。排查两天才定位到根因——三家对 required 字段和嵌套对象的解析逻辑压根不一样。

踩完这个坑我就不淡定了。虽然各家都管自己叫"Function Calling",但底层实现差得远。索性花一周设计了一套标准化评测,拿 Claude Opus 4.6、GPT-5.4、Gemini 2.5 Pro 做了 900 个 case 的横向对比。

评测方案设计

六个维度,900 个用例

为了覆盖实际 Agent 开发中的典型场景,测试拆成六个维度:

维度具体测试内容用例数
基础调用单工具、意图明确200
参数补全用户信息不全,模型需推理填参200
多工具串联单次请求涉及 2-3 个工具协作150
嵌套结构参数含 array、嵌套 object150
意图拒绝用户意图不匹配任何工具定义100
异常恢复工具报错后模型的重试行为100

每个模型各跑 3 轮,取平均值。

统一的工具定义

三家都用 OpenAI JSON Schema 格式定义工具,通过各自 SDK 做转换。测试工具集包含电商搜索、订单创建、天气查询三个典型场景:

import openai

client = openai.OpenAI(
    base_url="https://api.ofox.ai/v1",  # 统一走这个,方便切模型
    api_key="sk-xxx"
)

tools = [
    {
        "type": "function",
        "function": {
            "name": "search_products",
            "description": "搜索商品信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "搜索关键词"},
                    "category": {
                        "type": "string",
                        "enum": ["electronics", "clothing", "food"]
                    },
                    "price_range": {
                        "type": "object",
                        "properties": {
                            "min": {"type": "number", "description": "最低价(元)"},
                            "max": {"type": "number", "description": "最高价(元)"}
                        },
                        "description": "价格区间,包含 min 和 max 两个字段"
                    },
                    "sort_by": {
                        "type": "string",
                        "enum": ["price", "rating", "sales"]
                    }
                },
                "required": ["query"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "create_order",
            "description": "创建订单",
            "parameters": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "string"},
                    "quantity": {"type": "integer", "minimum": 1},
                    "shipping_address": {
                        "type": "object",
                        "properties": {
                            "city": {"type": "string"},
                            "street": {"type": "string"},
                            "zip": {"type": "string"}
                        },
                        "required": ["city", "street"]
                    }
                },
                "required": ["product_id", "quantity", "shipping_address"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "获取天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string"},
                    "date": {"type": "string", "format": "date"}
                },
                "required": ["location"]
            }
        }
    }
]

结果:Claude 和 GPT 并驾齐驱,Gemini 掉队

综合得分

模型基础调用参数补全多工具串联嵌套结构意图拒绝异常恢复加权综合
Claude Opus 4.699.5%94.2%91.3%96.7%97.0%88.3%94.5%
GPT-5.499.0%96.1%93.7%91.2%95.0%92.7%94.6%
Gemini 2.5 Pro98.5%90.8%86.4%84.3%93.0%85.0%89.7%

总分 Claude 和 GPT 几乎打平(差 0.1%),但偏科方向完全不同。

逐模型拆解

Claude 4.6:保守但精准

Claude 的策略是"宁可留空,也不瞎填"。用户说"帮我搜便宜的耳机",它的调用是这样的:

{
  "name": "search_products",
  "arguments": {
    "query": "耳机",
    "sort_by": "price"
  }
}

注意它没猜 category 也没编 price_range,留给工具用默认值处理。多数场景这是正确选择,但偶尔显得不够"聪明"。

嵌套对象是 Claude 的绝对强项。 shipping_address 之类的多层 JSON,Claude 格式正确率 96.7%,遥遥领先。

但它有个坑值得注意:tool_choice: "auto" 模式下,大约 3% 的概率,Claude 该调工具的时候选择了纯文本回复。 在多工具场景更明显。生产环境关键路径建议强制 tool_choice: "required"

GPT-5.4:编排王者,嵌套翻车

GPT 在多工具并行调度上真的强。"查一下北京明天天气,顺便搜搜适合出门穿的外套"——GPT 稳定地同时触发两个调用:

[
  {
    "name": "get_weather",
    "arguments": {"location": "北京", "date": "2026-03-26"}
  },
  {
    "name": "search_products",
    "arguments": {"query": "户外外套", "category": "clothing"}
  }
]

同一场景 Claude 有 8.7% 的概率退化成串行——先查天气,拿到结果,再搜商品。功能上没毛病,但多一轮 round-trip,延迟翻倍。

GPT 的雷区在嵌套对象。 price_range 这种 object 字段,大约 8.8% 的概率被序列化成字符串:

{
  "price_range": "{\"min\": 100, \"max\": 500}"
}

如果你的解析层没做兼容处理,直接炸。后面会讲怎么修。

Gemini 2.5 Pro:基础够用,复杂拉胯

简单的单工具场景 Gemini 没问题。但嵌套对象和多工具编排一上强度,差距就出来了。

最头疼的是 JSON 格式硬伤,15.7% 的嵌套对象输出有语法错误:

{
  "shipping_address": {
    "city": "上海",
    "street": "南京路100号"
  },  // ← 多了这个尾逗号
}

生产环境这就是直接 crash。

另一个毛病是"废话前置"——该直接调工具的地方,Gemini 会先输出一段分析文字,然后才给 tool_call。解析时需要额外处理。

工程层面的实战方案

踩完坑不能白踩,以下是我在项目里用的几个防御性写法。

1. Schema 描述越详细越好

别偷懒只写 "description": "价格范围",改成这样:

{
  "description": "价格区间对象,包含最低价和最高价,单位人民币元。示例:{\"min\": 100, \"max\": 500}",
  "type": "object",
  "properties": {
    "min": {"type": "number", "description": "最低价格(元)"},
    "max": {"type": "number", "description": "最高价格(元)"}
  }
}

就这一个改动,GPT 的嵌套序列化 bug 从 8.8% 降到 2.1%。

2. 参数解析兜底层

import json
import re

def safe_parse_arguments(raw_args):
    """兼容各家模型的参数格式差异"""
    if isinstance(raw_args, dict):
        # 检查是否有被序列化成 string 的嵌套对象
        for key, val in raw_args.items():
            if isinstance(val, str) and val.startswith('{'):
                try:
                    raw_args[key] = json.loads(val)
                except json.JSONDecodeError:
                    pass
        return raw_args

    if isinstance(raw_args, str):
        try:
            return json.loads(raw_args)
        except json.JSONDecodeError:
            # 修复 Gemini 常见的尾逗号问题
            cleaned = re.sub(r',\s*}', '}', raw_args)
            cleaned = re.sub(r',\s*]', ']', cleaned)
            return json.loads(cleaned)

    return raw_args

3. System Prompt 里声明并行策略

加一段简单的指令,效果显著:

当用户请求涉及多个工具调用时:
- 工具间无数据依赖 → 并行调用
- 后一个工具依赖前一个结果 → 串行调用并说明原因

Claude 加上之后,不必要的串行调用减少了约 60%。

4. 带反馈的重试机制

MAX_RETRIES = 2

async def call_with_retry(client, messages, tools):
    for attempt in range(MAX_RETRIES + 1):
        response = await client.chat.completions.create(
            model="claude-opus-4-6",
            messages=messages,
            tools=tools
        )
        tool_calls = response.choices[0].message.tool_calls

        if tool_calls and validate_tool_calls(tool_calls, tools):
            return tool_calls

        # 告诉模型哪里出了问题,让它自己修
        error_msg = get_validation_error(tool_calls)
        messages.append({
            "role": "tool",
            "content": f"参数格式错误: {error_msg},请修正后重新调用"
        })

    raise ToolCallError("超过最大重试次数")

费用对比

900 用例 × 3 轮的实际开销:

模型输入 tokens输出 tokens基础费用含重试总费用重试溢价
Claude Opus 4.62.1M380K$41.7$43.2+3.6%
GPT-5.42.0M410K$38.5$39.8+3.4%
Gemini 2.5 Pro2.1M450K$22.3$26.1+17.0%

Gemini 单价确实便宜,但重试导致的隐性成本达 17%。综合考虑稳定性的话,便宜不等于划算。

测试过程中涉及频繁切换三家模型,我是通过 ofox 一个 endpoint 统一管理的,省得分别维护三套 key 和 SDK,对这种横评场景确实方便。

选型建议

场景推荐模型原因
客服 / 对话 AgentClaude 4.6拒绝调用精准,不会误操作
数据处理流水线GPT-5.4多工具并行调度省时间
复杂嵌套参数Claude 4.6JSON 格式正确率最高
简单单工具三家差不多基础能力差距 <1%
预算敏感按实际重试率算Gemini 便宜但算上重试未必省

小结

2026 年 3 月的 Function Calling 现状:

  • Claude 4.6 和 GPT-5.4 是第一梯队,总分差 0.1%,但偏科明显——Claude 稳在结构化输出,GPT 强在并行编排
  • Gemini 2.5 Pro 简单场景 OK,复杂 Agent 场景需要额外的兜底代码
  • 没有万能选择——根据你的工具复杂度和调用模式选模型,比追排行榜有用

建议在你自己的真实工具集上跑一轮测试再做决定。模型行为和 schema 写法、prompt 风格强相关,公开 benchmark 不等于你的 benchmark。

最后更新:2026-03-25