✨ 复制成功!

以文会友,打造好学人设!

📋 已复制到剪贴板:

Function Calling 在 Agent 系统中的作用是什么?如何设计工具描述、参数 schema 和错误处理,才能提高工具调用的准确率和鲁棒性?

创建时间:2026-10-19 更新时间:2026-10-19 阅读次数:1064 次 分类:Agent与RAG应用

1、Function Calling 在 Agent 系统中的作用

Function Calling 是模型与外部世界之间的结构化接口。它的核心价值在于:让模型能够自主决定何时调用工具、调用哪个工具、传什么参数,而不是只能生成文本。

在 Agent 系统中,它承担几个关键角色:

(1)连接模型推理与真实系统

模型本身不能查数据库、不能发邮件、不能调 API。Function Calling 让模型输出一个结构化的调用请求(函数名 + 参数 JSON),由应用代码执行,再把结果回填给模型继续推理。这是 Agent 从“聊天”变成“做事”的第一步。

(2)支撑多步编排

Agent 的规划能力(ReAct、Plan-and-Execute 等)依赖 Function Calling 作为执行层。模型每一步的 Action 就是一次 Function Call,Observation 就是工具返回结果。没有 Function Calling,规划只是空想。

(3)实现可控的集成

模型不直接执行业务逻辑,只负责“点单”,应用代码负责“做菜”。开发者可以校验参数、控制权限、记录日志、处理错误。这种分层是 Agent 系统安全性和可审计性的基础。

一句话:Function Calling 让模型从“文本生成器”变成“系统编排器”,是 Agent 执行能力的底层机制。

2、如何设计工具描述

工具描述是影响工具调用准确率的最大单一因素。模型决定调不调、调哪个,唯一依据就是描述。

(1)描述必须回答四个问题

一份好的描述需要说清:

  • 做什么:工具的功能。
  • 何时用:什么场景下应该调用。
  • 何时不用:什么情况下不该调用。
  • 不做什么:明确边界,避免模型误用。

比如一个 deactivateUser 的描述:

“禁用用户账号,撤销所有会话并阻止登录。可逆。当客户要求关闭、取消、暂停或挂起账号时使用。不删除数据。如需永久删除,使用 deleteUser,该操作不可逆。”

这段描述同时做了三件事:说明功能、指出适用场景(客户的用词“关闭/取消/暂停”)、指出兄弟工具(deleteUser)避免混淆。

(2)包含用户的词汇

用户说“关掉账号”,API 叫 deactivateUser。描述里要出现“关闭”“取消”“暂停”这些用户实际会用的词,而不是只写“设置 active 为 false”。

(3)指出兄弟工具

当两个工具功能相近时,在描述里直接说“如果你要 X,用 Y 工具,不要用这个”。模型在对比两者的瞬间看到这句话,歧义就被消解了。

(4)命名要具体

search 太模糊。searchCustomersByEmail 同时告诉了模型搜什么、怎么搜。用 verbNoun 风格,保持一致性。

(5)控制工具数量

同时暴露的工具越多,模型选错的概率越大。建议同时活跃的工具控制在 20 个以内。如果工具很多,用工具检索(tool search)按需加载,或者按对话上下文只传相关子集。

3、如何设计参数 Schema

参数 Schema 的目标是:让模型很难产出错误的参数。

(1)用枚举约束封闭集合

如果某个参数只有固定几个合法值,用 enum。字符串类型让模型自由发挥,枚举让它只能从列表里选。

"status": {
  "type": "string",
  "enum": ["pending", "paid", "refunded", "cancelled"]
}

(2)单位写进参数名

amount 有歧义,模型可能猜美元或美分。amount_cents 没有歧义。同理 timeout_seconds、distance_meters。

(3)格式给示例

日期参数写“ISO 8601 格式,例如 2026-08-26”比只写“开始日期”准确得多。

(4)避免可表示的非法状态

toggle_light(on: bool, off: bool) 允许 on=true, off=true,这是逻辑矛盾。改成单个 state 枚举 ["on", "off"],矛盾状态就无法表示。

(5)required 要诚实

标记为 required 的参数必须是模型确实能提供的。如果模型没有信息来填某个参数,不要标记 required,而是在代码里提供默认值或从上下文中注入。反过来,可选参数太多会把失败推到运行时。

(6)扁平优于嵌套

模型填 {"customer": {"address": {"postal_code": "..."}}} 比填 customer_postal_code 更容易出结构错误。在工具边界拍平,在 executor 里重组。

(7)不要要求模型填它不知道的值

内部 ID、租户 UUID、计算出的哈希值,模型无法知道。这些应该由代码从会话或上下文中注入,而不是让模型猜。

4、如何设计错误处理

错误处理的核心原则:不要让一次坏的工具调用变成一次坏的答案。

(1)永远不要把错误吞掉

如果工具调用失败,代码返回空字符串或默认值,模型会以为工具成功了,然后基于空数据编一个答案。这是最危险的失败模式:用户看到一个自信的错误答案,系统没有任何异常。

(2)把错误以结构化形式返回给模型

错误应该作为 tool result 的一部分返回给模型,让模型能看到“哪里错了、值不值得重试”。常见做法是返回一个 JSON:

{"error": "invalid_arguments", "details": "...", "retryable": true}

模型收到这个信号后,通常会修正参数重试,或者告知用户无法完成。

(3)区分可重试和不可重试

可重试:网络超时、速率限制(429)、临时故障。代码层做指数退避重试,不要把这个决策丢给模型。

不可重试:参数语义错误、权限不足、资源不存在。返回给模型,让它修正参数或告知用户。

(4)设置超时和每轮调用上限

每个工具调用要有超时,每轮对话要有工具调用次数上限。否则模型可能陷入“调用失败→重试→再失败”的循环,消耗 token 和 API 配额。

(5)先验证再执行

不要信任模型传来的参数。用 Pydantic 或类似工具做语义校验(日期先后、数值范围、枚举值),校验失败返回错误给模型,而不是让工具带着错误参数执行。

(6)危险操作要有闸门

删除、支付、发消息这类不可逆操作,不要让模型直接触发。加确认步骤、权限校验、人工审批。模型负责“提议”,代码负责“批准”。

5、一句话总结

Function Calling 让模型能自主调用外部工具,是 Agent 执行能力的底层机制。提高准确率靠:描述说清做什么/何时用/何时不用/不做什么,参数用枚举和明确单位约束,工具数量控制。提高鲁棒性靠:错误不吞掉、结构化返回给模型、区分可重试、设置超时和上限、危险操作加闸门。

6、这道面试题的质量点评

优点

  • 结构完整:作用 → 描述设计 → Schema 设计 → 错误处理,覆盖 Function Calling 工程化的全链路。
  • 区分度很好:
    • 初级:能说“让模型调 API”。
    • 中级:能说枚举约束、描述要清晰。
    • 高级:能说错误不吞掉、结构化返回、可重试分类、语义校验、危险操作闸门。
  • 贴近真实痛点:工具调用错误和静默失败是 Agent 上线后最常见的问题。
  • 有追问空间:可以追问 strict 模式、tool_choice、并行调用、工具数量控制。

缺点

  • 偏工程细节:没做过生产级 Agent 的人可能只答“描述写好一点”。
  • 容易背原则:可能列一堆“最佳实践”但说不清为什么。
  • 缺少场景:没问“你实际遇到过什么工具调用失败?怎么修的?”
  • 没覆盖并行调用和 tool_choice:这些是 Function Calling 的重要机制,题目没提。

总体评价

质量:上。 适合中高级岗位,能有效区分“用过 Function Calling”和“真正做过生产级工具调用”的人。建议追问:

“strict 模式能保证什么?不能保证什么?”

“并行调用怎么处理?”

“工具数量多了怎么办?”

“你遇到过模型编造参数的情况吗?怎么处理的?”

“危险操作怎么加闸门?”

7、怎么回答才是最好的

回答原则

  • 先给作用:模型与外部系统的结构化接口,Agent 执行层。
  • 描述设计讲清四要素:做什么、何时用、何时不用、不做什么。
  • Schema 设计突出“让错误难以表示”:枚举、单位、必填诚实、扁平。
  • 错误处理突出“不让坏调用变坏答案”:结构化返回、可重试分类、超时上限、危险闸门。
  • 主动提机制:strict、tool_choice、并行调用、工具检索。
  • 结合实践:说“我们遇到过静默失败,后来强制错误返回”。

推荐回答结构

“Function Calling 是模型和外部系统之间的结构化接口。模型输出函数名和参数,代码执行,结果回填。它让 Agent 能真正做事,也是 ReAct 等规划模式的执行层。”

“描述设计上,最关键的是说清四件事:做什么、何时用、何时不用、不做什么。要包含用户的词汇,指出兄弟工具避免混淆,工具数量控制在 20 个以内。”

“Schema 设计的目标是让错误参数难以表示。封闭集合用 enum,单位写进参数名,required 要诚实,扁平优于嵌套,不要让模型填它不知道的值。”

“错误处理的核心原则是:永远不要把错误吞掉。失败要结构化返回给模型,区分可重试和不可重试。可重试的代码层退避,不可重试的让模型修正。要有超时和每轮调用上限,危险操作加确认闸门。”

“我们实际遇到过工具失败返回空字符串,模型编了一个答案。后来强制所有错误结构化返回,加上 Pydantic 语义校验,静默失败基本消失了。”

加分点

  • 提到 结构化接口、点单 vs 做菜、Agent 执行层。
  • 提到 描述四要素、用户词汇、兄弟工具、20 个工具上限。
  • 提到 enum、单位命名、required 诚实、扁平、不要让模型填未知值。
  • 提到 错误不吞掉、结构化返回、可重试分类、超时上限、危险闸门。
  • 提到 strict 模式、tool_choice、并行调用。
  • 结合真实生产经验。

减分点

  • 只说“让模型调函数”,不展开。
  • 不知道错误吞掉的危害。
  • 不知道枚举和单位约束。
  • 说“strict 开了就安全了”(strict 只保证格式,不保证语义正确)。
  • 不提危险操作闸门。

📌 面试天下网:一款便捷的大模型学习口袋书,让富士康流水线的打工人也能摸到改命逆天的机会!
📌 网站公告:【悬赏 200 元/篇】寻找“大模型面试战场”的一手回忆录
📌 网站公告:【大模型/Agent面试陪练1V1指导】正式启动......

评论专区

评论加载中...