功能
工具调用
工具调用(Tool Calling / Function Calling)让模型能够调用你定义的函数,获取外部信息或执行操作。
工作原理
- 你的应用 发送请求给模型
- 模型 决定需要调用工具,返回工具调用请求
- 你的应用 执行函数,返回结果给模型
- 模型 根据结果生成最终响应
基础用法
定义工具
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: '获取指定城市的天气信息',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: '城市名称,如 "北京"',
},
},
required: ['city'],
},
},
},
];发送请求
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: '北京今天天气怎么样?' }],
tools,
});
const choice = response.choices[0];
if (choice.finish_reason === 'tool_calls') {
// 模型请求调用工具
const toolCall = choice.message.tool_calls[0];
console.log('工具:', toolCall.function.name);
console.log('参数:', toolCall.function.arguments);
}执行工具并返回结果
// 1. 执行工具
const args = JSON.parse(toolCall.function.arguments);
const weatherData = await getWeather(args.city);
// 2. 将结果发回模型
const finalResponse = await client.chat.completions.create({
model: 'gpt-4o',
messages: [
{ role: 'user', content: '北京今天天气怎么样?' },
choice.message, // 包含 tool_calls 的 assistant 消息
{
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(weatherData),
},
],
tools,
});
console.log(finalResponse.choices[0].message.content);
// "北京今天晴天,气温 25°C,适合外出。"完整示例
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://api.byoks.com/v1',
apiKey: 'your-byoks-key',
});
// 定义工具
const tools: OpenAI.Chat.ChatCompletionTool[] = [
{
type: 'function',
function: {
name: 'get_weather',
description: '获取天气信息',
parameters: {
type: 'object',
properties: {
city: { type: 'string', description: '城市名' },
},
required: ['city'],
},
},
},
{
type: 'function',
function: {
name: 'search_web',
description: '搜索网页',
parameters: {
type: 'object',
properties: {
query: { type: 'string', description: '搜索关键词' },
},
required: ['query'],
},
},
},
];
// 工具执行函数
const toolHandlers: Record<string, (args: any) => Promise<any>> = {
get_weather: async ({ city }) => {
// 实际实现:调用天气 API
return { city, temp: 25, condition: '晴' };
},
search_web: async ({ query }) => {
// 实际实现:调用搜索 API
return { results: ['结果1', '结果2'] };
},
};
async function chat(userMessage: string) {
const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{ role: 'user', content: userMessage },
];
while (true) {
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages,
tools,
});
const choice = response.choices[0];
messages.push(choice.message);
if (choice.finish_reason === 'stop') {
return choice.message.content;
}
if (choice.finish_reason === 'tool_calls') {
for (const toolCall of choice.message.tool_calls!) {
const handler = toolHandlers[toolCall.function.name];
const args = JSON.parse(toolCall.function.arguments);
const result = await handler(args);
messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result),
});
}
}
}
}
// 使用
const answer = await chat('北京天气怎么样?顺便搜一下北京有什么好玩的');
console.log(answer);并行工具调用
模型可以同时请求多个工具调用:
if (choice.message.tool_calls) {
// 并行执行所有工具
const results = await Promise.all(
choice.message.tool_calls.map(async (toolCall) => {
const handler = toolHandlers[toolCall.function.name];
const args = JSON.parse(toolCall.function.arguments);
const result = await handler(args);
return {
role: 'tool' as const,
tool_call_id: toolCall.id,
content: JSON.stringify(result),
};
})
);
messages.push(...results);
}跨 Provider 支持
BYOKS 确保工具调用在不同 Provider 间格式一致:
| Provider | 原生格式 | BYOKS 格式 |
|---|---|---|
| OpenAI | tools + tool_calls | 相同 |
| Anthropic | tools + tool_use | 统一为 tool_calls |
functionDeclarations | 统一为 tools |
// 相同代码,适用于所有支持工具调用的 Provider
const models = ['gpt-4o', 'claude-3-5-sonnet-20241022', 'gemini-1.5-pro'];
for (const model of models) {
const response = await client.chat.completions.create({
model,
messages: [...],
tools, // 格式完全相同
});
}最佳实践
工具描述要清晰
// 好的描述
{
name: 'get_weather',
description: '获取指定城市当前的天气信息,包括温度、湿度、天气状况',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: '中国城市名称,如 "北京"、"上海"',
},
},
},
}
// 不好的描述
{
name: 'weather',
description: '天气',
parameters: { ... },
}处理错误
const toolHandlers = {
get_weather: async ({ city }) => {
try {
const data = await fetchWeather(city);
return data;
} catch (error) {
return { error: `无法获取 ${city} 的天气信息` };
}
},
};