Bỏ qua, đến nội dung chính
AI & Full-Stack11 min read22/08/2026

Tích hợp Streaming Generative UI vào Next.js với Vercel AI SDK

Xây dựng ứng dụng AI thế hệ mới: truyền luồng dữ liệu thời gian thực (Token Streaming), kết hợp Server-Sent Events và render Component tương tác động (Generative UI) từ LLM.

N

Nguyễn Duy Noa

Frontend Developer

Các ứng dụng tương tác với mô hình ngôn ngữ lớn (LLM) như ChatGPT hay Claude đã định nghĩa lại kỳ vọng của người dùng về giao diện phần mềm. Người dùng không còn chấp nhận ngồi chờ 5-10 giây để nhận một khối văn bản tĩnh. Họ mong muốn thấy câu trả lời xuất hiện tức thì theo dạng **Streaming Token** và các thành phần giao diện tương tác động (**Generative UI**) xuất hiện ngay khi AI đưa ra đề xuất.

Với **Vercel AI SDK** và kiến trúc Next.js App Router, việc tích hợp các tính năng AI này trở nên vô cùng mạch lạc và dễ dàng.

1. Sự khác biệt giữa Plain Streaming và Generative UI

Có hai cấp độ khi tích hợp AI vào giao diện người dùng:
1. Streaming Text (Level 1): LLM gửi về từng ký tự/từ qua Server-Sent Events (SSE). UI hiển thị hiệu ứng gõ chữ mượt mà.
2. Generative UI & Tool Calling (Level 2): Khi AI nhận diện yêu cầu xem thời tiết, đặt vé hay so sánh sản phẩm, AI sẽ gọi hàm (Tool Calling) và server trả về trực tiếp một React Component tương tác (thẻ Card, Biểu đồ, Form chọn ngày) thay vì chỉ là văn bản thô.

2. Tạo API Endpoint Streaming với Vercel AI SDK

Tạo Route Handler tại app/api/chat/route.ts kết nối với OpenAI hoặc Anthropic Claude:

app/api/chat/route.ts
typescript
import { openai } from "@ai-sdk/openai";
import { streamText } from "ai";

export const runtime = "edge";

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: openai("gpt-4o-mini"),
    system: "Bạn là trợ lý AI thông minh cho portfolio của Nguyễn Duy Noa.",
    messages,
  });

  return result.toDataStreamResponse();
}

3. Xây dựng giao diện Chat phía Client với hook useChat

Phía client sử dụng hook useChat để tự động xử lý kết nối stream, trạng thái loading và danh sách tin nhắn:

components/AIChatAssistant.tsx
tsx
"use client";

import { useChat } from "ai/react";
import { PaperPlaneTilt } from "@phosphor-icons/react";

export function AIChatAssistant() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();

  return (
    <div className="flex flex-col h-[500px] w-full max-w-lg bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden">
      {/* Messages list */}
      <div className="flex-1 overflow-y-auto p-4 space-y-3">
        {messages.map((m) => (
          <div
            key={m.id}
            className={`p-3 rounded-xl text-sm max-w-[85%] ${
              m.role === "user"
                ? "ml-auto bg-emerald-500 text-black font-medium"
                : "bg-zinc-800 text-zinc-200"
            }`}
          >
            {m.content}
          </div>
        ))}
        {isLoading && <div className="text-xs text-zinc-500 italic">AI đang phản hồi...</div>}
      </div>

      {/* Input box */}
      <form onSubmit={handleSubmit} className="p-3 border-t border-zinc-800 flex gap-2">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="Hỏi bất kỳ điều gì..."
          className="flex-1 bg-zinc-950 border border-zinc-800 rounded-xl px-4 py-2 text-sm text-zinc-100 focus:outline-none focus:border-emerald-500"
        />
        <button
          type="submit"
          className="p-2.5 bg-emerald-500 text-black rounded-xl hover:bg-emerald-400 transition-colors"
        >
          <PaperPlaneTilt size={18} weight="bold" />
        </button>
      </form>
    </div>
  );
}

Bạn đang gặp vấn đề tương tự?

Tôi có thể giúp bạn tối ưu website — liên hệ để trao đổi miễn phí.

Kết luận

Kỹ năng tích hợp AI vào giao diện người dùng đang nhanh chóng trở thành một năng lực phân hóa quan trọng giữa lập trình viên Frontend trung bình và lập trình viên cao cấp. Hãy bắt đầu đưa các yếu tố thông minh này vào sản phẩm của bạn ngay hôm nay.

AIVercel AI SDKNext.jsGenerative UIReact 19Streaming

Muốn thảo luận thêm?

Nếu bạn có câu hỏi cụ thể về web performance, React, hoặc muốn hợp tác dự án — liên hệ trực tiếp với tôi.

Gửi email