빠른 답변
LLMwithCrypto에서 chat completion을 어떻게 stream하나요?
POST https://llmwithcrypto.com/api/v1/chat/completions의 body에 "stream": true를 추가하세요. 그러면 LLMwithCrypto이 server-sent events로 응답합니다. 각 data: 줄은 delta.content에 텍스트 조각을 담은 chat.completion.chunk를 가지며, stream은 data: [DONE]로 끝납니다. "stream_options": {"include_usage": true}을 추가하면 마지막 chunk에서 토큰 수를 받습니다. 2026년 10월 23일 문서 기준으로, 이는 모든 모델에서 동작합니다.
굳이 stream하는 이유가 무엇인가요?
사람에게는, 전체 답변이 작성된 뒤가 아니라 잠깐 만에 첫 단어가 나타나기 때문입니다. 큰 모델의 긴 답변은 완성되기까지 수 초가 걸릴 수 있습니다. stream하면 독자는 곧바로 읽기 시작합니다.
프로그램에는 덜 중요합니다. 전체 텍스트가 필요한 스크립트는 streaming에서 얻는 것이 없고 파싱할 것만 많아집니다. 사람이 지켜볼 때는 stream하고, 그 외에는 일반 요청을 보내세요. 가격은 어느 쪽이든 같습니다. 잔액에서 토큰 단위로 결제합니다. 입력 및 출력 토큰은 모델 자체의 tokenizer로 계산되며, 해당 모델의 1M 토큰당 가격으로 청구됩니다. 오류로 끝난 호출은 비용이 들지 않습니다.
curl -sN "https://llmwithcrypto.com/api/v1/chat/completions" \
-H "Authorization: Bearer $LLMWITHCRYPTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"messages": [{"role": "user", "content": "Write a haiku about latency."}],
"stream": true,
"stream_options": {"include_usage": true},
"max_tokens": 120
}'
import os
from openai import OpenAI
client = OpenAI(
base_url="https://llmwithcrypto.com/api/v1",
api_key=os.environ["LLMWITHCRYPTO_API_KEY"],
)
stream = client.chat.completions.create(
model="deepseek-v4.1-flash",
messages=[{"role": "user", "content": "Write a haiku about latency."}],
stream=True,
stream_options={"include_usage": True},
max_tokens=120,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage:
print("\n", chunk.usage.prompt_tokens, "in,", chunk.usage.completion_tokens, "out")
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://llmwithcrypto.com/api/v1',
apiKey: process.env.LLMWITHCRYPTO_API_KEY,
});
const stream = await client.chat.completions.create({
model: 'deepseek-v4.1-flash',
messages: [{ role: 'user', content: 'Write a haiku about latency.' }],
stream: true,
stream_options: { include_usage: true },
max_tokens: 120,
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content;
if (text) process.stdout.write(text);
if (chunk.usage) console.log(`\n${chunk.usage.prompt_tokens} in, ${chunk.usage.completion_tokens} out`);
}
stream은 wire 상에서 어떻게 보이나요?
각 이벤트는 data: 로 시작하는 한 줄과 빈 줄로 이루어집니다. 첫 chunk는 보통 role을 담고, 다음 chunk들은 각각 content의 몇 글자를 담으며, finish_reason이 담긴 chunk가 답변을 닫습니다. include_usage을 사용하면 빈 choices 배열과 usage 객체를 담은 chunk가 하나 더 이어집니다. stream은 항상 data: [DONE]로 끝납니다. 아래의 id와 수치는 예시입니다.
data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{"content":"Packets"},"finish_reason":null}]}
data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{"content":" cross the"},"finish_reason":null}]}
data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-5a1e","object":"chat.completion.chunk","created":1792742400,"model":"deepseek-v4.1-flash","choices":[],"usage":{"prompt_tokens":14,"completion_tokens":19,"total_tokens":33}}
data: [DONE]
stream이 끊기면 어떻게 되나요?
잘못된 키나 잔액 부족처럼 첫 토큰 전에 발견된 오류는 stream이 아니라 JSON body를 담은 일반 HTTP 오류로 돌아옵니다. errors 페이지에 나열되어 있습니다. 생성 중 오류는 finish_reason 없이 stream을 일찍 종료합니다.
연결을 직접 닫으면 생성이 중단됩니다. 그러면 다른 호출과 마찬가지로 입력과 이미 생성된 토큰에 대해 비용을 지불합니다. 코드는 finish_reason도 [DONE]도 없이 끝난 stream을 불완전한 것으로 처리하고, 전체 답변이 필요하면 요청을 다시 보내야 합니다.
Streaming: 자주 묻는 질문
streaming이 더 비싼가요?
아니요. 같은 토큰이 같은 가격으로 청구됩니다. 잔액에서 토큰 단위로 결제합니다. 입력 및 출력 토큰은 모델 자체의 tokenizer로 계산되며, 해당 모델의 1M 토큰당 가격으로 청구됩니다. 오류로 끝난 호출은 비용이 들지 않습니다.
tool calling과 함께 stream할 수 있나요?
네, tool을 지원하는 모델에서 가능합니다. 함수 이름과 인자는 delta.tool_calls에 조각으로 도착하므로 사용 전에 이어 붙여야 합니다. tool calling 페이지에서는 stream하지 않는 루프를 보여주며, 이쪽이 시작하기에 더 단순합니다.
stream 호출에서 usage가 왜 안 나오나요?
"stream_options": {"include_usage": true}를 추가하세요. 추가하지 않으면 스트림에 토큰 수가 담기지 않습니다. 대시보드에는 여전히 표시됩니다.