Yayınlanma tarihi: 16 Temmuz 2026
Use the built-in Prompt API with the Vercel AI
SDK (Yerleşik istem API'sini Vercel AI SDK ile kullanma) başlıklı makalede, generateText(), streamText(), hibrit kod ve Output.object() kullanılarak yapılandırılmış çıkış olmak üzere dört temel oluşturma öğesini görmüştünüz. Bu öğelerin tümü @browser-ai/core tarafından desteklenir. Bu kez daha etkileşimli bir şey oluşturacaksınız: Prompt API kullanılamadığında otomatik olarak bir bulut modeline geri dönen, tamamen tarayıcıda çalışan tam bir akış sohbeti kullanıcı arayüzü.
Ne oluşturuyorsunuz?
Aşağıdakileri yapan bir React sohbet arayüzü:
- Çok turlu sohbeti yayınlamak için Vercel AI SDK'sının
useChatkancasını kullanır. - Arka uç sunucusu gerektirmeden model döngüsünü tarayıcıda çalıştırır.
- Prompt API kullanılamadığında otomatik olarak Gemini 2.5 Flash'a geri döner.
- Asistan yanıtlarını GitHub'a özgü Markdown olarak oluşturur ve yayın sırasında eksik jetonları işler.
- İlk jeton beklenirken "Düşünüyor…" parıltısı gösterilir.
- Yeni mesajlara otomatik olarak kaydırılır. Yukarı kaydırdığınızda en alta kaydırma düğmesi gösterilir.
Ek bağımlılıklar
ai, @browser-ai/core ve @ai-sdk/google ile birlikte sohbet kullanıcı arayüzü için React, AI SDK'nın React bağlamaları ve birkaç Markdown paketi gerekir:
npm install react react-dom @ai-sdk/react
npm install react-markdown remark-gfm harden-react-markdown
npm install -D @types/react @types/react-dom
Kullanıcı arayüzü için Tailwind CSS, bazı bileşen yardımcı programları ve simgeler için Lucide'i de ekleyin:
npm install -D tailwindcss postcss autoprefixer
npm install clsx tailwind-merge lucide-react
Oylama yapılandırması: çok girişli derleme
Projede zaten index.html var. chat.html öğesini ikinci giriş noktası olarak ekleyin
ve Vite'ı her ikisini de oluşturacak şekilde yapılandırın:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';
export default defineConfig({
plugins: [react()],
resolve: { alias: { '@': resolve(__dirname, './src') } },
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
chat: resolve(__dirname, 'chat.html'),
},
},
},
});
chat.html, yalnızca <div id="root"> ve bir komut dosyası etiketinden oluşur:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Built-in AI Chatbot</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/chat.tsx"></script>
</body>
</html>
Otomatik model seçimi
Uygulama, chatbot'ta bu seçimi otomatik olarak yapar: Önce yerleşik modeli dener ve Prompt API kullanılamıyorsa buluta geri döner.
Bu işlemi, React monte edilmeden önce, modül yükleme sırasında yapar. Böylece kullanıcı ilk mesajını yazdığında aracı hazır olur:
const agentPromise: Promise<ToolLoopAgent> = (async () => {
const builtIn = browserAI();
let model: any = builtIn;
if (typeof builtIn.availability === 'function') {
const availability = await builtIn.availability();
if (availability === 'unavailable') {
const { createGoogleGenerativeAI } = await import('@ai-sdk/google');
model = createGoogleGenerativeAI({ apiKey })('gemini-2.5-flash');
} else if (availability === 'downloadable') {
await builtIn.createSessionWithProgress(() => {});
}
}
return new ToolLoopAgent({ model, instructions: 'You are a helpful assistant.' });
})();
Yeni bileşen ToolLoopAgent; herhangi bir modelin üzerinde çok turlu bir sohbet döngüsünü yöneten yapay zeka SDK'sı soyutlamasıdır. Modeli ve sistem istemini alır ve ileri geri iletişimi dahili olarak yönetir.
UseChat'i kullanmak için ajanı bağlayın
@ai-sdk/react paketinin useChat kancası normalde bir HTTP uç noktasıyla iletişim kurar.
Tarayıcı tarafında çıkarım için bunun yerine DirectChatTransport kullanın. Bu işlev, ToolLoopAgent döngüsünü tamamen tarayıcıda çalıştırır ve sunucu kullanılmaz:
const transport = useMemo(() => new DirectChatTransport({ agent }), [agent]);
const { messages, sendMessage, status, stop } = useChat({ transport });
useMemo, görüşme durumunu tuttuğu için önemlidir ve kararlı bir referans olmalıdır.DirectChatTransport Her oluşturma işleminde yeniden oluşturmak, sohbeti sıfırlar.
useChat size şunları sunar:
Messages:UIMessage[]olarak tam görüşme, her birirolevepartsdizisiylesendMessage({ text }): Yeni bir kullanıcı dönüşü gönderir ve yanıtı yayınlamaya başlar.Status:'idle'|'submitted'|'streaming'|'error'Stop: devam eden bir oluşturma işlemini iptal eder
İletileri oluşturma
Her mesajda bir parts dizisi bulunur. Bu chatbot için yalnızca type:
'text' bölümleriyle ilgileniyoruz. Kullanıcı mesajları sağa hizalı bir balon olarak görünür. Asistan mesajları ise sola hizalı olup bir simge içerir:
const ChatMessage = ({ message, isStreaming }: { message: UIMessage; isStreaming: boolean }) => {
const isUser = message.role === 'user';
const textParts = message.parts.map((part, i) => {
if (part.type !== 'text') return null;
if (isUser) return <span key={i}>{part.text}</span>;
return <Response key={i} parseIncompleteMarkdown={isStreaming}>{part.text}</Response>;
});
if (isUser) {
return (
<div className="flex flex-col items-end gap-2 animate-fade-up">
<MessageContent className="w-fit max-w-[min(80%,56ch)] ...">
{textParts}
</MessageContent>
</div>
);
}
return (
<div className="flex items-start gap-3">
<AIIcon />
<MessageContent className="text-[13px] leading-[1.65]">{textParts}</MessageContent>
</div>
);
};
MessageContent ve Response, Yapay Zeka Öğeleri'dir.
Bunlar, npm'den yüklemek yerine projenize kopyaladığınız shadcn tarzı kaynak bileşenlerdir. Response, GitHub'a özgü Markdown (tablolar, görev listeleri, üstü çizili) için react-markdown ile remark-gfm, yapay zeka çıkışındaki bağlantı ve resimleri temizlemek için harden-react-markdown ile sarmalar.
İleti hâlâ yayınlanırken parseIncompleteMarkdown özelliği true olur. Yayın sırasında model, **bold yazabilir ancak henüz ** kapatmayabilir. Bu durumda, yıldız işareti olarak oluşturulacak bir sarkan jeton kalır. parseIncompleteMarkdown, açık olan **, __, `, ~~ öğelerini kapatır ve oluşturulan çıktının her artımlı parçada temiz kalması için sarkan [ bağlantı başlangıçlarını keser.
"Düşünüyor…" durumu
Bir mesaj gönderme ile ilk jetonu alma arasındaki süre status'dır.
'submitted'. Bu süre zarfında uygulamada animasyonlu bir parıltı gösterilir:
{status === 'submitted' && messages.at(-1)?.role !== 'assistant' && (
<ThinkingMessage />
)}
messages.at(-1)?.role !== 'assistant' koşulu, asistan mesajı akışı başladıktan sonra ışıltının yeniden görünmesini engeller.
ThinkingMessage, Shimmer bileşenini kullanır: background-clip: text kullanılarak hareketli gradyan içeren bir <span>, "Düşünülüyor…" metnine kapsamlı bir vurgu efekti verir.
Otomatik kaydırma
Yeni içerik geldiğinde uygulama en alta kaydırılır ancak yalnızca kullanıcı zaten en alttaysa. Kullanıcıları, okudukları bir şeyden veya sohbetin ortasından uzaklaştırmak rahatsız edici olabilir.
const [isAtBottom, setIsAtBottom] = useState(true);
useEffect(() => {
if (isAtBottom) endRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages, status, isAtBottom]);
const handleScroll = () => {
const el = containerRef.current;
if (!el) return;
setIsAtBottom(el.scrollHeight - el.scrollTop - el.clientHeight < 50);
};
isAtBottom yanlış olduğunda kaydırma çubuğunu en alta götürme düğmesi görünür ve kullanıcı en alta döndüğünde kaybolur.
Giriş alanı
Metin alanı, her giriş etkinliğinde yüksekliği auto olarak sıfırlanıp ardından scrollHeight olarak ayarlanarak yazarken otomatik olarak yeniden boyutlandırılır. Enter tuşuyla (Üst Karakter+Enter değil) gönderilir ve yanıt yayınlanırken Gönder düğmesinin yerini stop() işlevini çağıran bir Durdur düğmesi alır:
<textarea
onInput={(e) => {
const el = e.currentTarget;
el.style.height = 'auto';
el.style.height = `${el.scrollHeight}px`;
}}
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
if (input.trim() && !isStreaming) {
sendMessage({ text: input });
setInput('');
}
}
}}
/>;
{
isStreaming ? (
<Button variant="outline" onClick={stop}>
Stop
</Button>
) : (
<Button type="submit" disabled={!input.trim()}>
Send
</Button>
);
}
Yükleme durumu olan bir öğe bağlama
agentPromise asenkron olduğundan Chat öğesini oluşturmadan önce bunun tamamlanmasını bekleyin. Bir App sarmalayıcı, sözü yerine getirir ve bu sırada bir döndürücü gösterir:
function App() {
const [agent, setAgent] = (useState < ToolLoopAgent) | (null > null);
useEffect(() => {
agentPromise.then(setAgent);
}, []);
if (!agent) {
return (
<div className="flex h-dvh items-center justify-center">
<Loader size={20} />
</div>
);
}
return <Chat agent={agent} />;
}
Ajan çözüldüğünde (yerleşik modelin anında başlatılması veya modelin indirilmesinin beklenmesi) döndürücü kaybolur ve sohbet kullanıcı arayüzü yüklenir.
Demo
Canlı demo, tamamen tarayıcınızda çalışan tam işlevli bir chatbot'tur. Bir mesaj yazıp Enter tuşuna basın. İstem API'si kullanılabiliyorsa yanıt, ağ isteği olmadan doğrudan cihazdaki modelden yayınlanır. Tarayıcınız Prompt API'yi desteklemiyorsa otomatik olarak Gemini 2.5 Flash'a geri döner. Listede yer alan bir şeyi açıklamasını, kod snippet'i yazmasını veya Markdown biçimlendirmesi kullanmasını isteyin. Yanıtlar, biçimlendirilmiş kod blokları, tablolar ve satır içi kodlarla birlikte kullanıma hazır olarak oluşturulur.

Sonuç
Bu iki makale boyunca, Vercel AI SDK'nın tarayıcının yerleşik Prompt API'si ile neler yapabileceğini, ham oluşturma temellerinden cilalı bir akış sohbeti arayüzüne kadar tüm yönleriyle gördünüz.
Use the built-in Prompt API with the Vercel AI SDK (Vercel AI SDK ile yerleşik istem API'sini kullanma) başlıklı makalede, akış olmayan ve akışlı metin oluşturma için generateText() ve streamText()'yi kullanmayı, Output.object() ile yapılandırılmış JSON çıkışı istemeyi ve oluşturma mantığında değişiklik yapmadan çalışma zamanında yerleşik model ile bulut sağlayıcı arasında seçim yapan karma kod yazmayı öğrenmiştiniz.
Bu dokümanda, aynı yapı taşlarını alıp tam bir React kullanıcı arayüzüyle sarmaladınız: görüşme döngüsünü yönetmek için ToolLoopAgent, yanıtları doğrudan tarayıcıda yayınlamak için DirectChatTransport içeren useChat ve Markdown yanıtlarını geldikçe temiz bir şekilde oluşturmak için AI Elements bileşenleri. Tüm bunlar, Prompt API kullanılamadığında otomatik bulut yedeklemesiyle birlikte.
Sonuç olarak, tamamen tarayıcıda çalışan ve arka uç gerektirmeyen iki demo elde edilir:
- Yerleşik Prompt API'sini Vercel AI SDK demosuyla kullanma: Metin oluşturma, akış ve yapılandırılmış çıkış yan yana
- İstem API'si demosuyla Vercel AI SDK kullanıcı arayüzünü ve AI Elements'ı kullanma: Markdown oluşturma ve koyu mod özelliklerine sahip tam akışlı bir chatbot