AGTCloud API Docs
РуководстваСправочник APIИнтеграции и ресурсыОбновления и помощь

Streaming

Получайте вывод модели постепенно и правильно обрабатывайте события, приращения, завершение и обрывы потока.

Streaming позволяет клиенту получать приращения содержимого до завершения полного ответа модели. Он подходит для чатов, генерации длинных текстов и быстрого показа первых результатов, но требует правильной обработки границ событий, объединения содержимого, завершения и разрыва соединения.

Streaming меняет способ передачи результата, а не саму задачу

Обычно для одной задачи можно выбрать обычный или потоковый ответ. Сначала выполните обычный запрос, затем включите Streaming: так проще отличить проблемы параметров от ошибок разбора потока.

Проверки перед использованием

  1. В каталоге моделей убедитесь, что целевая модель поддерживает выбранный протокол и Streaming.
  2. Используйте endpoint и структуру событий выбранного протокола; не заставляйте один парсер угадывать все протоколы.
  3. Убедитесь, что клиент, обратный прокси и шлюз не буферизуют весь ответ перед его передачей.

Полные поля описаны в Reference: Chat Completions, Responses, Anthropic Messages и Gemini Stream Generate Content.

Минимальный потоковый запрос

Следующий пример включает потоковый вывод через 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": "Объясните экспоненциальную задержку в трёх пунктах."}
    ],
    "stream": true
  }'

--no-buffer позволяет cURL сразу показывать полученные данные, но не меняет структуру серверных событий.

Читайте события, а не сетевые пакеты

Количество байтов, переданных клиенту за один раз по HTTP, не равно размеру целого события. Один JSON-объект может быть разделён между блоками, а несколько событий — прийти в одном блоке.

Для SSE сначала выделяйте полные события по пустым строкам, затем читайте их содержимое 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: 'Объясните, что такое экспоненциальная задержка.' }],
    stream: true,
  }),
});

if (!response.ok || !response.body) {
  throw new Error(`Ошибка запроса: ${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);
  }
}

В производственном коде также обрабатывайте отмену запроса, тайм-аут чтения, heartbeat, события не в формате JSON и оставшийся необработанный буфер в конце потока.

Потоковые структуры четырёх протоколов

Chat обычно возвращает Chat Completion Chunk. Текст находится в choices[].delta.content, параметры инструментов могут быть в choices[].delta.tool_calls, причина завершения — в finish_reason; поток может заканчиваться [DONE].

Наличие интерфейса протокола не означает, что все модели возвращают все перечисленные типы содержимого. Реализуйте только ветви, которые использует приложение и действительно возвращает целевая модель.

Объединение текста и параметров инструментов

  • Объединяйте текстовые приращения отдельно по индексу кандидата, выходного элемента или Content Block.
  • Имя инструмента, ID вызова и параметры могут приходить частями; ведите отдельный буфер для каждого вызова.
  • Разбирайте параметры инструмента как JSON только после полного завершения; не выполняйте их по отдельным блокам.
  • Для краткого изложения рассуждения, Thinking Block и окончательного ответа используйте разные буферы, не смешивайте их в один текст.
  • Если Usage возвращается в конце, продолжайте читать соединение до получения события завершения.

Успех, ошибка и прерывание

СитуацияДействие клиента
Получено предусмотренное протоколом событие завершенияСохраните полный результат и Usage, отметьте запрос успешным
Получено событие ошибки или сбояСохраните уже показанное содержимое и отметьте запрос неуспешным
Соединение закрыто преждевременноОтметьте результат неполным, не выдавайте полученный текст за полный ответ
Пользователь остановил генерациюОтмените чтение и покажите состояние «Генерация остановлена»
Долго нет новых событийОтмените по политике тайм-аутов приложения и сохраните нужные диагностические данные

После показа части потокового ответа не следует автоматически повторять запрос бесконечно. Повтор может создать другой ответ и повторно вызвать инструменты или действия с побочными эффектами.

Проверка перед запуском

  • Страница показывает текст постепенно, а не только после закрытия соединения.
  • Китайские и многобайтовые символы не повреждаются при разделении блоков.
  • Параметры инструментов правильно объединяются по ID вызова и проверяются перед выполнением.
  • Отмена, разрыв сети, тайм-аут и серверные ошибки имеют явные состояния.
  • Логи не содержат API Key, полных чувствительных Prompt или неочищенных параметров инструментов.

Далее изучите Tool Calling и ошибки и устранение неполадок.

На этой странице