想象你走进一家餐厅,点了一道“宫保鸡丁,不要辣”。店长没有亲自下厨,而是在工单上写下:“炒菜台——宫保鸡丁,免辣”,递给后厨。炒菜台的师傅照单烹饪,出菜后传菜员把菜端回店长面前。店长确认菜品无误,才把菜送到你桌上。你全程只说了一句话,但背后是店长的决策、厨师的执行、传菜员的传递,环环相扣。 大模型的 Function Calling 机制,正是这套“店长派工”流程:大模型是店长,工具函数是后厨的各个工作台。店长不需要自己动手做菜,只需要写一张结构化的“派工单”(输出 JSON 格式的函数调用指令),由应用层(后厨)负责执行,再把结果端回来继续服务。这个能力,让大模型从只能“纸上谈兵”的聊天机器人,升级为真正能查天气、订机票、调数据库、操作系统的 AI 员工。
掌握 Function Calling,你就能让大模型从纸上谈兵升级为真正能查数据、调接口、操作系统的 AI 员工——这是构建 AI Agent 应用不可绕过的地基。
可视化演示
\u53ef\u89c6\u5316\u5c55\u793aFunction Calling\u7684\u5b8c\u6574\u8c03\u7528\u6d41\u7a0b\u3001\u53c2\u6570\u7ed3\u6784\u5316\u63d0\u53d6\u4e0eAgent\u5de5\u5177\u94fe\u8c03\u7528\uff0c\u4ea4\u4e92\u5207\u6362\u89c2\u5bdf\u5927\u6a21\u578b\u8fde\u63a5\u5916\u90e8\u5de5\u5177\u4e0eAPI\u7684\u6838\u5fc3\u673a\u5236\u3002
本节配有交互动效(进入视口后自动加载,约 3KB)。
Function Calling\u5b8c\u6574\u6d41\u7a0b \u7528\u6237\u610f\u56fe\u2192\u6a21\u578b\u9009\u62e9\u51fd\u6570\u2192\u53c2\u6570\u63d0\u53d6\u2192\u6267\u884c\u2192\u7ed3\u679c\u8fd4\u56de \u6a21\u578b\u8f93\u51faJSON\u683c\u5f0f\u51fd\u6570\u540d\u4e0e\u53c2\u6570\u503c User \u2192 LLM \u2192 f(args) \u2192 Result \u70b9\u51fb\u5207\u6362\u67e5\u770b\u53c2\u6570\u63d0\u53d6
概念与价值
店长有一本厚菜单,但他自己不做菜。顾客点“宫保鸡丁不要辣”,店长不犹豫——他知道炒菜台能完成,写下工单递过去。传统的聊天机器人就像一位只会口头答应的“假店长”,你说“帮我订张去上海的机票”,它只能回复“好的,请您去航司官网操作”。它没有手,接触不到任何真实系统。Function Calling 的出现,给这位店长装上了与后厨对话的传声筒:让模型输出一份“派工单”,由应用层的代码去真正动手。
在技术层面,Function Calling 是“将自然语言指令映射为结构化函数调用参数”的机制。模型输出的不是自由文本,而是包含函数名和参数值的 JSON 对象。这个 JSON 对象会被应用层解析、校验并执行。执行后的结果会被拼接到对话上下文中,模型再基于结果生成面向用户的最终答复。整个链路中,模型负责“思考”,应用层负责“行动”。
1. 传统模式:$\text{LLM}(x) \rightarrow \text{文本}$ — 模型仅根据用户输入 $x$ 生成一段文本回复,无法触碰真实世界。
2. 注入函数清单:$\mathcal{F}$ — 开发者把可用工具函数以结构化定义的方式注入给模型,相当于给店长看后厨岗位表。
3. 结构化输出:$\text{JSON}(f, \theta)$ — 模型输出选中的函数名 $f$ 与参数 $\theta$,相当于店长写下的派工单。
4. 执行与回传:$r \rightarrow \text{LLM}(x, r)$ — 应用层执行函数得到结果 $r$,拼回上下文让模型继续推理。
店长还是那个店长,但有了传声筒之后,他不再是“只说不做”的空谈者,而是能调动整个后厨资源的真正决策者。这就是 Function Calling 的核心价值:把大模型的“大脑”与外界的“手脚”连接起来,让 AI 从聊天进入行动时代。
工作原理
店长拿到顾客的订单后,心里会快速盘算:这道菜该找炒菜台还是烧烤台?要不要备注免辣?这个“盘算”的过程,就是模型在做意图识别和调度决策。Function Calling 的工作原理并不神秘——它本质上仍然是“预测下一个 token”。当用户说“北京今天天气怎样”,模型在概率分布中“感觉”到:最像的下一个输出应该是一个 JSON 调用指令,指向 get_weather 函数。
具体来说,模型会在开发者提供的函数列表中做“隐式的选择题”。它先理解用户意图,再判断哪个函数与意图最匹配,然后按照函数定义中的 JSON Schema 约束,填充出合法的参数值。整个过程发生在一次前向推理中,模型没有真的“运行”任何代码,它只是生成了看起来最合理的结构化文本。真正执行代码的是应用层。
1. 符号 $f^*$:被模型最终选中的那个函数,例如 get_weather。
2. 候选集合 $\mathcal{F}$:开发者注册进上下文的全部工具函数,相当于后厨的岗位表。
3. 条件概率:$P_{\theta}(f, \text{args} \mid x, \mathcal{F})$ — 给定用户输入 $x$ 和函数清单 $\mathcal{F}$,模型评估“调用 $f$ 并传参 args”的概率。
4. argmax 决策:$\mathop{\arg\max}$ — 取出概率最大的那个组合作为最终的函数调用输出。
店长的“盘算”看似是思考,其实是经验直觉的快速匹配。大模型也一样——它不懂天气,也不懂数据库,但它见过海量“问题—函数调用”的配对文本,知道什么时候该把派工单递给哪个工作台。理解这一点,你就不会对模型“偶尔选错函数”感到意外了。
函数定义
后厨的岗位表写得越清楚,店长派工就越准。如果岗位表上只写“张三——做菜”,店长怎么知道张三擅长川菜还是粤菜?同样,函数定义就是写给模型看的“岗位说明”。一份高质量的函数定义包含函数名、描述信息和参数 Schema 三部分。函数名要见名知意,比如 get_weather 就比 f1 直观得多;描述信息要说明函数做什么、什么时候用;参数 Schema 则规定每个参数的类型、是否必填、取值范围。
以查询天气为例,函数定义大致是:函数名 get_weather,描述“查询指定城市的当前天气和温度”,参数含 location(字符串,必填)和 unit(枚举:celsius/fahrenheit,可选)。模型看到这个定义后,遇到“北京热不热”就能输出 {"name": "get_weather", "arguments": {"location": "北京"}}。如果描述写得含糊,模型就可能把天气查询误判成搜索函数。
1. name 函数名:模型的输出指令中用它来指定目标函数,命名要见名知意。
2. description 描述:一段自然语言说明,告诉模型“这个函数是干什么的、适合什么场景”。
3. parameters 参数约束:JSON Schema 对象,声明每个参数的类型(string/number/boolean)、必填性(required)和可选枚举(enum)。
一份好的“岗位说明书”能让店长少犯糊涂,一份好的函数定义能让模型少犯错误。多花十分钟打磨 description 和参数 Schema,比事后追着修正错误调用要划算得多——这是所有 Function Calling 实战老手的第一条心得。
调用流程
一张完整的派工单,要经历“写单—递单—做菜—端回”四个环节。Function Calling 的调用流程同样是一套标准四步舞:工具注册、模型输出、应用层执行、结果回传。第一步,开发者把函数定义清单注入系统提示词,相当于把岗位表贴在店长眼前;第二步,模型根据用户输入输出 JSON 格式的函数调用;第三步,应用层解析 JSON、校验参数、执行真实函数;第四步,把函数返回结果拼接到对话上下文,让模型基于结果生成最终答复。
1. 工具注册:把函数定义清单注入模型输入,让模型“知道”有哪些可用函数。
2. 模型输出:$\text{LLM 输出 } (f, \theta)$ — 模型生成的 JSON 中包含函数名 $f$ 和参数对象 $\theta$。
3. 应用层执行:$\text{执行 } f(\theta) = r$ — 不是模型运行函数,而是应用层代码执行 $f(\theta)$ 并得到结果 $r$。
4. 二次推理:$\text{LLM}(x, r)$ — 原始输入 $x$ 与工具结果 $r$ 拼接,模型继续生成最终回复。
注意第三步有一个容易混淆的点:在 OpenAI 等平台的 API 设计中,模型返回的 function_call 不会自动执行——平台把“做菜”这一步留给开发者自己。这也意味着,执行逻辑的健壮性(参数校验、超时处理、异常兜底)完全掌握在应用层手中。店长可以写错单子,但后厨必须有自己的把关。
与Agent关系
店长不是只派一张单就结束。如果顾客点了满汉全席,店长会连续写多张工单:先让甜品台上甜点,再让炒菜台上主菜,最后让传菜员确认上齐。这就是 Agent(智能体)的工作方式。Function Calling 是 Agent 的“手”——Agent 在循环中反复调用 LLM,让模型决定“下一步做什么”,如果模型决定调用工具,Agent 就执行工具并把结果拼回上下文,然后再次询问模型,如此循环,直到模型认为任务完成。
这个循环是所有 Agent 框架的底层骨架。无论是 LangChain 的 AgentExecutor、OpenAI 的 Assistants API,还是 AutoGPT 式的自主 agent,核心都是“模型决策 → 工具执行 → 结果回传 → 再决策”的循环。Function Calling 为这个循环提供了标准化的“决策输出格式”——统一的 JSON 结构让框架可以轻松解析并调度工具。
1. 状态 $s_t$:第 $t$ 轮的完整对话上下文,包含历史消息、系统提示词和之前的工具结果。
2. 执行工具:$\text{exec}(f_t, \theta_t)$ — 调用第 $t$ 轮模型选中的函数 $f_t$ 并传入参数 $\theta_t$。
3. 拼接符号:$\oplus$ — 将工具结果作为新的消息追加到上下文中,形成下一轮的状态。
4. 终止条件:$f_t = \varnothing$ — 当模型不再输出函数调用(即输出普通文本)时,循环结束。
店长“派单—确认—再派单”的循环,背后是后厨—店长之间的信任协作。Agent 之所以强大,正是因为 Function Calling 给了它一双可持续行动的手。理解“循环 + 工具 + 结果回传”这个三角结构,你就理解了 ReAct、Plan-and-Execute 等几乎所有 Agent 模式的本质。
实践要点
一家餐厅想要稳定出品,光靠店长记性好不够,后厨必须有流程规范。Function Calling 工程化落地的核心,是围绕“选得对、传得准、执行稳”三个目标建立防御体系。选得对,靠的是函数描述质量——避免模糊词汇,对易混淆的函数做差异化描述;传得准,靠的是参数 Schema 约束——声明类型、必填项、枚举值,模型输出后还要做一次 JSON 解析和类型校验;执行稳,靠的是错误处理——给函数调用加 try-catch、超时限制、重试机制,甚至把执行错误作为工具结果回传给模型,让它“自我纠错”。
1. 选对函数:$P(\text{选对函数})$ — 取决于 description 是否清晰、函数之间的区分度是否足够。
2. 参数合法:$P(\text{参数合法})$ — 取决于 JSON Schema 约束与应用层校验,防止模型输出“字符串但 Schema 要求数字”这类问题。
3. 执行成功:$P(\text{执行成功})$ — 取决于代码健壮性:异常捕获、超时、重试、降级方案。
安全边界同样不可忽视。对于敏感操作(删除数据、发消息、支付),应用层应当做二次确认或白名单过滤。后厨的刀具需要上锁,Agent 的工具也需要权限控制。记住一条铁律:模型输出的只是“建议指令”,最终能不能执行、怎么执行,决定权永远在应用层。
局限与挑战
店长偶尔也会犯迷糊——看错菜名、写漏配料。Function Calling 同样存在固有局限。第一个挑战是幻觉误调用:模型可能“编造”一个不存在的函数名,或者把用户意图错误映射到一个不相关函数上。这类问题难以彻底根除,只能通过高质量函数描述和输出校验来降低概率。第二个挑战是上下文消耗:工具定义和每次调用的返回结果都要拼进上下文,Agent 多轮循环会导致 token 成本快速膨胀。
1. 描述成本:$|\text{工具描述}| \times N$ — 函数定义清单每轮都会随请求发送,$N$ 是调用轮数,函数越多、轮数越长,开销越大。
2. 结果成本:$\sum_{i=1}^{N} |r_i|$ — 每轮工具返回的结果 $r_i$ 也会留在上下文中,累积起来不可忽视。
3. 约等号:$\approx$ — 实际成本还包含系统提示词、用户消息等,这里只给出了核心部分。
第三个挑战是并发与限流:当大量用户同时触发 Agent 时,外部 API 的频率限制和成本压力会非常明显,需要设计缓存、队列和熔断机制。第四个挑战是评估测试:工具调用链路比纯文本对话复杂得多,需要构建专门的评测集来判断“选对了哪个函数、参数是否精确、最终回答是否满意”。这些挑战不是劝退理由,而是工程化路上的必经关卡——知道店长会犯哪些错,才能设计出防错的后厨流程。
AI 应用场景
智能客服工单系统
阶段:意图识别与工具调度
解决的问题:传统客服需要人工查询订单系统、退换货规则等多个内部系统,响应慢且人力成本高。接入 Function Calling 后,大模型先识别用户意图,再调用订单查询、物流跟踪、售后政策等函数,自动完成信息聚合与答复生成。
具体案例:用户向电商客服发送“我的 iPhone 充电器什么时候发货?”模型识别到“查物流”意图,调用 get_order_status(order_id) 和 track_delivery(tracking_no) 两个函数,返回物流信息后生成自然语言答复。人工客服只需处理模型无法解决的异常工单。
数据分析智能体
阶段:多轮工具调用与 Agent 循环
解决的问题:业务人员想查“华东区 Q3 销量 Top5 商品”,传统 BI 工具需要手写 SQL 或拖拽报表。Function Calling 让模型动态生成 SQL 查询函数调用,并在循环中不断修正查询条件,直到得到满意结果。
具体案例:在 DataAgent 系统中,模型调用 query_sales_database(sql) 后得到结果,发现数据不够细,再调用 group_by_region(sales_table, "华东") 进一步下钻。多轮函数调用完成后,模型用图表描述总结结论,业务人员全程用自然语言操作。
智能家居语音助手
阶段:函数定义与安全边界的工程实践
解决的问题:用户说“把客厅灯调暗到 30%,空调开到 26 度”,传统语音助手依赖预定义的槽位填充(slot filling),泛化能力差。Function Calling 让模型灵活组合多个设备控制函数。
具体案例:模型输出两个函数调用:control_light(room="客厅", brightness=30) 和 control_ac(room="客厅", temperature=26)。应用层对敏感操作(如开锁)做权限校验,对设备控制加超时重试,执行成功后再统一回复“好的,都为您设置好了”。
Python 演示
import json def get_weather(location, unit="celsius"): """模拟查询天气的外部工具函数""" table = {"北京": ("晴", 25), "上海": ("多云", 28), "广州": ("雷阵雨", 31)} weather, temp = table.get(location, ("未知", 0)) if unit == "fahrenheit": temp = round(temp * 9 / 5 + 32, 1) return json.dumps({ "location": location, "weather": weather, "temperature": temp, "unit": unit }, ensure_ascii=False) def get_time(city="北京"): """模拟查询时间的工具函数""" table = {"北京": "14:30", "上海": "14:30", "广州": "14:30"} return json.dumps({"city": city, "time": table.get(city, "未知")}, ensure_ascii=False) FUNCTIONS = { "get_weather": "查询指定城市的天气温度,参数 location 为城市名", "get_time": "查询指定城市的当前时间,参数 city 为城市名"} def model_parse_function_call(user_input): """模拟大模型:把自然语言映射为结构化函数调用""" if "天气" in user_input or "温度" in user_input: location = "北京" for city in ("北京", "上海", "广州"): if city in user_input: location = city break unit = "fahrenheit" if "华氏" in user_input else "celsius" return {"name": "get_weather", "arguments": {"location": location, "unit": unit}} if "时间" in user_input or "几点" in user_input: city = "北京" for c in ("北京", "上海", "广州"): if c in user_input: city = c break return {"name": "get_time", "arguments": {"city": city}} return None def execute_function(call): """应用层执行真实函数调用""" if call is None: return "未找到合适的工具" name = call["name"] args = call["arguments"] if name == "get_weather": return get_weather(**args) if name == "get_time": return get_time(**args) return json.dumps({"error": "未知函数"}, ensure_ascii=False) def run_agent(user_input): """模拟 Function Calling 完整链路:意图 -> JSON -> 执行 -> 回传""" print("用户输入:", user_input) call = model_parse_function_call(user_input) print("模型输出的函数调用:", json.dumps(call, ensure_ascii=False) if call else "无") result = execute_function(call) print("工具执行结果:", result) final_answer = "根据查询结果:" + result print("模型最终回复:", final_answer) return final_answer if __name__ == "__main__": run_agent("北京今天天气怎么样?") print() run_agent("上海现在几点了?")
def model_parse_function_call(user_input):模拟大模型将自然语言映射为结构化函数调用的核心逻辑。return {"name": "get_weather", "arguments": {...}}模型输出的 JSON 结构:函数名 + 参数对象。def execute_function(call):应用层执行器:解析模型输出,调度真实函数执行。return get_weather(**args)将参数字典解包后传给真实工具函数,完成实际调用。def run_agent(user_input):编排函数:按“意图→JSON→执行→回传”的顺序模拟完整链路。if __name__ == "__main__":程序入口,展示两个典型场景的调用效果。
常见误区
误区“大模型调用工具,不就是模型自己跑代码、查数据库吗?我只需要把函数描述传给它就行。”很多初学者以为模型收到指令后会主动执行代码,就像人一样“动手操作”。
正解大模型本质上是一个“文本生成器”。它只是根据训练学到的模式,生成一段符合语法的 JSON 调用指令,就像店长写一张派工单。真正执行函数的是应用层代码——解析 JSON、校验参数、调用 API、处理异常,每一步都是开发者写的程序在干活。如果应用层不写执行逻辑,模型输出再多 JSON 也无人响应。
为何常见:因为“调用”这个词太有迷惑性,让人以为模型在做执行动作;加上 Agent 演示中工具自动运行的效果,更强化了“模型自己在动手”的印象。
误区“函数名用 f1、f2、ffa 这种短名,节省 token,大模型一样能理解。”于是把 description 写成“一个函数”甚至留空。
正解函数描述是模型判断“何时使用该函数”的最重要信号。描述越清晰、越能区分相近函数,模型选对的概率越高。比如 get_weather 的描述写“查询指定城市当天天气与温度,适用于天气相关提问”,模型就能把它与 get_time 区分开。函数名和描述是给模型看的“说明书”,省了这几行字,后面可能要付出错误的调用结果来偿还。
为何常见:开发者习惯了给人类同事写简洁的函数名,因为人类能结合上下文补全。但模型没有“项目背景知识”,它只能看到你给它的那几行描述。
误区“把天气、新闻、股票、日历全写进一个 process() 函数,用一个 type 参数区分,这样模型只需要选一个函数,多省事。”
正解单一职责是函数设计的黄金法则。函数职责越单一,模型越容易通过 description 理解它的用途,参数 Schema 也越简单、越不容易出错。把所有逻辑塞进一个大函数会让 description 变得冗长含糊,参数结构变成一个大杂烩,模型反而更容易选错或填错参数。多个功能就拆分成多个函数,哪怕只是多个薄包装。
为何常见:开发者想减少函数数量来降低模型的选择难度,但适得其反——选择难度的关键不在数量,而在每个函数是否清晰可辨。
误区“大模型很聪明,它输出的 JSON 肯定是对的,直接拿去调用外部服务就行,不用校验。”
正解模型是概率生成器,偶尔会输出非法 JSON、参数名拼写错误、类型与 Schema 不匹配,甚至编造不存在的函数名。应用层必须做防御性校验:JSON 解析失败时要求模型重试,参数缺失时用默认值补齐,非法调用则阻止执行。更要把执行异常作为结果回传给模型,让它有机会自我纠正。把大模型当成一个“聪明但偶尔犯晕”的店长,后厨一定要有自己的把关。
为何常见:模型的输出太像正确代码了,而且 demo 中通常恰好成功,让人产生“每次都正确”的错觉。
误区“上一轮已经调用过 get_weather 了,这轮再问天气时,模型应该记得上次传了什么参数,我不用再传一遍工具定义。”
正解大模型没有跨请求的记忆。每轮请求都只包含当前上下文中的内容——工具描述、历史消息、之前的结果都会被拼进 input。如果应用层不把历史工具结果追加到消息列表,模型就“失忆”了。Agent 框架之所以能“记住”多轮调用,正是因为每一轮的完整记录都被拼回了上下文,同时受上下文窗口长度限制。
为何常见:人类有持续记忆,容易把模型拟人化,以为它记得一切对话历史。实际上模型每轮都是从零开始“重新阅读”整个上下文。
面试题
Q1. Function Calling 中模型输出的核心指令格式是什么?
- A.一段自然语言描述文本
- B.结构化 JSON 函数调用← 正确答案
- C.二进制编码的工具指令
- D.高维向量嵌入表示
答案:B。Function Calling 的核心是让模型输出结构化 JSON,包含函数名和参数对象。自然语言描述无法被程序可靠解析,二进制和向量表示也不是 API 层的标准输出。这就像店长写的派工单必须是“岗位名+菜名”的结构化格式,后厨才能按单执行。
Q2. 在 Function Calling 完整流程中,实际执行函数代码的是谁?
- A.大模型自身推理引擎
- B.应用层的业务代码← 正确答案
- C.操作系统的进程调度
- D.用户的浏览器插件
答案:B。模型只负责输出 JSON 指令,真正执行函数的是应用层代码。这对应餐厅里“店长写单、厨师做菜”的分工——模型是决策者,应用层是执行者。操作系统和浏览器插件都不是标准的函数执行主体。
Q3. 函数定义中的 description 字段最关键的作用是什么?
- A.设定函数的调用权限级别
- B.帮助模型选择合适的函数← 正确答案
- C.规定函数的超时时间上限
- D.决定函数返回值的类型
答案:B。description 是模型判断“何时该用这个函数”的核心依据,相当于岗位说明书。权限由应用层控制,超时是执行层的配置,返回类型由参数 Schema 之外的实际代码决定,都与 description 无关。
Q4. 模型输出的 JSON 中参数类型为字符串,而 Schema 声明为数字,应用层应当如何处理?
- A.直接将该参数丢弃并报错
- B.做一次类型转换和合法性校验← 正确答案
- C.返回错误后强制结束对话
- D.让模型重新预训练模型参数
答案:B。模型是概率生成器,偶尔会输出与 Schema 不一致的参数。成熟的应用层应该做类型转换尝试,失败则用默认值或要求模型重新输出,而不是直接崩溃。这就像后厨收到字迹模糊的工单,应该先跟店长确认,而不是扔掉工单。
Q5. Agent 循环中,工具调用结果被回传给模型后放在哪里?
- A.模型的训练数据集中
- B.对话上下文消息队列中← 正确答案
- C.系统的持久化数据库仓库
- D.独立于进程的内存空间中
答案:B。工具结果会作为一条新消息追加到对话消息列表,随下一轮请求一起发给模型。模型每轮只“看”上下文里的内容,不会把工具结果写入训练集或记忆库。这相当于传菜员把菜端回店长面前,店长看到后再决定下一步。
Q6. 下列哪种做法最有利于模型“选对”函数?
- A.将函数名全部改成简短缩写
- B.写清晰描述并提供调用示例← 正确答案
- C.把所有函数合并成一个大函数
- D.随机打乱函数清单的排列顺序
答案:B。清晰的 description 和示例能显著提升模型的选择准确率。缩写函数名、合并大函数、乱序排列都会增加模型的理解难度或引入不确定性。函数名应见名知意,描述要具体,职责要单一,这些才是“选对”的关键。
Q7. 以下哪些属于 Function Calling 的典型应用场景?
- A.查询实时天气信息← 正确答案
- B.检索数据库用户订单记录← 正确答案
- C.直接修改模型内部网络权值
- D.调用第三方接口发送通知消息← 正确答案
答案:ABD。Function Calling 适合连接外部工具和 API——查天气、查数据库、发消息都是典型应用。修改模型内部权值属于训练范畴,不可能也不应该通过工具调用来实现。工具调用是在模型外部发生的动作,模型本身不会因为调用而改变参数。
Q8. 关于函数参数 Schema 的约束能力,下列说法正确的有哪些?
- A.可以声明参数的具体类型约束← 正确答案
- B.可以标记参数是否为必填项← 正确答案
- C.可以限定参数的枚举取值集合← 正确答案
- D.可以直接执行任意系统级命令
答案:ABC。JSON Schema 支持类型(string/number)、必填(required)和枚举(enum)等约束,这些都能指导模型生成更规范的参数。但 Schema 只是“描述”约束,不具备执行能力——执行任意系统命令是应用层代码的功能,与 Schema 无关。
Q9. 下列哪些措施能有效提升 Function Calling 的系统可靠性?
- A.对模型输出先做 JSON 解析校验← 正确答案
- B.为函数执行添加超时与重试机制← 正确答案
- C.通过白名单过滤可用函数范围← 正确答案
- D.完全信任模型输出不设防御逻辑
答案:ABC。JSON 校验防止非法输出,超时重试应对工具不稳定,白名单过滤防止模型访问敏感函数——这三者构成可靠性防线。完全信任模型输出是危险做法,因为模型可能幻觉出不存在的函数名或错误参数,必须由应用层做最后把关。
Q10. 关于 Function Calling 的局限与挑战,下列说法错误的是哪一项?
- A.模型可能幻觉出不存在的函数名
- B.工具描述会持续消耗上下文 Token
- C.高并发场景需要设计合理的限流策略
- D.函数调用完全不受上下文长度限制← 正确答案
答案:D。幻觉误调用确实是已知风险,工具描述注入确实增加 Token 开销,高并发下也确有限流需求。但“不受上下文长度限制”是错的——工具描述和轮次结果都存放在上下文中,一旦超出窗口长度,早期的工具结果会被截断丢弃,Agent 的“记忆”也随之消失。