AGTCloud API Docs
Hướng dẫnAPI ReferenceTích hợp và tài nguyênCập nhật và hỗ trợ

Streaming

Nhận đầu ra mô hình từng phần và xử lý đúng sự kiện, dữ liệu tăng dần, hoàn tất và ngắt luồng.

Streaming cho phép ứng dụng liên tục nhận nội dung tăng dần trước khi mô hình hoàn thành câu trả lời. Cách này phù hợp với giao diện trò chuyện, tạo văn bản dài và các trường hợp cần hiển thị phần đầu sớm, nhưng ứng dụng phải xử lý đúng ranh giới sự kiện, ghép nội dung, trạng thái hoàn tất và ngắt kết nối.

Streaming thay đổi cách trả kết quả, không thay đổi tác vụ

Một tác vụ thường có thể trả kết quả không theo luồng hoặc theo luồng. Hoàn thành yêu cầu không theo luồng trước rồi bật Streaming giúp phân biệt vấn đề tham số với vấn đề phân tích luồng.

Kiểm tra trước khi sử dụng

  1. Kiểm tra trong Danh mục mô hình rằng mô hình hỗ trợ giao thức đã chọn và Streaming.
  2. Sử dụng endpoint và cấu trúc sự kiện tương ứng với giao thức; không dùng một bộ phân tích để suy đoán mọi giao thức.
  3. Đảm bảo ứng dụng, reverse proxy và gateway không đệm toàn bộ phản hồi rồi mới trả về một lần.

Các trường đầy đủ được mô tả trong Reference của Chat Completions, Responses, Anthropic Messages và Gemini Stream Generate Content.

Gửi yêu cầu theo luồng tối thiểu

Ví dụ sau bật đầu ra theo luồng qua Chat Completions:

curl --no-buffer 'https://api.agtcloud.cn/v1/chat/completions' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your-api-key' \
  --data '{
    "model": "MODEL_ID",
    "messages": [
      {"role": "user", "content": "Giải thích exponential backoff bằng ba ý."}
    ],
    "stream": true
  }'

--no-buffer giúp cURL hiển thị ngay dữ liệu đã nhận, không thay đổi cấu trúc sự kiện của máy chủ.

Đọc theo sự kiện, không theo gói dữ liệu mạng

Số byte mà kết nối HTTP chuyển cho ứng dụng mỗi lần không tương ứng với một sự kiện hoàn chỉnh. Một đối tượng JSON có thể bị chia thành nhiều khối dữ liệu, và nhiều sự kiện có thể đến trong cùng một khối.

Với SSE, ứng dụng cần nhận diện sự kiện hoàn chỉnh bằng dòng trống trước, rồi đọc nội dung data::

const response = await fetch('https://api.agtcloud.cn/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer your-api-key',
  },
  body: JSON.stringify({
    model: 'MODEL_ID',
    messages: [{ role: 'user', content: 'Giải thích exponential backoff là gì.' }],
    stream: true,
  }),
});

if (!response.ok || !response.body) {
  throw new Error(`Yêu cầu thất bại: ${response.status}`);
}

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';

while (true) {
  const { value, done } = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, { stream: true });
  const events = buffer.split('\n\n');
  buffer = events.pop() ?? '';

  for (const event of events) {
    const data = event
      .split('\n')
      .filter((line) => line.startsWith('data:'))
      .map((line) => line.slice(5).trimStart())
      .join('\n');

    if (!data || data === '[DONE]') continue;
    const chunk = JSON.parse(data);
    const delta = chunk.choices?.[0]?.delta?.content;
    if (delta) process.stdout.write(delta);
  }
}

Mã dùng trong môi trường production còn cần xử lý hủy yêu cầu, hết thời gian đọc, heartbeat, sự kiện không phải JSON và phần đệm chưa xử lý khi luồng kết thúc.

Cấu trúc luồng của bốn giao thức

Chat thường trả về Chat Completion Chunk. Văn bản nằm trong choices[].delta.content, tham số công cụ có thể nằm trong choices[].delta.tool_calls, và lý do kết thúc nằm trong finish_reason; luồng sự kiện có thể kết thúc bằng [DONE].

Có endpoint cho giao thức không có nghĩa mọi mô hình đều trả về tất cả loại nội dung trên. Chỉ triển khai các nhánh ứng dụng thực sự sử dụng và mô hình mục tiêu đã trả về.

Ghép văn bản và tham số công cụ

  • Ghép các phần văn bản tăng dần riêng theo chỉ số ứng viên, mục đầu ra hoặc Content Block.
  • Tên công cụ, ID lời gọi và tham số có thể đến nhiều lần; hãy duy trì bộ đệm riêng cho từng lời gọi.
  • Chỉ phân tích tham số công cụ thành JSON sau khi nhận đầy đủ; không thực thi từng khối.
  • Dùng các bộ đệm riêng cho tóm tắt suy luận, Thinking Block và câu trả lời cuối cùng; không trộn thành một đoạn văn bản.
  • Nếu giao thức trả Usage ở cuối, hãy tiếp tục đọc kết nối cho đến khi nhận sự kiện hoàn tất.

Xác định thành công, thất bại và gián đoạn

Hiện tượngXử lý phía ứng dụng
Nhận sự kiện hoàn tất do giao thức quy địnhLưu kết quả đầy đủ và Usage, đánh dấu yêu cầu thành công
Nhận sự kiện lỗi hoặc thất bạiLưu nội dung đã hiển thị và đánh dấu yêu cầu thất bại
Kết nối đóng sớmĐánh dấu chưa hoàn chỉnh; không coi văn bản đã nhận là câu trả lời đầy đủ
Người dùng chủ động dừngHủy đọc và hiển thị “Đã dừng tạo nội dung” trên giao diện
Không có sự kiện mới trong thời gian dàiHủy theo chính sách thời gian chờ của ứng dụng và giữ thông tin cần thiết để khắc phục sự cố

Sau khi yêu cầu theo luồng đã hiển thị một phần nội dung, không tự động gửi lại vô hạn. Việc thử lại có thể tạo câu trả lời khác hoặc kích hoạt lại công cụ và các hành vi có tác dụng phụ.

Kiểm tra trước khi đưa vào production

  • Trang hiển thị văn bản từng phần, không chờ đến khi kết nối đóng.
  • Ký tự tiếng Trung và ký tự nhiều byte không bị lỗi do chia khối dữ liệu.
  • Tham số công cụ được ghép đúng theo ID lời gọi và được kiểm tra tính hợp lệ trước khi thực thi.
  • Các trường hợp người dùng hủy, mất mạng, hết thời gian chờ và lỗi máy chủ đều có trạng thái rõ ràng.
  • Nhật ký không ghi API Key, toàn bộ Prompt nhạy cảm hoặc tham số công cụ chưa được che thông tin nhạy cảm.

Tiếp theo, xem Tool Calling và Lỗi và khắc phục sự cố.

Trên trang này