7.1 KiB
Les 17: Vercel AI SDK - AI Features in je App
Hoofdstuk
Deel 4: Advanced AI Features (Les 13-18)
Beschrijving
Bouw AI-powered features in je apps met de Vercel AI SDK. Leer hoe je chat interfaces, streaming responses en AI-gegenereerde content implementeert.
Te Behandelen
Groepsdiscussie (15 min)
Bespreek klassikaal de Cursor .cursorrules ervaringen uit Les 16 - welke regels zorgen voor betere AI output?
Waarom Vercel AI SDK?
Het probleem: Direct API calls naar OpenAI/Anthropic zijn complex:
- Streaming handmatig implementeren
- Error handling
- State management
De oplossing: Vercel AI SDK
- Simpele React hooks
- Built-in streaming
- Provider-agnostic (OpenAI, Anthropic, etc.)
- Edge-ready
Installatie & Setup
npm install ai @ai-sdk/openai
# of voor Anthropic:
npm install ai @ai-sdk/anthropic
Environment variable:
# .env.local
OPENAI_API_KEY=sk-xxxxx
Core Hooks
useChat - Voor Conversaties
'use client'
import { useChat } from 'ai/react'
export function ChatComponent() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat()
return (
<div className="flex flex-col h-screen">
<div className="flex-1 overflow-y-auto p-4">
{messages.map(m => (
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
<span className="inline-block p-2 rounded-lg bg-gray-100">
{m.content}
</span>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="p-4 border-t">
<input
value={input}
onChange={handleInputChange}
placeholder="Type a message..."
className="w-full p-2 border rounded"
/>
<button type="submit" disabled={isLoading}>
{isLoading ? 'Sending...' : 'Send'}
</button>
</form>
</div>
)
}
useCompletion - Voor Single Completions
import { useCompletion } from 'ai/react'
export function SummaryComponent() {
const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion()
return (
<div>
<form onSubmit={handleSubmit}>
<textarea
value={input}
onChange={handleInputChange}
placeholder="Paste text to summarize..."
/>
<button type="submit">Summarize</button>
</form>
{completion && <p>{completion}</p>}
</div>
)
}
API Routes
app/api/chat/route.ts:
import { openai } from '@ai-sdk/openai'
import { streamText } from 'ai'
export async function POST(req: Request) {
const { messages } = await req.json()
const result = streamText({
model: openai('gpt-4o-mini'),
system: 'You are a helpful cooking assistant. Suggest recipes based on ingredients.',
messages,
})
return result.toDataStreamResponse()
}
Met custom system prompt:
const result = streamText({
model: openai('gpt-4o-mini'),
system: `You are a recipe assistant for the AI Recipe Generator app.
When the user provides ingredients:
1. Suggest 2-3 recipes they could make
2. List required additional ingredients (if any)
3. Provide brief cooking instructions
Be concise and practical.`,
messages,
})
Streaming Responses
Waarom streaming?
- Betere UX (user ziet direct resultaat)
- Snellere perceived performance
- Geen wachten op complete response
Hoe het werkt:
- Server stuurt tokens één voor één
- Client rendert elke token direct
- User ziet "typing" effect
Loading indicator:
{isLoading && (
<div className="flex items-center gap-2">
<div className="animate-pulse">●</div>
<span>AI is thinking...</span>
</div>
)}
Integratie met Supabase
Conversations opslaan:
// Maak tabel in Supabase:
// conversations: id, user_id, created_at
// messages: id, conversation_id, role, content, created_at
// Na elke message:
async function saveMessage(conversationId: string, role: string, content: string) {
await supabase.from('messages').insert({
conversation_id: conversationId,
role,
content
})
}
In je component:
const { messages, input, handleSubmit } = useChat({
onFinish: async (message) => {
await saveMessage(conversationId, message.role, message.content)
}
})
Error Handling
const { messages, error, reload } = useChat()
{error && (
<div className="p-4 bg-red-100 text-red-700 rounded">
<p>Something went wrong. Please try again.</p>
<button onClick={reload}>Retry</button>
</div>
)}
Cost Management
Model keuze:
| Model | Kosten | Gebruik voor |
|---|---|---|
| gpt-4o-mini | Goedkoop | Meeste taken |
| gpt-4o | Duur | Complexe reasoning |
| claude-3-haiku | Goedkoop | Simpele taken |
| claude-3-sonnet | Medium | Balans |
Bespaartips:
- Gebruik gpt-4o-mini als default
- Korte system prompts
- Beperk conversation history
- Caching waar mogelijk
Tools
- Vercel AI SDK (
aipackage) - Next.js API Routes
- OpenAI API / Anthropic API
- Cursor
- Supabase
Lesopdracht (2 uur)
Bouw een AI Chat Component
Deel 1: Setup (20 min)
npm install ai @ai-sdk/openai- Voeg
OPENAI_API_KEYtoe aan.env.local - Maak
app/api/chat/route.ts
Deel 2: Basic Chat (40 min)
- Maak
components/Chat.tsx - Implementeer
useChathook - Bouw chat UI met Tailwind
- Test streaming werkt
Deel 3: System Prompt (30 min)
- Schrijf system prompt voor je eindproject:
- Recipe Generator: cooking assistant
- Budget Buddy: financial advisor
- Travel Planner: travel expert
- Test met relevante vragen
Deel 4: Supabase Integratie (30 min)
- Maak
messagestabel - Sla berichten op met
onFinish - Laad history bij page load
Deliverable
- Werkende AI chat met streaming
- Custom system prompt
- Messages opgeslagen in Supabase
Huiswerk (2 uur)
Bouw AI Feature voor Eindproject
Deel 1: Core AI Feature (1 uur)
Implementeer de AI chat die past bij je eindproject:
| Project | AI Feature |
|---|---|
| Recipe Generator | "Wat kan ik maken met kip en rijst?" |
| Budget Buddy | "Analyseer mijn uitgaven deze maand" |
| Travel Planner | "Plan een weekend Barcelona" |
- Custom system prompt
- Context uit je database meegeven
Deel 2: UX Polish (30 min)
Voeg toe:
- Streaming indicator
- Suggested prompts / quick actions
- Copy response button
- Clear chat button
- Error handling
Deel 3: Documentatie (30 min)
Maak docs/AI-FEATURE.md:
- Welke AI feature heb je gebouwd?
- Wat doet de system prompt?
- Hoe integreert het met Supabase?
- Welke model keuzes heb je gemaakt?
Deliverable
- AI feature in eindproject
- Deployed preview
- AI-FEATURE.md documentatie
Leerdoelen
Na deze les kan de student:
- Vercel AI SDK installeren en configureren
useChatenuseCompletionhooks gebruiken- Streaming responses implementeren
- API routes opzetten voor AI providers
- Custom system prompts schrijven
- Chat history opslaan in Supabase
- Error handling en loading states implementeren
- Kostenbewust omgaan met AI APIs