Function Calling 的完整机制——模型真的「调用」函数了吗?

Q3-03工具调用机制高频Function Calling工具调用JSON Schema并行调用结构化输出MCP

谁在问:一面必问的机制题;面试官用它区分「只用过框架封装」和「手写过 messages 循环」

口语化问法

  • Function Calling 你讲讲完整流程。模型是真的把我的函数执行了吗?
  • 从我发出请求到工具结果回到用户面前,中间经过几次模型调用?
  • 模型返回的那个参数,你直接拿去执行吗?

考察意图

看着是概念题,实际是手感题。用框架封装的人(agent.run(query) 一把梭)和手写过 messages 循环的人,答案的颗粒度完全不一样。面试官在验四件事:

  1. 知不知道模型不执行任何东西——它只输出意图,执行权和安全边界 100% 在你的代码里。答错这条,后面所有安全类追问都不用问了。
  2. 知不知道一个回合的完整结构——工具结果要以特定角色回灌,而且要带上 id 对应关系。
  3. 知不知道工具定义是要花 token 的——工具越多,上下文越贵、选得越不准。
  4. 处没处理过异常——参数非法、并行 id 对不上、返回体过大,这三个是生产必遇。

参考答案

图 2 · 60 分与 90 分差在哪:代价、演进、怎么验证

60

60 分答案(及格线)

模型没有执行任何函数,它只是输出了一段结构化的调用意图。完整回合六步:

  1. 我把工具的 JSON Schema 描述(名字、用途、参数定义)随请求一起发给模型;
  2. 模型在生成时决定要用工具,输出一个 tool_call:工具名 + 参数 JSON + 一个调用 id;
  3. 接口返回时告知本轮因工具调用而结束,控制权回到我的代码
  4. 我的代码校验参数、执行真正的函数、拿到结果;
  5. 我把结果作为一条工具角色的消息(带上对应的 id)追加进消息列表,连同完整历史再发一次请求
  6. 模型基于结果生成最终答案,或者再发起下一次 tool_call——循环由此形成。

所以一次工具调用至少两次模型请求。「Function Calling」这个名字有误导性,它其实是「Function Intent Generation」:模型负责说要调什么,执行永远是你的事。

90

90 分答案(有生产经验的回答)

在六步基础上补五层。

1. 边界意识:安全线全在我这侧。 模型没有网络、没有副作用,它输出的只是文本。所以权限校验、参数白名单、幂等键、审计日志,一个都不能指望模型自觉——全部写在执行前那一层。凡是「让模型别调删除接口」这种靠提示词的防护,都不叫防护。

2. 结构化输出保证语法,不保证语义。 现在主流接口都支持约束解码(constrained decoding,按 schema 约束采样)保证输出是合法 JSON、字段齐全。这解决的是解析失败,不解决参数编造——模型照样能给你填一个不存在的订单号。所以 schema 校验之后还要有业务校验。约束解码的代价也要知道:schema 越复杂越容易拖慢生成甚至降低语义质量,字段特别多的时候不如拆成两次调用;纯自由文本任务上则完全没必要开。

3. 并行工具调用的坑。 一轮可能返回多个 tool_call,必须每个都回一条结果消息、id 一一对上,漏一条通常直接报错。而且并行只对只读工具安全——有写副作用的要串行 + 幂等键,否则模型一口气发三个「创建工单」你就有三张工单。三段式看它:解决时延(多个独立查询一轮打完);代价是多份结果同时涌进上下文、错误处理复杂化;返回体大或有副作用或彼此依赖时不该用。

4. Token 经济学,这是分水岭。 工具定义每一轮都随请求重发,工具越多、描述越长,固定开销越高。更麻烦的是工具结果一旦进上下文,后面每一轮都在重发它——一个返回 5 万字的检索工具,成本是复利的,不是一次性的。我的做法是工具输出裁剪到必要字段、长结果只回摘要 + 一个引用句柄,需要细节时再用句柄取。工具数量上也有经验拐点:截至 2026-08,多数模型在工具超过 20 个左右后选择准确率会明显退化(各家差异大,要自己测),治理手段是按场景装载、命名空间分层、合并语义相近的工具。

5. 与 MCP、Skills 的分工(2026 常被连着问)。 Function Calling 是模型侧的表达方式;MCP 是工具的发现与传输层协议,MCP Server 提供的工具最终还是要转成模型的 tools schema 再发给模型,两者不是替代关系。截至 2026-08,MCP 2026-07-28 规范把协议核心改成了无状态(取消了 initialize 握手和会话 id),业务状态的新范式是工具返回显式 handle——这恰好和上面「长结果回句柄」的做法对上了。Agent Skills 则是另一维度:它是操作手册(渐进式披露,一个 skill 的「广告」约 100 token),MCP 是手。手册教怎么做事,工具才是做事的能力。

追问链

图 1 · 五层追问树:面试官会往哪儿挖
执行权 100% 在你的代码里,追问就顺着「你的代码」逐层挖

  1. 模型返回的参数一定是合法 JSON 吗?非法或字段缺失怎么处理?

    期望开了约束解码语法才可靠,但不能假设。先 schema 校验(类型、枚举、必填)→ 再业务校验(订单号存在吗、日期合法吗)→ 失败别抛给用户也别重试原请求,把可操作错误当工具结果回灌让模型自改,限 1–2 次。红线:参数等同用户输入,绝不拼进 SQL/shell/eval
    信号区分「语法校验」与「业务校验」并提到把错误回灌让模型自愈 → 手写过循环;答「框架会处理」「加个 try-catch」→ 只用过封装
  2. 一轮返回 3 个 tool_call,怎么执行回灌?有副作用的工具能并行吗?

    期望三个都要执行,失败的也回一条;每个 tool_call_id 对应一条结果消息 —— 漏了或顺序错会接口报错或模型串线。并行只对只读、无依赖的工具安全;写操作串行 + 幂等键,因为模型可能重复发起。部分失败要如实告诉模型哪个失败、为什么,让它决定重试还是换路径,而不是整轮抛异常
    信号主动提 id 一一对应、部分失败如实回灌、写操作幂等 → 处理过线上;答「并行更快所以都并行」→ 没遇到过重复下单
  3. 一个检索工具返回 10 万字,怎么办?

    期望这是复利成本:结果进上下文后每轮重发,还挤占上下文让决策变差。工具侧裁剪(只返决策要用的字段,别原样丢数据库行)→ 摘要或分页(top-k + 总数 + 提示还有更多)→ 句柄化(返引用 id,要细节再取;MCP 2026-07 转无状态后的范式)。每次都要全量说明粒度错了,该拆
    信号说出「结果进上下文后每轮都重发」这个复利效应 → 算过成本;只答「截断一下」→ 知道现象不知道原因
  4. 工具从 5 个涨到 50 个,模型开始选错,你怎么治?

    期望这是已知退化,不是提示词不诚恳。按性价比:①按场景分批装载 ②检索式选工具,先挑候选再给模型 ③相近的合并成带 type 参数的一个 ④参数用 enum 收窄 ⑤写清「什么时候不要用」,负向比正向管用 ⑥命名空间分层,别叫 get_data。要有评测:标注 query 测准确率
    信号给出「按需装载 + 负向描述 + 有评测」的组合拳 → 治理过工具集;只答「把描述写详细点」→ 还停在单工具视角
  5. 线上出现模型没调工具、自己把查询结果编出来回答用户,怎么定位、怎么止血?

    期望先定性trace 里有没有 tool_call:「没调就编」≠「调了不用」→ 按排查成本:①描述与问法不符 ②system prompt 没硬约束 ③上下文已有像答案的内容 ④前几轮报错致模型放弃(最隐蔽)⑤档位/采样被改 → 止血:高危意图强制调工具 + 输出校验闸:价格/库存/单号本轮结果里找不到即拒答 → badcase 进回归集 +「该调没调」率
    信号先分「没调」还是「调了不用」、想到「历史工具失败导致模型放弃」→ 排查过真事故;一上来「改提示词强调必须调用」→ 对幻觉最不可靠的一招
一句「模型只输出意图、执行 100% 在你的代码里」就把用框架的和手写过 messages 循环的分开;前四层验回合结构与成本,第 5 层验事故排查顺序。

评分要点

  1. 明确说出模型不执行函数,只输出调用意图
  2. 讲清完整回合:schema 随请求下发 → tool_call → 代码执行 → 结果回灌 → 再次请求
  3. 知道一次工具调用至少两次模型请求,且每次重发完整历史
  4. 提到工具结果必须带 id 对应回灌
  5. 知道结构化输出保证语法不保证语义,执行前要有业务校验
  6. 说得出工具定义与工具结果的 token 成本(尤其是结果的复利效应)
  7. 加分:并行调用的 id 对齐与副作用/幂等问题
  8. 加分:工具数量与选择准确率的退化,及治理手段
  9. 加分:能说清 FC 与 MCP、Agent Skills 的分工(截至 2026-08)

常见错误

「模型调用了我的函数」——最核心的误解。追问「它怎么访问你的内网数据库」就露馅。
只说「传 tools 参数,它就会调」,说不清结果怎么回去、要不要再请求一次——用过封装没看过 messages。
以为工具结果是「返回给模型的私有通道」,不知道它就是上下文里的一条普通消息,要占 token、要被后续每轮重发。
完全不提参数校验,默认模型给的参数可以直接执行——安全意识缺失,这一条在 toB 场景是硬伤。
把 MCP 说成「Function Calling 的升级版/替代品」——层次搞混了(详见 Q3-08)。
「让提示词强调一定要调工具就行」——把架构问题当文案问题。
讲不出任何异常场景(参数缺失、工具超时、返回过长、并行 id 对不上),说明只跑通过 happy path。

关联学习