Function Calling
一句话定义:LLM 输出结构化函数调用(函数名+参数 JSON),由外部代码执行后回传结果,让模型能"动手"。
1. 机制
- 宿主把工具描述(名称/描述/参数 schema)注入。
- 模型决定调哪个函数、填什么参数。
- 输出结构化
{"name":..., "arguments":...}。 - 宿主执行真实函数。
- 结果作为消息回传,模型继续。
2. 与 Agent / Tools 关系
| Function Calling | Agent Tools | |
|---|---|---|
| 是什么 | 模型输出「函数名 + 参数」的协议/机制 | 具体可执行能力(搜索、读文件、调 API…) |
| 角色 | 怎么调 | 调什么 |
| 粒度 | 单次行动 | 工具目录里的一项 |
- Tools:挂在 Agent 上的能力清单(可调函数)。
- Function Calling:让模型选中并执行某一项 Tool 的通道。
- Function Calling 是"单次行动";Agent 是"多步循环",每步的 act 往往就是一次 Function Calling。
- 没有 Tools,Function Calling 无事可做;没有 Function Calling(或同类机制),Agent 很难稳定"动手"。
一句话:Agent = LLM + Tools + Memory + Loop,其中 Tools 的调用方式 ≈ Function Calling。
3. Node.js 示例(OpenAI 风格)
一次 Function Calling:定义 tool → 注入 → 模型选工具 → 宿主执行 → 回传结果。
import OpenAI from "openai";
const client = new OpenAI();
// Tools:能力清单(描述 + JSON Schema)
const tools = [
{
type: "function",
function: {
name: "get_weather",
description: "查询某城市当前天气",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "城市名,如 北京" },
},
required: ["city"],
},
},
},
];
// 真实执行函数(宿主侧,不是模型执行)
async function getWeather({ city }) {
// 实际应调天气 API;此处演示
return { city, temp_c: 28, condition: "晴" };
}
const toolImpl = { get_weather: getWeather };
const messages = [
{ role: "user", content: "北京今天天气怎么样?" },
];
// ① 把 tools 注入,模型可能返回 tool_calls
let res = await client.chat.completions.create({
model: "gpt-4o",
messages,
tools,
});
const msg = res.choices[0].message;
messages.push(msg);
// ② Function Calling:按 name + arguments 执行
for (const call of msg.tool_calls ?? []) {
const fn = toolImpl[call.function.name];
const args = JSON.parse(call.function.arguments);
const result = await fn(args);
// ③ 结果回传,模型继续生成自然语言回答
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(result),
});
}
res = await client.chat.completions.create({
model: "gpt-4o",
messages,
tools,
});
console.log(res.choices[0].message.content);
// → 例如:「北京今天晴,气温约 28°C。」
Agent 循环版:把上面包进 while,直到模型不再发 tool_calls(或达到步数上限)。
async function runAgent(userText, { maxSteps = 5 } = {}) {
const messages = [{ role: "user", content: userText }];
for (let step = 0; step < maxSteps; step++) {
const res = await client.chat.completions.create({
model: "gpt-4o",
messages,
tools,
});
const msg = res.choices[0].message;
messages.push(msg);
// 无工具调用 → 本轮结束,返回最终文本
if (!msg.tool_calls?.length) return msg.content;
// 每一步 act = 一次(或一批)Function Calling
for (const call of msg.tool_calls) {
const fn = toolImpl[call.function.name];
const args = JSON.parse(call.function.arguments);
const result = await fn(args);
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(result),
});
}
}
throw new Error("超出最大步数,需设终止条件");
}
4. 工具设计原则
- 名称与描述清晰,说明用途与边界。
- 参数用 JSON Schema 约束类型/枚举/必填。
- 危险操作加审批/白名单。
- 返回裁剪,避免上下文膨胀。
- 错误返回结构化,便于模型重试。
5. 注意事项
- 描述不清会误选/误填。
- 模型可能幻觉参数值。
- 防注入:工具返回内容可能含恶意指令。
- 多工具时按场景分组。
6. 学习要点
- Function Calling 让 LLM 从"说"变"做"。
- Tools 是能力,Function Calling 是调用机制;Agent 用循环把多次调用串起来。
- 工具描述质量决定调用准确率。
- 是 Agent 与 MCP 的底层执行原语。
7. 参考资料
- OpenAI Function Calling 文档
- "Toolformer: Language Models Can Teach Themselves to Use Tools"
评论
评论加载中…