// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages } = await req.json();
const result = await streamText({
model: openai('gpt-4o'),
messages,
});
return result.toDataStreamResponse();
}Am implementat recent streaming-ul pentru un asistent AI la un proiect cu peste 15.000 de utilizatori activi lunar. Dacă ai lăsat vreodată un user să aștepte 15 secunde până când un model ca GPT-4 termină de generat tot răspunsul, știi deja că UX-ul e pur și simplu horror. Streaming-ul prin Server-Sent Events (SSE) e obligatoriu în scenariul ăsta.
Totuși, să scrii manual parsarea de stream-uri pe client, să gestionezi conexiunile pierdute și să faci auto-scroll-ul ăla fluid e o muncă destul de plictisitoare și consumatoare de timp. Aici intervine Vercel AI SDK. Cu hook-ul useChat pe client și streamText pe backend, am redus timpul de implementare pentru un chat complet de la câteva zile la mai puțin de o oră. Practic, am salvat cam 70% din codul de boilerplate pe care îl scriam de obicei pentru gestionarea stării chat-ului.
Cum arată setup-ul pe backend
În Next.js (App Router), tot ce trebuie să faci în Route Handler este să folosești funcția streamText din SDK. Nu mai ai nevoie de hack-uri cu headere HTTP scrise de mână sau de gestionat manual ReadableStream.
Definim ruta în app/api/chat/route.ts. Ne legăm direct de OpenAI (sau Anthropic, Cohere etc.) și returnăm un răspuns formatat direct pentru stream. Am setat maxDuration la 30 de secunde pentru că modelele mai mari pot avea un timp de răspuns inițial mai lent.
Clientul devine extrem de simplu
Pe partea de client, în componenta React, importăm useChat. Acest hook se ocupă singur de apelarea endpoint-ului /api/chat (pe care îl caută implicit), gestionează input-ul utilizatorului, istoricul mesajelor și, cel mai important, face append la token-urile noi pe măsură ce sosesc de la server.
Primești direct un array de messages pe care îl poți randa într-un simplu .map(). E excelent cum se updatează UI-ul în timp real fără niciun useEffect dubios scris de tine.
Trade-off-urile de care nu-ți spune nimeni în tutoriale
Sună perfect la prima vedere, dar hai să vorbim despre minusurile pe care le-am simțit pe pielea mea în producție.
În primul rând, ești destul de blocat în ecosistemul lor. Dacă vrei să folosești altceva decât rutele lor standard sau dacă vrei să controlezi fin protocolul de transport, useChat devine incredibil de rigid. Am pățit asta când am vrut să trimit metadate custom complexe (cum ar fi ID-urile documentelor folosite ca surse într-un sistem RAG) în paralel cu textul generat.
Deși acum au introdus conceptul de data stream în SDK, tot trebuie să te pliezi pe structura lor. Dacă ai nevoie să trimiți JSON-uri complexe amestecate cu text în mod complet custom, s-ar putea ca un controller SSE scris de tine de la zero să fie o decizie mai sănătoasă pe termen lung.
În al doilea rând, atenție la costurile de hosting pe Vercel. Streaming-ul ține conexiunile deschise mai mult timp. La un volum mare de utilizatori simultani, s-ar putea să lovești destul de repede limitele de timeout pe serverless functions (pe planul free ai 10 secunde limită, pe Pro ai 60). De aceea, pentru producție seriosă, e recomandat să rulezi route handler-ul pe runtime: 'edge' sau să muți endpoint-ul pe un VPS separat.
Voi ce folosiți pentru chat-urile cu LLM-uri în producție? Ați rămas pe Vercel AI SDK sau v-ați scris propriul sistem de streaming pe websockets ori SSE curat?