Tôi đã xây dựng một AI Chat Client dạng streaming mà không bị "phát điên"
Tôi muốn xây dựng một giao diện chat nơi AI phản hồi trong thời gian thực. Tôi muốn có hiệu ứng đánh máy mượt mà đó.
Nó khó hơn tôi tưởng. Vấn đề không nằm ở AI. Vấn đề nằm ở đường truyền dữ liệu giữa API và trình duyệt.
Tôi đã thử ba cách khác nhau để giải quyết vấn đề này.
Phương pháp Chờ đợi (The Wait Method) Tôi gọi API và đợi cho đến khi nhận được toàn bộ phản hồi rồi mới hiển thị. Cách này hoạt động, nhưng giao diện (UI) bị đóng băng trong vài giây. Người dùng nghĩ rằng ứng dụng bị lỗi. Họ nhấn "Send" liên tục. Đây là một trải nghiệm người dùng tồi tệ.
Phương pháp Polling (The Polling Method) Tôi đã nghĩ đến việc để máy chủ gửi một job ID. Sau đó, client sẽ yêu cầu cập nhật mỗi giây một lần. Việc này đòi hỏi quản lý máy chủ rất nặng nề. Các bản cập nhật xuất hiện theo từng cụm ngẫu nhiên. Nó không hề mượt mà.
Phương pháp WebSocket (The WebSocket Method) Tôi đã thử dùng Socket.IO. Điều này làm tăng thêm sự phức tạp khủng khiếp. Tôi phải quản lý việc kết nối lại (reconnections), heartbeat và đồng bộ hóa trạng thái (state synchronization). Đối với một ứng dụng chat đơn giản, WebSockets là quá mức cần thiết.
Giải pháp đơn giản hơn: Server-Sent Events (SSE).
Hầu hết các AI API đã gửi phản hồi thông qua SSE qua HTTP. Tôi đã ngừng tìm kiếm các công cụ phức tạp và sử dụng fetch API có sẵn.
Bằng cách sử dụng response.body.getReader(), tôi đọc trực tiếp luồng byte. Tôi tự mình phân tích (parse) giao thức SSE. Cách tiếp cận này giúp giao diện luôn phản hồi nhanh và sử dụng HTTP tiêu chuẩn.
Tại sao cách này hiệu quả:
- Không cần máy chủ WebSocket.
- Không cần logic kết nối lại phức tạp.
- Nó hoạt động với bất kỳ API nào hỗ trợ SSE.
- Bạn có thể dừng luồng một cách dễ dàng bằng cách sử dụng AbortController.
Cũng có những sự đánh đổi.
- Bạn không thể đẩy các bản cập nhật tới client nếu không có yêu cầu (request).
- Nếu kết nối bị ngắt, bạn sẽ mất phần phản hồi đang nhận dở.
Nếu bạn xây dựng một ứng dụng chat, hãy tránh dùng WebSockets trừ khi bạn cần giao tiếp hai chiều (bidirectional communication). Hãy trung thành với HTTP streaming. Nó đơn giản và đáng tin cậy hơn.
Chiến lược streaming của bạn là gì? Bạn sử dụng WebSockets hay SSE? Hãy cho tôi biết ở phần bình luận nhé.
Nguồn: https://dev.to/__c1b9e06dc90a7e0a676b/i-built-a-streaming-ai-chat-client-without-losing-my-mind-3gi0