AI From U AI FROM U.COM

Blog / Hướng dẫn

Streaming và giới hạn 100 giây ở lớp biên

Vì sao một request không streaming chạy dài bị lớp biên cắt sau khoảng 100 giây, một field duy nhất chặn được điều đó, và đồng hồ đo làm gì quanh một stream.

Một request không streaming sẽ không gửi về cho bạn một byte nào cho tới khi cả câu trả lời đã hình thành xong. Với một dòng trả lời thì bạn không thấy gì; với một lần sinh nội dung dài thì đó chính là toàn bộ vấn đề. Có thể mất vài phút giữa lúc request của bạn tới được model và lúc byte đầu tiên của câu trả lời lẽ ra quay về, mà lớp biên CDN đứng trước site này chỉ cho phép khoảng 100 giây im lặng trước khi nó bỏ cuộc với response. Quá mốc đó, request chết ở lớp biên trong khi model vẫn đang viết. Chỉ một field chặn được chuyện này, và số tiền bạn bị trừ không thay đổi vì bạn bật nó.

Vì sao một request buffered chạy dài lại chết

Một request buffered là một vòng đi về với một quãng nghỉ dài ở giữa. Client của bạn gửi body đi, model viết trọn câu trả lời, và chỉ khi token cuối cùng xong xuôi thì những byte đầu tiên mới chạy ngược về trên kết nối. Giữa hai thời điểm đó, kết nối không mang gì cả — và lớp biên đang nhìn đúng cái không-gì ấy: khoảng 100 giây im lặng là tất cả những gì nó cho phép trước khi kết luận rằng response sẽ không tới. Cái bạn nhìn thấy là một request hỏng. Cái đã xảy ra là câu trả lời vẫn đang được viết.

Một request streaming thì không có quãng nghỉ nào để mà hết giờ. Byte rời đi về phía client của bạn ngay từ token đầu tiên, và mọi token sau đó tới nơi đúng lúc nó được sinh ra, nên kết nối không bao giờ im đủ lâu để lớp biên bỏ cuộc. Đây là chỗ đáng giữ lại: cái này không phải một timeout dài hơn, nó là một response không bao giờ lặng đi. Một lần sinh nội dung mất bốn phút thì stream suốt bốn phút, và về tới nơi.

Bản sửa chỉ là một field

Streaming ở đây không phải một endpoint khác, một key khác hay một mức giá khác. Nó là một field trong chính body bạn vẫn đang gửi, stream: true, và nó chạy y như nhau trên /v1/chat/completions lẫn trên /v1/responses.

POST /v1/chat/completions

{
  "model": "astra",
  "stream": true,
  "messages": [
    {"role": "user", "content": "Write the report."}
  ]
}

Các SDK chính thức viết cùng một field đó theo cách của mình: stream=True trong Python, stream: true trong Node. Thứ đổi ở phía bạn chỉ là hình dạng câu trả lời — những chunk bạn duyệt qua khi chúng tới, thay vì một object bạn ngồi chờ — và thư viện client nào cũng đã viết sẵn vòng lặp ấy cho bạn.

Đồng hồ đo làm gì quanh một stream

Streaming không đưa bạn ra ngoài đồng hồ đo, và cũng không đưa bạn một hoá đơn không kiểm được. Phần usage vẫn về: frame cuối cùng của stream mang theo số token, và với chat completions thì gateway tự đặt stream_options.include_usage, nên đó không phải thứ bạn có thể quên yêu cầu. Đồng hồ đo quyết toán trên đúng những con số ấy, dù câu trả lời có được stream hay không.

Quanh chỗ đó, trình tự vẫn là trình tự mà mọi request ở đây đi theo. Một phần giữ chỗ được lấy ra lúc request bắt đầu — số dư trong portal của bạn đổi ngay lúc đó, không phải lúc token cuối cùng rơi xuống — và việc quyết toán diễn ra trên phần usage mà frame cuối của stream báo về, ở đúng các mức giá đã ghi lúc giữ chỗ. Nếu kết nối đứt giữa chừng, phần giữ chỗ được đưa đi đối soát rồi trả lại chứ không bị tính tiền: những token chưa bao giờ tới được một lần quyết toán thì không bao giờ bị trừ.

Ba cái đồng hồ, không phải một

Khi một request có vẻ chậm, portal sẽ nói cho bạn biết đó là kiểu chậm nào. Mỗi request được giữ ba cái đồng hồ — upload, thời gian tới token đầu tiên, và tổng — vì đó là ba vấn đề khác nhau đội chung một chữ. Upload dài là đường lên của chính bạn đang đưa body sang cho chúng tôi, và không gì ở phía này rút ngắn nó được. Thời gian tới token đầu tiên ngắn mà tổng dài là một lần sinh nội dung dài đang làm đúng việc của nó — đúng trường hợp mà streaming sinh ra để phục vụ. Thời gian tới token đầu tiên mà dài mới là cái đáng viết thư cho chúng tôi.

Còn một con số nữa mà client nên đọc. Khi một request bị từ chối bằng 429, header Retry-After đi qua nguyên vẹn — đó chính là header mà các SDK chính thức dựa vào để giãn nhịp thử lại, nên một client tôn trọng nó sẽ chờ đúng khoảng thời gian chúng tôi thật sự gửi, thay vì đoán lấy một con số.

Nếu kết nối đứt giữa chừng, phần giữ chỗ được đưa đi đối soát rồi trả lại chứ không bị tính tiền: những token chưa bao giờ tới được một lần quyết toán thì không bao giờ bị trừ.