为什么今天学这个
上周解决“让模型稳定返回程序能读的数据”。今天开始让模型请求业务工具。Function Calling 不是让模型直接执行函数,而是生成一张结构化调用申请单;工具白名单、参数、权限与执行都留在应用服务。
一张图讲清楚
用户请求
模型提出 tool call
服务端校验
业务工具执行
结果回流并回答
模型可返回零个、一个或多个调用。应用循环执行,直到得到最终回答,或触发轮数、时间、费用及人工确认上限。
三个核心要点
- 模型只有提议权:工具名来自注册表,参数按 Schema 再校验。
- 工具结果仍是上下文:保留调用 ID、参数、结果与错误,再请求模型组织最终答案。
- 循环必须能停:设置最大轮数、总超时、预算、重复检测与高风险人工确认。
最小可运行示例
const tools = {
get_weather: async ({ city }) => {
if (typeof city !== "string" || !city) throw Error("city 必填");
return { city, temperature: 26, condition: "晴" };
}
};
const messages = [{ role: "user", content: "北京天气如何?" }];
for (let round = 0; round < 3; round++) {
const response = await fakeModel(messages);
if (response.type === "final") { console.log(response.text); break; }
const fn = tools[response.name];
if (!fn) throw Error(`未注册工具: ${response.name}`);
const output = await fn(response.arguments);
messages.push({ role: "assistant", tool_call: response });
messages.push({ role: "tool", tool_call_id: response.id,
content: JSON.stringify(output) });
}
预期输出:北京 26℃,晴。完整可复制版本、依赖与输入输出见同日 Markdown。
生产环境会怎么翻车
- 不存在的工具:服务端白名单拒绝,返回结构化错误。
- 写操作重复:使用业务幂等键,超时后先对账再重试。
- 循环不停止:限制轮数、总超时与重复调用签名。
- 报错后编成功:把错误作为 tool result 明确回传,最终状态以业务系统为准。
动手练习
增加 get_weather 与 create_reminder 两个工具。完成条件:未知工具被拒;缺参数有可读错误;最多三轮;相同提醒 ID 不会重复创建;每轮记录调用 ID、耗时与结果。
面试表达
30 秒回答
Function Calling 是模型提出结构化调用、应用校验并执行、再把结果回传给模型的循环。模型不直接碰业务函数;服务端控制注册表、Schema、权限、超时和幂等,并给整个循环设置预算与停止条件。
3 分钟追问框架
按协议层、执行层、控制层展开:协议层声明工具和调用 ID;执行层映射固定函数并校验身份与资源范围;控制层负责轮数、超时、预算、幂等、审计和人工确认。
今日自测
1. 为什么模型没有真正“调用函数”?
它只生成调用意图;应用决定是否合法并执行代码。
2. 为什么副作用工具不能超时后无脑重试?
第一次可能已成功,需用幂等键并查询外部状态。
3. 相同参数连续查询三次怎样停止?
生成规范化调用签名检测重复,并结合轮数与总超时安全失败或转人工。
权威来源与明天
明天:进入 Tool Schema,让每张调用申请单更难填错。本页为课程内容,不构成招聘承诺。