스트리밍

스트리밍 (Streaming)

모델이 응답을 한 번에 다 보내는 대신, 생성되는 대로 조각조각 내려받고 싶을 때 스트리밍을 써요. 토큰이 만들어지는 순간부터 화면에 표시되니, 긴 답변에서도 사용자가 기다리는 느낌 없이 실시간 피드백을 받을 수 있죠. 이 페이지에서는 스트리밍을 켜는 방법과 응답 형태를 확인해요.

출처: xAI 공식 문서 — Streaming

스트리밍의 기본 동작

스트리밍 출력은 텍스트 출력 능력이 있는 모든 모델(채팅, 이미지 이해 등)에서 지원돼요. 이미지 출력 능력만 있는 모델(이미지 생성)은 지원하지 않습니다.

동작 원리는 Server-Sent Events (SSE)예요. 서버가 콘텐츠의 델타를 이벤트 스트림으로 계속 보내 주는 방식이죠.

스트리밍을 켜려면 요청에 "stream": true를 설정하면 됩니다.

SDK로 스트리밍하기

추론 모델과 함께 쓸 때는 연결이 일찍 끊기지 않도록 요청 타임아웃을 직접 늘려 두는 것이 좋아요.

import os
from xai_sdk import Client
from xai_sdk.chat import user, system

client = Client(
    api_key=os.getenv("XAI_API_KEY"),
    timeout=3600,  # 추론 모델용 타임아웃을 길게 잡기
)

chat = client.chat.create(model="grok-4.6")
chat.append(system("You are Grok, a helpful and maximally truthful AI built by xAI."))
chat.append(user("Explain how neural networks learn in two sentences."))

for response, chunk in chat.stream():
    print(chunk.content, end="", flush=True)  # 각 청크의 콘텐츠
    print(response.content, end="", flush=True)  # response 객체는 청크를 자동 누적

print(response.content)  # 전체 응답

response 객체가 청크들을 자동으로 누적해 주므로, 루프가 끝난 뒤 response.content로 전체 응답을 바로 꺼낼 수 있어요.

수신되는 이벤트 스트림

SSE 응답은 대략 이런 형태로 도착합니다. 각 이벤트는 chat.completion.chunk 객체이고 delta.content에 새로 생성된 조각이 실려 와요.

data: { "id": "<completion_id>", "object": "chat.completion.chunk", "created": <creation_time>, "model": "grok-4.6", "choices":[{ "index": 0, "delta":{ "content": "Ah", "role": "assistant" }}], "usage":{ "prompt_tokens": 41, "completion_tokens": 1, "total_tokens": 42, "prompt_tokens_details":{ "text_tokens": 41, "audio_tokens": 0, "image_tokens": 0, "cached_tokens": 0 }}, "system_fingerprint": "fp_xxxxxxxxxx" }
data: { "id": "<completion_id>", "object": "chat.completion.chunk", "created": <creation_time>, "model": "grok-4.6", "choices":[{ "index": 0, "delta":{ "content": ",", "role": "assistant" }}], "usage":{ "prompt_tokens": 41, "completion_tokens": 2, "total_tokens": 43, "prompt_tokens_details":{ "text_tokens": 41, "audio_tokens": 0, "image_tokens": 0, "cached_tokens": 0 }}, "system_fingerprint": "fp_xxxxxxxxxx" }
data: [DONE]

이벤트 스트림을 직접 파싱하기보다는 클라이언트 SDK를 써서 파싱하는 걸 권장해요. SDK가 이 형식을 알아서 처리해 주니까요.

더 알아보기