Потоковые ответы
Чтение SSE, сборка текста и обработка завершения
Потоковая передача позволяет получать ответ по мере генерации
API использует Server-Sent Events, тип содержимого text/event-stream
Chat Completions
Передайте stream: true
Для счётчиков добавьте stream_options: {"include_usage": true}
curl -N https://api.getapi.ru/v1/chat/completions \
-H "Authorization: Bearer $GETAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1-mini",
"messages": [{"role": "user", "content": "Объясни HTTP"}],
"max_tokens": 256,
"stream": true,
"stream_options": {"include_usage": true}
}'Пример последовательности событий, счётчики опущены
data: {"id":"chatcmpl-example","choices":[{"index":0,"delta":{"content":"HTTP"},"finish_reason":null}]}
data: {"id":"chatcmpl-example","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]Сборка результата
- Разберите SSE-события, разделённые пустой строкой
- Объедините строки
data:внутри одного события - Для
[DONE]завершите обработку - Для JSON добавляйте
choices[].delta.contentк тексту соответствующего варианта - Сохраняйте
usageиз любого события, где это поле присутствует - Сохраняйте причину завершения из
finish_reason
choices может быть пустым в событии со счётчиками
Первое событие может содержать только роль, а последнее только причину завершения
Порядок usage и завершающего фрагмента зависит от модели
Отсутствие текста в отдельном событии не означает конец ответа
Python SDK
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["GETAPI_API_KEY"],
base_url="https://api.getapi.ru/v1",
max_retries=0,
)
stream = client.chat.completions.create(
model="gpt-4.1-mini",
messages=[{"role": "user", "content": "Объясни HTTP"}],
max_tokens=256,
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
for choice in chunk.choices:
if choice.delta.content:
print(choice.delta.content, end="", flush=True)Messages
Передайте stream: true в POST /v1/messages
Обрабатывайте message_start, content_block_start, content_block_delta, content_block_stop, message_delta и message_stop
Текстовые изменения находятся в delta.text
Блоки инструментов и рассуждений разбираются по типу
Не ожидайте маркер [DONE] в этом формате
GenerateContent
Используйте POST /v1beta/models/{model}:streamGenerateContent?alt=sse
Текст находится в частях candidates[].content.parts[]
Сохраняйте нетекстовые поля отдельно, не подставляйте их в пользовательский текст
Responses
Текст поступает в response.output_text.delta
response.completed содержит итоговый ответ
Полный текст из response.output_text.done не добавляется к уже накопленным фрагментам второй раз
Разрыв соединения и ошибки
До начала SSE сервис может вернуть обычную JSON-ошибку После начала потока проверяйте события ошибок и корректное завершение выбранного формата
Закрытие соединения завершает чтение, но само по себе не доказывает полноту ответа Если соединение оборвалось до завершающего признака, пометьте результат как неполный Не повторяйте автоматически действия инструментов, уже выполненные приложением