Saída de transmissão
Receba o sinal de saída de texto por token como é gerado.
Activar a transmissão
OpenAI Chat Completions
Não há uso por padrão. Preparar. `stream_options` Para conseguir a contagem de fichas no último pedaço.
```python Python {7,8}
import os
from openai import OpenAI
client = OpenAI(api_key=os.getenv("DASHSCOPE_API_KEY"), base_url="https://maas.qwencloudapi.com/compatible-mode/v1")
completion = client.chat.completions.create(
model="qwen3.7-plus",
messages=[{"role": "user", "content": "Hi"}],
stream=True, # ← enable streaming
stream_options={"include_usage": True}, # ← usage in last chunk only
)
for chunk in completion:
if chunk.choices:
print(chunk.choices[0].delta.content or "", end="", flush=True)
elif chunk.usage: # ← last chunk: usage only
print(f"\nTokens: {chunk.usage.total_tokens}")
```
```javascript Node.js {7,8}
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.DASHSCOPE_API_KEY, baseURL: "https://maas.qwencloudapi.com/compatible-mode/v1" });
const stream = await client.chat.completions.create({
model: "qwen3.7-plus",
messages: [{ role: "user", content: "Hi" }],
stream: true, // ← enable streaming
stream_options: { include_usage: true }, // ← usage in last chunk
});
for await (const chunk of stream) {
if (chunk.choices?.length > 0)
process.stdout.write(chunk.choices[0]?.delta?.content || "");
else if (chunk.usage)
console.log(`\nTokens: ${chunk.usage.total_tokens}`);
}
```
```bash curl
curl -X POST https://maas.qwencloudapi.com/compatible-mode/v1/chat/completions \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" --no-buffer \
-d '{"model":"qwen3.7-plus","messages":[{"role":"user","content":"Hi"}],"stream":true,"stream_options":{"include_usage":true}}'
```
OpenAI Responses API
```python Python {6}
import os
from openai import OpenAI
client = OpenAI(api_key=os.getenv("DASHSCOPE_API_KEY"), base_url="https://maas.qwencloudapi.com/compatible-mode/v1")
stream = client.responses.create(
model="qwen3.7-plus",
input="Hi",
stream=True, # ← enable streaming
)
for event in stream:
if event.type == "response.output_text.delta":
print(event.delta, end="", flush=True)
elif event.type == "response.completed":
print(f"\nTokens: {event.response.usage.total_tokens}")
```
```javascript Node.js {6}
import OpenAI from "openai";
const client = new OpenAI({ apiKey: process.env.DASHSCOPE_API_KEY, baseURL: "https://maas.qwencloudapi.com/compatible-mode/v1" });
const stream = await client.responses.create({
model: "qwen3.7-plus",
input: "Hi",
stream: true, // ← enable streaming
});
for await (const event of stream) {
if (event.type === "response.output_text.delta")
process.stdout.write(event.delta);
else if (event.type === "response.completed")
console.log(`\nTokens: ${event.response.usage.total_tokens}`);
}
```
```bash curl
curl -X POST https://maas.qwencloudapi.com/compatible-mode/v1/responses \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" --no-buffer \
-d '{"model":"qwen3.7-plus","input":"Hi","stream":true}'
```
DashScope
Ao contrário do OpenAI compatível (único pedaço), DashScope retorna o uso de fichas em tempo real em **cada pedaço** — útil para monitorar custos ou parar cedo.
Qwen3.5 e Qwen3.6 Modelos usam o `multimodal-generation` Endpoint mostrado abaixo. Modelos anteriores, como qwen-plus e qwen-max Use o `text-generation` Endpoint em vez disso. Veja [Referência da API DashScope] (/api-reference/chat/dashscope) para detalhes.
```python Python {10,11}
from http import HTTPStatus
import dashscope
dashscope.base_http_api_url = 'https://maas.qwencloudapi.com/api/v1'
from dashscope import MultiModalConversation
responses = MultiModalConversation.call(
model="qwen3.7-plus",
messages=[{"role": "user", "content": [{"text": "Hi"}]}],
stream=True, # ← enable streaming
incremental_output=True, # ← recommended: new tokens only per chunk
)
for resp in responses:
if resp.status_code == HTTPStatus.OK:
content = resp.output.choices[0].message.content
if content:
print(content[0]["text"], end="", flush=True)
```
```java Java {12,14}
import java.util.*;
import com.alibaba.dashscope.aigc.multimodalconversation.*;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.utils.Constants;
Constants.baseHttpApiUrl = "https://maas.qwencloudapi.com/api/v1";
MultiModalConversationParam param = MultiModalConversationParam.builder()
.apiKey(apiKey).model("qwen3.7-plus")
.messages(Arrays.asList(
MultiModalConversationMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(Collections.singletonMap("text", "Hi"))).build()))
.incrementalOutput(true) // ← recommended: new tokens only
.build();
new MultiModalConversation().streamCall(param) // ← streamCall, not call
.subscribe(msg -> System.out.print(
msg.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text")));
```
```bash curl
curl -X POST https://maas.qwencloudapi.com/api/v1/services/aigc/multimodal-generation/generation \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" -H "Content-Type: application/json" \
-H "X-DashScope-SSE: enable" \
-d '{"model":"qwen3.7-plus","input":{"messages":[{"role":"user","content":[{"text":"Hi"}]}]},"parameters":{"incremental_output":true}}'
```
Formato do evento
Cada evento SSE é um data: Linha contendo um pedaço de JSON. A final data: [DONE] sinaliza o fim do fluxo.
data: {"choices":[{"delta":{"content":"I am"},...,"finish_reason":null}],...}
data: {"choices":[{"delta":{"content":" Qwen"},...,"finish_reason":null}],...}
data: {"choices":[{"delta":{"content":""},...,"finish_reason":"stop"}],...}
data: [DONE]
Flutuando com o modo de pensar
Duas fases de transmissão: pensar primeiro, depois a resposta.
OpenAI Chat Completions
```python
for chunk in completion:
delta = chunk.choices[0].delta
if hasattr(delta, "reasoning_content") and delta.reasoning_content:
print(delta.reasoning_content, end="", flush=True) # ← phase 1: thinking
if hasattr(delta, "content") and delta.content:
print(delta.content, end="", flush=True) # ← phase 2: answer
```
OpenAI Responses API
```python
for event in stream:
if event.type == "response.reasoning_text.delta":
print(event.delta, end="", flush=True) # ← phase 1: thinking
elif event.type == "response.output_text.delta":
print(event.delta, end="", flush=True) # ← phase 2: answer
```
DashScope
```python
for chunk in completion:
msg = chunk.output.choices[0].message
if msg.reasoning_content: # ← phase 1: thinking
print(msg.reasoning_content, end="", flush=True)
if msg.content: # ← phase 2: answer
print(msg.content, end="", flush=True)
```
→ Configuração completa:/developer-guides/text-generation/thinking) | Qwen3-Omni[Audio e vídeo] (/developer-guides/speech/multimodal-speech)
Flutuando com chamadas de ferramentas
Quando o streaming [função chamando] (/developer-guides/tool-calling/function-calling Respostas, argumentos de chamada de ferramentas chegam como deltas incrementais que devem ser concatenados antes da análise JSON.
Chat Completions
Cada pedaço `delta` pode conter `tool_calls[i].function.arguments` - uma corda parcial JSON. Acumule todos os fragmentos por índice de chamada de ferramentas, então `JSON.parse()` A corda completa.
```python
tool_args = {}
for chunk in completion:
delta = chunk.choices[0].delta
if delta.tool_calls:
for tc in delta.tool_calls:
tool_args.setdefault(tc.index, "")
tool_args[tc.index] += tc.function.arguments or ""
# After stream ends:
for idx, args_str in tool_args.items():
parsed = json.loads(args_str)
```
Responses API
Chamadas de ferramentas emitem `response.function_call_arguments.delta` eventos. Concatenar deltas até `response.function_call_arguments.done`.
```python
args_buffer = ""
for event in stream:
if event.type == "response.function_call_arguments.delta":
args_buffer += event.delta
elif event.type == "response.function_call_arguments.done":
parsed = json.loads(args_buffer)
args_buffer = ""
```
Com [modo de pensar] (/developer-guides/text-generation/thinking) habilitado, o fluxo entrega três fases: pensando em fichas, em seguida, ferramenta chamar deltas, em seguida, (depois de enviar resultados de ferramentas) a resposta final.
Notas
- ** Nginx proxy**: conjunto
proxy_buffering offou eventos SSE vão amortecer - Alta concordância: tamanho de conexão, monitora descritores de arquivos
- ** Web frontend **: use
ReadableStream+TextDecoderStream - Qualidade: streaming não afeta a qualidade da resposta.
- Modelos únicos de trilhos QWQ e QVQ só suportam saída de streaming. Chamadas sem transmissão para esses modelos falharão ou retornarão conteúdo vazio.
FAQ
Qual é a diferença entre streaming e chamadas não-streaming?
- As chamadas não-streaming têm um tempo máximo de pelo menos 300 segundos, a duração real varia de acordo com a região de implantação e o modelo.
- As chamadas não-streaming retornam a resposta completa como um único objeto JSON. A transmissão de chamadas retorna os dados gradualmente através do protocolo SSE, onde cada pedaço contém conteúdo gerado parcial que o cliente deve concatenar.
- Ambos suportam o modo JSON, Function Call e outras características sem diferenças funcionais.
Recomendamos usar a saída de streaming para evitar problemas de tempo e proporcionar uma melhor experiência ao usuário.
** A saída de streaming suporta o modo JSON (produção estruturada)?
Sim. Preparar. stream para true e response_format para {"type": "json_object"} no mesmo pedido. O modelo devolverá o conteúdo de JSON incrementalmente através de streaming. A saída completa concatenada será válida JSON.