ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

深入浅出Function Calling①-零基础保姆级教程

深入浅出Function Calling①-零基础保姆级教程 第 1 章Function Calling 原理 —— 模型只会填申请表1.1 先粉碎最大误解误解开启 Function Calling 后大模型会自己执行我的函数。真相模型永远不会、也没有能力执行任何代码。它做的唯一一件事输出一份结构化的调用申请单——我想调用get_weather参数{city: 北京}。执行这个函数的是你写的 Python 代码把结果告诉模型的也是你。完整分工背下这张图面试画它用户: 北京今天多热 │ ▼ [1] 你的代码 ──(问题 工具清单)──▶ 大模型 [2] 大模型思考: 这得查实时数据我的工具清单里有 get_weather ◀──(申请单: get_weather, {city:北京})── 大模型 ← 模型只做到这 [3] 你的代码: 解析申请单 → 真的去调 get_weather(北京) → 拿到 晴 32℃ [4] 你的代码 ──(把 晴 32℃ 作为工具结果追加进对话)──▶ 大模型 [5] 大模型: 基于工具结果组织人话 ◀──北京今天晴32℃注意防晒 │ ▼ 用户看到最终回答为什么这样设计安全与控制权执行权 100% 在你手里——你可以校验参数、拦截危险操作、记录日志、要求人工确认。模型是大脑你的代码是手脚手脚长在你身上。1.2 工具清单长什么样JSON Schema你通过请求的tools参数递交工具清单每个工具 名字 描述 参数结构JSON Schema 格式2023 年 OpenAI 定的这套写法已成全行业标准weather_tool { type: function, function: { name: get_weather, description: 查询指定城市的当前实时天气。当用户询问天气、气温、要不要带伞等问题时使用。, parameters: { type: object, properties: { city: { type: string, description: 城市中文名例如北京、上海。用户没说城市时先追问不要瞎猜。, }, }, required: [city], }, }, }灵魂在 description模型完全靠读这两段文字决定什么时候用这个工具、参数怎么填。描述写得含糊模型就乱调、漏调、瞎填参1.3 底层原理一句话面试加分点Function Calling 不是什么外挂机关模型在 SFT/后训练阶段被专门训练过看到工具清单 需要外部能力时输出特定格式的调用文本服务端把这段文本解析成tool_calls字段给你。本质仍是下一个 token 预测——所以它也可能填错参数、编造不存在的工具名你的代码必须防。第 2 章Function Calling 完整闭环手撕级逐步拆解★本章是全套教程的心脏。我们把一次完整闭环拆成五步慢动作每步打印现场。先抄着跑通再合上书默写——面试手撕题就考这个。2.0 准备一个真的能查天气的函数fc_step_by_step.py —— Function Calling 五步慢动作 import os, json, requests from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI(api_keyos.getenv(DEEPSEEK_API_KEY), base_urlhttps://api.deepseek.com) MODEL deepseek-chat def get_weather(city: str) - str: 真实天气wttr.in 免费接口无需注册 try: resp requests.get(fhttps://wttr.in/{city}?format3, timeout10) resp.raise_for_status() return resp.text.strip() # 形如 北京: ⛅ 32°C except requests.RequestException as e: return f天气查询失败{e} TOOLS [{ type: function, function: { name: get_weather, description: 查询指定城市的当前实时天气。用户询问天气/气温/穿衣/带伞时使用。, parameters: { type: object, properties: {city: {type: string, description: 城市中文名如北京}}, required: [city], }, }, }]第 1 步带着工具清单发起提问messages [ {role: system, content: 你是贴心的生活助手。涉及实时信息必须使用工具禁止凭记忆编造。}, {role: user, content: 上海今天热不热要穿短袖吗}, ] resp client.chat.completions.create(modelMODEL, messagesmessages, toolsTOOLS)第 2 步检查模型的答复——它没回答它在递申请单msg resp.choices[0].message print(finish_reason:, resp.choices[0].finish_reason) # tool_calls ← 第4章表格应验 print(content:, msg.content) # None 或空 —— 没说话 print(tool_calls:, msg.tool_calls) tc msg.tool_calls[0] # 第一张申请单 print(申请单ID:, tc.id) # 如 call_abc123回传结果要对号 print(想调用:, tc.function.name) # get_weather print(参数(JSON字符串!):, tc.function.arguments) # {city: 上海}关键细节arguments是字符串不是字典必须json.loads解析第 3 步你来执行args json.loads(tc.function.arguments) # {city: 上海} result get_weather(**args) # ** 解包成关键字参数01教程10.4 print(工具执行结果:, result) # 上海: ☀️ 34°C第 4 步把申请单 执行结果按顺序补进对话史全流程最易错处messages.append(msg) # ① 先补模型那条带 tool_calls 的 assistant 消息 messages.append({ # ② 再补工具结果role 必须是 tool role: tool, tool_call_id: tc.id, # ③ 对准申请单ID —— 多工具时全靠它对号入座 content: result, })三条铁律先 assistant 后 tool顺序反了直接报 400tool_call_id 必须匹配SDK 允许直接 append 消息对象msg落库存 JSON 时用msg.model_dump()。第 5 步再问一次模型基于结果说人话final client.chat.completions.create(modelMODEL, messagesmessages, toolsTOOLS) print(最终回答:, final.choices[0].message.content) # → 上海今天34℃妥妥的短袖天注意防晒补水 print(finish_reason:, final.choices[0].finish_reason) # stop —— 这轮是正常说话2.1 复盘messages 的完整演变把这个结构刻进脑子[ {role: system, content: 你是贴心的生活助手...禁止编造}, {role: user, content: 上海今天热不热要穿短袖吗}, {role: assistant, tool_calls: [get_weather(city上海) 申请单], content: None}, {role: tool, tool_call_id: call_abc123, content: 上海: ☀️ 34°C}, {role: assistant, content: 上海今天34℃妥妥的短袖天...}, ]role 家族至此集齐四位system规矩、user提问、assistant回答或申请工具、tool工具结果。
返回列表