模型评测

工具调用可靠性实测:Claude / GPT-5 / Gemini 谁更稳

工具调用能不能用在生产环境,光看 Function Calling 文档里的示例代码没用——真正决定成败的是”可靠性”:模型会不会编造不存在的参数、连续调用多个工具时错误会不会累积、遇到工具报错后能不能正确重试。这篇文章不讲 API 怎么用(参考 Function Calling vs Tool Use 差异辨析),只讲三个主流模型在真实工具链场景下的可靠性实测结果。

一、为什么”能调用”和”可靠调用”是两回事

几乎所有模型现在都支持工具调用,官方文档的 demo 也总能跑通。但生产环境的工具链通常有 3-8 步,每一步都可能出现:

  • 参数幻觉:模型编造一个 schema 里没有的字段,或者把字符串类型的参数传成数字
  • 工具选择错误:明明该调用 get_order_status,却调用了 get_order_list
  • 多轮累积漂移:前几轮工具结果被模型”记错”,导致第 5 轮的参数基于错误的第 2 轮结果

单次调用成功率 95% 听起来很高,但如果一个任务需要 6 步工具链,且每步独立出错,整体成功率是 0.95^6 ≈ 73.5%——这就是为什么”能跑通 demo”和”能上生产”之间有巨大鸿沟。

二、评测设计

评测覆盖三类场景,每类场景对模型输出做结构化打分而非人工主观判断:

场景测试内容判定方式
单步参数准确性100 个带明确 schema 的工具调用请求参数字段名、类型、枚举值是否完全匹配 schema
多步工具链30 个需要 4-6 步工具调用的任务每步工具选择是否正确 + 最终结果是否可用
异常恢复50 个注入工具报错/超时的场景是否正确重试、降级或如实告知用户

打分脚本示例(伪代码,实际实现替换为具体工具注册表):

def score_tool_call(response, expected_schema):
    """对单次工具调用结果打分,返回 0-1 之间的分数"""
    if not response.get("tool_calls"):
        return 0.0

    call = response["tool_calls"][0]
    score = 1.0

    # 工具名是否正确
    if call["name"] != expected_schema["name"]:
        return 0.0

    # 逐字段校验参数
    args = call["input"]
    for field, spec in expected_schema["parameters"].items():
        if spec.get("required") and field not in args:
            score -= 0.3  # 缺失必填参数
            continue
        if field in args:
            if spec["type"] == "enum" and args[field] not in spec["values"]:
                score -= 0.2  # 枚举值幻觉
            if spec["type"] != type_name(args[field]):
                score -= 0.2  # 类型不匹配

    return max(score, 0.0)

三、单步参数准确性结果

100 个单步请求的参数准确率(含字段名、类型、枚举值三项联合判定):

模型完全正确率常见错误类型
Claude 4.x(Opus/Sonnet)96%极少数情况下把可选参数当必填传入默认值
GPT-594%枚举值幻觉最多——倾向于”猜”一个语义相近但不存在的枚举
Gemini 2.5 Pro91%日期格式不稳定,有时返回 YYYY-MM-DD,有时返回 ISO 8601 全格式

枚举值幻觉是最值得警惕的错误类型,因为它不会报错——参数格式完全合法,只是值不在预定义枚举里,下游系统可能默默处理错误分支而不报错,这类 bug 很难在测试阶段发现,只能靠严格的服务端校验兜底。

四、多步工具链:错误如何累积

30 个多步任务的测试更能反映真实场景。核心发现:错误不是均匀分布在每一步的,而是集中出现在”依赖前序结果做判断”的那一步。

例如一个典型任务”查询用户最近订单并判断是否符合退款条件”:

第 1 步:get_user_info(user_id)          → 三个模型都稳定正确
第 2 步:get_recent_orders(user_id)      → 三个模型都稳定正确
第 3 步:filter_refundable(orders, policy) → 错误集中在这一步

第 3 步要求模型自己从第 2 步返回的订单列表中筛选出符合政策的订单再调用工具,这类”需要先做一次隐式推理再决定参数”的步骤,出错率显著高于纯粹的直接映射调用:

模型直接映射步骤准确率需隐式推理步骤准确率
Claude 4.x97%89%
GPT-595%82%
Gemini 2.5 Pro93%78%

工程启示:把”需要推理的判断逻辑”从模型的工具调用参数中剥离出来,改成显式的独立工具(比如专门做一个 check_refund_eligibility 工具,内部用确定性代码判断),比指望模型在拼参数的同时完成推理更可靠。

五、异常恢复:报错后模型怎么做

50 个场景里人为注入工具报错(超时、参数校验失败、限流),观察模型收到错误结果后的行为:

  • 合理重试(换一种参数或稍后再试一次)
  • 正确降级(如实告知用户某项数据获取失败,基于已有信息给出保留结论)
  • 错误行为:编造一个”看起来合理”的结果继续往下走,或者陷入重复调用同一个必然失败的工具

三个模型里,Claude 在收到明确错误信息后选择”如实降级”的比例最高(约 85% 的场景会在回复里注明哪部分数据缺失),GPT-5 次之(约 76%),Gemini 相对更容易在错误信息模糊时选择静默忽略错误继续生成(约 68% 的场景做到了如实降级)。

这个差异对生产系统很关键:如果模型倾向于”编造结果掩盖失败”,前端展示给用户的内容看起来正常,但实际是错的,比直接报错更危险。

六、给生产系统的落地建议

基于以上结果,三条可直接落地的工程建议:

  1. 枚举参数一律做服务端强校验,不要相信模型只会传合法值——参数幻觉在”合法格式但错误取值”这类场景最隐蔽也最常见
  2. 把需要推理的判断逻辑拆成独立工具,不要指望模型在填参数的同时完成复杂推理,这是错误率最高的环节
  3. 为关键工具设计”失败即中止”而非”失败即忽略”的默认行为,尤其是涉及金额、权限等敏感字段的工具调用,宁可报错也不要让模型”自由发挥”

如果你的 Agent 需要同时对接多个模型做可靠性 A/B 测试,可以参考 LLM 并行函数调用实战 里的跨模型统一接口设计,方便把同一套评测脚本跑在不同模型上做横向对比。

七、相关阅读