← 문서 목록

스트리밍

Chat 스트리밍

퀵스타트의 환경변수를 준비하고 stream: true를 지정합니다. stream_options.include_usage: true이면 마지막에 사용량 청크를 받습니다.

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["EVERYAIS_API_KEY"],
    base_url="https://api.everyais.com/v1",
    timeout=240.0,
)
stream = client.chat.completions.create(
    model=os.environ["EVERYAIS_MODEL"],
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
    stream_options={"include_usage": True},
)
try:
    for chunk in stream:
        if chunk.choices:
            print(chunk.choices[0].delta.content or "", end="", flush=True)
        if chunk.usage:
            print("\nUsage:", chunk.usage.total_tokens)
finally:
    stream.close()

SSE 이벤트 읽기

  • Chat은 data: {...} 프레임을 보내고 data: [DONE]으로 끝납니다.
  • 마지막 사용량 청크는 choices: []일 수 있습니다. choices[0]을 바로 읽지 마세요.
  • : ok 같은 주석 프레임은 연결 유지를 위한 heartbeat입니다. JSON으로 파싱하지 않습니다.
  • 네트워크 chunk와 SSE 이벤트 경계는 다릅니다. 직접 구현한다면 빈 줄까지 버퍼링하고 UTF-8을 점진적으로 디코딩하세요.

Messages · Responses

API종료와 사용량
/v1/messagesmessage_start · content_block_delta · message_delta · message_stop 등 Anthropic 이벤트
/v1/responsesresponse.output_text.delta · response.completed 등 Responses 이벤트

각 SDK의 스트림 소비 방식을 사용하세요. Chat의 [DONE] 처리를 다른 형식에 그대로 적용하면 안 됩니다. Responses의 background: true는 스트림 대신 작업 JSON을 반환합니다.

오류와 연결 종료

HTTP 200으로 스트림이 시작된 뒤에도 provider 오류가 이벤트 본문으로 도착할 수 있습니다. 오류 이벤트나 예외, 정상 종료 이벤트 없이 끊긴 연결을 성공으로 처리하지 마세요. 요청을 중단할 때는 스트림을 닫고, 재시도 전에 이미 생성된 출력과 청구 내역을 확인하세요. Idempotency-Key는 완료된 SSE를 재생하지 않습니다.

웹 검색 출처는 마지막 부분에 도착합니다. 웹 검색의 최종 usage와 출처 처리를 함께 확인하세요.