Vercel AI SDK 是官方推出的、专为现代 Web 应用设计的 AI 开发工具集:它把 LLM 调用、流式响应、工具调用、多步 Agent 编排等复杂逻辑封装为简洁的 React/Vue/Svelte 组件和 Node.js API,让开发者在几行代码内就能实现 “ChatGPT 式” 的交互体验。配合 Vercel Edge Functions 的全球边缘执行,AI 响应延迟可降到 100ms 以内。本文从 SDK 核心到 RAG 实战,完整覆盖 AI Web 应用的构建路径。
一、Vercel AI SDK 架构
1.1 模块组成
Vercel AI SDK 分为三个核心包:
| 包名 | 用途 | 安装命令 |
|---|---|---|
ai | 核心模块:流式响应、tool calling、object generation | npm install ai |
@ai-sdk/react | React hooks:useChat、useCompletion、useObject | npm install @ai-sdk/react |
@ai-sdk/openai | OpenAI 提供商适配器 | npm install @ai-sdk/openai |
@ai-sdk/anthropic | Anthropic (Claude) 适配器 | npm install @ai-sdk/anthropic |
@ai-sdk/google | Google (Gemini) 适配器 | npm install @ai-sdk/google |
1.2 为什么用 AI SDK 而不是直接调 OpenAI API?
| 维度 | 直接调用 OpenAI SDK | Vercel AI SDK |
|---|---|---|
| 流式响应 | 手动处理 ReadableStream | 一行代码 streamText() |
| 前端 Hook | 自己写 useState/useEffect | useChat() 内置 |
| 多模型切换 | 改 endpoint + 参数 | 统一 API,换 provider 即可 |
| Tool Calling | 手动解析 function call | 内置工具调用与编排 |
| 状态管理 | 自行维护 | 自动管理对话状态与加载态 |
| Vercel 集成 | 手动适配 | 原生适配 Edge/Node |
结论:如果你在做 Web Chat 界面,AI SDK 节省 80% 的样板代码。
二、快速开始:流式聊天界面
2.1 安装依赖
npm install ai @ai-sdk/openai
2.2 后端 API(App Router)
// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export const runtime = 'edge'; // Edge 运行,低延迟
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
maxTokens: 4096,
temperature: 0.7,
});
return result.toDataStreamResponse();
}
2.3 前端 Chat UI
// app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();
return (
<div className="max-w-2xl mx-auto p-4">
<div className="space-y-4 mb-4 min-h-[400px]">
{messages.map(m => (
<div
key={m.id}
className={`p-3 rounded-lg ${
m.role === 'user'
? 'bg-blue-100 ml-8'
: 'bg-gray-100 mr-8'
}`}
>
<div className="text-xs font-bold mb-1">
{m.role === 'user' ? 'You' : 'AI'}
</div>
<div className="whitespace-pre-wrap">{m.content}</div>
</div>
))}
{isLoading && (
<div className="bg-gray-100 p-3 rounded-lg mr-8">
<div className="animate-pulse">Thinking...</div>
</div>
)}
</div>
<form onSubmit={handleSubmit} className="flex gap-2">
<input
value={input}
onChange={handleInputChange}
placeholder="Ask something..."
className="flex-1 p-2 border rounded"
/>
<button
type="submit"
disabled={isLoading}
className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
>
Send
</button>
</form>
</div>
);
}
2.4 useChat Hook 详解
const {
messages, // 当前对话历史 { id, role, content }[]
input, // 输入框当前值
handleInputChange, // 输入框 onChange
handleSubmit, // 表单 onSubmit
isLoading, // AI 是否正在回复
error, // 错误信息
reload, // 重新生成最后一条回复
stop, // 停止流式输出
setMessages, // 手动设置消息(用于初始化/导入)
append, // 手动追加消息
} = useChat({
api: '/api/chat', // 自定义 API 路径
initialMessages: [], // 初始消息
maxToolRoundtrips: 5, // 工具调用最大轮次
onFinish: (msg) => { // 流结束回调
console.log('Chat finished:', msg);
},
onError: (err) => { // 错误回调
console.error('Chat error:', err);
},
});
三、Tool Calling(工具调用)
让 AI 不仅能聊天,还能"操作"你的系统:查天气、查数据库、发邮件、调用 API。
3.1 基础工具定义
// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText, tool } from 'ai';
import { z } from 'zod';
export const runtime = 'edge';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
messages,
tools: {
// 工具 1:获取天气
getWeather: tool({
description: 'Get the current weather in a location',
parameters: z.object({
location: z.string().describe('City name, e.g. "Tokyo"'),
unit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
}),
execute: async ({ location, unit }) => {
const res = await fetch(`https://api.weatherapi.com/v1/current.json?q=${location}&key=${process.env.WEATHER_API_KEY}`);
const data = await res.json();
return {
temperature: unit === 'celsius' ? data.current.temp_c : data.current.temp_f,
condition: data.current.condition.text,
};
},
}),
// 工具 2:查询数据库
findUser: tool({
description: 'Find a user by email in the database',
parameters: z.object({
email: z.string().email(),
}),
execute: async ({ email }) => {
// 这里可以是 Prisma 查询
return { id: '123', email, name: 'John Doe' };
},
}),
},
});
return result.toDataStreamResponse();
}
3.2 前端展示工具调用结果
// app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();
return (
<div>
{messages.map(m => (
<div key={m.id}>
<strong>{m.role}:</strong> {m.content}
{/* 展示工具调用 */}
{m.toolInvocations?.map(tool => (
<div key={tool.toolCallId} className="bg-yellow-50 p-2 my-2 rounded">
<div className="text-sm text-gray-600">
Tool: {tool.toolName}({JSON.stringify(tool.args)})
</div>
<div className="text-sm">
Result: {JSON.stringify(tool.result)}
</div>
</div>
))}
</div>
))}
{/* ... 输入表单 ... */}
</div>
);
}
3.3 多步 Agent 工作流
AI SDK 自动支持多轮工具调用:
用户:帮我查一下北京的天气,然后发给 dev@company.com
↓
AI:调用 getWeather({ location: "Beijing" })
↓
工具返回:{ temperature: 25, condition: "Sunny" }
↓
AI:调用 sendEmail({ to: "dev@company.com", body: "北京今天 25°C,晴天" })
↓
工具返回:{ sent: true }
↓
AI:已为您查询北京天气(25°C,晴天)并发送邮件给 dev@company.com
在前端配置 maxToolRoundtrips:
const { messages, ... } = useChat({
maxToolRoundtrips: 5, // 允许 AI 最多调用 5 轮工具
});
四、多模型供应商切换
AI SDK 的核心设计:更换供应商只需换 import,API 完全一致。
4.1 OpenAI → Anthropic (Claude)
// 后端:换导入和 model id
import { anthropic } from '@ai-sdk/anthropic';
const result = streamText({
model: anthropic('claude-3-5-sonnet-20241022'),
messages,
});
前端代码完全不变。
4.2 OpenAI → Google (Gemini)
import { google } from '@ai-sdk/google';
const result = streamText({
model: google('gemini-1.5-pro'),
messages,
});
4.3 统一的工具调用(跨模型)
AI SDK 的工具调用 API 是模型无关的。定义 tools 的方式和使用方式,不管底层是 GPT-4、Claude 还是 Gemini,代码完全一致。
五、RAG(检索增强生成)
RAG = 向量检索 + LLM 生成:先把知识库文档转换为向量存入数据库,用户提问时先检索相关内容,再让 LLM 基于检索结果回答。
5.1 向量库选择
| 向量库 | 特点 | 与 Vercel 配合 |
|---|---|---|
| Pinecone | 托管服务、性能好 | API 调用,任何 runtime 可用 |
| Supabase Vector | Postgres + pgvector,开箱即用 | 与 Vercel + Prisma 完美搭档 |
| Qdrant | 开源/托管、功能强 | API 调用 |
| Vercel KV | Redis 兼容 | 目前不支持向量索引 |
| Weaviate | 企业级、GraphQL 接口 | API 调用 |
5.2 基于 Supabase Vector 的 RAG 实现
// 1. 初始化 Supabase 客户端
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!
);
// 2. 文档向量化(通常在后台任务中执行)
import { openai } from '@ai-sdk/openai';
import { embed } from 'ai';
async function indexDocument(content: string, title: string, slug: string) {
const { embedding } = await embed({
model: openai.embedding('text-embedding-3-small'),
value: content,
});
await supabase.from('documents').insert({
title,
content,
slug,
embedding,
});
}
// 3. RAG 查询 API
// app/api/rag/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_KEY!
);
export const runtime = 'edge';
export async function POST(req: Request) {
const { messages } = await req.json();
const lastMessage = messages[messages.length - 1];
// (a) 把用户问题向量化
const { embedding } = await embed({
model: openai.embedding('text-embedding-3-small'),
value: lastMessage.content,
});
// (b) 向量检索:找最相关的 3 篇文档
const { data: documents } = await supabase.rpc('match_documents', {
query_embedding: embedding,
match_threshold: 0.7,
match_count: 3,
});
// (c) 构造系统提示,注入检索到的上下文
const context = documents?.map((d: any) =>
`Title: ${d.title}\nContent: ${d.content}`
).join('\n\n');
const systemPrompt = `You are a helpful assistant. Use the following context to answer the user's question.
If the context doesn't contain the answer, say "I don't have enough information."
Context:
${context}`;
// (d) 流式生成回答
const result = streamText({
model: openai('gpt-4o'),
system: systemPrompt,
messages,
});
return result.toDataStreamResponse();
}
5.3 Supabase Vector 的 SQL 函数
-- 创建 documents 表
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
title TEXT,
content TEXT,
slug TEXT UNIQUE,
embedding VECTOR(1536)
);
-- 创建向量相似度搜索函数
CREATE OR REPLACE FUNCTION match_documents(
query_embedding VECTOR(1536),
match_threshold FLOAT,
match_count INT
)
RETURNS TABLE(
id BIGINT,
title TEXT,
content TEXT,
slug TEXT,
similarity FLOAT
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT
documents.id,
documents.title,
documents.content,
documents.slug,
1 - (documents.embedding <=> query_embedding) AS similarity
FROM documents
WHERE 1 - (documents.embedding <=> query_embedding) > match_threshold
ORDER BY documents.embedding <=> query_embedding
LIMIT match_count;
END;
$$;
六、结构化数据生成(Object Generation)
让 AI 直接返回结构化的 JSON,而非自由文本。
// app/api/extract/route.ts
import { openai } from '@ai-sdk/openai';
import { generateObject } from 'ai';
import { z } from 'zod';
export const runtime = 'edge';
export async function POST(req: Request) {
const { text } = await req.json();
const { object } = await generateObject({
model: openai('gpt-4o'),
schema: z.object({
title: z.string().describe('Meeting title'),
date: z.string().describe('Meeting date in YYYY-MM-DD format'),
attendees: z.array(z.string()).describe('List of attendees'),
actionItems: z.array(z.object({
task: z.string(),
assignee: z.string(),
dueDate: z.string().optional(),
})),
}),
prompt: `Extract meeting information from the following text:\n\n${text}`,
});
return Response.json(object);
}
前端使用:
const [result, setResult] = useState(null);
async function extractMeeting() {
const res = await fetch('/api/extract', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: meetingNotesText }),
});
setResult(await res.json());
}
七、v0:AI 辅助生成界面
7.1 什么是 v0?
v0 是 Vercel 推出的 AI 设计工具:输入自然语言描述,AI 会自动生成现代前端页面代码(基于 Next.js + Tailwind + shadcn/ui),你可以一键导出到 Vercel 部署。
7.2 v0 工作流程
1. 访问 v0.dev
2. 输入描述:"A SaaS landing page with hero, features, pricing, CTA"
3. v0 生成可交互的页面预览
4. 聊天式修改:"Make the hero section dark mode"
5. 满意后 → Export → Vercel 一键部署
6. 下载源码到本地继续开发(Next.js + Tailwind)
7.3 v0 与 AI SDK 联用
v0 生成的 UI 可以与 AI SDK 无缝结合:
// v0 生成的 Chat 界面 + AI SDK
generated by v0:
<ChatLayout />
<MessageList />
<InputArea />
// 你只需接入 useChat
export default function Page() {
const chat = useChat();
return <ChatLayout {...chat} />;
}
八、性能优化
8.1 Edge Functions 优化 AI 延迟
// 把 AI API 放在 Edge,用户就近到边缘节点
export const runtime = 'edge';
// 国内用户:日本/香港节点 → OpenAI API
// 欧洲用户:法兰克福节点 → OpenAI API
// 美洲用户:美国节点 → OpenAI API
延迟基准:
- 直接从中国调 OpenAI API:800-2000ms+
- Edge Function(日本节点)调 OpenAI API:200-500ms
- Edge Function + 流式响应:用户 50ms 内开始看到"打字机"效果
8.2 缓存常见问题回答
// 为 FAQ 查询加缓存
export async function POST(req: Request) {
const { messages } = await req.json();
const lastMessage = messages[messages.length - 1].content;
// 简单问题命中缓存
const cacheKey = `faq:${await hash(lastMessage)}`;
const cached = await redis.get(cacheKey);
if (cached) return Response.json(JSON.parse(cached));
const result = streamText({
model: openai('gpt-4o'),
messages,
});
// AI 回答写入缓存(10 分钟)
const response = result.toDataStreamResponse();
// ... 在流结束后写缓存
return response;
}
常见问题(FAQ)
AI SDK 和 LangChain 有什么区别?
- LangChain:Python/Node 通用框架,适合复杂 Agent 编排、链式处理、数据加载
- AI SDK:专注 Web 前端体验(流式 UI、hooks),和 Next.js/Vercel 生态深度集成
- 建议:简单 Chat/RAG 用 AI SDK;复杂多步骤工作流用 LangChain(后端)+ AI SDK(前端)
AI SDK 支持哪些模型?
官方适配器:OpenAI、Anthropic Claude、Google Gemini、Mistral、Groq(Llama)、Azure OpenAI。社区适配器覆盖大部分主流模型。
流式响应在 Vercel 上有时中断?
检查:
- Functions 执行时间是否超时(Pro 计划 60s,Hobby 10s)
- 使用
streamText而非generateText(后者等待完整响应,容易超时) - 考虑升级到 Enterprise(超时 900s)或使用 Inngest 做长轮
RAG 的向量检索精度怎么提升?
- 使用更高质量的 embedding 模型(
text-embedding-3-largevstext-embedding-3-small) - 对长文档做分块(chunking),每块 500-1000 token
- 重排序(Reranking):先用向量召回 TOP-10,再用 Cross-Encoder 排序取 TOP-3
- 混合检索:BM25 + 向量搜索结合
v0 生成的代码可以商用吗?
可以。v0 生成的代码遵循 MIT 许可,无限制。但你仍需自己配置 API Key、域名等生产要素。
相关阅读
- Vercel 详解:前端与 AI 应用的一站式云平台
- Vercel Edge Functions 深度指南
- 用 Vercel 部署 Next.js + Postgres SaaS 实战
- Vercel Middleware 实战指南
- Vercel 专题导航
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。