Κατασκευάζοντας το Πρώτο σας Generative UI με το Vercel AI SDK
Βήμα-βήμα οδηγός για τη δημιουργία της πρώτης σας AI-powered διεπαφής με streaming συστατικά.
Προαπαιτούμενα
Πριν ξεκινήσουμε, βεβαιωθείτε ότι έχετε:
- Node.js 18+ εγκατεστημένο
- Ένα έργο Next.js 14+ που χρησιμοποιεί το App Router
- Ένα κλειδί API OpenAI (ή Anthropic — το SDK υποστηρίζει και τα δύο)
- Βασική εξοικείωση με τα React Server Components
Αν είστε νέος στο RSC, αφιερώστε 15 λεπτά στα έγγραφα του Next.js για τα Server Components πρώτα. Η συνάρτηση streamUI του Vercel AI SDK εξαρτάται από το RSC και γίνεται πολύ πιο κατανοητή μόλις κατανοήσετε το μοντέλο.
Τι Κατασκευάζουμε
Θα κατασκευάσουμε έναν απλό AI-powered βοηθό που παράγει διαδραστική διεπαφή βάσει prompt χρήστη. Στο τέλος αυτού του οδηγού, θα έχετε μια λειτουργική δυνατότητα Generative UI που:
- Λαμβάνει ένα prompt κειμένου από τον χρήστη
- Μεταδίδει με streaming συστατικά React πίσω από τον server
- Αποδίδει διαδραστικές κάρτες και γραφήματα βάσει των αποφάσεων του AI
Το παράδειγμα αφορά έναν χρηματοοικονομικό βοηθό που μπορεί να εμφανίζει τιμές μετοχών και δεδομένα καιρού — αρκετά απλό για γρήγορη κατανόηση, αρκετά σύνθετο για να δείξει πραγματικά μοτίβα.
⚠️ Το AI SDK RSC και το
streamUIείναι επισημασμένα από τη Vercel ως experimental. Για production projects η Vercel συνιστά το AI SDK UI (useChatαπό@ai-sdk/react). Αυτό το άρθρο δείχνει ένα λειτουργικό μοτίβο RSC streaming για πρωτότυπα, demos και ελεγχόμενα περιβάλλοντα· για production αξιολόγησε τους trade-offs και δες την ενότητα «Πότε το Vercel AI SDK ΔΕΝ είναι η κατάλληλη επιλογή». Migration guide RSC → UI.
Βήμα 1: Εγκατάσταση Εξαρτήσεων
npm install ai@^4 @ai-sdk/openai@^1 zod
Pin v4 — η τελευταία σειρά με RSC API στη μορφή parameters: και import από ai/rsc. Για v5+ δες τη σημείωση στο τέλος του άρθρου.
Το πακέτο ai είναι ο πυρήνας του Vercel AI SDK. Το @ai-sdk/openai είναι ο πάροχος OpenAI (αντικατέστησε με @ai-sdk/anthropic αν προτιμάς Claude). Το zod χειρίζεται την επικύρωση παραμέτρων εργαλείων — έτσι ορίζεις ποιες παραμέτρους μπορεί να περνά το AI σε κάθε συστατικό.
Προσθέστε το κλειδί API σας στο .env.local:
OPENAI_API_KEY=sk-...
Βήμα 2: Δημιουργία Βιβλιοθήκης Συστατικών
Ορίστε τα συστατικά που μπορεί να παράγει το AI. Αυτά είναι κανονικά συστατικά React — δεν έχουν τίποτα ειδικό για AI. Η βασική αρχή σχεδιασμού: κατασκευάστε συστατικά που είναι χρήσιμα αυτόνομα, και θα μπορούν να τα συνθέτει το AI.
// components/weather-card.tsx
interface WeatherCardProps {
city: string;
temperature: number;
conditions: string;
humidity: number;
}
export function WeatherCard({ city, temperature, conditions, humidity }: WeatherCardProps) {
return (
<div className="rounded-lg border bg-card p-6 shadow-sm">
<h3 className="text-lg font-semibold">{city}</h3>
<div className="mt-2 flex items-baseline gap-2">
<span className="text-4xl font-bold">{temperature}°C</span>
<span className="text-muted-foreground">{conditions}</span>
</div>
<p className="mt-2 text-sm text-muted-foreground">
Humidity: {humidity}%
</p>
</div>
);
}
// components/stock-ticker.tsx
interface StockTickerProps {
symbol: string;
price: number;
change: number;
changePercent: number;
}
export function StockTicker({ symbol, price, change, changePercent }: StockTickerProps) {
const isPositive = change >= 0;
const sign = isPositive ? '+' : '';
const color = isPositive ? 'text-green-600' : 'text-red-600';
return (
<div className="rounded-lg border bg-card p-6 shadow-sm">
<div className="flex items-center justify-between">
<h3 className="text-xl font-bold">{symbol}</h3>
<span className={`text-sm font-medium ${color}`}>
{sign}{changePercent.toFixed(2)}%
</span>
</div>
<div className="mt-2 flex items-baseline gap-2">
<span className="text-3xl font-bold">${price.toFixed(2)}</span>
<span className={`text-sm ${color}`}>
{sign}{change.toFixed(2)} today
</span>
</div>
</div>
);
}
// components/loading-skeleton.tsx
export function CardSkeleton({ height = 'h-32' }: { height?: string }) {
return (
<div className={`animate-pulse rounded-lg bg-muted ${height} w-full`} />
);
}
Βήμα 3: Ορισμός Εργαλείων AI (Server Action)
Αυτός είναι ο πυρήνας του Generative UI. Δημιουργήστε ένα server action που συνδέει τα συστατικά σας με το AI ως «εργαλεία» — συναρτήσεις που το μοντέλο μπορεί να αποφασίσει να καλέσει:
// app/actions.tsx
'use server';
import { streamUI } from 'ai/rsc';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';
import { WeatherCard } from '@/components/weather-card';
import { StockTicker } from '@/components/stock-ticker';
import { CardSkeleton } from '@/components/loading-skeleton';
export async function generateUI(prompt: string) {
const result = await streamUI({
model: openai('gpt-4o'),
system: `You are a helpful financial and information assistant.
Use the available tools to display information visually
whenever possible. Prefer showing components over text responses.
When asked about weather or stocks, always use the appropriate tool.`,
prompt,
tools: {
showWeather: {
description: 'Display current weather conditions for a city. Use this when the user asks about weather, temperature, or climate.',
parameters: z.object({
city: z.string().describe('The city name, e.g. "Paris" or "New York"'),
temperature: z.number().describe('Current temperature in Celsius'),
conditions: z.string().describe('Weather description, e.g. "Partly cloudy"'),
humidity: z.number().min(0).max(100).describe('Relative humidity percentage'),
}),
generate: async function* (params) {
// Yield skeleton αμέσως ενώ τα δεδομένα «φορτώνουν»
yield <CardSkeleton height="h-36" />;
// Σε πραγματική εφαρμογή, εδώ θα ανακτούσατε live δεδομένα καιρού
return <WeatherCard {...params} />;
},
},
showStock: {
description: 'Display a stock price and daily change. Use this when the user asks about stock prices, market data, or a company\'s shares.',
parameters: z.object({
symbol: z.string().describe('Stock ticker symbol, e.g. "AAPL" or "TSLA"'),
price: z.number().describe('Current stock price in USD'),
change: z.number().describe('Price change today in USD'),
changePercent: z.number().describe('Percentage price change today'),
}),
generate: async function* (params) {
yield <CardSkeleton height="h-32" />;
return <StockTicker {...params} />;
},
},
},
});
return result.value;
}
Τρία πράγματα αξίζει να κατανοήσετε για αυτόν τον κώδικα:
Η συνάρτηση generate είναι async generator. Η λέξη-κλειδί yield αποστέλλει το skeleton αμέσως — πριν το AI τελειώσει την επίλυση παραμέτρων. Το return αποστέλλει το τελικό συστατικό. Έτσι λειτουργεί το streaming Generative UI.
Οι περιγραφές εργαλείων είναι οδηγίες για το AI. Τα πεδία description είναι αυτό που διαβάζει το μοντέλο για να αποφασίσει ποιο εργαλείο θα καλέσει. Γράψτε τα με σαφήνεια, συμπεριλαμβάνοντας πότε το εργαλείο πρέπει και πότε δεν πρέπει να χρησιμοποιείται.
Τα σχήματα Zod επιβάλλουν τη σύμβαση. Το AI δεν μπορεί να περάσει άκυρες παραμέτρους αν ορίσετε αυστηρά σχήματα Zod. Τα σφάλματα επικύρωσης εντοπίζονται πριν αποδοθεί το συστατικό.
Βήμα 4: Κατασκευή της Διεπαφής
// app/page.tsx
'use client';
import { useState } from 'react';
import { generateUI } from './actions';
const EXAMPLE_PROMPTS = [
"What's the weather like in Tokyo?",
"Show me Apple's current stock price",
"Compare the weather in London and New York",
"How is Tesla stock doing?",
];
export default function Home() {
const [prompt, setPrompt] = useState('');
const [messages, setMessages] = useState<Array<{ prompt: string; ui: React.ReactNode }>>([]);
const [loading, setLoading] = useState(false);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!prompt.trim() || loading) return;
const currentPrompt = prompt;
setPrompt('');
setLoading(true);
const ui = await generateUI(currentPrompt);
setMessages(prev => [...prev, { prompt: currentPrompt, ui }]);
setLoading(false);
}
return (
<main className="mx-auto max-w-2xl p-8">
<h1 className="text-3xl font-bold">Generative UI Demo</h1>
<p className="mt-2 text-muted-foreground">
Ask about weather or stocks — watch the AI generate the right interface.
</p>
{/* Παραδείγματα prompt */}
<div className="mt-4 flex flex-wrap gap-2">
{EXAMPLE_PROMPTS.map(p => (
<button
key={p}
onClick={() => setPrompt(p)}
className="rounded-full border px-3 py-1 text-sm hover:bg-muted"
>
{p}
</button>
))}
</div>
{/* Πεδίο εισαγωγής prompt */}
<form onSubmit={handleSubmit} className="mt-6 flex gap-2">
<input
value={prompt}
onChange={e => setPrompt(e.target.value)}
placeholder="Ask anything..."
className="flex-1 rounded-md border bg-background px-4 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
/>
<button
type="submit"
disabled={loading || !prompt.trim()}
className="rounded-md bg-primary px-4 py-2 text-sm text-primary-foreground disabled:opacity-50"
>
{loading ? 'Generating...' : 'Ask'}
</button>
</form>
{/* Έξοδος παραγόμενης διεπαφής */}
<div className="mt-8 space-y-6">
{messages.map((msg, i) => (
<div key={i}>
<p className="mb-2 text-sm font-medium text-muted-foreground">
"{msg.prompt}"
</p>
{msg.ui}
</div>
))}
</div>
</main>
);
}
Βήμα 5: Εκτέλεση και Δοκιμή
npm run dev
Δοκιμάστε αυτά τα prompts με τη σειρά για να δείτε διαφορετικές συμπεριφορές:
- «What's the weather in Paris?» — μονή WeatherCard
- «Show me Apple stock» — μονό StockTicker
- «Compare the weather in London and New York» — το AI καλεί
showWeatherδύο φορές, παράγοντας δύο κάρτες δίπλα-δίπλα - «How's Tesla doing and what's the weather in San Francisco?» — το AI καλεί και τα δύο εργαλεία, παράγοντας μικτούς τύπους συστατικών
Το τρίτο prompt είναι η βασική επίδειξη: χωρίς επιπλέον κώδικα, το μοντέλο συνθέτει πολλαπλά συστατικά για να απαντήσει σε μια πολυμερή ερώτηση.
Τι Συμβαίνει Κάτω από την Επιφάνεια
Όταν υποβάλλετε ένα prompt:
- Ο client καλεί το server action
generateUI - Το
streamUIαποστέλλει το prompt + ορισμούς εργαλείων στο OpenAI API - Το μοντέλο επιλέγει ποια εργαλεία θα καλέσει και με ποιες παραμέτρους
- Η συνάρτηση
generateκάθε εργαλείου αποδίδει αμέσως ένα skeleton - Το AI τελειώνει την επίλυση παραμέτρων, και επιστρέφεται το τελικό συστατικό
- Το React αποδίδει το συστατικό στη θέση του skeleton
Το πρωτόκολλο streaming RSC είναι αυτό που κάνει αυτό να λειτουργεί. Ο server σειριοποιεί δέντρα συστατικών React και τα μεταδίδει στον client σταδιακά. Αυτό διαφέρει από ένα JSON API — ο client λαμβάνει αποδοθέντα συστατικά, όχι ακατέργαστα δεδομένα.
Διαχείριση Σφαλμάτων
Τα παραγόμενα συστατικά μπορεί να αποτύχουν με τρόπους που τα χειροκίνητα συστατικά δεν αποτυγχάνουν. Περιτυλίξτε την παραγόμενη έξοδο σε ένα error boundary:
// components/genui-error-boundary.tsx
'use client';
import { Component, ReactNode } from 'react';
interface Props { children: ReactNode }
interface State { hasError: boolean; error: Error | null }
export class GenUIErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
render() {
if (this.state.hasError) {
return (
<div className="rounded-lg border border-destructive/50 bg-destructive/5 p-4">
<p className="text-sm text-destructive">
This component could not render. The AI may have passed unexpected data.
</p>
</div>
);
}
return this.props.children;
}
}
Περιτυλίξτε το στη σελίδα σας γύρω από την παραγόμενη έξοδο διεπαφής.
Συμβουλές Ανάπτυξης
Μεταβλητές περιβάλλοντος: Το OPENAI_API_KEY πρέπει να είναι διαθέσιμο στο περιβάλλον παραγωγής σας. Στο Vercel, προσθέστε το στις ρυθμίσεις του έργου στην ενότητα Environment Variables.
Edge runtime: Η συνάρτηση streamUI λειτουργεί σε Edge runtime, που μειώνει σημαντικά τους χρόνους cold start. Προσθέστε export const runtime = 'edge' στο αρχείο server action σας.
Περιορισμός ρυθμού: Χωρίς περιορισμό ρυθμού, ένας χρήστης θα μπορούσε να παράγει χιλιάδες αιτήματα AI. Προσθέστε έναν rate limiter πριν από την κλήση streamUI. Το πακέτο @upstash/ratelimit ενσωματώνεται καλά με το Next.js.
Επιλογή μοντέλου: Το gpt-4o παράγει τις καλύτερες επιλογές συστατικών αλλά κοστίζει περισσότερο. Το gpt-4o-mini είναι περίπου 15× φθηνότερο (openai.com/api/pricing, 2026-05) και λειτουργεί καλά για απλά σύνολα συστατικών. Δοκίμασε και τα δύο με τους συγκεκριμένους ορισμούς εργαλείων σου.
Μεθοδολογία υπολογισμού TCO: τα νούμερα υπολογίζονται με παραδοχές: μέσο prompt ~800 input + ~300 output tokens στο gpt-4o (ή ~$0,001 στο gpt-4o-mini), 1 αίτημα/session, τιμές OpenAI για 2026-05, MAU ≈ DAU × 30%. Βαθμονόμησε με βάση το δικό σου workload.
Επόμενα Βήματα
Αυτός ο οδηγός κάλυψε τα θεμελιώδη. Για Generative UI παραγωγής:
- Προσθέστε περισσότερα εργαλεία — κάθε νέο συστατικό που προσθέτετε στο registry επεκτείνει αυτό που μπορεί να απαντήσει το AI
- Υλοποιήστε caching αποτελεσμάτων εργαλείων — αποθηκεύστε στην κρυφή μνήμη συνηθισμένα ερωτήματα για μείωση καθυστέρησης και κόστους
- Προσθέστε streaming κείμενο παράλληλα με συστατικά διεπαφής ώστε το AI να μπορεί να εξηγεί τι εμφανίζει
- Χρησιμοποιήστε structured outputs για πιο αξιόπιστη παραγωγή παραμέτρων
- Ρυθμίστε observability — καταγράψτε κάθε κλήση εργαλείου, τις παραμέτρους της και τις αλληλεπιδράσεις χρήστη
Η τεκμηρίωση του Vercel AI SDK καλύπτει όλα αυτά τα μοτίβα σε βάθος, και το αποθετήριο παραδειγμάτων διαθέτει αξιόλογα πρότυπα production-grade για μελέτη.
Σε AI SDK v5/v6
Αν χρησιμοποιείς νεότερες εκδόσεις SDK, οι βασικές διαφορές από τον κώδικα αυτού του άρθρου:
parameters:στον ορισμό εργαλείου →inputSchema:- Import
import { streamUI } from 'ai/rsc'→import { streamUI } from '@ai-sdk/rsc' - Το RSC παραμένει επισημασμένο ως experimental από τη Vercel — για production συνιστάται το AI SDK UI (
useChat).
Θέλεις να υλοποιήσεις Generative UI στο προϊόν σου; Ας συζητήσουμε την περίπτωσή σου — από την εμπειρία μας σε consulting, το GenUI stack ταιριάζει καλά σε dashboards και εσωτερικά εργαλεία· για regulated surfaces και δημόσιες σελίδες με υψηλή κίνηση τα trade-offs συνήθως δεν κλείνουν.
Alex
Μηχανικός & Σύμβουλος Generative UI
Senior μηχανικός με εξειδίκευση σε διεπαφές με τεχνητή νοημοσύνη και συστήματα Generative UI. Βοηθά ομάδες προϊόντος να παραδίδουν γρηγορότερα με το κατάλληλο GenUI stack.
Σχετικά Άρθρα
Κατασκευάζοντας το Πρώτο σας Generative UI με το Vercel AI SDK
Βήμα-βήμα οδηγός για τη δημιουργία της πρώτης σας AI-powered διεπαφής με streaming συστατικά.
Προσβασιμότητα σε Generative UI: Δημιουργία Συμπεριληπτικών AI Διεπαφών
Πρακτικός οδηγός για προσβάσιμα γεννητικά interfaces — screen readers, πλοήγηση με πληκτρολόγιο και συνδυαστικά προβλήματα προσβασιμότητας.
CopilotKit vs Vercel AI SDK vs Thesys: Σύγκριση Frameworks
Μια ειλικρινής σύγκριση των τριών κύριων frameworks Generative UI, με πλεονεκτήματα, μειονεκτήματα και πότε να χρησιμοποιείτε το καθένα.
Μείνετε μπροστά στο Generative UI
Εβδομαδιαία άρθρα, ενημερώσεις framework και πρακτικοί οδηγοί υλοποίησης — απευθείας στα εισερχόμενά σας.
Χρειάζεστε βοήθεια για να υλοποιήσετε όσα μόλις διαβάσατε;
Κλείστε Δωρεάν Συμβουλευτική