Function Calling 调用工具总出错?问题多半在这份 schema 里

上周排查一个 Agent 的问题,现象很怪:模型明明「调用」了工具,但传回来的参数永远差一个字段,重试三次全是同一个错。查到最后发现,问题不在模型,在我给它的工具描述里------那个字段压根没写进 parameters。

这件事让我把「Function Calling」这条链路重新捋了一遍。这篇从工程角度讲清楚:模型到底怎么决定调用哪个工具、参数是怎么来的、以及为什么你写的 schema 决定了它的成功率。

一、先纠正一个常见误解

很多人以为「AI 会调工具」= 模型自己去执行了函数。不是的。

模型做的唯一一件事,是根据上下文输出一段结构化文本 ,表示「我要调用 X,参数是 Y」。真正执行 X(Y) 的,是你的代码。

所以一条完整的调用链是:

rust 复制代码
用户问题 + 工具清单  ->  模型输出 tool_call 意图
                     ->  你的程序执行对应函数
                     ->  把执行结果回传给模型
                     ->  模型生成最终回答

模型是「决策层」,你的代码是「执行层」。分清楚这一点,后面所有排查都有方向:调用失败,先看执行层收到了什么,再看模型为什么这么给。

二、工具清单就是一份 JSON Schema

各家 API 的字段名略有差异,但结构是通的。一个工具长这样:

json 复制代码
{
  "name": "search_article",
  "description": "在本平台已发布文章里按关键词检索,返回标题与链接",
  "parameters": {
    "type": "object",
    "properties": {
      "keyword": { "type": "string", "description": "检索关键词" },
      "limit":   { "type": "integer", "description": "返回条数,默认 5" }
    },
    "required": ["keyword"]
  }
}

注意 description 出现在两个层级:工具级和参数级。这两层描述,就是模型填参数的唯一依据。

三、参数填错,八成是 schema 的锅

我踩过的坑,基本都能归到这几类:

  1. required 漏标 。模型不知道哪些必填,于是有时传有时不传,你的函数就收到 undefined。
  2. 参数级 description 缺失 。模型只能靠参数名猜语义,limit 猜成「页码」也不奇怪。
  3. 类型不写 。本该是整数,模型传了 "5",服务端校验直接 400。
  4. 工具级 description 太泛。两个工具都写「查询数据」,模型就随机挑一个。

第 4 条尤其隐蔽:出错时你以为是模型笨,其实是你给了两个它分不清的选项。

四、失败信息要原样回传

工具执行出错时,别只回一个 "error"。把真实原因带上:

vbnet 复制代码
Tool error: missing required property 'keyword'. 
Fix: provide the 'keyword' string argument.

模型看到具体缺什么、怎么改,才会换参数重试;只给一个 error,它大概率原地重试同一个调用,然后触发你的重试上限。

顺带加两层保护:参数校验 (schema 之外再校一次类型和边界)和单轮调用次数上限(防止模型在失败里打转)。

五、MCP 解决的是另一个问题

上面这套是「模型怎么表达调用意图」。但工程上还有一层麻烦:同一个工具,想让它在不同客户端里都能用,每个客户端都得适配一遍。

MCP(Model Context Protocol)就是来标准化这一层的:工具方写一个 Server 声明能力,任何支持 MCP 的客户端都能自动发现并调用,换模型、换客户端,工具侧不用重写。

它和 Function Calling 不是二选一------MCP 管「工具从哪来、怎么被发现」,Function Calling 管「模型怎么把调用意图表达出来」。实际链路是:

rust 复制代码
MCP Server 暴露工具
   -> 客户端转成 Function Calling 所需的 schema
   -> 模型输出调用意图
   -> 客户端执行并回传

六、什么时候不用上 MCP

只有一个客户端、工具三五个、也不会换模型------直接用 Function Calling 就够了,多一层协议只是多一层维护。

值得上 MCP 的信号:工具要跨团队复用,或者你希望换模型时工具侧零改动。

小结(自查用)

  • 工具级 description:说清「什么场景用、什么场景别用」
  • 参数级 description + required + 类型:一个都不能省
  • 失败时把真实原因回传,别只给 error
  • 有参数校验,有单轮调用上限
  • 工具清单别堆相似项,模型会选错

一句话:模型负责决策,你负责执行和兜底。 把这两件事分清,工具调用的问题基本都能定位到具体那一层。


作者:信可维 · AI 实战。记录能跑通的方案。

相关推荐
Decay__31 分钟前
SQLServer 索引与 SQL 优化 —— 聚集索引、非聚集索引、覆盖索引、碎片维护与执行计划
运维·数据库·sql·mysql·架构
Dawson Zhu2 小时前
【分布式训练④】张量并行与序列并行:把单层参数切碎分到多张卡
人工智能·语言模型·架构·aigc·agi
码客-ygluu5 小时前
一个通用游戏数据服务器
c++·架构
炫酷的大高个7 小时前
98% 连跑 20 次只剩 67%,我算了大模型重试账
人工智能·架构·开源
用户6602676118797 小时前
AI 代码上线前的第 24 道门禁:上线失败时,怎样在 10 分钟内退回?
后端·架构
humcomm8 小时前
设计与架构 · 01 sidecar 会消失吗:从 Istio ambient GA 到 AWS App Mesh 关停,一次服务网格数据面的重新洗牌
架构·istio·aws
Eyfcom9 小时前
〖物流低代码实战 01〗物流页面可视化搭建的底层架构:协议、引擎与产物的三重奏
低代码·架构·快递系统·物料体系·物流低代码实战
浪遏17 小时前
recruitment-cli:让 AI 接手求职招聘,从架构到一次发送超时
架构·typescript·node.js
小雉系统20 小时前
BcoreOS安全通信架构:FsSession 抗算法后门安全设计
算法·安全·架构
JAVA前线21 小时前
用《实践论》分析前沿部署工程师:AI时代听见炮声的人
架构·ai编程