Vercel AI SDK Skill
Provider-agnostic TypeScript toolkit — streaming, tools, structured output, agents cho Next.js/React. Source: vercel/ai (MIT)
Install
npm install ai
# Provider cụ thể
npm install @ai-sdk/anthropic @ai-sdk/openai @ai-sdk/google
Core APIs
generateText — one-shot
import { generateText } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'
const { text } = await generateText({
model: anthropic('claude-sonnet-4-6'),
prompt: 'Giải thích async/await trong 3 câu',
})
console.log(text)
streamText — streaming response
import { streamText } from 'ai'
const result = streamText({
model: anthropic('claude-sonnet-4-6'),
prompt: 'Viết một bài thơ về Hà Nội',
})
for await (const chunk of result.textStream) {
process.stdout.write(chunk)
}
generateObject — structured output (Zod)
import { generateObject } from 'ai'
import { z } from 'zod'
const { object } = await generateObject({
model: anthropic('claude-sonnet-4-6'),
schema: z.object({
title: z.string(),
tags: z.array(z.string()),
priority: z.enum(['low', 'medium', 'high']),
}),
prompt: 'Tạo một task: fix bug login timeout',
})
// object.title, object.tags, object.priority — type-safe
Tool calling
import { generateText, tool } from 'ai'
import { z } from 'zod'
const result = await generateText({
model: anthropic('claude-sonnet-4-6'),
tools: {
getWeather: tool({
description: 'Lấy thời tiết tại thành phố',
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => {
return { temp: 32, condition: 'sunny', city }
},
}),
},
maxSteps: 5, // cho phép multi-turn tool calls
prompt: 'Thời tiết Hà Nội hôm nay thế nào?',
})
console.log(result.text)
React / Next.js integration
Chat UI với useChat
// app/api/chat/route.ts
import { anthropic } from '@ai-sdk/anthropic'
import { streamText } from 'ai'
export async function POST(req: Request) {
const { messages } = await req.json()
const result = streamText({
model: anthropic('claude-sonnet-4-6'),
messages,
})
return result.toDataStreamResponse()
}
// app/page.tsx
'use client'
import { useChat } from 'ai/react'
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat()
return (
<div>
{messages.map(m => (
<div key={m.id}><b>{m.role}:</b> {m.content}</div>
))}
<form
<input value={input} placeholder="Nhập tin nhắn..." />
<button type="submit">Gửi</button>
</form>
</div>
)
}
useObject — streaming structured data
import { experimental_useObject as useObject } from 'ai/react'
import { taskSchema } from './schema'
export default function TaskGen() {
const { object, submit, isLoading } = useObject({
api: '/api/generate-task',
schema: taskSchema,
})
return (
<div>
<button => submit('Fix login bug')}>Generate</button>
{isLoading && <p>Đang tạo...</p>}
{object?.title && <h2>{object.title}</h2>}
</div>
)
}
Multi-modal (image input)
const { text } = await generateText({
model: anthropic('claude-sonnet-4-6'),
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'Mô tả ảnh này' },
{ type: 'image', image: new URL('https://example.com/image.png') },
],
}],
})
Provider switching (zero code change)
// Đổi provider chỉ cần đổi 1 dòng
import { openai } from '@ai-sdk/openai'
import { google } from '@ai-sdk/google'
const model = process.env.PROVIDER === 'openai'
? openai('gpt-4o')
: google('gemini-2.0-flash')
Middleware (logging, caching, rate limit)
import { wrapLanguageModel, extractReasoningMiddleware } from 'ai'
const model = wrapLanguageModel({
model: anthropic('claude-sonnet-4-6'),
middleware: extractReasoningMiddleware({ tagName: 'think' }),
})