Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:23:50 +08:00
commit 5135e7aaf4
24 changed files with 4973 additions and 0 deletions

View File

@@ -0,0 +1,209 @@
# AI SDK Core - Official Documentation Links
Organized links to official AI SDK and provider documentation.
---
## AI SDK Core Documentation
### Getting Started
- **Introduction:** https://ai-sdk.dev/docs/introduction
- **AI SDK Core Overview:** https://ai-sdk.dev/docs/ai-sdk-core/overview
- **Foundations:** https://ai-sdk.dev/docs/foundations/overview
### Core Functions
- **Generating Text:** https://ai-sdk.dev/docs/ai-sdk-core/generating-text
- **Streaming Text:** https://ai-sdk.dev/docs/ai-sdk-core/streaming-text
- **Generating Structured Data:** https://ai-sdk.dev/docs/ai-sdk-core/generating-structured-data
- **Streaming Structured Data:** https://ai-sdk.dev/docs/ai-sdk-core/streaming-structured-data
### Tool Calling & Agents
- **Tools and Tool Calling:** https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling
- **Agents Overview:** https://ai-sdk.dev/docs/agents/overview
- **Building Agents:** https://ai-sdk.dev/docs/agents/building-agents
### Advanced Topics (Not Replicated in This Skill)
- **Embeddings:** https://ai-sdk.dev/docs/ai-sdk-core/embeddings
- **Image Generation:** https://ai-sdk.dev/docs/ai-sdk-core/generating-images
- **Transcription (Audio to Text):** https://ai-sdk.dev/docs/ai-sdk-core/generating-transcriptions
- **Speech (Text to Audio):** https://ai-sdk.dev/docs/ai-sdk-core/generating-speech
- **MCP Tools:** https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools
- **Telemetry:** https://ai-sdk.dev/docs/ai-sdk-core/telemetry
- **Generative UI (RSC):** https://ai-sdk.dev/docs/ai-sdk-rsc
---
## Migration & Troubleshooting
- **v4 → v5 Migration Guide:** https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
- **All Error Types (28 total):** https://ai-sdk.dev/docs/reference/ai-sdk-errors
- **Troubleshooting Guide:** https://ai-sdk.dev/docs/troubleshooting
- **Common Issues:** https://ai-sdk.dev/docs/troubleshooting/common-issues
- **Slow Type Checking:** https://ai-sdk.dev/docs/troubleshooting/common-issues/slow-type-checking
---
## Provider Documentation
### Provider Overview
- **All Providers:** https://ai-sdk.dev/providers/overview
- **Provider Selection Guide:** https://ai-sdk.dev/providers/overview#provider-selection
### OpenAI
- **OpenAI Provider Docs:** https://ai-sdk.dev/providers/ai-sdk-providers/openai
- **OpenAI Platform:** https://platform.openai.com/
- **API Keys:** https://platform.openai.com/api-keys
- **Rate Limits:** https://platform.openai.com/account/rate-limits
- **Pricing:** https://openai.com/api/pricing/
### Anthropic
- **Anthropic Provider Docs:** https://ai-sdk.dev/providers/ai-sdk-providers/anthropic
- **Anthropic Console:** https://console.anthropic.com/
- **Claude Models:** https://docs.anthropic.com/en/docs/models-overview
- **Rate Limits:** https://docs.anthropic.com/en/api/rate-limits
- **Pricing:** https://www.anthropic.com/pricing
### Google
- **Google Provider Docs:** https://ai-sdk.dev/providers/ai-sdk-providers/google
- **Google AI Studio:** https://aistudio.google.com/
- **API Keys:** https://aistudio.google.com/app/apikey
- **Gemini Models:** https://ai.google.dev/models/gemini
- **Pricing:** https://ai.google.dev/pricing
### Cloudflare Workers AI
- **Workers AI Provider (Community):** https://ai-sdk.dev/providers/community-providers/cloudflare-workers-ai
- **Cloudflare Workers AI Docs:** https://developers.cloudflare.com/workers-ai/
- **AI SDK Configuration:** https://developers.cloudflare.com/workers-ai/configuration/ai-sdk/
- **Available Models:** https://developers.cloudflare.com/workers-ai/models/
- **GitHub (workers-ai-provider):** https://github.com/cloudflare/ai/tree/main/packages/workers-ai-provider
- **Pricing:** https://developers.cloudflare.com/workers-ai/platform/pricing/
### Community Providers
- **Community Providers List:** https://ai-sdk.dev/providers/community-providers
- **Ollama:** https://ai-sdk.dev/providers/community-providers/ollama
- **FriendliAI:** https://ai-sdk.dev/providers/community-providers/friendliai
- **LM Studio:** https://ai-sdk.dev/providers/community-providers/lmstudio
---
## Framework Integration
### Next.js
- **Next.js App Router Integration:** https://ai-sdk.dev/docs/getting-started/nextjs-app-router
- **Next.js Pages Router Integration:** https://ai-sdk.dev/docs/getting-started/nextjs-pages-router
- **Next.js Documentation:** https://nextjs.org/docs
### Node.js
- **Node.js Integration:** https://ai-sdk.dev/docs/getting-started/nodejs
### Vercel Deployment
- **Vercel Functions:** https://vercel.com/docs/functions
- **Vercel Streaming:** https://vercel.com/docs/functions/streaming
- **Vercel Environment Variables:** https://vercel.com/docs/projects/environment-variables
### Cloudflare Workers
- **Cloudflare Workers Docs:** https://developers.cloudflare.com/workers/
- **Wrangler CLI:** https://developers.cloudflare.com/workers/wrangler/
- **Workers Configuration:** https://developers.cloudflare.com/workers/wrangler/configuration/
---
## API Reference
- **generateText:** https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text
- **streamText:** https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-text
- **generateObject:** https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-object
- **streamObject:** https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-object
- **Tool:** https://ai-sdk.dev/docs/reference/ai-sdk-core/tool
- **Agent:** https://ai-sdk.dev/docs/reference/ai-sdk-core/agent
---
## GitHub & Community
- **GitHub Repository:** https://github.com/vercel/ai
- **GitHub Issues:** https://github.com/vercel/ai/issues
- **GitHub Discussions:** https://github.com/vercel/ai/discussions
- **Discord Community:** https://discord.gg/vercel
---
## Blog Posts & Announcements
- **AI SDK 5.0 Release:** https://vercel.com/blog/ai-sdk-5
- **Vercel AI Blog:** https://vercel.com/blog/category/ai
- **Engineering Blog (Agents):** https://www.anthropic.com/engineering
---
## TypeScript & Zod
- **Zod Documentation:** https://zod.dev/
- **TypeScript Handbook:** https://www.typescriptlang.org/docs/
---
## Complementary Skills
For complete AI SDK coverage, also see:
- **ai-sdk-ui skill:** Frontend React hooks (useChat, useCompletion, useObject)
- **cloudflare-workers-ai skill:** Native Cloudflare Workers AI binding (no multi-provider)
---
## Quick Navigation
### I want to...
**Generate text:**
- Docs: https://ai-sdk.dev/docs/ai-sdk-core/generating-text
- Template: `templates/generate-text-basic.ts`
**Stream text:**
- Docs: https://ai-sdk.dev/docs/ai-sdk-core/streaming-text
- Template: `templates/stream-text-chat.ts`
**Generate structured output:**
- Docs: https://ai-sdk.dev/docs/ai-sdk-core/generating-structured-data
- Template: `templates/generate-object-zod.ts`
**Use tools:**
- Docs: https://ai-sdk.dev/docs/ai-sdk-core/tools-and-tool-calling
- Template: `templates/tools-basic.ts`
**Build an agent:**
- Docs: https://ai-sdk.dev/docs/agents/overview
- Template: `templates/agent-with-tools.ts`
**Migrate from v4:**
- Docs: https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
- Reference: `references/v5-breaking-changes.md`
**Fix an error:**
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors
- Reference: `references/top-errors.md`
**Set up a provider:**
- Reference: `references/providers-quickstart.md`
**Deploy to production:**
- Reference: `references/production-patterns.md`
---
**Last Updated:** 2025-10-21

View File

@@ -0,0 +1,621 @@
# AI SDK Core - Production Patterns
Best practices for deploying AI SDK Core in production environments.
---
## Performance Optimization
### 1. Streaming for Long-Form Content
**Always use streaming for user-facing long-form content:**
```typescript
// ✅ GOOD: User-facing (better perceived performance)
app.post('/chat', async (req, res) => {
const stream = streamText({
model: openai('gpt-4'),
prompt: req.body.message,
});
return stream.toDataStreamResponse();
});
// ❌ BAD: User waits for entire response
app.post('/chat', async (req, res) => {
const result = await generateText({
model: openai('gpt-4'),
prompt: req.body.message,
});
return res.json({ response: result.text });
});
// ✅ GOOD: Background tasks (no user waiting)
async function processDocument(doc: string) {
const result = await generateText({
model: openai('gpt-4'),
prompt: `Analyze: ${doc}`,
});
await saveToDatabase(result.text);
}
```
### 2. Set Appropriate maxOutputTokens
```typescript
// ✅ GOOD: Limit token usage based on use case
const shortSummary = await generateText({
model: openai('gpt-4'),
prompt: 'Summarize in 2 sentences',
maxOutputTokens: 100, // Prevents over-generation
});
const article = await generateText({
model: openai('gpt-4'),
prompt: 'Write article',
maxOutputTokens: 2000, // Appropriate for long-form
});
// ❌ BAD: No limit (can waste tokens/money)
const unlimited = await generateText({
model: openai('gpt-4'),
prompt: 'Write something',
// No maxOutputTokens
});
```
### 3. Cache Provider Instances
```typescript
// ✅ GOOD: Reuse provider instances
const gpt4 = openai('gpt-4-turbo');
const claude = anthropic('claude-3-5-sonnet-20241022');
app.post('/chat', async (req, res) => {
const result = await generateText({
model: gpt4, // Reuse
prompt: req.body.message,
});
return res.json({ response: result.text });
});
// ❌ BAD: Create new instance every time
app.post('/chat', async (req, res) => {
const result = await generateText({
model: openai('gpt-4-turbo'), // New instance each call
prompt: req.body.message,
});
});
```
### 4. Optimize Zod Schemas (Especially in Workers)
```typescript
// ❌ BAD: Complex schema at top level (slow startup)
const ComplexSchema = z.object({
// 50+ fields with deep nesting
});
// ✅ GOOD: Define schemas inside functions
function generateStructuredData() {
const schema = z.object({
// Schema definition here
});
return generateObject({ model: openai('gpt-4'), schema, prompt: '...' });
}
// ✅ GOOD: Split into smaller reusable schemas
const AddressSchema = z.object({ street: z.string(), city: z.string() });
const PersonSchema = z.object({ name: z.string(), address: AddressSchema });
```
---
## Error Handling
### 1. Wrap All AI Calls in Try-Catch
```typescript
async function generateSafely(prompt: string) {
try {
const result = await generateText({
model: openai('gpt-4'),
prompt,
});
return { success: true, data: result.text };
} catch (error) {
if (error instanceof AI_APICallError) {
console.error('API call failed:', error.statusCode, error.message);
return { success: false, error: 'AI service temporarily unavailable' };
} else if (error instanceof AI_NoContentGeneratedError) {
console.error('No content generated');
return { success: false, error: 'Unable to generate response' };
} else {
console.error('Unknown error:', error);
return { success: false, error: 'An error occurred' };
}
}
}
```
### 2. Handle Specific Error Types
```typescript
import {
AI_APICallError,
AI_NoObjectGeneratedError,
AI_TypeValidationError,
AI_RetryError,
} from 'ai';
async function robustGeneration(prompt: string) {
try {
return await generateText({ model: openai('gpt-4'), prompt });
} catch (error) {
switch (error.constructor) {
case AI_APICallError:
if (error.statusCode === 429) {
// Rate limit - wait and retry
await wait(5000);
return retry();
} else if (error.statusCode >= 500) {
// Provider issue - try fallback
return generateText({ model: anthropic('claude-3-5-sonnet-20241022'), prompt });
}
break;
case AI_RetryError:
// All retries failed - use fallback provider
return generateText({ model: google('gemini-2.5-pro'), prompt });
case AI_NoContentGeneratedError:
// Content filtered - return safe message
return { text: 'Unable to generate response for this input.' };
default:
throw error;
}
}
}
```
### 3. Implement Retry Logic
```typescript
async function generateWithRetry(prompt: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await generateText({
model: openai('gpt-4'),
prompt,
maxRetries: 2, // Built-in retry
});
} catch (error) {
if (i === maxRetries - 1) throw error; // Last attempt failed
// Exponential backoff
const delay = Math.pow(2, i) * 1000;
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
```
### 4. Log Errors Properly
```typescript
function logAIError(error: any, context: Record<string, any>) {
const errorLog = {
timestamp: new Date().toISOString(),
type: error.constructor.name,
message: error.message,
statusCode: error.statusCode,
responseBody: error.responseBody,
context,
stack: error.stack,
};
// Send to monitoring service (e.g., Sentry, Datadog)
console.error('AI SDK Error:', JSON.stringify(errorLog));
// Track metrics
metrics.increment('ai.error', {
type: error.constructor.name,
statusCode: error.statusCode,
});
}
try {
const result = await generateText({ model: openai('gpt-4'), prompt });
} catch (error) {
logAIError(error, { prompt, model: 'gpt-4' });
throw error;
}
```
---
## Cost Optimization
### 1. Choose Appropriate Models
```typescript
// Model selection based on task complexity
async function generateWithCostOptimization(prompt: string, complexity: 'simple' | 'medium' | 'complex') {
const models = {
simple: openai('gpt-3.5-turbo'), // $0.50 / 1M tokens
medium: openai('gpt-4-turbo'), // $10 / 1M tokens
complex: openai('gpt-4'), // $30 / 1M tokens
};
return generateText({
model: models[complexity],
prompt,
});
}
// Usage
await generateWithCostOptimization('Translate to Spanish', 'simple');
await generateWithCostOptimization('Analyze sentiment', 'medium');
await generateWithCostOptimization('Complex reasoning task', 'complex');
```
### 2. Set Token Limits
```typescript
// Prevent runaway costs
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Write essay',
maxOutputTokens: 500, // Hard limit
});
// Adjust limits per use case
const limits = {
chatMessage: 200,
summary: 300,
article: 2000,
analysis: 1000,
};
```
### 3. Cache Results
```typescript
import { LRUCache } from 'lru-cache';
const cache = new LRUCache<string, string>({
max: 1000, // Max 1000 items
ttl: 1000 * 60 * 60, // 1 hour TTL
});
async function generateWithCache(prompt: string) {
const cacheKey = `ai:${hash(prompt)}`;
// Check cache
const cached = cache.get(cacheKey);
if (cached) {
console.log('Cache hit');
return { text: cached, cached: true };
}
// Generate
const result = await generateText({
model: openai('gpt-4'),
prompt,
});
// Store in cache
cache.set(cacheKey, result.text);
return { text: result.text, cached: false };
}
```
### 4. Monitor Usage
```typescript
// Track token usage
let totalTokensUsed = 0;
let totalCost = 0;
async function generateWithTracking(prompt: string) {
const result = await generateText({
model: openai('gpt-4'),
prompt,
});
// Track tokens
totalTokensUsed += result.usage.totalTokens;
// Estimate cost (GPT-4: $30/1M tokens)
const cost = (result.usage.totalTokens / 1_000_000) * 30;
totalCost += cost;
console.log(`Tokens: ${result.usage.totalTokens}, Cost: $${cost.toFixed(4)}`);
console.log(`Total tokens: ${totalTokensUsed}, Total cost: $${totalCost.toFixed(2)}`);
return result;
}
```
---
## Cloudflare Workers Best Practices
### 1. Lazy Initialization
```typescript
// ✅ GOOD: Import inside handler
export default {
async fetch(request, env) {
const { generateText } = await import('ai');
const { createWorkersAI } = await import('workers-ai-provider');
const workersai = createWorkersAI({ binding: env.AI });
const result = await generateText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'Hello',
});
return new Response(result.text);
}
};
// ❌ BAD: Top-level imports (startup overhead)
import { generateText } from 'ai';
const workersai = createWorkersAI({ binding: env.AI }); // Runs at startup!
```
### 2. Monitor Startup Time
```bash
# Wrangler reports startup time
npx wrangler deploy
# Output shows:
# Startup Time: 287ms (must be <400ms)
```
### 3. Handle Streaming Properly
```typescript
app.post('/chat/stream', async (c) => {
const workersai = createWorkersAI({ binding: c.env.AI });
const stream = streamText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'Hello',
});
// Return ReadableStream for Workers
return new Response(stream.toTextStream(), {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'X-Content-Type-Options': 'nosniff',
},
});
});
```
---
## Next.js / Vercel Best Practices
### 1. Server Actions for Mutations
```typescript
// app/actions.ts
'use server';
export async function generateContent(input: string) {
const result = await generateText({
model: openai('gpt-4'),
prompt: input,
maxOutputTokens: 500,
});
return result.text;
}
// app/page.tsx (Client Component)
'use client';
import { generateContent } from './actions';
export default function Page() {
const [loading, setLoading] = useState(false);
async function handleSubmit(formData: FormData) {
setLoading(true);
const result = await generateContent(formData.get('input') as string);
setLoading(false);
}
return <form action={handleSubmit}>...</form>;
}
```
### 2. Server Components for Initial Loads
```typescript
// app/page.tsx (Server Component)
export default async function Page() {
// Generate on server
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Welcome message',
});
// No loading state needed
return <div>{result.text}</div>;
}
```
### 3. API Routes for Streaming
```typescript
// app/api/chat/route.ts
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.toDataStreamResponse();
}
```
---
## Monitoring and Logging
### 1. Track Key Metrics
```typescript
// Token usage
metrics.gauge('ai.tokens.total', result.usage.totalTokens);
metrics.gauge('ai.tokens.prompt', result.usage.promptTokens);
metrics.gauge('ai.tokens.completion', result.usage.completionTokens);
// Response time
const startTime = Date.now();
const result = await generateText({ model: openai('gpt-4'), prompt });
metrics.timing('ai.response_time', Date.now() - startTime);
// Error rate
metrics.increment('ai.errors', { type: error.constructor.name });
```
### 2. Structured Logging
```typescript
import winston from 'winston';
const logger = winston.createLogger({
format: winston.format.json(),
transports: [new winston.transports.Console()],
});
logger.info('AI generation started', {
model: 'gpt-4',
promptLength: prompt.length,
userId: user.id,
});
const result = await generateText({ model: openai('gpt-4'), prompt });
logger.info('AI generation completed', {
model: 'gpt-4',
tokensUsed: result.usage.totalTokens,
responseLength: result.text.length,
duration: Date.now() - startTime,
});
```
---
## Rate Limiting
### 1. Queue Requests
```typescript
import PQueue from 'p-queue';
// Limit: 50 requests per minute
const queue = new PQueue({
concurrency: 5,
interval: 60000,
intervalCap: 50,
});
async function generateQueued(prompt: string) {
return queue.add(() =>
generateText({ model: openai('gpt-4'), prompt })
);
}
```
### 2. Monitor Rate Limits
```typescript
async function generateWithRateCheck(prompt: string) {
const result = await generateText({
model: openai('gpt-4'),
prompt,
});
// Check rate limit headers (provider-specific)
console.log('Remaining requests:', response.headers['x-ratelimit-remaining']);
console.log('Resets at:', response.headers['x-ratelimit-reset']);
return result;
}
```
---
## Security
### 1. Sanitize User Inputs
```typescript
function sanitizePrompt(userInput: string): string {
// Remove potential prompt injections
return userInput
.replace(/system:/gi, '')
.replace(/ignore previous/gi, '')
.slice(0, 1000); // Limit length
}
const result = await generateText({
model: openai('gpt-4'),
prompt: sanitizePrompt(req.body.message),
});
```
### 2. Validate API Keys
```typescript
// Startup validation
function validateEnv() {
const required = ['OPENAI_API_KEY', 'ANTHROPIC_API_KEY'];
for (const key of required) {
if (!process.env[key]) {
throw new Error(`Missing: ${key}`);
}
if (!process.env[key].match(/^sk-/)) {
throw new Error(`Invalid format: ${key}`);
}
}
}
validateEnv();
```
---
## Deployment
See Vercel's official deployment documentation:
https://vercel.com/docs/functions
For Cloudflare Workers:
https://developers.cloudflare.com/workers/
---
**Last Updated:** 2025-10-21

View File

@@ -0,0 +1,329 @@
# AI SDK Core - Providers Quick Start
Quick reference for setting up the top 4 AI providers with AI SDK v5.
---
## OpenAI
**Package:** `@ai-sdk/openai`
**Version:** 2.0.53+
**Maturity:** Excellent
### Setup
```bash
npm install @ai-sdk/openai
```
```bash
# .env
OPENAI_API_KEY=sk-...
```
### Usage
```typescript
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
const result = await generateText({
model: openai('gpt-4-turbo'),
prompt: 'Hello',
});
```
### Available Models
| Model | Use Case | Cost | Speed |
|-------|----------|------|-------|
| gpt-5 | Latest (if available) | High | Medium |
| gpt-4-turbo | Complex reasoning | High | Medium |
| gpt-4 | High quality | High | Slow |
| gpt-3.5-turbo | Simple tasks | Low | Fast |
### Common Errors
- **401 Unauthorized**: Invalid API key
- **429 Rate Limit**: Exceeded RPM/TPM limits
- **500 Server Error**: OpenAI service issue
### Links
- Docs: https://ai-sdk.dev/providers/ai-sdk-providers/openai
- API Keys: https://platform.openai.com/api-keys
- Rate Limits: https://platform.openai.com/account/rate-limits
---
## Anthropic
**Package:** `@ai-sdk/anthropic`
**Version:** 2.0.0+
**Maturity:** Excellent
### Setup
```bash
npm install @ai-sdk/anthropic
```
```bash
# .env
ANTHROPIC_API_KEY=sk-ant-...
```
### Usage
```typescript
import { anthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
const result = await generateText({
model: anthropic('claude-3-5-sonnet-20241022'),
prompt: 'Hello',
});
```
### Available Models
| Model | Use Case | Context | Speed |
|-------|----------|---------|-------|
| claude-3-5-sonnet-20241022 | Best balance | 200K | Medium |
| claude-3-opus-20240229 | Highest intelligence | 200K | Slow |
| claude-3-haiku-20240307 | Fast and cheap | 200K | Fast |
### Common Errors
- **authentication_error**: Invalid API key
- **rate_limit_error**: Rate limit exceeded
- **overloaded_error**: Service overloaded, retry
### Links
- Docs: https://ai-sdk.dev/providers/ai-sdk-providers/anthropic
- API Keys: https://console.anthropic.com/
- Model Details: https://docs.anthropic.com/en/docs/models-overview
---
## Google
**Package:** `@ai-sdk/google`
**Version:** 2.0.0+
**Maturity:** Excellent
### Setup
```bash
npm install @ai-sdk/google
```
```bash
# .env
GOOGLE_GENERATIVE_AI_API_KEY=...
```
### Usage
```typescript
import { google } from '@ai-sdk/google';
import { generateText } from 'ai';
const result = await generateText({
model: google('gemini-2.5-pro'),
prompt: 'Hello',
});
```
### Available Models
| Model | Use Case | Context | Free Tier |
|-------|----------|---------|-----------|
| gemini-2.5-pro | Complex reasoning | 1M | Generous |
| gemini-2.5-flash | Fast & efficient | 1M | Generous |
| gemini-2.5-flash-lite | Ultra-fast | 1M | Generous |
### Common Errors
- **SAFETY**: Content filtered by safety settings
- **QUOTA_EXCEEDED**: Rate limit exceeded
- **INVALID_ARGUMENT**: Invalid parameters
### Links
- Docs: https://ai-sdk.dev/providers/ai-sdk-providers/google
- API Keys: https://aistudio.google.com/app/apikey
- Model Details: https://ai.google.dev/models/gemini
---
## Cloudflare Workers AI
**Package:** `workers-ai-provider`
**Version:** 2.0.0+
**Type:** Community Provider
**Maturity:** Good
### Setup
```bash
npm install workers-ai-provider
```
```jsonc
// wrangler.jsonc
{
"ai": {
"binding": "AI"
}
}
```
### Usage
```typescript
import { createWorkersAI } from 'workers-ai-provider';
import { generateText } from 'ai';
// In Cloudflare Worker handler
const workersai = createWorkersAI({ binding: env.AI });
const result = await generateText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'Hello',
});
```
### Available Models
| Model | Use Case | Notes |
|-------|----------|-------|
| @cf/meta/llama-3.1-8b-instruct | General purpose | Recommended |
| @cf/meta/llama-3.1-70b-instruct | Complex tasks | Slower |
| @cf/mistral/mistral-7b-instruct-v0.1 | Alternative | Good quality |
### Common Issues
- **Startup Limit**: Move imports inside handlers
- **270ms+**: Lazy-load AI SDK to avoid startup overhead
### Important Notes
1. **Startup Optimization Required:**
```typescript
// BAD: Top-level import causes startup overhead
const workersai = createWorkersAI({ binding: env.AI });
// GOOD: Lazy initialization
export default {
async fetch(request, env) {
const workersai = createWorkersAI({ binding: env.AI });
// Use here
}
}
```
2. **When to Use:**
- Multi-provider scenarios (OpenAI + Workers AI)
- Using AI SDK UI hooks
- Need consistent API across providers
3. **When to Use Native Binding:**
- Cloudflare-only deployment
- Maximum performance
- See: `cloudflare-workers-ai` skill
### Links
- Docs: https://ai-sdk.dev/providers/community-providers/cloudflare-workers-ai
- Models: https://developers.cloudflare.com/workers-ai/models/
- GitHub: https://github.com/cloudflare/ai/tree/main/packages/workers-ai-provider
---
## Provider Comparison
| Feature | OpenAI | Anthropic | Google | Cloudflare |
|---------|--------|-----------|--------|------------|
| **Quality** | Excellent | Excellent | Excellent | Good |
| **Speed** | Medium | Medium | Fast | Fast |
| **Cost** | Medium | Medium | Low | Lowest |
| **Context** | 128K | 200K | 1M | 128K |
| **Structured Output** | ✅ | ✅ | ✅ | ⚠️ |
| **Tool Calling** | ✅ | ✅ | ✅ | ⚠️ |
| **Streaming** | ✅ | ✅ | ✅ | ✅ |
| **Free Tier** | ❌ | ❌ | ✅ | ✅ |
---
## Multi-Provider Setup
```typescript
import { openai } from '@ai-sdk/openai';
import { anthropic } from '@ai-sdk/anthropic';
import { google } from '@ai-sdk/google';
import { generateText } from 'ai';
// Use different providers for different tasks
const complexTask = await generateText({
model: openai('gpt-4'), // Best reasoning
prompt: 'Complex analysis...',
});
const longContext = await generateText({
model: anthropic('claude-3-5-sonnet-20241022'), // Long context
prompt: 'Document: ' + longDocument,
});
const fastTask = await generateText({
model: google('gemini-2.5-flash'), // Fast and cheap
prompt: 'Quick summary...',
});
```
---
## Fallback Pattern
```typescript
async function generateWithFallback(prompt: string) {
try {
return await generateText({ model: openai('gpt-4'), prompt });
} catch (error) {
console.error('OpenAI failed, trying Anthropic...');
try {
return await generateText({ model: anthropic('claude-3-5-sonnet-20241022'), prompt });
} catch (error2) {
console.error('Anthropic failed, trying Google...');
return await generateText({ model: google('gemini-2.5-pro'), prompt });
}
}
}
```
---
## All Providers
AI SDK supports 25+ providers. See full list:
https://ai-sdk.dev/providers/overview
**Other Official Providers:**
- xAI (Grok)
- Mistral
- Azure OpenAI
- Amazon Bedrock
- DeepSeek
- Groq
**Community Providers:**
- Ollama (local models)
- FriendliAI
- Portkey
- LM Studio
- Baseten
---
**Last Updated:** 2025-10-21

739
references/top-errors.md Normal file
View File

@@ -0,0 +1,739 @@
# AI SDK Core - Top 12 Errors & Solutions
Comprehensive guide to the most common AI SDK Core errors with actionable solutions.
---
## 1. AI_APICallError
**Type:** Network/API Error
**Frequency:** Very Common
**Severity:** High
### Cause
API request to provider failed due to:
- Invalid API key
- Network connectivity issues
- Rate limit exceeded
- Provider service outage
### Solution
```typescript
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);
// Handle specific status codes
if (error.statusCode === 401) {
// Invalid API key
console.error('Check OPENAI_API_KEY environment variable');
} else if (error.statusCode === 429) {
// Rate limit - implement exponential backoff
await wait(Math.pow(2, retryCount) * 1000);
// retry...
} else if (error.statusCode >= 500) {
// Provider issue - retry later
console.error('Provider service issue, retry in 1 minute');
}
}
}
```
### Prevention
- Validate API keys at application startup
- Implement retry logic with exponential backoff
- Monitor rate limits via response headers
- Handle network errors gracefully
- Set reasonable timeouts
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-api-call-error
---
## 2. AI_NoObjectGeneratedError
**Type:** Generation Error
**Frequency:** Common
**Severity:** Medium
### Cause
Model didn't generate a valid object matching the Zod schema:
- Schema too complex for model
- Prompt doesn't provide enough context
- Model capabilities exceeded
- Safety filters triggered
### Solution
```typescript
import { AI_NoObjectGeneratedError } from 'ai';
try {
const result = await generateObject({
model: openai('gpt-4'),
schema: z.object({
// Complex schema
name: z.string(),
age: z.number(),
nested: z.object({ /* ... */ }),
}),
prompt: 'Generate a person',
});
} catch (error) {
if (error instanceof AI_NoObjectGeneratedError) {
console.error('No valid object generated');
// Solutions:
// 1. Simplify schema
const simpler = z.object({
name: z.string(),
age: z.number(),
});
// 2. Add more context
const betterPrompt = 'Generate a person profile with name (string) and age (number, 18-80)';
// 3. Try different model
const result2 = await generateObject({
model: openai('gpt-4'), // GPT-4 better than 3.5 for complex objects
schema: simpler,
prompt: betterPrompt,
});
}
}
```
### Prevention
- Start with simple schemas, add complexity gradually
- Include examples in prompt: `"Generate like: { name: 'Alice', age: 30 }"`
- Use GPT-4 or Claude for complex structured output
- Test schemas with sample data first
- Add descriptions to schema fields using `.describe()`
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-no-object-generated-error
---
## 3. Worker Startup Limit (270ms+)
**Type:** Cloudflare Workers Issue
**Frequency:** Common (Workers only)
**Severity:** High (blocks deployment)
### Cause
AI SDK v5 + Zod initialization overhead exceeds Cloudflare Workers startup limit (must be <400ms):
- Top-level imports of AI SDK packages
- Complex Zod schemas at module level
- Provider initialization at startup
### Solution
```typescript
// ❌ BAD: Top-level imports cause startup overhead
import { createWorkersAI } from 'workers-ai-provider';
import { generateText } from 'ai';
import { complexSchema } from './schemas'; // Heavy Zod schemas
const workersai = createWorkersAI({ binding: env.AI }); // Runs at startup!
// ✅ GOOD: Lazy initialization inside handler
export default {
async fetch(request, env) {
// Import inside handler
const { createWorkersAI } = await import('workers-ai-provider');
const { generateText } = await import('ai');
const workersai = createWorkersAI({ binding: env.AI });
const result = await generateText({
model: workersai('@cf/meta/llama-3.1-8b-instruct'),
prompt: 'Hello',
});
return new Response(result.text);
}
};
```
### Alternative Solution (Move Schemas Inside Routes)
```typescript
// ❌ BAD: Top-level schema
import { z } from 'zod';
const PersonSchema = z.object({ /* complex schema */ });
// ✅ GOOD: Schema inside handler
export default {
async fetch(request, env) {
const { z } = await import('zod');
const PersonSchema = z.object({ /* complex schema */ });
// Use schema here
}
};
```
### Prevention
- Never initialize AI SDK at module top-level in Workers
- Move all imports inside route handlers
- Minimize top-level Zod schemas
- Monitor Worker startup time: `wrangler deploy` shows startup duration
- Target < 270ms startup time to be safe (limit is 400ms)
### Resources
- Cloudflare Workers AI Docs: https://developers.cloudflare.com/workers-ai/configuration/ai-sdk/
- GitHub: Search "Workers startup limit" in Vercel AI SDK issues
---
## 4. streamText Fails Silently
**Type:** Streaming Error
**Frequency:** Occasional
**Severity:** Medium (hard to debug)
### Cause
Stream errors are swallowed by `createDataStreamResponse()` or framework response handling:
- Error occurs during streaming
- Error handler not set up
- Response already committed
- Client disconnects
### Solution
```typescript
// ✅ GOOD: Add explicit error handling
const stream = streamText({
model: openai('gpt-4'),
prompt: 'Hello',
});
try {
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
} catch (error) {
// Error may not reach here if stream swallows it
console.error('Stream error:', error);
}
// ✅ BETTER: Always log on server side
console.log('Starting stream...');
const stream = streamText({
model: openai('gpt-4'),
prompt: 'Hello',
});
stream.result.then(
(result) => console.log('Stream success:', result.usage),
(error) => console.error('Stream failed:', error) // This will catch errors!
);
return stream.toDataStreamResponse();
```
### Prevention
- Always check server logs for stream errors
- Implement server-side error monitoring (e.g., Sentry)
- Test stream error handling explicitly
- Use `try-catch` around stream consumption
- Monitor for unexpected stream terminations
### Resources
- GitHub Issue: #4726
---
## 5. AI_LoadAPIKeyError
**Type:** Configuration Error
**Frequency:** Very Common (setup)
**Severity:** High (blocks usage)
### Cause
API key missing or invalid:
- `.env` file not loaded
- Wrong environment variable name
- API key format invalid
- Environment variable not set in deployment
### Solution
```typescript
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);
// Debugging steps:
console.log('OPENAI_API_KEY exists:', !!process.env.OPENAI_API_KEY);
console.log('Key starts with sk-:', process.env.OPENAI_API_KEY?.startsWith('sk-'));
// Common issues:
// 1. .env not loaded → use dotenv or similar
// 2. Wrong variable name → check provider docs
// 3. Key format wrong → verify in provider dashboard
}
}
```
### Prevention
```typescript
// Validate at startup
function validateEnv() {
const required = ['OPENAI_API_KEY', 'ANTHROPIC_API_KEY'];
for (const key of required) {
if (!process.env[key]) {
throw new Error(`Missing required environment variable: ${key}`);
}
}
}
validateEnv();
```
### Environment Variable Names
| Provider | Variable Name |
|----------|---------------|
| OpenAI | `OPENAI_API_KEY` |
| Anthropic | `ANTHROPIC_API_KEY` |
| Google | `GOOGLE_GENERATIVE_AI_API_KEY` |
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-load-api-key-error
---
## 6. AI_InvalidArgumentError
**Type:** Validation Error
**Frequency:** Common (development)
**Severity:** Low (easy to fix)
### Cause
Invalid parameters passed to AI SDK function:
- Negative `maxOutputTokens`
- Invalid temperature (must be 0-2)
- Wrong parameter types
- Missing required parameters
### Solution
```typescript
import { AI_InvalidArgumentError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
maxOutputTokens: -1, // ❌ Invalid!
temperature: 3.0, // ❌ Must be 0-2
prompt: 'Hello',
});
} catch (error) {
if (error instanceof AI_InvalidArgumentError) {
console.error('Invalid argument:', error.message);
// Fix: Check parameter types and values
}
}
```
### Prevention
- Use TypeScript for compile-time type checking
- Validate inputs before calling AI SDK functions
- Read function signatures carefully
- Check official docs for parameter constraints
- Use IDE autocomplete
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-invalid-argument-error
---
## 7. AI_NoContentGeneratedError
**Type:** Generation Error
**Frequency:** Occasional
**Severity:** Medium
### Cause
Model generated no content:
- Safety filters blocked output
- Prompt triggered content policy
- Model configuration issue
- Empty prompt
### Solution
```typescript
import { AI_NoContentGeneratedError } from 'ai';
try {
const result = await generateText({
model: openai('gpt-4'),
prompt: 'Some potentially problematic prompt',
});
} catch (error) {
if (error instanceof AI_NoContentGeneratedError) {
console.error('No content generated');
// Return user-friendly message
return {
text: 'Unable to generate response. Please try different input.',
error: true,
};
}
}
```
### Prevention
- Sanitize user inputs
- Avoid prompts that may trigger safety filters
- Have fallback messaging
- Log occurrences for analysis
- Test with edge cases
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-no-content-generated-error
---
## 8. AI_TypeValidationError
**Type:** Validation Error
**Frequency:** Common (with generateObject)
**Severity:** Medium
### Cause
Zod schema validation failed on generated output:
- Model output doesn't match schema
- Schema too strict
- Model misunderstood schema
- Invalid JSON generated
### Solution
```typescript
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
email: z.string().email(), // Strict format
}),
prompt: 'Generate person',
});
} catch (error) {
if (error instanceof AI_TypeValidationError) {
console.error('Validation failed:', error.message);
// Solutions:
// 1. Relax schema
const relaxed = z.object({
age: z.number(), // Remove min/max
email: z.string().optional(), // Make optional
});
// 2. Add guidance in prompt
const better = await generateObject({
model: openai('gpt-4'),
schema: relaxed,
prompt: 'Generate person with age 18-80 and valid email',
});
}
}
```
### Prevention
- Start with lenient schemas, tighten gradually
- Use `.optional()` for unreliable fields
- Add validation hints in field descriptions
- Test with various prompts
- Use mode: 'json' when available
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-type-validation-error
---
## 9. AI_RetryError
**Type:** Network Error
**Frequency:** Occasional
**Severity:** High
### Cause
All retry attempts failed:
- Persistent network issue
- Provider outage
- Invalid configuration
- Unreachable API endpoint
### Solution
```typescript
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);
console.error('Retry count:', error.retryCount);
// Implement circuit breaker
if (isProviderDown()) {
switchToFallbackProvider();
}
}
}
```
### Prevention
- Investigate root cause of failures
- Adjust retry configuration if needed
- Implement circuit breaker pattern
- Have fallback providers
- Monitor provider status pages
### Resources
- Docs: https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-retry-error
---
## 10. Rate Limiting Errors
**Type:** API Limit Error
**Frequency:** Common (production)
**Severity:** High
### Cause
Exceeded provider rate limits:
- RPM (Requests Per Minute) exceeded
- TPM (Tokens Per Minute) exceeded
- Concurrent request limit hit
- Free tier limits reached
### Solution
```typescript
// 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: any) {
if (error.statusCode === 429) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s, 8s...
console.log(`Rate limited, waiting ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
throw new Error('Rate limit retries exhausted');
}
// Or use queue
import PQueue from 'p-queue';
const queue = new PQueue({ concurrency: 5, interval: 60000, intervalCap: 50 });
async function generateQueued(prompt: string) {
return queue.add(() => generateText({ model: openai('gpt-4'), prompt }));
}
```
### Prevention
- Monitor rate limit headers in responses
- Queue requests to stay under limits
- Upgrade provider tier if needed
- Implement request throttling
- Cache results when possible
### Resources
- OpenAI Rate Limits: https://platform.openai.com/account/rate-limits
- Anthropic Rate Limits: https://docs.anthropic.com/en/api/rate-limits
---
## 11. TypeScript Performance with Zod
**Type:** Development Issue
**Frequency:** Occasional
**Severity:** Low (annoying)
### Cause
Complex Zod schemas slow down TypeScript type checking:
- Deeply nested schemas
- Many union types
- Recursive types
- Top-level complex schemas
### Solution
```typescript
// ❌ BAD: Complex schema at top level
const ComplexSchema = z.object({
// 100+ fields with nested objects...
});
// ✅ GOOD: Define inside function
function generateData() {
const schema = z.object({
// Complex schema here
});
return generateObject({ model: openai('gpt-4'), schema, prompt: '...' });
}
// ✅ GOOD: Use z.lazy() for recursive
type Category = { name: string; subcategories?: Category[] };
const CategorySchema: z.ZodType<Category> = z.lazy(() =>
z.object({
name: z.string(),
subcategories: z.array(CategorySchema).optional(),
})
);
// ✅ GOOD: Split large schemas
const AddressSchema = z.object({ /* ... */ });
const PersonSchema = z.object({
address: AddressSchema, // Reuse smaller schema
});
```
### Prevention
- Avoid top-level complex schemas
- Use `z.lazy()` for recursive types
- Split large schemas into smaller ones
- Use type assertions where appropriate
- Enable `skipLibCheck` in tsconfig.json if desperate
### Resources
- Troubleshooting: https://ai-sdk.dev/docs/troubleshooting/common-issues/slow-type-checking
---
## 12. Invalid JSON Response (Provider-Specific)
**Type:** Provider Issue
**Frequency:** Rare
**Severity:** Medium
### Cause
Some models occasionally return invalid JSON:
- Model error
- Provider API issue
- Specific model version bug (e.g., Imagen 3.0)
### Solution
```typescript
// Use built-in retry and mode selection
try {
const result = await generateObject({
model: openai('gpt-4'),
schema: mySchema,
prompt: 'Generate data',
mode: 'json', // Force JSON mode (GPT-4 supports this)
maxRetries: 3, // Retry on invalid JSON
});
} catch (error) {
// Fallback to different model
console.error('GPT-4 failed, trying Claude...');
const result2 = await generateObject({
model: anthropic('claude-3-5-sonnet-20241022'),
schema: mySchema,
prompt: 'Generate data',
});
}
```
### Prevention
- Use `mode: 'json'` when available
- Prefer GPT-4/Claude for structured output
- Implement retry logic
- Validate responses
- Have fallback models
### Resources
- GitHub Issue: #4302 (Imagen 3.0 Invalid JSON)
---
## For More Errors
See complete error reference (28 total error types):
https://ai-sdk.dev/docs/reference/ai-sdk-errors
---
**Last Updated:** 2025-10-21

View File

@@ -0,0 +1,522 @@
# AI SDK v4 → v5 Migration Guide
Complete guide to breaking changes from AI SDK v4 to v5.
---
## Overview
AI SDK v5 introduced **extensive breaking changes** to improve consistency, type safety, and functionality. This guide covers all critical changes with before/after examples.
**Migration Effort:** Medium-High (2-8 hours depending on codebase size)
**Automated Migration Available:**
```bash
npx ai migrate
```
---
## Core API Changes
### 1. Parameter Renames
**Change:** `maxTokens``maxOutputTokens`, `providerMetadata``providerOptions`
**Before (v4):**
```typescript
const result = await generateText({
model: openai.chat('gpt-4'),
maxTokens: 500,
providerMetadata: {
openai: { user: 'user-123' }
},
prompt: 'Hello',
});
```
**After (v5):**
```typescript
const result = await generateText({
model: openai('gpt-4'),
maxOutputTokens: 500,
providerOptions: {
openai: { user: 'user-123' }
},
prompt: 'Hello',
});
```
**Why:** `maxOutputTokens` is clearer that it limits generated tokens, not prompt tokens. `providerOptions` better reflects that it's for provider-specific configuration.
---
### 2. Tool Definitions
**Change:** `parameters``inputSchema`, tool properties renamed
**Before (v4):**
```typescript
const tools = {
weather: {
description: 'Get weather',
parameters: z.object({
location: z.string(),
}),
execute: async (args) => {
return { temp: 72, location: args.location };
},
},
};
// In tool call result:
console.log(toolCall.args); // { location: "SF" }
console.log(toolCall.result); // { temp: 72 }
```
**After (v5):**
```typescript
import { tool } from 'ai';
const tools = {
weather: tool({
description: 'Get weather',
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }) => {
return { temp: 72, location };
},
}),
};
// In tool call result:
console.log(toolCall.input); // { location: "SF" }
console.log(toolCall.output); // { temp: 72 }
```
**Why:** `inputSchema` clarifies it's a Zod schema. `input`/`output` are clearer than `args`/`result`.
---
### 3. Message Types
**Change:** `CoreMessage``ModelMessage`, `Message``UIMessage`
**Before (v4):**
```typescript
import { CoreMessage, convertToCoreMessages } from 'ai';
const messages: CoreMessage[] = [
{ role: 'user', content: 'Hello' },
];
const converted = convertToCoreMessages(uiMessages);
```
**After (v5):**
```typescript
import { ModelMessage, convertToModelMessages } from 'ai';
const messages: ModelMessage[] = [
{ role: 'user', content: 'Hello' },
];
const converted = convertToModelMessages(uiMessages);
```
**Why:** `ModelMessage` better reflects that these are messages for the model. `UIMessage` is for UI hooks.
---
### 4. Tool Error Handling
**Change:** `ToolExecutionError` removed, errors now appear as content parts
**Before (v4):**
```typescript
import { ToolExecutionError } from 'ai';
const tools = {
risky: {
execute: async (args) => {
throw new ToolExecutionError({
message: 'API failed',
cause: originalError,
});
},
},
};
// Error would stop execution
```
**After (v5):**
```typescript
const tools = {
risky: tool({
execute: async (input) => {
// Just throw regular errors
throw new Error('API failed');
},
}),
};
// Error appears as tool-error content part
// Model can see the error and retry or handle it
```
**Why:** Enables automated retry in multi-step scenarios. Model can see and respond to errors.
---
### 5. Multi-Step Execution
**Change:** `maxSteps``stopWhen` with conditions
**Before (v4):**
```typescript
const result = await generateText({
model: openai.chat('gpt-4'),
tools: { /* ... */ },
maxSteps: 5,
experimental_continueSteps: true,
prompt: 'Complex task',
});
```
**After (v5):**
```typescript
import { stopWhen, stepCountIs } from 'ai';
const result = await generateText({
model: openai('gpt-4'),
tools: { /* ... */ },
stopWhen: stepCountIs(5),
prompt: 'Complex task',
});
// Or stop on specific tool:
stopWhen: hasToolCall('finalize')
// Or custom condition:
stopWhen: (step) => step.stepCount > 5 || step.hasToolCall('finish')
```
**Why:** More flexible control over when multi-step execution stops. `experimental_continueSteps` no longer needed.
---
### 6. Message Structure
**Change:** Simple `content` string → `parts` array
**Before (v4):**
```typescript
const message = {
role: 'user',
content: 'Hello',
};
// Tool calls embedded in message differently
```
**After (v5):**
```typescript
const message = {
role: 'user',
content: [
{ type: 'text', text: 'Hello' },
],
};
// Tool calls as parts:
const messageWithTool = {
role: 'assistant',
content: [
{ type: 'text', text: 'Let me check...' },
{
type: 'tool-call',
toolCallId: '123',
toolName: 'weather',
args: { location: 'SF' },
},
],
};
```
**Part Types:**
- `text`: Text content
- `file`: File attachments
- `reasoning`: Extended thinking (Claude)
- `tool-call`: Tool invocation
- `tool-result`: Tool result
- `tool-error`: Tool error (new in v5)
**Why:** Unified structure for all content types. Enables richer message formats.
---
### 7. Streaming Architecture
**Change:** Single chunk format → start/delta/end lifecycle
**Before (v4):**
```typescript
stream.on('chunk', (chunk) => {
console.log(chunk.text);
});
```
**After (v5):**
```typescript
for await (const part of stream.fullStream) {
if (part.type === 'text-delta') {
console.log(part.textDelta);
} else if (part.type === 'finish') {
console.log('Stream finished:', part.finishReason);
}
}
// Or use simplified textStream:
for await (const text of stream.textStream) {
console.log(text);
}
```
**Stream Event Types:**
- `text-delta`: Text chunk
- `tool-call-delta`: Tool call chunk
- `tool-result`: Tool result
- `finish`: Stream complete
- `error`: Stream error
**Why:** Better structure for concurrent streaming and metadata.
---
### 8. Tool Streaming
**Change:** Enabled by default
**Before (v4):**
```typescript
const result = await generateText({
model: openai.chat('gpt-4'),
tools: { /* ... */ },
toolCallStreaming: true, // Opt-in
});
```
**After (v5):**
```typescript
const result = await generateText({
model: openai('gpt-4'),
tools: { /* ... */ },
// Tool streaming enabled by default
});
```
**Why:** Better UX. Tools stream by default for real-time feedback.
---
### 9. Package Reorganization
**Change:** Separate packages for RSC and React
**Before (v4):**
```typescript
import { streamUI } from 'ai/rsc';
import { useChat } from 'ai/react';
import { LangChainAdapter } from 'ai';
```
**After (v5):**
```typescript
import { streamUI } from '@ai-sdk/rsc';
import { useChat } from '@ai-sdk/react';
import { LangChainAdapter } from '@ai-sdk/langchain';
```
**Install:**
```bash
npm install @ai-sdk/rsc @ai-sdk/react @ai-sdk/langchain
```
**Why:** Cleaner package structure. Easier to tree-shake unused functionality.
---
## UI Hook Changes (See ai-sdk-ui Skill)
Brief summary (detailed in `ai-sdk-ui` skill):
1. **useChat Input Management:** No longer managed by hook
2. **useChat Actions:** `append()``sendMessage()`
3. **useChat Props:** `initialMessages``messages` (controlled)
4. **StreamData Removed:** Replaced by message streams
See: `ai-sdk-ui` skill for complete UI migration guide
---
## Provider-Specific Changes
### OpenAI
**Change:** Default API changed
**Before (v4):**
```typescript
const model = openai.chat('gpt-4'); // Uses Chat Completions API
```
**After (v5):**
```typescript
const model = openai('gpt-4'); // Uses Responses API
// strictSchemas: true → strictJsonSchema: true
```
**Why:** Responses API is newer and has better features.
---
### Google
**Change:** Search grounding moved to tool
**Before (v4):**
```typescript
const model = google.generativeAI('gemini-pro', {
googleSearchRetrieval: true,
});
```
**After (v5):**
```typescript
import { google, googleSearchRetrieval } from '@ai-sdk/google';
const result = await generateText({
model: google('gemini-pro'),
tools: {
search: googleSearchRetrieval(),
},
prompt: 'Search for...',
});
```
**Why:** More flexible. Search is now a tool like others.
---
## Migration Checklist
- [ ] Update package versions (`ai@^5.0.76`, `@ai-sdk/openai@^2.0.53`, etc.)
- [ ] Run automated migration: `npx ai migrate`
- [ ] Review automated changes
- [ ] Update all `maxTokens``maxOutputTokens`
- [ ] Update `providerMetadata``providerOptions`
- [ ] Convert tool `parameters``inputSchema`
- [ ] Update tool properties: `args``input`, `result``output`
- [ ] Replace `maxSteps` with `stopWhen(stepCountIs(n))`
- [ ] Update message types: `CoreMessage``ModelMessage`
- [ ] Remove `ToolExecutionError` handling (just throw errors)
- [ ] Update package imports (`ai/rsc``@ai-sdk/rsc`)
- [ ] Test streaming behavior
- [ ] Update TypeScript types
- [ ] Test tool calling
- [ ] Test multi-step execution
- [ ] Check for message structure changes in your code
- [ ] Update any custom error handling
- [ ] Test with real API calls
---
## Common Migration Errors
### Error: "maxTokens is not a valid parameter"
**Solution:** Change to `maxOutputTokens`
### Error: "ToolExecutionError is not exported from 'ai'"
**Solution:** Remove ToolExecutionError, just throw regular errors
### Error: "Cannot find module 'ai/rsc'"
**Solution:** Install and import from `@ai-sdk/rsc`
```bash
npm install @ai-sdk/rsc
import { streamUI } from '@ai-sdk/rsc';
```
### Error: "model.chat is not a function"
**Solution:** Remove `.chat()` call
```typescript
// Before: openai.chat('gpt-4')
// After: openai('gpt-4')
```
### Error: "maxSteps is not a valid parameter"
**Solution:** Use `stopWhen(stepCountIs(n))`
---
## Testing After Migration
```typescript
// Test basic generation
const test1 = await generateText({
model: openai('gpt-4'),
prompt: 'Hello',
});
console.log('✅ Basic generation:', test1.text);
// Test streaming
const test2 = streamText({
model: openai('gpt-4'),
prompt: 'Hello',
});
for await (const chunk of test2.textStream) {
process.stdout.write(chunk);
}
console.log('\n✅ Streaming works');
// Test structured output
const test3 = await generateObject({
model: openai('gpt-4'),
schema: z.object({ name: z.string() }),
prompt: 'Generate a person',
});
console.log('✅ Structured output:', test3.object);
// Test tools
const test4 = await generateText({
model: openai('gpt-4'),
tools: {
test: tool({
description: 'Test tool',
inputSchema: z.object({ value: z.string() }),
execute: async ({ value }) => ({ result: value }),
}),
},
prompt: 'Use the test tool with value "hello"',
});
console.log('✅ Tools work');
```
---
## Resources
- **Official Migration Guide:** https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
- **Automated Migration:** `npx ai migrate`
- **GitHub Discussions:** https://github.com/vercel/ai/discussions
- **v5 Release Blog:** https://vercel.com/blog/ai-sdk-5
---
**Last Updated:** 2025-10-21