eduardweb.
AI & LLMsIntermediar#ai#nextjs#typescript#react#vercel-ai-sdk

Streaming de la LLM-uri în Next.js: Cum am scăzut latența percepută cu Vercel AI SDK

De Andreea Crăciun, 30 iul. 2026 · 11 vizualizări · 3 like-uri

Postat 30 iul. 2026
typescript
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 = streamText({
    model: openai('gpt-4o-mini'),
    messages,
  });

  return result.toDataStreamResponse();
}

Am refăcut recent modulul de asistență AI la un proiect SaaS cu peste 12k useri activi, unde un răspuns complet dura cam 4-5 secunde. Utilizatorii credeau că aplicația s-a blocat și dădeau refresh continuu. Trecerea de la un endpoint clasic de JSON la streaming prin Vercel AI SDK a scăzut latența percepută (Time To First Token) de la 4.2 secunde la sub 200ms.

Iată cum implementezi asta curat în Next.js App Router fără să-ți prinzi urechile în gestionarea manuală de headers și ReadableStream.

De ce nu facem SSE de mână în Next.js?

Teoretic, Server-Sent Events înseamnă doar să pui header-ul Content-Type: text/event-stream și să trimiți bucăți de text prin ReadableStream. Am încercat varianta asta acum un an pe un proiect mai vechi. Rezultatul? Cod boilerplate de 150 de linii, probleme la reconectare când pica rețeaua mobilă și un chin teribil să fac parser pe client ca să lipesc token-ii corect fără să stric caracterele UTF-8 la jumătatea cuvântului.

Vercel AI SDK elimină toată mizeria asta. Primești două abstractizări foarte solide: streamText pe server și hook-ul useChat pe client.

Backend-ul: Simplu și la obiect

În Next.js App Router, creezi un Route Handler în app/api/chat/route.ts. Folosim pachetul ai și @ai-sdk/openai. Codul trimite mesajele primite de la client direct la modelul LLM și returnează un răspuns de tip stream optimizat pentru SDK-ul din frontend.

Frontend-ul: Hook-ul useChat face tot greul

Pe client, folosești hook-ul useChat dintr-o componentă React. Acesta gestionează automat:

  1. Trimiterea request-ului POST către /api/chat.
  2. Ascultarea stream-ului SSE.
  3. Starea locală de messages (istoricul conversației).
  4. Auto-append la ultimul mesaj pe măsură ce sosesc token-ii.

Nu mai ai nevoie de useState pentru input, nici pentru mesaje și nici pentru starea de loading. Hook-ul îți dă totul din cutie.

Trade-off-uri reale: La ce să fii atent

Nimic nu e perfect în producție, iar streaming-ul vine cu câteva capcane de care m-am lovit direct:

  • Costuri pe Serverless: Dacă folosești Vercel sau AWS Lambda, o conexiune care stă deschisă 10-15 secunde cât generează un model un răspuns lung îți consumă timp de execuție. Dacă ai spike-uri de trafic, s-ar putea să ai o surpriză la factură.
  • Edge Runtime vs Node Runtime: În Edge Runtime latența inițială e minusculă, dar nu ai acces la pachete Node.js native (de exemplu dacă vrei să salvezi mesajele în DB folosind un ORM ce necesită conexiuni TCP clasice). Eu prefer să țin Route Handler-ul pe Node runtime și să fac salvarea în DB după ce stream-ul s-a încheiat.
  • Drop-uri de rețea: Dacă utilizatorul pierde conexiunea la jumătatea generării, stream-ul se taie. useChat gestionează binișor cazul, dar mesajul parțial rămas pe ecran trebuie marcat corespunzător în bază de date, altfel istoricul devine incoerent.

Pentru 90% din proiecte, Vercel AI SDK e no-brainer. Economisești ore de muncă și UX-ul e infinit mai bun.

Voi cum gestionați streaming-ul de la LLM-uri? Ați mers pe pachetul de la Vercel sau v-ați construit wrapper propriu pe WebSocket/SSE?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.