代码参考文档:https://api-docs.deepseek.com/zh-cn/guides/function_calling
文案生成:Grok3
AI API请求中tools
参数的用法全解析
在调用现代AI模型(如OpenAI或DeepSeek)的API时,tools
参数是一个强大的功能,可以让模型不仅仅生成文本,还能通过外部工具完成复杂任务,比如查天气、调节情绪、搜索信息等。这篇博客将详细讲解tools
参数的用法,从基本定义到多工具场景的处理。
什么是tools
参数?
tools
是AI API(如client.chat.completions.create
)的一个可选参数,用于告诉模型有哪些外部工具可以用。它本质上是一个JSON数组,每个元素定义一个工具的功能、参数和描述。模型会根据用户输入和对话上下文,决定是否调用这些工具,并返回调用请求(tool_calls
),由开发者执行后反馈结果。
简单来说,tools
像是给AI一个“工具箱”,让它在需要时“借用”你的代码能力。
基本用法:一个工具的例子
我们以一个简单的天气查询工具为例,看看tools
怎么用。假设用Node.js调用DeepSeek API:
工具定义
const tools = [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get weather of a location.',
parameters: {
type: 'object',
properties: {
location: { type: 'string', description: 'The city, e.g., Hangzhou' }
},
required: ['location']
}
}
}
];
type: 'function'
:表示这是一个函数工具。name
:工具的唯一标识,AI通过它认出要调用哪个。description
:描述工具功能,AI靠这个判断适用场景。parameters
:定义工具需要的输入,格式遵循JSON Schema。
调用API
const { OpenAI } = require('openai');
const client = new OpenAI({ apiKey: '<your api key>', baseUrl: 'https://api.deepseek.com' });
async function sendMessages(messages) {
const response = await client.chat.completions.create({
model: 'deepseek-chat',
messages,
tools
});
return response.choices[0].message;
}
async function main() {
let messages = [{ role: 'user', content: 'How’s the weather in Hangzhou?' }];
let message = await sendMessages(messages);
if (message.tool_calls) {
messages.push(message); // 保存tool_calls
const toolCall = message.tool_calls[0];
const args = JSON.parse(toolCall.function.arguments);
const result = `Weather in ${args.location} is 24°C`; // 模拟执行
messages.push({ role: 'tool', tool_call_id: toolCall.id, content: result });
message = await sendMessages(messages);
console.log(message.content); // 输出最终回答
}
}
main();
执行流程
- 用户问:“杭州天气怎么样?”
- 模型返回
tool_calls
,要求调用get_weather({"location": "Hangzhou"})
。 - 代码执行工具,返回结果“24°C”。
- 模型根据结果生成回答:“Hangzhou的天气是24°C。”
这里的关键是:AI不直接查天气,而是通过tools
告诉你要用get_weather
,你负责实现具体逻辑。
AI如何选择工具?
AI选择工具的过程并不神秘,它靠的是:
- 用户输入:比如“天气”触发
get_weather
。(无需代码) - 工具描述:
description
越清晰,AI越容易匹配。 - 上下文:
messages
里的对话历史帮AI判断需求。
比如用户说“我很生气”,如果有个adjust_emotion
工具(描述为“Adjust user emotion”),AI可能会调用它,而不是get_weather
。
多工具场景:如何处理?
当tools
里有很多工具时,逻辑稍微复杂,但核心不变。假设有三个工具:
const tools = [
{ type: 'function', function: { name: 'adjust_emotion', description: 'Adjust user emotion.', parameters: { ... } } },
{ type: 'function', function: { name: 'get_weather', description: 'Get weather.', parameters: { ... } } },
{ type: 'function', function: { name: 'get_time', description: 'Get time.', parameters: { ... } } }
];
const toolFunctions = {
adjust_emotion: ({ current_emotion, context }) => ({ should_adjust: true, new_emotion: 'calm' }),
get_weather: ({ location }) => `Weather in ${location} is 24°C`,
get_time: ({ location }) => `Time in ${location} is ${new Date().toLocaleTimeString()}`
};
async function main() {
let messages = [{ role: 'user', content: '我很生气,北京天气和时间呢?' }];
let message = await sendMessages(messages);
if (message.tool_calls) {
messages.push(message);
for (const toolCall of message.tool_calls) {
const args = JSON.parse(toolCall.function.arguments);
const result = toolFunctions[toolCall.function.name](args);
messages.push({
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(result)
});
}
message = await sendMessages(messages);
console.log(message.content); // “别生气,北京天气24°C,时间14:30。”
}
}
多工具的特点
- **多
tool_calls
**:一个输入可能触发多个工具,返回数组。 - 独立处理:每个
tool_call
对应一条role: "tool"
消息,符合规范。 - 结果整合:AI会根据所有工具结果生成自然回答。
Token消耗:工具的影响
tools
参数和相关消息会占用token:
tools
定义:每次请求都传,10个工具≈200-300 token。- **
messages
**:包括用户输入、tool_calls
和工具结果,历史越长token越多。 - 输出:
tool_calls
和最终回答算输出token。
一个多工具流程(3工具)可能用100-150 token,工具越多消耗越高。优化方法:
- 精简描述。
- 清理不必要的
messages
历史。
自定义示例:调节情绪工具
来看一个有趣的例子:设计一个调节情绪的工具。
工具定义
{
"type": "function",
"function": {
"name": "adjust_emotion",
"description": "Adjust user emotion based on context.",
"parameters": {
"type": "object",
"properties": {
"current_emotion": { "type": "string", "enum": ["happy", "sad", "angry", "calm"] },
"context": { "type": "string" }
},
"required": ["current_emotion", "context"]
}
}
}
工具响应
工具内部函数举例
toolFunctions.adjust_emotion = ({ current_emotion, context }) => {
if (current_emotion === 'angry' && context.includes('生气')) {
return { should_adjust: true, new_emotion: 'calm' };
}
return { should_adjust: false, new_emotion: null };
};
用户说“我很生气”,AI调用adjust_emotion
,返回calm
,然后生成安抚性回复。
(这里grok简化了,我的实际想法是获取该情绪下的对话模板并更改提示词)
(另外,这里的解释可能有歧义,实际过程是AI仅返回json格式的输出,要本地主动地检查json文件并调用方法——工具调用方法前面有讲述——然后把工具方法返回内容添加到message里传给AI)
注意事项与优化
- 描述要精准:避免功能重叠,AI才能选对工具。
- 多工具管理:用对象映射(如
toolFunctions
)保持代码清晰。 - 测试验证:多试几种输入,确保AI选择合理。
- token控制:工具太多时,动态传必要的
tools
,减少开销。
(辅助AI正愁没有用武之地,用在这里正合适)
结语
tools
参数让AI从单纯的“说话机器”变成了“智能助手”,能通过外部工具解决实际问题。无论是单个工具还是多工具场景,只要定义清晰、逻辑合理,就能轻松集成到你的应用中。
我说两句
function_calling能很好地简化流程,过去我的设想一直是辅助AI动态修改提示词来达到这一效果,虽然想想效果不差,但到底太臃肿了,不正式。
在利用tools情况下,可以将需要的tools方法和参数封装起来,放在同级目录的两个文件tools.json
和tool_functions.js
里,使用如下方法调用,结构清晰,一目了然。
// 从当前文件夹路径导入
const tools = require('./tools.json');// 需要添加后缀否则会作为模块导入
const toolFunctions = require('./tool_functions');// js文件可以不用
当然AI也提到了,如果使用过多的tools,可能会导致token消耗过多,因此辅助AI可以动态识别判断需要传输的tool方法,可以说依旧在岗。
tools的用法当然不仅限于AI说的,那就是我之前AI本地提权的设想,对AI响应流程合理规划后完全适用。
AI调用方法会是未来很核心的功能,本身工具使用就是大模型性能参考标准之一。
当前deepseek-chat工具使用会导致空回复,我尝试多次没有成功,官方说下一版本会修复。
此方悬停