Streaming Claude tới Trình duyệt với Backpressure thực thụ

Việc streaming các token của LLM rất dễ để đạt được 80% sự hoàn thiện. 20% còn lại mới là nơi hầu hết các nhà phát triển thất bại. Các thiết lập ngây thơ có thể hoạt động trên máy cục bộ của bạn nhưng sẽ bị lỗi khi kết nối chậm hoặc khi sử dụng các mô hình tốc độ cao.

Nếu bạn muốn streaming ở cấp độ production, bạn phải xử lý hai vấn đề cụ thể sau.

1. Vấn đề về Nginx Buffer

Nhiều nhà phát triển quên mất header X-Accel-Buffering. Nếu không đặt giá trị này thành no, Nginx sẽ đệm (buffer) luồng dữ liệu của bạn. Người dùng sẽ không thấy gì cho đến khi toàn bộ phản hồi kết thúc. Điều này làm mất đi mục đích của việc streaming.

2. Vấn đề về Stream bị bỏ dở

Đây là sai lầm tốn kém nhất. Nếu người dùng đóng tab hoặc mất kết nối trong khi mô hình đang tạo nội dung, máy chủ vẫn tiếp tục chạy. Vòng lặp của bạn vẫn tiếp tục lấy các token từ Claude. Bạn phải trả tiền cho những đầu ra mà không ai nhìn thấy.

Giải pháp: Abort từ đầu đến cuối

Bạn phải liên kết tín hiệu yêu cầu (request signal) với luồng Claude. Khi client ngắt kết nối, máy chủ phải dừng việc tạo nội dung ngay lập tức.

Trong route Next.js của bạn, hãy truyền request signal vào Anthropic SDK:

  • Sử dụng { signal: request.signal } trong lời gọi SDK của bạn.
  • Thêm một event listener cho abort signal.
  • Gọi llm.abort()controller.close() khi có sự kiện abort xảy ra.

Điều này sẽ dừng việc tạo nội dung và ngăn hóa đơn của bạn tăng lên.

Ở phía Frontend

Trình duyệt nhận các chunk tại các ranh giới ngẫu nhiên. Bạn phải đệm (buffer) các chunk này và chia tách chúng theo dấu phân cách SSE.

  • Sử dụng AbortController trong lời gọi fetch.
  • Trả controller đó về React component của bạn.
  • Gọi controller.abort() trong hàm cleanup của component.

Điều này đảm bảo tín hiệu abort truyền từ UI ngược trở lại máy chủ của bạn.

Một mẹo cuối cùng về hiệu suất: Các mô hình nhanh phát ra token nhanh hơn mức DOM có thể repaint. Việc cập nhật React state cho mỗi token đơn lẻ sẽ làm UI của bạn bị lag. Hãy đệm các token và cập nhật theo từng đợt (batches). Điều này giúp giao diện của bạn mượt mà hơn.

Đừng chỉ xây dựng các luồng stream chỉ để demo. Hãy tắt proxy buffering và truyền tải các tín hiệu abort để tiết kiệm chi phí và xây dựng các ứng dụng mạnh mẽ.

Source: https://dev.to/pavelespitia/streaming-claude-to-the-browser-with-backpressure-that-actually-works-4oaf

Optional learning community: https://t.me/GyaanSetuAi