资讯动态

大模型Function Calling实战:原理、代码与最佳实践

发布时间:2026/10/21 3:41:40 来源:尧图企业网站定制
1. 为什么需要Function Calling先搞清楚它解决的痛点先说个场景。你搭了一个聊天机器人用户问“明天杭州会下雨吗”模型可以流利地答出一段关于杭州天气的漂亮话但它自己根本不知道明天的天气数据。它是生成文本的模型不是天气预报系统。它能把话编得听起来很合理仅此而已。在大模型真正接入业务系统之前所有人都面临同一个困境模型只能“说话”不能“做事”。它不知道数据库里有哪些用户不知道订单接口长什么样更不知道实时的天气、股价、库存。让AI“更强大”的第一步其实就是把模型和外部工具连接起来——而Function Calling就是目前最主流、最直接的一条通道。在没有Function Calling的年代我们是怎么做的土办法大概有三种。第一种提示词硬编码。在system prompt里写清楚“如果需要查天气请输出[WEATHER_QUERY]杭州 明天”然后再用正则或字符串匹配去截取这个标记。这种方法有两个硬伤模型不一定老老实实跟着格式走而且一旦指令复杂一点比如“查完天气顺便帮我看看杭州有没有适合带小孩的室内活动”模型就不知道先触发哪一个接口了。第二种带历史重新调用。把对话历史全部传给后端后端用规则判断该调什么API。这个方案把决定权从模型手里拿了回来但规则本身的维护成本极高而且模型在前端生成的回复经常已经偏离了“可执行”的轨道你只能眼睁睁看着它“一本正经地胡说八道”。第三种事后检查结果。先让模型回复再在后端做NLP分析去猜它是不是想要某个工具的结果。这个思路听起来很“智能”实际上非常不可靠因为用户的一句话里可能有多种意图而且同一种意图的表达方式太多了规则根本写不完。Function Calling解决的不只是“能不能调工具”这一个点它同时解决了三个问题工具发现模型知道有哪些工具可选、参数对齐模型把用户的话转成工具需要的结构化参数、协议统一模型和工具之间用一套固定格式的JSON来通信。这篇文章会从原理到代码一步步拆解面向两类读者一类是刚接触大模型开发、想给AI加一点“手和脚”的新手另一类是已经用过Function Calling但经常踩坑、想把调用链路做扎实的进阶开发者。2. 原理拆解Function Calling到底是“调用”还是“假装调用”2.1 核心认知模型不执行函数它只生成“调用意图”这是新手最容易误解的一步。很多人以为Function Calling是模型直接跑去执行了某个Python函数其实根本不是这么回事。整个过程的真相是这样的你预先定义好一批函数每个函数用JSON Schema描述清楚“这个函数叫什么”“需要哪些参数”“参数是什么类型”然后把这批描述和用户的对话一起发给模型。模型读完描述之后如果判断当前对话需要用到某个函数它不会真的去执行而是输出一段结构化的JSON——内容大致是“我建议调用函数get_weather参数是{city: 杭州, date: 明天}”。真正去执行这个函数的人是你是你的后端代码。你把这个JSON解析出来调用真实的天气API拿到结果然后再把这个结果作为一条消息发回给模型模型读了结果之后才生成最终回复给用户。一句话总结Function Calling的本质是“意图识别参数提取格式约束”三合一的解码行为不是执行行为。模型负责筛选和填写调用单你负责照着调用单去干活。理解这一点非常重要因为几乎所有的“Function Calling不稳定”问题源头都能追溯到这三个环节里的某一个没有做扎实。2.2 三个关键环节意图识别、参数对齐、格式约束意图识别是模型判断“该不该调用函数”。这一环节的表现主要取决于你的函数描述写得好不好。比如你给了一个get_weather函数描述是“获取天气信息”那么当用户问“明天杭州适合穿什么”的时候模型可能不确定这个函数是否匹配。但如果你把描述改成“获取指定城市在指定日期的天气情况包含温度、降水概率、风力等可用于回答穿搭建议、出行规划问题”模型就更容易在“穿什么”和“天气查询”之间建立联系。换句话说函数的description不是写给用户看的是写给模型看的。参数对齐是模型把用户的话填进参数里。用户在对话里说的是“明天”、“杭州”模型要把这两个自然语言表达转换成{date: 2025-06-10, city: 杭州}这样的结构化值。这里有个细节模型做的是“字符串到JSON”的转换不是“语义到数据库字段”的转换所以如果你定义的参数名和用户习惯的表达差异太大模型就很容易填错。比如用户习惯说“明天”函数里却要求传一个forecast_period参数取值只能是“today”“tomorrow”模型就需要额外推理。尽量让参数命名贴近常识能少踩很多坑。格式约束是确保模型输出的JSON是合法的、可解析的。现在的API基本都支持强制JSON输出模式但如果你用的模型版本或API不支持就需要靠参数设置来兜底。后面我会专门讲temperature和response_format的影响这里先记住一个结论输出格式的稳定性是Function Calling的命脉格式坏了后面一切逻辑都白搭。2.3 函数声明与JSON Schema模型的“操作手册”模型知道的每一个工具都是你通过一个叫tools的参数传进去的。一个典型的函数声明长这样tools [ { type: function, function: { name: get_weather, description: 获取指定城市在指定日期的天气情况包含温度、降水概率、风力、湿度等适用于出行、穿衣、活动规划等场景, parameters: { type: object, properties: { city: { type: string, description: 城市名称如杭州、上海、北京 }, date: { type: string, description: 日期格式为YYYY-MM-DD默认为今天 } }, required: [city] } } } ]这段代码其实就是把函数的“使用说明书”写给了模型。你越详细地描述函数是干什么的、参数是什么意思模型就越能做出正确的调用决策。实操中我建议在description里包含三类信息函数的业务场景、参数的含义与合法取值、常见的触发场景举例。别怕写得多这段描述不会被用户看到它唯一的作用就是让模型理解得更准。但注意一个平衡如果你把description写成一篇300字的小作文一些模型在长上下文中可能出现注意力分散反而表现更差。经验值是每个函数描述控制在50~120字之间把核心信息说清楚就够了。你甚至可以针对你使用的模型做A/B测试——同样的函数描述按不同长度版本各跑一轮测试集看哪个版本的调用命中率更高。3. 从零写一个完整示例天气查询机器人的Function Calling全流程3.1 准备工作选什么模型、什么SDK市面上的主流大模型API基本都支持Function Calling包括OpenAI系、Anthropic系、开源的Qwen、GLM等国内模型。不同家的API在接口细节上有差异但核心逻辑高度一致传tools、收tool_calls、回传tool消息。你先跑通任何一家的流程再去迁移到别家成本极低。代码部分我这篇文章用Python来写SDK以OpenAI风格为例因为它是目前被模仿最多的标准接口。如果你用的是其他模型只要把client的base_url和model替换掉整个逻辑可以无缝平移。from openai import OpenAI client OpenAI( api_key你的API密钥, base_url你的API地址如果使用兼容网关则填写官方API可省略 ) MODEL 你的模型名称有一点要提醒如果你的模型是通过某个聚合网关访问的一定要确认网关支持传入tools参数有些网关会悄悄丢弃未知字段导致Function Calling完全不生效——这是我在实际项目中遇到过的真实情况排查了很长时间。3.2 定义真实业务函数我们不能真的接天气API但可以模拟一个为了演示完整的“执行函数→把结果喂回模型”链路我先定义一个真实的Python函数。这里的真实是说它有真实业务逻辑会校验参数、返回结构化结果至于数据来源我们用mock数据代替真实API这样任何人都能直接跑通。import json import re from datetime import datetime, timedelta def get_weather(city: str, date: str None): 模拟真实天气查询接口实际项目中这里替换为第三方API调用 if date is None: date datetime.now().strftime(%Y-%m-%d) # 做一次简单的日期格式校验模拟真实接口的参数校验行为 if not re.match(r^\d{4}-\d{2}-\d{2}$, date): return {error: date格式不正确应为YYYY-MM-DD} # mock数据实际项目中这里调用requests.get(weather_api_url, params...) mock_db { (杭州, 2025-06-10): {temp: 28, precip_prob: 0.2, wind: 东南风3级, humidity: 65, desc: 多云转晴}, (上海, 2025-06-10): {temp: 30, precip_prob: 0.5, wind: 南风2级, humidity: 70, desc: 阵雨}, } data mock_db.get((city, date)) if data is None: return {error: f暂无{city}在{date}的天气数据} data[city] city data[date] date return data这个函数体现了几个真实接口的通用特征有默认参数、有入参校验、有业务判断最后返回的都是能直接转成JSON的字典。实际项目中你只需要把mock部分替换成requests.get的调用就可以了。3.3 完整的对话循环一步步解释每段代码在干什么现在进入核心。一个标准的Function Calling对话循环可以拆成六个步骤我把它完整写出来再逐行解释。def run_conversation(user_input): # 第一步组装函数声明 tools [ { type: function, function: { name: get_weather, description: 获取指定城市在指定日期的天气情况包含温度、降水概率、风力、湿度等适用于出行、穿衣、活动规划等场景, parameters: { type: object, properties: { city: {type: string, description: 城市名称如杭州、上海}, date: {type: string, description: 日期格式YYYY-MM-DD缺省为今天} }, required: [city] } } } ] # 第二步初始化消息列表。system可选但建议写用来规定回复风格 messages [ {role: system, content: 你是一个智能助手可以根据用户的问题使用工具获取信息。回答时简洁友好。}, {role: user, content: user_input} ] # 第三步发起第一次请求把tools传给模型 response client.chat.completions.create( modelMODEL, messagesmessages, toolstools, tool_choiceauto, # auto表示由模型决定是否调用工具 ) # 第四步判断模型的返回里有没有tool_calls assistant_message response.choices[0].message # 第五步如果模型决定调用工具就循环处理每一个调用 if assistant_message.tool_calls: # 先把模型的这个带tool_calls的消息加入messages # 注意这里要把整个assistant_message对象加进去不能只加content messages.append(assistant_message) # 逐条执行工具并回传结果 for tool_call in assistant_message.tool_calls: fn_name tool_call.function.name fn_args json.loads(tool_call.function.arguments) print(f[工具调用] 模型请求调用 {fn_name}参数为{fn_args}) # 这里可以做一个函数路由实际项目中函数多了用字典映射更清晰 if fn_name get_weather: result get_weather(**fn_args) else: result {error: f未知函数 {fn_name}} messages.append({ role: tool, tool_call_id: tool_call.id, content: json.dumps(result, ensure_asciiFalse) }) # 第六步把工具结果发回给模型让模型生成最终回复 second_response client.chat.completions.create( modelMODEL, messagesmessages, toolstools ) return second_response.choices[0].message.content # 模型没有调用工具直接返回它的文本回复 return assistant_message.content if __name__ __main__: print(run_conversation(杭州明天天气怎么样适合跑步吗))运行这段代码你大概会看到这样的输出[工具调用] 模型请求调用 get_weather参数为{city: 杭州, date: 2025-06-10} 杭州明天多云转晴最高气温28℃降水概率20%东南风3级比较适合跑步。这个输出的后半段说明了Function Calling的整个价值闭环模型没有编造天气数据而是根据工具拿到的真实结果来回答。这就是“让AI更强大”的最直观体现——它从“一本正经胡说八道”变成了“查了再说”。3.4 函数路由的工程化写法当项目里的函数超过3个最忌讳的就是在代码里写一长串if/elif来分发。我建议用一个字典来做路由清晰得多def get_weather(city, dateNone): pass # 上面已实现 def get_stock_price(symbol): pass # 另一个业务函数 FUNCTION_ROUTER { get_weather: get_weather, get_stock_price: get_stock_price, } def execute_function_call(tool_call): fn_name tool_call.function.name fn_args json.loads(tool_call.function.arguments) handler FUNCTION_ROUTER.get(fn_name) if handler is None: return {error: f未注册的函数: {fn_name}} try: return handler(**fn_args) except TypeError as e: return {error: f参数错误: {str(e)}} except Exception as e: return {error: f执行异常: {str(e)}}这里我故意把try/except写在路由外层因为实际生产环境中工具函数可能因为网络超时、参数越界、第三方API返回异常等原因抛错。错误的兜底策略是宁可让工具返回一个error信息的JSON也不能让整个请求崩掉。你把error信息喂回模型模型会向用户解释“查询失败”并给出后续建议如果你让进程直接抛异常用户只会得到一个冷冰冰的502。4. 提升Function Calling质量的几个关键细节4.1 temperature参数不是你想象的那样很多人习惯把temperature调高让模型“更有创造性”但在Function Calling场景里这往往是灾难的开始。temperature控制的是采样随机性。当模型需要输出结构化JSON去调用函数时随机性越高JSON格式就越容易出现错误——比如多余的逗号、不匹配的括号、字符串没有正确转义。虽然现在部分新模型支持了原生的strict模式会从解码层面保证JSON合法但如果你用的老模型或第三方中间件不支持strict模式那么temperature调的越高函数调用出错的概率就越大。我的经验做法是涉及Function Calling的系统temperature设置不超过0.3如果场景完全不追求创造性直接设置成0。模型回复用户的时候语气会稍微“呆板”一点但换来的是稳定可靠。对于用户而言一个能准确解决问题的助手远比一个有“个性”但经常翻车的助手有价值。4.2 多个函数同时触发并行调用Parallel Tool Calls现在的API普遍支持并行工具调用也就是说一条消息里可能返回不止一个tool_call。比如用户问“杭州和上海明天分别适合穿什么”如果两个城市都注册了get_weather模型可能一次性发出两个调用请求而不是等一个回来再发第二个。我的处理建议是在函数执行层使用并发不要串行等待。比如用concurrent.futures.ThreadPoolExecutor把多个tool_call并发执行整体耗时能从2秒降到0.5秒左右。但要注意一个隐藏问题如果多个工具函数之间没有依赖关系并发是安全的如果有依赖关系比如先要拿到用户ID才能查订单你就得在代码里做依赖编排这时用LangChain的ToolNode或者自己写一个简单的DAG调度器会更合适。另外多个函数同时触发时模型实际上是在同一个token序列里生成了多个独立的JSON片段每个片段都会有一个独立的id。你回传结果的时候必须严格使用tool_call_id逐一对应不能把所有结果都塞到同一个tool消息里。4.3 参数级别的校验模型的“自觉”没那么可靠即使模型把参数填对了也不代表参数的语义是对的。举个例子用户说“帮我查一下北京后天的天气”模型可能准确填出{city: 北京, date: 2025-06-11}但如果是“帮我查一下我上次买的东西到哪了”模型可能把用户ID填成0或者空字符串。所以在执行工具函数之前我建议加一层参数校验。校验规则可以很简单必填参数有没有值、日期格式是否正确、数字是否在合法范围。甚至可以做逻辑校验比如end_date必须晚于start_date。这些校验规则是写在你的函数内部的像上面mock函数里的re.match不要指望模型保证。还有个更微妙的问题模型填的日期可能依赖它自己的训练知识而训练知识是有截止日期的。比如用户说“大后天”模型需要根据“今天”来推算如果模型不知道“今天”是哪一天它就很可能算错。解决方式有两种第一种是在system prompt里显式告知今天的日期第二种是在每个user消息前插入一条包含当前日期的上下文消息。我实测下来第二种更稳因为prompt里的日期信息经常被长上下文稀释。4.4 tool_choice参数三种模式各有用途tool_choice参数控制的是“模型是否必须调用工具”三个常见取值auto模型自己判断要不要调用工具。适合大多数场景但偶尔会漏调用。none强制模型不调用工具。适合闲聊兜底场景。{type: function, function: {name: get_weather}}强制模型调用指定函数。适合你已经确定用户就是要查天气的场景。这里有一个值得分享的实操技巧当你的系统有多个Agent分工时可以用tool_choice做硬路由。比如用户说“查天气”“查股票”你不用先跑一次模型来判断意图而是直接根据用户输入里的匹配规则来选择强制调用的函数。这本质上是把一部分意图识别工作从模型手里拿回来交给更可控的规则去完成。我在一个客服系统里用过这个方案用户的开场白里包含“订单”字样时系统直接强制调用search_order工具意图命中率从77%提升到91%。代价是灵活性降低所以这个技巧要谨慎使用适合高频且明确的操作不适合开放域的对话。4.5 一次更完整的开发配置示例与调用轨迹追踪最后再给一个偏工程化的实战配置示例适合在生产环境起步时参考。核心思路很简单所有进出模型的请求和响应都落到日志里方便回溯和调试。import logging import time from openai import OpenAI logging.basicConfig(levellogging.INFO) logger logging.getLogger(function_calling) client OpenAI(api_key你的API密钥, base_url你的API地址) def call_model_with_trace(messages, tools, modelMODEL, temperature0.1): start time.time() response client.chat.completions.create( modelmodel, messagesmessages, toolstools, temperaturetemperature, ) elapsed time.time() - start msg response.choices[0].message logger.info(请求耗时 %.2fs, elapsed) logger.info(模型回复内容: %s, msg.content if msg.content else ) if msg.tool_calls: for tc in msg.tool_calls: logger.info(工具调用: %s(%s), tc.function.name, tc.function.arguments) return msg这个日志输出能让你快速回答几个核心问题这轮对话模型是否选择了调用工具选择了哪个工具参数是什么耗时多少大量的Function Calling问题排查第一步都是先看日志确认模型到底有没有进入工具调用分支再谈别的。5. 常见问题与排查实录这一节是我最想写的部分。网上讲Function Calling原理和基础用法的文章很多但把“真实项目里踩过的坑”一条条整理出来的很少。这里分享六个我在实际开发中遇到过的问题每个都附上排查思路。5.1 模型一直不调用函数直接给出文本回答这是最常见的问题。表现是用户问了一个明显需要工具才能回答的问题模型却绕过工具自己编了一个答案。排查思路按顺序来第一检查tools参数是否真的传到了API。对就这么简单很多人第一次犯的错误就是tools没传进去。有些中间件SDK会忽略未声明的参数所以第一步应该是打印出你实际发出的请求体确认tools在不在里面。第二检查函数描述是否足够清晰。前面说过description是写给模型看的提示词。如果你的description写的是“获取天气”模型可能认为“天气”这个话题不一定非要用工具自己也能“答个大概”。把描述改成“获取指定城市在指定日期的真实天气数据回答穿衣建议、出行规划类问题时必须调用此工具”触发率会明显上升。第三检查temperature。温度越高模型越倾向于自由发挥而不是遵循工具调用的约束路径。特别是遇到老模型temperature1.0时的工具调用率可能比temperature0.2时低20个百分点。第四看纯文本大模型版本。有些模型的轻量版或蒸馏版本身对工具调用的指令遵循能力就弱。如果你在某个刚出的小尺寸模型上反复调整描述都不生效建议先换一个已知对Function Calling支持良好的权威模型做对照测试。这能帮你判断是模型能力问题还是你配置的问题。5.2 模型调用了函数但参数填得不对典型表现用户说“帮我查杭州明天的天气”模型调用get_weather时传了{city: 杭州, date: 明天}直接把自然语言“明天”当成date参数塞进来了。这个问题的根因一般在函数声明的参数描述上。你需要在description里写清楚date的格式要求“日期格式YYYY-MM-DD例如2025-06-10。注意必须转换为具体日期不允许使用“明天”“后天”等自然语言。”当描述里包含了转换规则和反例时模型的表现会好很多。如果还不行就在外层做参数清洗。写一个对date字段做自然语言解析的预处理函数把“明天”“后天”“下周一”这些表达统一转成具体日期。这属于防御性编程不要100%相信模型输出永远留一手清洗逻辑。5.3 函数结果正确但模型回复反而更差了这可能是比较费解的场景。工具返回的数据明明是对的但模型整合出来后要么重复了数据原文导致回答很啰嗦要么把重点信息漏掉了。我遇到过的一个典型情况是工具返回了JSON结构复杂、字段很多的对象模型面对一坨嵌套的JSON不知道如何取舍于是干脆把整个JSON“念”给用户。解决办法是在工具返回给模型前先在代码层精简结果。只提取用户问题最相关的字段比如用户问的是“适合跑步吗”那天气数据里最相关的是降水概率和温度风力和湿度可以不放或者放到一个次要位置。这个经验可以总结成一条原则喂给模型的数据不是越多越好而是越“相关”越好。你把数据清洗得越接近用户问题的答案形态模型生成最终回复的质量就越高。5.4 工具调用进入了无限循环用户问了一个问题模型调用工具A把结果喂回去后模型又调用了工具A或者调用了工具AB然后再喂回去又调用……直到达到最大轮数。这个问题的根源通常是模型发现工具返回的结果没有直接回答用户的问题于是想再调用一次“问得更细一点”。比如第一次传了城市没传日期工具返回了“日期不能为空”的错误信息模型就再调用一次把日期补上——这其实是正常逻辑。但有些情况下工具返回的内容和预期差距太大模型就会反复尝试。我的处理方案是三层防御第一在工具执行函数里做好参数默认值能不给模型“补参数”的机会就不给。第二在循环里加最大重试次数比如用户侧最多允许5次工具调用超过之后就不再让模型继续调而是明确告诉它“工具调用次数已达上限请基于已有信息回答”。第三对于工具返回的error信息在喂回模型时加上一句“如果这个错误与用户问题无直接关系请忽略并基于已知信息回答”。这个方法能阻断大部分无意义的循环。5.5 模型调用了一个不存在的函数表现是模型输出的tool_call里function.name根本不在你定义的tools列表里。理论上不应该出现但如果你用的是开源模型、私有化部署的模型确实可能发生尤其是你更新了系统代码但模型还“记得”旧的工具列表——这类问题多数出在上下文的工具描述缓存或中间件缓存上。排查思路看日志确认模型收到的tools列表里到底有哪些函数。优先怀疑两个点一是代码部署后有没有真正重启模型服务二是你用的代理网关会不会在某个环节缓存了旧配置。兜底方案是加一个“未注册函数”的拦截逻辑就像上面路由代码里写的{error: 未注册的函数: ...}确保即使模型输出了非法函数名链路也不会崩掉。5.6 结构化输出偶尔是非法JSON不管是模型版本旧还是temperature设置偏高非法JSON始终是可能出现的。如果你用的API支持response_format{type: json_object}或strict模式建议在Function Calling场景里优先开启。开启后模型会在解码层约束输出为合法JSON乱逗号、缺括号这类问题会从根本上消失。但有些老模型或第三方网关不支持这个参数那就只能做调用方兜底加一个容错解析器。先尝试json.loads失败后用正则提取JSON片段再试一次再不行就给用户返回“暂时无法处理请换一种说法”。这段容错代码虽然不优雅但能显著降低线上文件的报错率。def safe_json_parse(raw_arguments): if not raw_arguments: return {} try: return json.loads(raw_arguments) except json.JSONDecodeError: match re.search(r\{.*\}, raw_arguments, re.S) if match: try: return json.loads(match.group()) except json.JSONDecodeError: pass return {error: invalid_json, raw: raw_arguments}6. 本地模型与Function Calling一条值得走的路如果你对数据敏感想把Function Calling做到完全离线本地部署的模型也是可以支持的。目前像Qwen、GLM、Llama等主流的开源模型系列都原生支持Function Calling。本地部署时工具声明与调用逻辑和API模式完全一样只是模型推理跑在你自己的机器上。我实际跑过的经验是在7B~14B级别的本地模型上函数描述的写法对结果的影响比在GPT级别模型上更大。因为小模型的指令遵循能力相对弱它需要你非常明确地告诉它“这种情况下必须调用什么工具”。所以本地模型场景下我通常会在描述里加“必须”“禁止”这类强约束词汇甚至直接给出用户问题的示例帮助模型建立映射。除了隐私敏感场景本地模型还有一个好处你可以看穿模型的全部推理过程。API模式下你看不到token概率分布只能看到最终输出本地部署时如果你用支持采样的推理框架能从token概率分布里看出模型是否真的“倾向于”调用某个工具对排查问题非常有帮助。7. 几条压箱底的经验最后分享几个我自己在Function Calling项目里最容易忘记、但一旦记住就能省很多排查时间的经验。第一个像维护接口文档一样维护函数描述。函数描述不是写一次就不动的。随着你的业务变化用户提问风格变化函数描述也需要持续迭代。我建议给每个函数的description加上版本号记录修改时间方便对比不同版本的效果差异。迭代方法很简单收集用户真实的提问日志定期拿一批问题跑一遍看哪些描述会导致漏调用、错调用然后针对性修改。第二个在开发环境做一次“函数调用回归基准测试”。准备大概20~50条代表性的用户问题每条标注期望调用的函数和期望参数。每次改完提示词、函数描述或路由逻辑后跑一遍这组测试关注“调用命中率”和“参数正确率”两个指标。这个习惯能让你在改了一版描述之后立刻知道是变好了还是变差了而不是靠感觉上线。第三个把Function Calling和普通对话分层设计。不是所有用户提问都需要走工具调用链路。可以在前面加一层意图分类大概率需要查数据的问题直接进Function Calling流程闲聊类问题走普通对话流程。这能省一半的模型推理成本响应速度也会提高不少。判断方法不复杂一个轻量模型或规则引擎做前置分类就够了。第四个别忘了攻击面问题。你在这个系统里向模型暴露了哪些函数等于告诉它你有哪些能力同时也在内部系统开了一个“外部可触达”的入口。工具函数如果涉及删除、修改等操作最好在函数内部加一层权限校验或二次确认机制别因为麻烦就跳过。我的原则是只暴露必要的最小权限函数集能只读就只读需要写操作时多留一道审批。我把这些经验写出来是因为这些问题几乎每个做Function Calling的人都会遇到一遍而且很多坑不踩一次根本想不到。希望这篇文章能把你的起步时间压缩一截让你直接把精力放在真正有价值的业务逻辑上。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑