🤔 什么是 Tools?为什么需要它?
大模型本身是静态的,它的知识截止于训练数据的时间点,并且无法直接与外部世界交互。 Tools(工具) 就是大模型的"双手"和"眼睛"。
简单来说,Tool 是一个可以被模型调用的函数。 当你在 AI SDK 中定义一个 Tool 时,你实际上是告诉模型:"嘿,如果你遇到这个问题,可以调用这个函数,我会给你返回结果。"
一个标准的 Tool 包含三个核心要素:
- description (描述) :告诉模型这个工具是干嘛的(这其实也是 Prompt 的一部分)。
- inputSchema (输入定义) :定义模型需要提供什么参数(通常使用 Zod 定义)。
- execute (执行逻辑) :当模型决定调用工具时,实际运行的异步函数。
🛠️ 实战:定义你的第一个自定义工具 (Custom Tool)
AI SDK 提供了一个极其优雅的 tool 辅助函数。我们以一个经典的"获取天气"为例。
1. 安装依赖
首先确保你安装了必要的库:
Bash
npm install ai zod
2. 编写工具代码
TypeScript
javascript
import { tool } from 'ai';
import { z } from 'zod';
// 定义一个名为 weatherTool 的工具
export const weatherTool = tool({
// 1. 描述:非常重要,模型根据它决定是否调用
description: '获取指定地点的实时天气信息',
// 2. 参数结构:使用 Zod 定义,模型会严格遵守这个结构生成参数
inputSchema: z.object({
location: z.string().describe('需要查询天气的城市或地点,例如:London, Beijing'),
unit: z.enum(['celsius', 'fahrenheit']).optional().default('celsius').describe('温度单位'),
}),
// 3. 执行逻辑:模型调用时自动运行
execute: async ({ location, unit }) => {
// 在真实场景中,这里会调用第三方天气 API
console.log(`正在查询 ${location} 的天气...`);
// 模拟返回数据
const temp = 25;
return {
location,
temperature: temp,
unit,
condition: 'Sunny',
note: '这是一个模拟数据',
};
},
});
💡 提示 :
inputSchema中的.describe()非常关键,它会被转换成 JSON Schema 喂给大模型,帮助模型理解参数的含义。
🔗 连接模型:让 AI 使用工具
定义好工具后,我们需要通过 generateText 或 streamText 将其绑定到模型上。
这里假设你已经配置好了 OpenAI 或其他 Provider。
TypeScript
javascript
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai'; // 或其他 provider
import { weatherTool } from './tools'; // 引入上面定义的工具
async function askAI() {
const { text, toolResults } = await generateText({
model: openai('gpt-4o'), // 确保模型支持 Function Calling
// 将工具注册到 tools 对象中
tools: {
weather: weatherTool,
},
// 开启多步交互(关键!)
// 如果不设置 maxSteps,模型只会生成工具调用参数,而不会执行并利用结果生成最终回复
maxSteps: 5,
prompt: '上海现在的天气怎么样?适合穿什么衣服?',
});
console.log('AI 回复:', text);
}
askAI();
幕后发生了什么?(Roundtrip 原理)
当你设置 maxSteps: 5 时,AI SDK 自动处理了一个复杂的循环:
- 用户提问:"上海天气如何?"
- 模型思考 :发现需要天气信息,决定调用
weather工具,生成参数{ location: "Shanghai", unit: "celsius" }。 - AI SDK 介入 :检测到模型想调用工具,自动运行
weatherTool.execute函数。 - 获取结果 :函数返回
{ temperature: 25, condition: 'Sunny' }。 - 回传模型:AI SDK 将工具的运行结果作为一种特殊的"消息"发回给模型。
- 最终生成:模型结合查询到的天气数据,生成最终回答:"上海现在 25 度,晴天,非常舒适,建议穿T恤..."
🧩 进阶:三种工具类型的区别
AI SDK 文档中提到了三种工具类型,理解它们的区别对于高级开发很重要:
1. Custom Tools (自定义工具) - 最常用
- 特点 :你完全控制。你需要编写
inputSchema和execute函数。 - 适用场景:查数据库、调内部 API、执行业务逻辑。
- 代码 :即上面演示的
tool({...})。
2. Provider-Defined Tools (提供商定义工具)
- 特点 :提供商(如 Anthropic)定义好了 schema,但代码在你本地运行。
- 例子 :Anthropic 的
bash或text_editor工具。模型经过专门训练,能更精准地使用这些特定工具。 - 适用场景:当你想利用特定模型对特定工具的强项时(例如让 Claude 帮你写代码并存文件)。
TypeScript
javascript
// 伪代码示例
import { anthropic } from '@ai-sdk/anthropic';
const result = await generateText({
model: anthropic('claude-3-5-sonnet-20240620'),
tools: {
// 引用 Anthropic 定义好的 bash 工具结构
bash: anthropic.tools.bash_20250124({
// 你仍然需要提供执行逻辑(因为这是在你服务器上跑的)
execute: async ({ command }) => await myRunCommand(command),
}),
},
prompt: "列出当前目录下的文件",
});
3. Provider-Executed Tools (提供商执行工具)
- 特点 :完全在云端运行。Schema 和 执行逻辑都由提供商搞定。
- 例子 :OpenAI 的
web_search(联网搜索) 或 Code Interpreter。 - 适用场景:不想自己折腾基础设施,直接用现成的强力功能。
TypeScript
php
// 伪代码示例
import { openai } from '@ai-sdk/openai';
const result = await generateText({
model: openai('gpt-4-turbo'),
tools: {
// 直接启用 OpenAI 的联网搜索,你不需要写任何代码
web_search: openai.tools.webSearch(),
},
prompt: "今天的科技新闻头条是什么?",
});
📦 工具生态:不要重复造轮子
AI SDK 的一大优势是工具可以被打包成 npm 包共享。你可以直接使用社区现成的工具库:
- 联网搜索 :
@tavily/ai-sdk,@exalabs/ai-sdk(Exa.ai) - 浏览器操作 :
@browserbasehq/ai-sdk - 企业集成 :
@composio/ai-sdk(连接 GitHub, Salesforce 等)
使用示例 (以 Tavily 搜索为例):
TypeScript
javascript
import { tavily } from '@tavily/core'; // 假设的包结构,具体看文档
import { tool } from 'ai';
// 很多库直接导出了兼容 AI SDK 的 tool 对象
// const searchTool = ...
// 然后在 generateText 中直接用:
// tools: { webSearch: searchTool }
💡 最佳实践 Tips
- Prompt Engineering 在描述里 :
description字段本质上就是 Prompt。如果模型不愿意调用工具,尝试把描述写得更详细、更诱人。 - Schema 越细越好 :在 Zod 中使用
.describe()不仅是文档,更是给模型的指令。 - 错误处理 :在
execute函数中即使报错,最好也try-catch并返回一个包含错误信息的字符串,而不是直接抛出异常导致程序崩溃。这样模型有机会看到错误并尝试自我修正(例如参数填错了,模型看到错误提示后可能会重试)。 - 控制步骤 :
maxSteps不要设置过大,防止模型陷入死循环;也不要设置过小,复杂的任务可能需要多次调用工具。
结语
Vercel AI SDK 的 Tools 抽象非常清晰,它抹平了不同模型提供商(OpenAI, Anthropic, Google 等)在 Function Calling 格式上的差异。学会了这一套,你就可以轻松切换模型,构建出真正实用的 AI Agent。