Streaming¶
Defina "stream": true em requisições de completion ou chat para
receber Server-Sent Events. Esta página documenta a ordem exata
dos chunks, os campos em cada chunk e os frames terminais.
Básico de Server-Sent Events¶
O servidor emite um evento por linha, no formato SSE padrão:
data: {"id":"...","object":"text_completion",...}
data: {"id":"...","object":"text_completion",...}
data: [DONE]
Uma linha em branco separa eventos. O prefixo data: é
obrigatório; clientes usam EventSource
ou qualquer biblioteca SSE para ler o stream.
Stream de completion de texto¶
POST /v1/completions com "stream": true emite chunks com
choices[].text carregando o texto incremental:
curl -N http://127.0.0.1:8080/v1/completions \
-H 'content-type: application/json' \
-d '{"prompt":"Once upon a time","max_tokens":32,"stream":true}'
data: {"id":"cmpl-...","object":"text_completion","choices":[{"text":" Once","index":0}]}
data: {"id":"cmpl-...","object":"text_completion","choices":[{"text":" upon","index":0}]}
data: {"id":"cmpl-...","object":"text_completion","choices":[{"text":" a","index":0}]}
data: [DONE]
Defina "logprobs": true para também receber por token tokens,
text_offset, token_logprobs e top_logprobs em cada chunk.
Contrato de stream de chat¶
POST /v1/chat/completions com "stream": true emite chunks nesta
ordem exata:
- Um primeiro chunk com
choices[0].deltacontendo{"role": "assistant"}e sem conteúdo. Este frame é enviado apenas depois que o servidor terminou de validaroptions, o prompt de chat e o sampler, então uma requisição malformada nunca produz um frame de role válido. - Zero ou mais chunks de conteúdo com
choices[0].delta.contentdefinido como o texto decodificado nesse passo echoices[0].delta.roleomitido. - Um chunk terminal com
choices[0].deltaigual a{}echoices[0].finish_reasondefinido como"stop","length", ou"tool_calls". - Um frame SSE final
data: [DONE].
sequenceDiagram
participant C as Cliente
participant S as Servidor
C->>S: POST /v1/chat/completions (stream=true)
S-->>C: chunk { delta: { role: "assistant" } }
S-->>C: chunk { delta: { content: "Once" } }
S-->>C: chunk { delta: { content: " upon" } }
S-->>C: chunk { delta: {}, finish_reason: "stop" }
S-->>C: data: [DONE]
Se a validação falha antes da geração, o stream termina com um
evento SSE de error carregando a mensagem de validação e nenhum
frame de role é emitido.
Exemplo curl trabalhado¶
curl -N http://127.0.0.1:8080/v1/chat/completions \
-H 'content-type: application/json' \
-d '{
"messages": [{"role":"user","content":"Hello!"}],
"max_tokens": 16,
"stream": true
}'
A saída se parece com:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hi"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" there"}}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]
Streaming com tools¶
Quando o modelo emite uma tool call, os chunks carregam
delta.tool_calls com os argumentos incrementais da função. O
chunk terminal tem finish_reason: "tool_calls" em vez de
"stop".
curl -N http://127.0.0.1:8080/v1/chat/completions \
-H 'content-type: application/json' \
-d '{
"messages": [{"role":"user","content":"Weather in Tokyo?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get weather for a city",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}],
"tool_choice": "auto",
"stream": true
}'
data: {"choices":[{"delta":{"role":"assistant"}}]}
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"id":"call_weather","type":"function","function":{"name":"get_weather","arguments":""}}]}}]}
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]}}]}
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"city"}}]}}]}
data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\\\"Tokyo\\\"}"}}]}}]}
data: {"choices":[{"delta":{},"finish_reason":"tool_calls"}]}
data: [DONE]
Erros durante o streaming¶
Se o modelo errar no meio da geração (ex. um LlamaError), o
stream termina com um evento SSE de error:
O código de status HTTP na resposta ainda é 200 (SSE não carrega
um código de status por evento); o cliente deve ler o tipo do
evento para detectar o erro.
Bibliotecas cliente¶
Os chunks correspondem ao formato de streaming da OpenAI, então
qualquer biblioteca cliente OpenAI funciona depois que você
apontá-la para http://127.0.0.1:8080/v1:
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8080/v1", api_key="not-needed")
stream = client.chat.completions.create(
model="local-model",
messages=[{"role": "user", "content": "Hello!"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
print(delta.content, end="", flush=True)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://127.0.0.1:8080/v1",
apiKey: "not-needed",
});
const stream = await client.chat.completions.create({
model: "local-model",
messages: [{ role: "user", content: "Hello!" }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content ?? "";
process.stdout.write(content);
}
Por onde ir a partir daqui¶
- Referência da API — cada campo de requisição.
- Saída estruturada — combinando
stream: truecomresponse_format. - Executando o servidor — flags de boot e presets.