前阵子我接了个活,要给我们的 AI 助手接上订餐能力,让用户直接对着模型说"帮我点个外卖",它就能自己调后端接口下单。我心想这有啥难的,现在模型不都支持 Function Calling(函数调用,让模型在对话中主动声明"我要调用哪个函数、参数填什么",再由程序真正去执行)吗?文档一翻,schema(函数接口描述,告诉模型这个函数能干嘛、参数是啥格式)一写,半天就调通了。模型也确实听话,用户说"来份宫保鸡丁",它"啪"一下就把 placeOrder 调了。我得意得不行,觉得这波 Agent 稳稳的。结果上线第二周,我打开后台日志一看,血压直接拉满——有人问"今天天气咋样",它居然帮我下单了一份湖南菜。

今天就想跟你唠唠 Function Calling 这个事。太多人跟我当初一样,觉得给模型接上工具调用,就是"打开开关、写个函数描述、万事大吉"。真在生产里跑过你才知道,Function Calling 是把双刃剑,它给了模型"手",但你没教它"什么时候该出手"。这个认知,我要是早点想通,能少改八百次代码。

先说个最要命的坑——模型调用函数的"时机"和"依据",你得管住。我最初的设计特别天真:把系统里所有函数一股脑全挂上去,连查天气、查快递这种无关紧要的也给模型列上。结果模型为了"表现积极",逮着啥都想调。用户随口一句"今天有点冷",它可能就推断出"用户可能想点热饮",自作主张帮你下单了。我这才反应过来,Function Calling 里的 schema 不只是"说明书",它还是"权限边界"。你暴露给模型的函数越少、描述写得越克制,它越不容易自作主张。我把那些跟主流程无关的函数全下掉了,天气这种明明该走别的分支的,也单独拆了个小助手去管,这才消停。

这里我得插句闲话——那阵子我天天被"模型乱下单"支配,有天我女朋友路过看我盯着日志发呆,问我"你这是在给机器人当妈吗,还得教它啥时候别乱伸手"。我一想还真是,Function Calling 落到工程上,本质就是在跟模型玩"信任边界"的游戏,你不把规则钉死,它逮着空子就钻。后来我还真把这事当成"给不靠谱新同事划权限"来设计了,一下子思路就通了。

第二个坑更隐蔽,是参数校验必须你自己做,别指望模型填的都对。Function Calling 是"模型负责声明意图,你负责真正执行",但它声明出来的参数,是从自然语言里猜出来的,天生就有幻觉风险。有一次用户说"帮我把明天的会挪到下午三点",模型给我回的参数是 startTime: "2026-09-19T15:00:00",看着挺正常,可它压根没问我"明天到底星期几、几点钟算下午",直接猜了个时间戳。要不是我在执行层做了一层严格的参数白名单校验(只允许特定格式、特定范围的取值),这个会议就得被排到不知道哪天去。所以记住,模型给的参数永远当"待审核的草稿",程序侧得做类型、范围、枚举校验,缺一项都不能往下走。宁可拒绝执行,也不要传个错参数过去让后端背锅。

我还踩过一个挺反直觉的坑——循环调用没有死循环保护,能把你的 API 配额烧穿。Agent 的工作流是"模型说调函数→你执行→把结果喂回去→模型再决定下一步"。看起来没问题,但要是函数返回的结果模型理解不了,或者你给它的上下文太短导致它每次都"失忆",它就会一遍遍重复调同一个函数。我测的时候一切正常,一上线被用户并发一压,同一个查询接口被一个会话连续调了四十多次,日志刷屏,账单也好看。从那以后我强制加了调用次数上限和"同类调用合并"的逻辑,一个会话里同一个函数调超过三次就停下来问用户,这才把坑填上。

再顺带说个容易被忽略的——函数返回的结构别太花哨,模型读不懂就等于白调。我以为返回值越详细越好,把接口返回的 JSON 原封不动塞回去,结果里面嵌套了七八层,还有一堆无关字段。模型被绕晕了,经常"假装看懂"然后开始编。后来我改成每个函数只返回"模型做决定真正需要的最小字段",加一句人话说明(比如"下单成功,订单号 12345"),模型的准确率一下就上去了。你是在给模型喂"决策素材",不是给它倒数据仓库。

说到这儿你可能也猜到了,我最后那套订餐助手,Function Calling 的 schema 精修了不下五版,函数从二十个砍到六个,每个返回都做了瘦身和校验,乱调的问题基本绝迹。这一通折腾下来我算彻底明白:Function Calling 真正难的不是"让模型会调函数",是"在模型和你的系统之间立好规矩"。模型天生是个热情的、爱猜的"实习生",你得既给它干活的手,又给它画清楚哪些别碰、怎么干才算数。

其实往深了想,Function Calling 就是 Agent 世界的"权限模型"。它把"意图理解"交给模型,把"安全执行"留给你,这条边界划得多清楚,你的 Agent 就能跑得多稳。划不清楚,轻则功能错乱,重则出安全风险。所以别急着往 schema 里堆函数,先想明白:哪些值得暴露、参数怎么校验、循环怎么兜底、返回怎么精简。这四件事做扎实了,Function Calling 才是真香。

最后抛个问题吧:你自己在给模型接工具的时候,有没有被它"自作主张"坑过?或者你有没有遇到过"明明函数描述写得很清楚,模型就是调不对"的诡异场景?评论区聊聊,我特别想知道,是不是每个搞 Agent 的人,都经历过一次"看着模型一本正经地干了一件蠢事,然后你只能一边叹气一边加校验"的深夜。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐