Function Calling 原理与工程落地

📅 2026/7/1 20:16:35
Function Calling 原理与工程落地
1. Function Calling 到底是什么Function Calling 不是让大模型自己去联网、查库、发请求。大模型本身并不会直接执行代码它做的是“决策”判断当前问题是否需要调用工具如果需要就按照开发者提前定义好的 JSON Schema输出一段结构化的调用请求。真正执行动作的是你的后端代码。它拿到模型输出的函数名和参数后再去查数据库、请求 API、调用内部服务最后把工具返回结果塞回对话让模型基于真实结果生成最终回答。用一句话概括Function Calling 是把用户的自然语言意图翻译成后端系统可以安全执行的结构化函数调用。2. 它解决的不是“聊天”而是“行动”普通大模型回答问题本质是在生成文本。可是业务系统里很多需求不是“回答一句话”就够了而是要完成一个动作查订单、订会议室、改地址、拉报表、发短信、创建工单。如果没有 Function Calling开发者只能让模型输出“我需要查询订单”再靠关键词、正则或 if/else 去猜模型想干什么。这种方式最大的问题是不可控模型说法稍微换一下后端解析就可能失败工具一多判断逻辑会越来越乱。Function Calling 的核心变化是模型不再用自然语言“描述动作”而是输出机器可解析的 tool_calls。它把“我要查北京天气”变成 get_weather({city: 北京})。这一步看似简单却把大模型从聊天窗口拉进了真实业务系统。3. 三个角色开发者、模型、宿主代码理解 Function Calling先把三个角色分清楚。开发者负责写工具说明书也就是工具 Schema。它告诉模型有哪些工具每个工具能做什么什么时候该用需要哪些参数参数有什么限制。模型负责读说明书然后判断当前用户问题是否需要工具。如果需要它输出结构化调用请求包含函数名和参数。宿主代码负责真正执行。它要校验参数、鉴权、路由函数、调用外部 API、处理超时和异常再把结果返回给模型。开发者定义工具边界控制哪些能力能被模型看到。模型选择工具并生成参数但不直接执行任何动作。宿主代码执行真实函数并承担安全、权限、稳定性责任。4. 工具 Schemadescription 不是注释是决策依据工具 Schema 可以理解成给模型看的接口文档。它不只是为了让后端解析更重要的是帮助模型判断“该不该调用这个工具”和“参数应该怎么填”。其中最容易被低估的是 description。很多人只写“查询天气”“查询订单”这会导致模型误调。更好的写法是把工具边界、适用场景、不适用场景、参数格式、限制条件都写清楚。如果工具用于生产系统建议尽量启用严格模式并把参数约束写进 Schema而不是只靠 prompt 口头提醒。OpenAI 官方文档也建议使用 strict mode让函数调用更可靠地遵循 Schema严格模式下还要求对象设置 additionalProperties: false并把 properties 中字段列入 required。5. 一个完整的工具定义示例下面这个例子用的是 Chat Completions 风格。重点不在模型名称而在工具定义结构name 要稳定description 要讲清边界parameters 要明确类型、枚举、必填字段和 additionalProperties。tools[{type:function,function:{name:get_weather,description:(查询中国大陆城市的实时天气。仅用于用户明确询问当前天气、温度、风向、湿度。不支持未来多日预报。city 必须是中文城市名。),parameters:{type:object,properties:{city:{type:string,description:城市名称例如 北京、上海不要带省份},unit:{type:string,enum:[celsius,fahrenheit],description:温度单位默认使用 celsius}},required:[city,unit],additionalProperties:False},strict:True}}]这个 Schema 的价值在于它把“模型可能会猜”的地方尽量变成了“系统明确规定”。模型如果要调用 get_weather就必须给出 city 和 unit不能随便生成未知字段。6. 运行时流程两轮对话加一次中间执行Function Calling 的运行时不是一次请求结束而是一个闭环。第一轮你把用户问题和工具列表发给模型。模型判断需要工具时不直接输出最终答案而是返回 tool_calls。这个返回值的意思是我还不能回答我需要你先帮我执行这个函数。中间执行阶段你的代码读取 tool_calls解析函数名和参数做参数校验、鉴权、路由然后调用真实业务函数。第二轮你把工具执行结果放回对话历史再请求模型。模型拿到真实结果后才生成最终自然语言答案。from openaiimportOpenAIimportjson clientOpenAI()messages[{role:user,content:北京今天天气怎么样}]# 第一轮模型判断是否需要调用工具completionclient.chat.completions.create(modelgpt-5.5,messagesmessages,toolstools,)assistant_msgcompletion.choices[0].message messages.append(assistant_msg)# 中间执行你的代码执行真正的函数fortool_callinassistant_msg.tool_calls or[]: nametool_call.function.name argsjson.loads(tool_call.function.arguments)ifnameget_weather:resultget_weather(cityargs[city],unitargs[unit])else: result{error:unknown tool}messages.append({role:tool,tool_call_id:tool_call.id,content:json.dumps(result,ensure_asciiFalse)})# 第二轮模型基于工具结果生成最终答案finalclient.chat.completions.create(modelgpt-5.5,messagesmessages,toolstools,)print(final.choices[0].message.content)7. 并行调用能并行但不能乱并行当用户的问题包含多个互不依赖的子任务时模型可以在一次响应里返回多个 tool_calls。例如“查北京、上海、广州三个城市天气”每个城市之间没有依赖关系代码可以并发执行。但如果任务存在依赖就不能并行。比如“先查我的订单再根据订单号查物流”第二步依赖第一步结果必须串行执行。这个判断在 Agent 编排里非常重要因为错误并行会造成参数缺失、重复请求甚至业务状态错乱。importasyncio async def run_tool_call(tool_call): nametool_call.function.name argsjson.loads(tool_call.function.arguments)ifnameget_weather:returnawait async_get_weather(**args)raise ValueError(funsupported tool: {name})# 只有工具之间互不依赖时才适合并行执行resultsawait asyncio.gather(*[run_tool_call(call)forcallinassistant_msg.tool_calls])8. 工程落地必须加防线Function Calling 让模型可以连接真实业务系统也意味着风险会被放大。一个工具如果能查数据、发消息、改订单、删文件就不能直接让模型“想调就调”。生产环境里工具调用必须像普通后端接口一样治理工具白名单、参数校验、用户鉴权、租户隔离、限流、超时、重试、熔断、幂等、审计日志一个都不能少。尤其是高风险动作例如付款、删除、发短信、发邮件、修改用户资料建议加入二次确认或审批流。模型可以提出动作建议但最终执行权要掌握在业务系统手里。ALLOWED_TOOLS{get_weather,query_order}def call_function(name: str, args: dict, user_ctx: dict):ifname notinALLOWED_TOOLS:return{error:tool_not_allowed}# 业务参数二次校验不只依赖模型输出validate_args_by_schema(name, args)# 权限校验用户只能查自己的订单ifnamequery_order:assert args[user_id]user_ctx[user_id]returnquery_order(args[order_id], user_ctx[user_id])ifnameget_weather:returnget_weather(args[city], args.get(unit,celsius))9. Function Calling、RAG、MCP、Agent 的关系很多人会把 Function Calling、RAG、MCP、Agent 混在一起。其实它们处在不同层次。Function Calling 解决的是“怎么把自然语言变成结构化函数调用”。RAG 解决的是“怎么从知识库找证据”。MCP 更像工具和资源连接协议解决“工具怎么被统一暴露、发现和调用”。Agent 则是在目标驱动下做多步规划、调用工具、观察结果、继续决策。在一个真实系统里这几者经常组合使用Agent 负责规划RAG 负责查知识Function Calling 负责调用业务 APIMCP 负责统一连接外部工具服务。10. 如何评估 Function Calling 做得好不好工具调用不能只看最终回答像不像人话更要看链路质量。一个系统可能最终话术很好听但工具选错了、参数填错了、权限绕过了这都属于严重问题。评估时至少要拆成四层工具选择是否准确参数是否正确执行是否稳定最终回答是否忠实使用了工具结果。Berkeley Function Calling Leaderboard 这类评测也把函数调用准确性作为独立能力来衡量说明工具调用本身已经是大模型工程里的关键能力。工具选择准确率该调用时是否调用不该调用时是否克制。参数正确率字段、类型、枚举、格式、业务约束是否正确。执行成功率API 成功率、超时率、重试次数、错误恢复能力。最终答案忠实度回答是否基于工具结果而不是继续编造。安全指标越权调用、危险动作、敏感信息泄露、提示注入是否被拦截。11. 上线前排雷Demo 能跑不代表生产可用Function Calling 的 demo 很容易做出来难的是把它放进真实业务。真实用户会省略参数、表达模糊、连续追问、夹杂无关信息工具也会超时、报错、返回空数据。系统如果没有完整防线就会从“智能助手”变成“不稳定的自动化脚本”。上线前建议准备一批对抗样例闲聊场景、模糊参数、错误城市、越权订单、注入文本、工具超时、重复提交、并行依赖、超长工具结果。每一类都要有明确的预期行为。12. 面试时可以这样总结Function Calling 的核心不是“让模型调用 API”而是建立一套清晰的分工机制开发者用 JSON Schema 描述工具模型根据用户问题决定是否调用并生成结构化参数宿主代码执行真实函数再把结果交回模型生成最终答案。这套机制解决了过去靠自然语言解析工具意图的不稳定问题也让工具调用可以被审计、限权、重试和评估。真正落地时Schema 设计、description 质量、参数校验、权限控制、异常处理、并行/串行编排、链路观测都会直接决定系统是否可靠。记住最关键的一句话模型负责决策代码负责执行业务系统负责安全边界。内容来源Function Calling 原理与工程落地