关于 ai-sdk-core
使用 Vercel AI SDK v5 构建后端 AI 功能的技能,面向应用开发者。内容涵盖按提供方配置文本生成、流式输出、经模式验证的结构化结果、工具调用和多步骤 Agent。
主要功能
- 01文本生成与流式输出
- 02经模式验证的结构化结果
- 03模型提供方集成
- 04工具调用与多步骤 Agent
- 05生成错误处理
适用场景
- 01为应用添加流式聊天
- 02从文本提取并验证 JSON
- 03构建可调用工具的 AI 工作流
- 04运行批量文本生成任务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jackspace/ claudeskillz --skill ai-sdk-core安装后在 Claude Code 中输入/ai-sdk-core确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdSKILL.jsonVERIFICATION_REPORT.md详细介绍
AI SDK 核心
使用 Vercel AI SDK v5 构建可用于生产环境的后端 AI。
快速入门(5 分钟)
安装
# Core package
npm install ai
# Provider packages (install what you need)
npm install @ai-sdk/openai # OpenAI (GPT-5, GPT-4, GPT-3.5)
npm install @ai-sdk/anthropic # Anthropic (Claude Sonnet 4.5, Opus 4, Haiku 4)
npm install @ai-sdk/google # Google (Gemini 2.5 Pro/Flash/Lite)
npm install workers-ai-provider # Cloudflare Workers AI
# Schema validation
npm install zod
环境变量
# .env
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_GENERATIVE_AI_API_KEY=...
第一个示例:生成文本
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = await generateText({
model: openai('gpt-4-turbo'),
prompt: 'What is TypeScript?',
});
console.log(result.text);
第一个示例:流式聊天
import { streamText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
const stream = streamText({
model: anthropic('claude-sonnet-4-5-20250929'),
messages: [
{ role: 'user', content: 'Tell me a story' },
],
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
第一个示例:结构化输出
import { generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({
name: z.string(),
age: z.number(),
skills: z.array(z.string()),
}),
prompt: 'Generate a person profile for a software engineer',
});
console.log(result.object);
// { name: "Alice", age: 28, skills: ["TypeScript", "React"] }
核心函数
generateText()
生成文本补全,可选使用工具并执行多步操作。
签名:
async function generateText(options: {
model: LanguageModel;
prompt?: string;
messages?: Array<ModelMessage>;
system?: string;
tools?: Record<string, Tool>;
maxOutputTokens?: number;
temperature?: number;
stopWhen?: StopCondition;
// ... other options
}): Promise<GenerateTextResult>
基本用法:
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const result = await generateText({
model: openai('gpt-4-turbo'),
prompt: 'Explain quantum computing',
maxOutputTokens: 500,
temperature: 0.7,
});
console.log(result.text);
console.log(`Tokens: ${result.usage.totalTokens}`);
使用消息(聊天格式):
const result = await generateText({
model: openai('gpt-4-turbo'),
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is the weather?' },
{ role: 'assistant', content: 'I need your location.' },
{ role: 'user', content: 'San Francisco' },
],
});
使用工具:
import { tool } from 'ai';
import { z } from 'zod';
const result = await generateText({
model: openai('gpt-4'),
tools: {
weather: tool({
description: 'Get the weather for a location',
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
// API call here
return { temperature: 72, condition: 'sunny' };
},
}),
},
prompt: 'What is the weather in Tokyo?',
});
适用场景:
- 需要最终响应(非流式)
- 希望等待工具执行完成
- 无需流式处理时使用更简单的代码
- 构建批处理/定时任务
错误处理:
import { AI_APICallError, AI_NoContentGeneratedError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4-turbo'),
prompt: 'Hello',
});
console.log(result.text);
} catch (error) {
if (error instanceof AI_APICallError) {
console.error('API call failed:', error.message);
// Check rate limits, API key, network
} else if (error instanceof AI_NoContentGeneratedError) {
console.error('No content generated');
// Prompt may have been filtered
} else {
console.error('Unknown error:', error);
}
}
streamText()
以实时分块的方式流式生成文本补全。
签名:
function streamText(options: {
model: LanguageModel;
prompt?: string;
messages?: Array<ModelMessage>;
system?: string;
tools?: Record<string, Tool>;
maxOutputTokens?: number;
temperature?: number;
stopWhen?: StopCondition;
// ... other options
}): StreamTextResult
基本流式处理:
import { streamText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
const stream = streamText({
model: anthropic('claude-sonnet-4-5-20250929'),
prompt: 'Write a poem about AI',
});
// Stream to console
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
// Or get final result
const finalResult = await stream.result;
console.log(finalResult.text);
使用工具进行流式处理:
const stream = streamText({
model: openai('gpt-4'),
tools: {
// ... tools definition
},
prompt: 'What is the weather?',
});
// Stream text chunks
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
处理数据流:
const stream = streamText({
model: openai('gpt-4-turbo'),
prompt: 'Explain AI',
});
// Option 1: Text stream
for await (const text of stream.textStream) {
console.log(text);
}
// Option 2: Full stream (includes metadata)
for await (const part of stream.fullStream) {
if (part.type === 'text-delta') {
console.log(part.textDelta);
} else if (part.type === 'tool-call') {
console.log('Tool called:', part.toolName);
}
}
// Option 3: Wait for final result
const result = await stream.result;
console.log(result.text, result.usage);
适用场景:
- 面向用户的实时响应
- 长篇内容生成
- 希望展示进度
- 提升感知性能
生产环境模式:
// Next.js API Route
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';
export async function POST(request: Request) {
const { messages } = await request.json();
const stream = streamText({
model: openai('gpt-4-turbo'),
messages,
});
// Return stream to client
return stream.toDataStreamResponse();
}
错误处理:
// Recommended: Use onError callback (added in v4.1.22)
const stream = streamText({
model: openai('gpt-4-turbo'),
prompt: 'Hello',
onError({ error }) {
console.error('Stream error:', error);
// Custom error handling
},
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
// Alternative: Manual try-catch
try {
const stream = streamText({
model: openai('gpt-4-turbo'),
prompt: 'Hello',
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
} catch (error) {
console.error('Stream error:', error);
}
generateObject()
生成由 Zod 架构验证的结构化输出。
签名:
async function generateObject<T>(options: {
model: LanguageModel;
schema: z.Schema<T>;
prompt?: string;
messages?: Array<ModelMessage>;
system?: string;
mode?: 'auto' | 'json' | 'tool';
// ... other options
}): Promise<GenerateObjectResult<T>>
基本用法:
import { generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({
recipe: z.object({
name: z.string(),
ingredients: z.array(z.object({
name: z.string(),
amount: z.string(),
})),
instructions: z.array(z.string()),
}),
}),
prompt: 'Generate a recipe for chocolate chip cookies',
});
console.log(result.object.recipe);
嵌套架构:
const PersonSchema = z.object({
name: z.string(),
age: z.number(),
address: z.object({
street: z.string(),
city: z.string(),
country: z.string(),
}),
hobbies: z.array(z.string()),
});
const result = await generateObject({
model: openai('gpt-4'),
schema: PersonSchema,
prompt: 'Generate a person profile',
});
数组和联合类型:
// Array of objects
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({
people: z.array(z.object({
name: z.string(),
role: z.enum(['engineer', 'designer', 'manager']),
})),
}),
prompt: 'Generate a team of 5 people',
});
// Union types
const result = await generateObject({
model: openai('gpt-4'),
schema: z.discriminatedUnion('type', [
z.object({ type: z.literal('text'), content: z.string() }),
z.object({ type: z.literal('image'), url: z.string() }),
]),
prompt: 'Generate content',
});
适用场景:
- 需要结构化数据(JSON、表单等)
- 验证至关重要
- 从非结构化输入中提取数据
- 构建使用 JSON 的 AI 工作流
错误处理:
import { AI_NoObjectGeneratedError, AI_TypeValidationError } from 'ai';
try {
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({ name: z.string() }),
prompt: 'Generate a person',
});
} catch (error) {
if (error instanceof AI_NoObjectGeneratedError) {
console.error('Model did not generate valid object');
// Try simplifying schema or adding examples
} else if (error instanceof AI_TypeValidationError) {
console.error('Zod validation failed:', error.message);
// Schema doesn't match output
}
}
streamObject()
以增量更新的方式流式生成结构化输出。
签名:
function streamObject<T>(options: {
model: LanguageModel;
schema: z.Schema<T>;
prompt?: string;
messages?: Array<ModelMessage>;
mode?: 'auto' | 'json' | 'tool';
// ... other options
}): StreamObjectResult<T>
基本用法:
import { streamObject } from 'ai';
import { google } from '@ai-sdk/google';
import { z } from 'zod';
const stream = streamObject({
model: google('gemini-2.5-pro'),
schema: z.object({
characters: z.array(z.object({
name: z.string(),
class: z.string(),
stats: z.object({
hp: z.number(),
mana: z.number(),
}),
})),
}),
prompt: 'Generate 3 RPG characters',
});
// Stream partial updates
for await (const partialObject of stream.partialObjectStream) {
console.log(partialObject);
// { characters: [{ name: "Aria" }] }
// { characters: [{ name: "Aria", class: "Mage" }] }
// { characters: [{ name: "Aria", class: "Mage", stats: { hp: 100 } }] }
// ...
}
UI 集成模式:
// Server endpoint
export async function POST(request: Request) {
const { prompt } = await request.json();
const stream = streamObject({
model: openai('gpt-4'),
schema: z.object({
summary: z.string(),
keyPoints: z.array(z.string()),
}),
prompt,
});
return stream.toTextStreamResponse();
}
// Client (with useObject hook from ai-sdk-ui)
const { object, isLoading } = useObject({
api: '/api/analyze',
schema: /* same schema */,
});
// Render partial object as it streams
{object?.summary && <p>{object.summary}</p>}
{object?.keyPoints?.map(point => <li key={point}>{point}</li>)}
适用场景:
- 实时结构化数据(表单、仪表板)
- 展示渐进式完成过程
- 大型结构化输出
- 改善生成较慢时的用户体验
提供方设置与配置
OpenAI
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
// API key from environment (recommended)
// OPENAI_API_KEY=sk-...
const model = openai('gpt-4-turbo');
// Or explicit API key
const model = openai('gpt-4', {
apiKey: process.env.OPENAI_API_KEY,
});
// Available models
const gpt5 = openai('gpt-5'); // Latest (released August 2025)
const gpt4 = openai('gpt-4-turbo');
const gpt35 = openai('gpt-3.5-turbo');
const result = await generateText({
model: gpt4,
prompt: 'Hello',
});
常见错误:
AI_LoadAPIKeyError:检查OPENAI_API_KEY环境变量429 Rate Limit:实施指数退避,升级套餐401 Unauthorized:API 密钥格式无效
速率限制: OpenAI 对 RPM(每分钟请求数)和 TPM(每分钟 Token 数)设有限制。请实现重试逻辑:
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Hello',
maxRetries: 3, // Built-in retry
});
Anthropic
import { anthropic } from '@ai-sdk/anthropic';
// ANTHROPIC_API_KEY=sk-ant-...
const claude = anthropic('claude-sonnet-4-5-20250929');
// Available models (Claude 4.x family, released 2025)
const sonnet45 = anthropic('claude-sonnet-4-5-20250929'); // Latest, recommended
const sonnet4 = anthropic('claude-sonnet-4-20250522'); // Released May 2025
const opus4 = anthropic('claude-opus-4-20250522'); // Highest quality
// Legacy models (Claude 3.x, deprecated)
// const sonnet35 = anthropic('claude-3-5-sonnet-20241022'); // Use Claude 4.x instead
// const opus3 = anthropic('claude-3-opus-20240229');
// const haiku3 = anthropic('claude-3-haiku-20240307');
const result = await generateText({
model: sonnet45,
prompt: 'Explain quantum entanglement',
});
常见错误:
AI_LoadAPIKeyError:检查ANTHROPIC_API_KEY环境变量overloaded_error:使用指数退避重试rate_limit_error:等待后重试
最佳实践:
- Claude 擅长处理长上下文任务(200K+ Token)
- 推荐使用 Claude 4.x:Anthropic 已于 2025 年弃用 Claude 3.x
- 使用 Sonnet 4.5,在速度和质量之间取得平衡(最新模型)
- 如需避免使用最新模型,可使用 Sonnet 4,获得稳定的生产环境表现
- 使用 Opus 4,获得最高质量的推理能力并处理复杂任务
import { google } from '@ai-sdk/google';
// GOOGLE_GENERATIVE_AI_API_KEY=...
const gemini = google('gemini-2.5-pro');
// Available models (all GA since June-July 2025)
const pro = google('gemini-2.5-pro');
const flash = google('gemini-2.5-flash');
const lite = google('gemini-2.5-flash-lite');
const result = await generateText({
model: pro,
prompt: 'Analyze this data',
});
常见错误:
AI_LoadAPIKeyError:检查GOOGLE_GENERATIVE_AI_API_KEYSAFETY:内容被安全设置过滤QUOTA_EXCEEDED:触发速率限制
最佳实践:
- Gemini Pro:最适合推理和分析
- Gemini Flash:速度快、成本效益高,适用于大多数任务
- 免费套餐的限额较为宽松
- 适用于多模态任务(结合图像输入)
Cloudflare Workers AI
import { Hono } from 'hono';
import { generateText } from 'ai';
import { createWorkersAI } from 'workers-ai-provider';
interface Env {
AI: Ai;
}
const app = new Hono<{ Bindings: Env }>();
app.post('/chat', async (c) => {
// Create provider inside handler (avoid startup overhead)
const workersai = createWorkersAI({ binding: c.env.AI });
const result = await generateText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'What is Cloudflare?',
});
return c.json({ response: result.text });
});
export default app;
wrangler.jsonc:
{
"name": "ai-sdk-worker",
"compatibility_date": "2025-10-21",
"ai": {
"binding": "AI"
}
}
重要说明:
启动优化: AI SDK v5 + Zod 可能导致 Workers 启动时间超过 270ms。解决方案:
- 将导入移至处理程序内部:
// BAD (startup overhead)
import { createWorkersAI } from 'workers-ai-provider';
const workersai = createWorkersAI({ binding: env.AI });
// GOOD (lazy init)
app.post('/chat', async (c) => {
const { createWorkersAI } = await import('workers-ai-provider');
const workersai = createWorkersAI({ binding: c.env.AI });
// ...
});
- 尽量减少顶层 Zod 架构:
// Move complex schemas into route handlers
适用 workers-ai-provider 的场景:
- 多提供方场景(OpenAI + Workers AI)
- 使用 AI SDK UI hooks 搭配 Workers AI
- 需要在不同提供方之间使用一致的 API
适用原生绑定的场景:
对于不需要多提供方支持的纯 Cloudflare 部署,请改用 cloudflare-workers-ai 技能,以获得最高性能。
工具调用与 Agent
基本工具定义
import { generateText, tool } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
const result = await generateText({
model: openai('gpt-4'),
tools: {
weather: tool({
description: 'Get the weather for a location',
inputSchema: z.object({
location: z.string().describe('The city and country, e.g. "Paris, France"'),
unit: z.enum(['celsius', 'fahrenheit']).optional(),
}),
execute: async ({ location, unit = 'celsius' }) => {
// Simulate API call
const data = await fetch(`https://api.weather.com/${location}`);
return { temperature: 72, condition: 'sunny', unit };
},
}),
convertTemperature: tool({
description: 'Convert temperature between units',
inputSchema: z.object({
value: z.number(),
from: z.enum(['celsius', 'fahrenheit']),
to: z.enum(['celsius', 'fahrenheit']),
}),
execute: async ({ value, from, to }) => {
if (from === to) return { value };
if (from === 'celsius' && to === 'fahrenheit') {
return { value: (value * 9/5) + 32 };
}
return { value: (value - 32) * 5/9 };
},
}),
},
prompt: 'What is the weather in Tokyo in Fahrenheit?',
});
console.log(result.text);
// Model will call weather tool, potentially convertTemperature, then answer
v5 工具变更:
parameters→inputSchema(Zod schema)- 工具属性:
args→input,result→output - 移除
ToolExecutionError(现在使用tool-error内容部分)
Agent 类
Agent 类简化了使用工具进行多步执行的过程。
import { Agent, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
const weatherAgent = new Agent({
model: anthropic('claude-sonnet-4-5-20250929'),
system: 'You are a weather assistant. Always convert temperatures to the user\'s preferred unit.',
tools: {
getWeather: tool({
description: 'Get current weather for a location',
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
return { temp: 72, condition: 'sunny', unit: 'fahrenheit' };
},
}),
convertTemp: tool({
description: 'Convert temperature between units',
inputSchema: z.object({
fahrenheit: z.number(),
}),
execute: async ({ fahrenheit }) => {
return { celsius: (fahrenheit - 32) * 5/9 };
},
}),
},
});
const result = await weatherAgent.run({
messages: [
{ role: 'user', content: 'What is the weather in SF in Celsius?' },
],
});
console.log(result.text);
// Agent will call getWeather, then convertTemp, then respond
何时使用 Agent,何时使用原始 generateText:
- 在以下情况下使用 Agent: 多个工具、复杂工作流、多步推理
- 在以下情况下使用 generateText: 简单的单步任务、使用一两个工具、需要完全掌控
多步执行
使用 stopWhen 条件控制何时停止多步执行。
import { generateText, stopWhen, stepCountIs, hasToolCall } from 'ai';
import { openai } from '@ai-sdk/openai';
// Stop after specific number of steps
const result = await generateText({
model: openai('gpt-4'),
tools: { /* ... */ },
prompt: 'Research TypeScript and create a summary',
stopWhen: stepCountIs(5), // Max 5 steps (tool calls + responses)
});
// Stop when specific tool is called
const result = await generateText({
model: openai('gpt-4'),
tools: {
research: tool({ /* ... */ }),
finalize: tool({ /* ... */ }),
},
prompt: 'Research and finalize a report',
stopWhen: hasToolCall('finalize'), // Stop when finalize is called
});
// Combine conditions
const result = await generateText({
model: openai('gpt-4'),
tools: { /* ... */ },
prompt: 'Complex task',
stopWhen: (step) => step.stepCount >= 10 || step.hasToolCall('finish'),
});
v5 变更:
已移除 maxSteps 参数。改用 stopWhen(stepCountIs(n))。
动态工具(v5 新功能)
根据上下文在运行时添加工具:
const result = await generateText({
model: openai('gpt-4'),
tools: (context) => {
// Context includes messages, step count, etc.
const baseTool = {
search: tool({ /* ... */ }),
};
// Add tools based on context
if (context.messages.some(m => m.content.includes('weather'))) {
baseTool.weather = tool({ /* ... */ });
}
return baseTools;
},
prompt: 'Help me with my task',
});
v4→v5 关键迁移指南
AI SDK v5 引入了大量破坏性变更。如果要从 v4 迁移,请遵循本指南。
破坏性变更概览
-
参数重命名
maxTokens→maxOutputTokensproviderMetadata→providerOptions
-
工具定义
parameters→inputSchema- 工具属性:
args→input,result→output
-
消息类型
CoreMessage→ModelMessageMessage→UIMessageconvertToCoreMessages→convertToModelMessages
-
工具错误处理
- 移除
ToolExecutionError类 - 现在使用
tool-error内容部分 - 支持自动重试
- 移除
-
多步执行
maxSteps→stopWhen- 使用
stepCountIs()或hasToolCall()
-
消息结构
- 简单的
content字符串 →parts数组 - 部分类型:文本、文件、推理、工具调用、工具结果
- 简单的
-
流式架构
- 单个数据块 → start/delta/end 生命周期
- 并发流使用唯一 ID
-
工具流式传输
- 默认启用
- 移除
toolCallStreaming选项
-
包重组
ai/rsc→@ai-sdk/rscai/react→@ai-sdk/reactLangChainAdapter→@ai-sdk/langchain
迁移示例
之前(v4):
import { generateText } from 'ai';
const result = await generateText({
model: openai.chat('gpt-4'),
maxTokens: 500,
providerMetadata: { openai: { user: 'user-123' } },
tools: {
weather: {
description: 'Get weather',
parameters: z.object({ location: z.string() }),
execute: async (args) => { /* args.location */ },
},
},
maxSteps: 5,
});
之后(v5):
import { generateText, tool, stopWhen, stepCountIs } from 'ai';
const result = await generateText({
model: openai('gpt-4'),
maxOutputTokens: 500,
providerOptions: { openai: { user: 'user-123' } },
tools: {
weather: tool({
description: 'Get weather',
inputSchema: z.object({ location: z.string() }),
execute: async ({ location }) => { /* input.location */ },
}),
},
stopWhen: stepCountIs(5),
});
迁移检查清单
- 将所有
maxTokens更新为maxOutputTokens - 将
providerMetadata更新为providerOptions - 将工具的
parameters转换为inputSchema - 更新工具执行函数:
args→input - 用
stopWhen(stepCountIs(n))替换maxSteps - 更新消息类型:
CoreMessage→ModelMessage - 移除
ToolExecutionError处理 - 更新包导入(
ai/rsc→@ai-sdk/rsc) - 测试流式行为(架构已变更)
- 更新 TypeScript 类型
自动迁移
AI SDK 提供了迁移工具:
npx ai migrate
该工具会自动更新大多数破坏性变更。请仔细检查变更。
官方迁移指南: https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
12 大常见错误及解决方案
1. AI_APICallError
原因: API 请求失败(网络、身份验证、速率限制)。
解决方案:
import { AI_APICallError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Hello',
});
} catch (error) {
if (error instanceof AI_APICallError) {
console.error('API call failed:', error.message);
console.error('Status code:', error.statusCode);
console.error('Response:', error.responseBody);
// Check common causes
if (error.statusCode === 401) {
// Invalid API key
} else if (error.statusCode === 429) {
// Rate limit - implement backoff
} else if (error.statusCode >= 500) {
// Provider issue - retry
}
}
}
预防措施:
- 启动时验证 API 密钥
- 使用指数退避实现重试逻辑
- 监控速率限制
- 妥善处理网络错误
2. AI_NoObjectGeneratedError
原因: 模型未能生成符合 schema 的有效对象。
解决方案:
import { AI_NoObjectGeneratedError } from 'ai';
try {
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({ /* complex schema */ }),
prompt: 'Generate data',
});
} catch (error) {
if (error instanceof AI_NoObjectGeneratedError) {
console.error('No valid object generated');
// Solutions:
// 1. Simplify schema
// 2. Add more context to prompt
// 3. Provide examples in prompt
// 4. Try different model (gpt-4 better than gpt-3.5 for complex objects)
}
}
预防措施:
- 从简单的 schema 开始,逐步增加复杂度
- 在提示词中加入示例:“生成一个类似这样的人员:{ name: 'Alice', age: 30 }”
- 对于复杂的结构化输出,使用 GPT-4
- 先用示例数据测试 schema
3. Worker 启动时间限制(270ms+)
原因: AI SDK v5 加上 Zod 初始化开销,导致 Cloudflare Workers 启动时间超出限制。
解决方案:
// BAD: Top-level imports cause startup overhead
import { createWorkersAI } from 'workers-ai-provider';
import { complexSchema } from './schemas';
const workersai = createWorkersAI({ binding: env.AI });
// GOOD: Lazy initialization inside handler
export default {
async fetch(request, env) {
const { createWorkersAI } = await import('workers-ai-provider');
const workersai = createWorkersAI({ binding: env.AI });
// Use workersai here
}
}
预防措施:
- 将 AI SDK 导入移至路由处理程序内部
- 尽量减少顶层 Zod schema
- 监控 Worker 启动时间(必须小于 400ms)
- 使用 Wrangler 的启动时间报告
GitHub 问题: 在 Vercel AI SDK 问题中搜索 “Workers startup limit”
4. streamText 静默失败
原因: createDataStreamResponse 可能会吞掉流错误。
状态: ✅ 已解决 — 已在 [email protected] 中修复(2025 年 2 月)
解决方案(推荐):
// Use the onError callback (added in v4.1.22)
const stream = streamText({
model: openai('gpt-4'),
prompt: 'Hello',
onError({ error }) {
console.error('Stream error:', error);
// Custom error logging and handling
},
});
// Stream safely
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
替代方案(手动 try-catch):
// Fallback if not using onError callback
try {
const stream = streamText({
model: openai('gpt-4'),
prompt: 'Hello',
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
} catch (error) {
console.error('Stream error:', error);
}
预防措施:
- 使用
onError回调正确捕获错误(推荐) - 实现服务端错误监控
- 明确测试流错误处理
- 在生产环境中始终在服务端记录日志
GitHub Issue: #4726(已解决)
5. AI_LoadAPIKeyError
原因: API 密钥缺失或无效。
解决方案:
import { AI_LoadAPIKeyError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Hello',
});
} catch (error) {
if (error instanceof AI_LoadAPIKeyError) {
console.error('API key error:', error.message);
// Check:
// 1. .env file exists and loaded
// 2. Correct env variable name (OPENAI_API_KEY)
// 3. Key format is valid (starts with sk-)
}
}
预防措施:
- 在应用启动时验证 API 密钥
- 使用环境变量验证(例如 zod)
- 在开发环境中提供清晰的错误消息
- 说明必需的环境变量
6. AI_InvalidArgumentError
原因: 传递给函数的参数无效。
解决方案:
import { AI_InvalidArgumentError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
maxOutputTokens: -1, // Invalid!
prompt: 'Hello',
});
} catch (error) {
if (error instanceof AI_InvalidArgumentError) {
console.error('Invalid argument:', error.message);
// Check parameter types and values
}
}
预防措施:
- 使用 TypeScript 进行类型检查
- 在调用 AI SDK 函数之前验证输入
- 仔细阅读函数签名
- 查看官方文档,了解参数限制
7. AI_NoContentGeneratedError
原因: 模型未生成任何内容(安全过滤器等)。
解决方案:
import { AI_NoContentGeneratedError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Some prompt',
});
} catch (error) {
if (error instanceof AI_NoContentGeneratedError) {
console.error('No content generated');
// Possible causes:
// 1. Safety filters blocked output
// 2. Prompt triggered content policy
// 3. Model configuration issue
// Handle gracefully:
return { text: 'Unable to generate response. Please try different input.' };
}
}
预防措施:
- 清理用户输入
- 避免可能触发安全过滤器的提示词
- 准备备用提示信息
- 记录发生次数以便分析
8. AI_TypeValidationError
原因: 生成的输出未通过 Zod 架构验证。
解决方案:
import { AI_TypeValidationError } from 'ai';
try {
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({
age: z.number().min(0).max(120), // Strict validation
}),
prompt: 'Generate person',
});
} catch (error) {
if (error instanceof AI_TypeValidationError) {
console.error('Validation failed:', error.message);
// Solutions:
// 1. Relax schema constraints
// 2. Add more guidance in prompt
// 3. Use .optional() for unreliable fields
}
}
预防措施:
- 从宽松的架构开始,逐步收紧
- 对可能并非总是存在的字段使用
.optional() - 在字段描述中添加验证提示
- 使用各种提示词进行测试
9. AI_RetryError
原因: 所有重试均失败。
解决方案:
import { AI_RetryError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Hello',
maxRetries: 3, // Default is 2
});
} catch (error) {
if (error instanceof AI_RetryError) {
console.error('All retries failed');
console.error('Last error:', error.lastError);
// Check root cause:
// - Persistent network issue
// - Provider outage
// - Invalid configuration
}
}
预防措施:
- 调查失败的根本原因
- 如有需要,调整重试配置
- 在提供商服务中断时实现熔断器模式
- 准备备用提供商
10. 速率限制错误
原因: 超出提供商的速率限制(RPM/TPM)。
解决方案:
// Implement exponential backoff
async function generateWithBackoff(prompt: string, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await generateText({
model: openai('gpt-4'),
prompt,
});
} catch (error) {
if (error instanceof AI_APICallError && error.statusCode === 429) {
const delay = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited, waiting ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
throw new Error('Rate limit retries exhausted');
}
预防措施:
- 监控速率限制标头
- 对请求进行排队,以确保不超出限制
- 如有需要,升级提供商套餐
- 实现请求限流
11. 使用 Zod 时的 TypeScript 性能问题
原因: 复杂的 Zod 架构会减慢 TypeScript 类型检查。
解决方案:
// Instead of deeply nested schemas at top level:
// const complexSchema = z.object({ /* 100+ fields */ });
// Define inside functions or use type assertions:
function generateData() {
const schema = z.object({ /* complex schema */ });
return generateObject({ model: openai('gpt-4'), schema, prompt: '...' });
}
// Or use z.lazy() for recursive schemas:
type Category = { name: string; subcategories?: Category[] };
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({
name: z.string(),
subcategories: z.array(CategorySchema).optional(),
})
);
预防措施:
- 避免使用顶层复杂架构
- 对递归类型使用
z.lazy() - 将大型架构拆分为较小的架构
- 在适当情况下使用类型断言
官方文档: https://ai-sdk.dev/docs/troubleshooting/common-issues/slow-type-checking
12. 无效 JSON 响应(特定于提供商)
原因: 某些模型偶尔会返回无效 JSON。
解决方案:
// Use built-in retry and mode selection
const result = await generateObject({
model: openai('gpt-4'),
schema: mySchema,
prompt: 'Generate data',
mode: 'json', // Force JSON mode (supported by GPT-4)
maxRetries: 3, // Retry on invalid JSON
});
// Or catch and retry manually:
try {
const result = await generateObject({
model: openai('gpt-4'),
schema: mySchema,
prompt: 'Generate data',
});
} catch (error) {
// Retry with different model
const result = await generateObject({
model: openai('gpt-4-turbo'),
schema: mySchema,
prompt: 'Generate data',
});
}
预防措施:
- 在可用时使用
mode: 'json' - 结构化输出优先使用 GPT-4
- 实现重试逻辑
- 验证响应
GitHub Issue: #4302(Imagen 3.0 无效 JSON)
更多错误: 请参阅完整错误参考:https://ai-sdk.dev/docs/reference/ai-sdk-errors
生产环境最佳实践
性能
1. 对长篇内容始终使用流式传输:
// User-facing: Use streamText
const stream = streamText({ model: openai('gpt-4'), prompt: 'Long essay' });
return stream.toDataStreamResponse();
// Background tasks: Use generateText
const result = await generateText({ model: openai('gpt-4'), prompt: 'Analyze data' });
2. 设置合适的 maxOutputTokens:
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Short answer',
maxOutputTokens: 100, // Limit tokens to save cost
});
3. 缓存提供商实例:
// Good: Reuse provider instances
const gpt4 = openai('gpt-4-turbo');
const result1 = await generateText({ model: gpt4, prompt: 'Hello' });
const result2 = await generateText({ model: gpt4, prompt: 'World' });
4. 优化 Zod 架构:
// Avoid complex nested schemas at top level in Workers
// Move into route handlers to prevent startup overhead
错误处理
1. 将所有 AI 调用包装在 try-catch 中:
try {
const result = await generateText({ /* ... */ });
} catch (error) {
// Handle specific errors
if (error instanceof AI_APICallError) { /* ... */ }
else if (error instanceof AI_NoContentGeneratedError) { /* ... */ }
else { /* ... */ }
}
2. 实现重试逻辑:
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Hello',
maxRetries: 3,
});
3. 正确记录错误:
console.error('AI SDK Error:', {
type: error.constructor.name,
message: error.message,
statusCode: error.statusCode,
timestamp: new Date().toISOString(),
});
成本优化
1. 选择合适的模型:
// Simple tasks: Use cheaper models
const simple = await generateText({ model: openai('gpt-3.5-turbo'), prompt: 'Hello' });
// Complex reasoning: Use GPT-4
const complex = await generateText({ model: openai('gpt-4'), prompt: 'Analyze...' });
2. 合理设置 maxOutputTokens:
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Summarize in 2 sentences',
maxOutputTokens: 100, // Prevent over-generation
});
3. 尽可能缓存结果:
const cache = new Map();
async function getCachedResponse(prompt: string) {
if (cache.has(prompt)) return cache.get(prompt);
const result = await generateText({ model: openai('gpt-4'), prompt });
cache.set(prompt, result.text);
return result.text;
}
Cloudflare Workers 专项
1. 将导入移到处理程序内部:
// Avoid startup overhead
export default {
async fetch(request, env) {
const { generateText } = await import('ai');
const { openai } = await import('@ai-sdk/openai');
// Use here
}
}
2. 监控启动时间:
# Wrangler reports startup time
wrangler deploy
# Check output for startup duration (must be <400ms)
3. 正确处理流式传输:
// Return ReadableStream for streaming responses
const stream = streamText({ model: openai('gpt-4'), prompt: 'Hello' });
return new Response(stream.toTextStream(), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
Next.js / Vercel 专属
1. 使用 Server Actions 执行变更:
'use server';
export async function generateContent(input: string) {
const result = await generateText({
model: openai('gpt-4'),
prompt: input,
});
return result.text;
}
2. 使用 Server Components 执行初始加载:
// app/page.tsx
export default async function Page() {
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Welcome message',
});
return <div>{result.text}</div>;
}
3. 实现加载状态:
'use client';
import { useState } from 'react';
import { generateContent } from './actions';
export default function Form() {
const [loading, setLoading] = useState(false);
async function handleSubmit(formData: FormData) {
setLoading(true);
const result = await generateContent(formData.get('input'));
setLoading(false);
}
return (
<form action={handleSubmit}>
<input name="input" />
<button disabled={loading}>
{loading ? 'Generating...' : 'Submit'}
</button>
</form>
);
}
4. 关于部署: 请参阅 Vercel 的官方部署文档:https://vercel.com/docs/functions
何时使用此技能
以下情况使用 ai-sdk-core:
- 构建后端 AI 功能(服务端文本生成)
- 实现服务端文本生成(Node.js、Workers、Next.js)
- 创建结构化 AI 输出(JSON、表单、数据提取)
- 使用工具构建 AI Agent(多步工作流)
- 集成多个 AI 提供商(OpenAI、Anthropic、Google、Cloudflare)
- 从 AI SDK v4 迁移到 v5
- 遇到 AI SDK 错误(AI_APICallError、AI_NoObjectGeneratedError 等)
- 在 Cloudflare Workers 中使用 AI(配合 workers-ai-provider)
- 在 Next.js Server Components/Actions 中使用 AI
- 需要跨不同 LLM 提供商使用一致的 API
以下情况不要使用此技能:
- 构建 React 聊天 UI(改用 ai-sdk-ui 技能)
- 需要 useChat 等前端钩子(改用 ai-sdk-ui 技能)
- 需要嵌入或图像生成等高级主题(请查阅官方文档)
- 在不使用多提供商的情况下构建原生 Cloudflare Workers AI 应用(改用 cloudflare-workers-ai 技能)
- 需要生成式 UI / RSC(请参阅 https://ai-sdk.dev/docs/ai-sdk-rsc)
依赖项与版本
{
"dependencies": {
"ai": "^5.0.81",
"@ai-sdk/openai": "^2.0.56",
"@ai-sdk/anthropic": "^2.0.38",
"@ai-sdk/google": "^2.0.24",
"workers-ai-provider": "^2.0.0",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/node": "^20.11.0",
"typescript": "^5.3.3"
}
}
版本说明:
- AI SDK v5.0.81+(稳定版,截至 2025 年 10 月的最新版本)
- v6 仍处于 Beta 阶段,本技能不涉及
- Zod 兼容性:本技能使用 Zod 3.x,但 AI SDK 5 官方同时支持 Zod 3.x 和 Zod 4.x(最新版本为 4.1.12)
- 新项目推荐使用 Zod 4(于 2025 年 8 月发布)
- Zod 4 存在不兼容变更:错误 API、
.default()行为、移除了ZodError.errors - 使用 Zod 4 时,
zod-to-json-schema可能会出现一些对等依赖项警告 - 迁移指南请参阅 https://zod.dev/v4/changelog
- 为兼容 v5,提供商包需使用 2.0+
检查最新版本:
npm view ai version
npm view @ai-sdk/openai version
npm view @ai-sdk/anthropic version
npm view @ai-sdk/google version
npm view workers-ai-provider version
npm view zod version # Check for Zod 4.x updates
官方文档链接
核心文档
- AI SDK 简介: https://ai-sdk.dev/docs/introduction
- AI SDK Core 概览: https://ai-sdk.dev/docs/ai-sdk-core/overview
- 生成文本: https://ai-sdk.dev/docs/ai-sdk-core/generating-text
- 生成结构化数据: https://ai-sdk.dev/docs/ai-sdk-core/generating-structured-data
- 工具与工具调用: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling
- Agent 概览: https://ai-sdk.dev/docs/agents/overview
- 基础知识: https://ai-sdk.dev/docs/foundations/overview
高级主题(本技能未涵盖)
- 嵌入: https://ai-sdk.dev/docs/ai-sdk-core/embeddings
- 图像生成: https://ai-sdk.dev/docs/ai-sdk-core/generating-images
- 转录: https://ai-sdk.dev/docs/ai-sdk-core/generating-transcriptions
- 语音: https://ai-sdk.dev/docs/ai-sdk-core/generating-speech
- MCP 工具: https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools
- 遥测: https://ai-sdk.dev/docs/ai-sdk-core/telemetry
- 生成式 UI: https://ai-sdk.dev/docs/ai-sdk-rsc
迁移与故障排查
- v4→v5 迁移指南: https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
- 所有错误类型(共 28 种): https://ai-sdk.dev/docs/reference/ai-sdk-errors
- 故障排查指南: https://ai-sdk.dev/docs/troubleshooting
提供商文档
- OpenAI 提供商: https://ai-sdk.dev/providers/ai-sdk-providers/openai
- Anthropic 提供商: https://ai-sdk.dev/providers/ai-sdk-providers/anthropic
- Google 提供商: https://ai-sdk.dev/providers/ai-sdk-providers/google
- 所有提供商(25+): https://ai-sdk.dev/providers/overview
- 社区提供商: https://ai-sdk.dev/providers/community-providers
Cloudflare 集成
- Workers AI Provider(社区): https://ai-sdk.dev/providers/community-providers/cloudflare-workers-ai
- Cloudflare Workers AI 文档: https://developers.cloudflare.com/workers-ai/
- workers-ai-provider GitHub: https://github.com/cloudflare/ai/tree/main/packages/workers-ai-provider
- Cloudflare AI SDK 配置: https://developers.cloudflare.com/workers-ai/configuration/ai-sdk/
Vercel / Next.js 集成
- Vercel AI SDK 5.0 博客: https://vercel.com/blog/ai-sdk-5
- Next.js App Router 集成: https://ai-sdk.dev/docs/getting-started/nextjs-app-router
- Next.js Pages Router 集成: https://ai-sdk.dev/docs/getting-started/nextjs-pages-router
- Vercel Functions: https://vercel.com/docs/functions
- Vercel Streaming: https://vercel.com/docs/functions/streaming
GitHub 与社区
- GitHub 仓库: https://github.com/vercel/ai
- GitHub 问题: https://github.com/vercel/ai/issues
- Discord 社区: https://discord.gg/vercel
模板与参考资料
此技能包含:
- 13 个模板: 位于
templates/的即用型代码示例 - 5 份参考文档: 位于
references/的详细指南 - 1 个脚本: 位于
scripts/的版本检查器
所有文件均已优化,可直接复制粘贴到你的项目中。
最后更新: 2025-10-29 技能版本: 1.1.0 AI SDK 版本: 5.0.81+