Skip to main content
Geração de texto

Streaming output

Em aplicações de chat em tempo real ou geração de textos longos, tempos de espera prolongados prejudicam a experiência do usuário e podem causar timeouts no servidor, resultando em falhas nas tarefas. A saída em streaming resolve esses problemas ao retornar continuamente fragmentos de texto à medida que o modelo os gera.

Como funciona

A saída em streaming utiliza o protocolo Server-Sent Events (SSE). Após o início de uma requisição em streaming, o servidor estabelece uma conexão HTTP persistente com o cliente. Sempre que o modelo gera um bloco de texto (chamado de chunk), ele o envia imediatamente por essa conexão. Quando todo o conteúdo é gerado, o servidor transmite um sinal de encerramento. O cliente escuta o fluxo de eventos, recebendo e processando os chunks de texto em tempo real — por exemplo, renderizando caracteres um a um na interface. Isso difere das chamadas sem streaming, que retornam todo o conteúdo de uma só vez.
Os componentes acima são apenas para referência e não enviam requisições reais.

Faturamento

A saída em streaming segue a mesma regra de faturamento das chamadas sem streaming, cobrando com base no número de tokens de entrada e saída na requisição. Se uma requisição for interrompida, os tokens de saída serão contabilizados apenas para a parte gerada antes de o servidor receber a solicitação de encerramento.

Como usar

As edições open source do Qwen3, as edições comercial e open source do QwQ, o QVQ e o Qwen-Omni suportam apenas saída em streaming.

Etapa 1: Configure sua chave de API e selecione uma região

Você deve ter obtained an API key e tê-la configurado como variável de ambiente.
Configurar sua chave de API como variável de ambiente ( DASHSCOPE_API_KEY ) é mais seguro do que codificá-la diretamente no código.

Etapa 2: Faça uma requisição em streaming

  • OpenAI compatible
  • DashScope
  • Como ativar Defina stream como true.
  • Visualizar uso de tokens O protocolo OpenAI não retorna o uso de tokens por padrão. Defina stream_options={"include_usage": true} para que o último chunk de dados retornado inclua informações sobre o uso de tokens.
  • Python
  • Node.js
  • curl
import os
from openai import OpenAI

# 1. Prepare: Initialize the client
client = OpenAI(
    # Configure the API key using an environment variable to avoid hard coding.
    api_key=os.environ["DASHSCOPE_API_KEY"],
    # The API key is tightly bound to a region. Ensure base_url matches the region of your API key.
    # Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# 2. Make a streaming request
completion = client.chat.completions.create(
    model="qwen-plus",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Please introduce yourself"}
    ],
    stream=True,
    stream_options={"include_usage": True}
)

# 3. Handle the streaming response
# Store response fragments in a list. Joining them at the end is more efficient than repeated string concatenation.
content_parts = []
print("AI: ", end="", flush=True)

for chunk in completion:
    if chunk.choices:
        content = chunk.choices[0].delta.content or ""
        print(content, end="", flush=True)
        content_parts.append(content)
    elif chunk.usage:
        print("\n--- Request usage ---")
        print(f"Input Tokens: {chunk.usage.prompt_tokens}")
        print(f"Output Tokens: {chunk.usage.completion_tokens}")
        print(f"Total Tokens: {chunk.usage.total_tokens}")

full_response = "".join(content_parts)
# print(f"\n--- Full response ---\n{full_response}")

Resposta

AI: Hello! I am Qwen, a large-scale language model independently developed by Tongyi Lab under Alibaba Group. I can answer questions, create content such as stories, official documents, emails, scripts, perform logical reasoning, programming, express opinions, play games, and more. I support multiple languages, including but not limited to Chinese, English, German, French, and Spanish. If you have any questions or need help, feel free to ask me anytime!
--- Request usage ---
Input Tokens: 26
Output Tokens: 87
Total Tokens: 113

Saída em streaming para modelos multimodais

Modelos multimodais permitem adicionar imagens, áudio e outros conteúdos às conversas. A implementação de saída em streaming desses modelos difere dos modelos apenas de texto nos seguintes aspectos:
  • Construção da mensagem do usuário: As entradas de modelos multimodais incluem não apenas texto, mas também imagens, áudio e outras informações multimodais.
  • Interface do SDK DashScope: Use a interface MultiModalConversation no SDK Python do DashScope. Utilize a classe MultiModalConversation no SDK Java do DashScope.
Para modelos multimodais, consulte Image and video understanding , Text extraction , Audio understanding—Qwen3-Omni-Captioner , Kimi , entre outros. O modelo Qwen-Omni suporta apenas saída em streaming porque sua saída pode incluir texto ou áudio e outros conteúdos multimodais. A análise de seus resultados difere de outros modelos. Para detalhes, consulte Omni-modal .
  • OpenAI compatible
  • DashScope
  • Python
  • Node.js
  • curl
from openai import OpenAI
import os

client = OpenAI(
    # If you haven't configured an environment variable, replace the next line with your Model Studio API key: api_key="sk-xxx"
    # API keys differ by region. Get your API key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),

    # China (Beijing) region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    base_url="https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
    model="qwen3-vl-plus",  # Replace with other multimodal models as needed and adjust messages accordingly
    messages=[
        {"role": "user",
         "content": [{"type": "image_url",
                    "image_url": {"url": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241022/emyrja/dog_and_girl.jpeg"},},
                    {"type": "text", "text": "What scene is depicted in the image?"}]}],
    stream=True,
  # stream_options={"include_usage": True}
)
full_content = ""
print("Streaming output content:")
for chunk in completion:
    # If stream_options.include_usage is True, the last chunk's choices field is an empty list and should be skipped (token usage can be obtained via chunk.usage)
    if chunk.choices and chunk.choices[0].delta.content != "":
        full_content += chunk.choices[0].delta.content
        print(chunk.choices[0].delta.content)
print(f"Full content: {full_content}")
from openai import OpenAI
import os

client = OpenAI(
    # API keys differ by region. Get your API key: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
    # If you haven't configured an environment variable, replace the next line with your Model Studio API key: api_key="sk-xxx"
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # Singapore region URL. Replace {WorkspaceId} with your actual workspace ID. URLs vary by region.
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
    model="qwen3-vl-plus",  # Replace with other multimodal models as needed and adjust messages accordingly
    messages=[
        {"role": "user",
        "content": [{"type": "image_url",
                    "image_url": {"url": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"},},
                    {"type": "text", "text": "What scene is depicted in the image?"}]}],
    stream=True,
  # stream_options={"include_usage": True}
)
full_content = ""
print("Streaming output content:")
for chunk in completion:
    # If stream_options.include_usage is True, the last chunk's choices field is an empty list and should be skipped (token usage can be obtained via chunk.usage)
    if chunk.choices and chunk.choices[0].delta.content != "":
        full_content += chunk.choices[0].delta.content
        print(chunk.choices[0].delta.content)
print(f"Full content: {full_content}")

Saída em streaming para modelos de raciocínio

Modelos de raciocínio retornam primeiro reasoning_content (o processo de pensamento) e depois retornam content (a resposta). Determine se o estágio atual é de raciocínio ou de resposta com base no status do pacote de dados.
Para detalhes sobre modelos de raciocínio, consulte Deep thinking , Image and video understanding , Visual reasoning .
Para a implementação de saída em streaming do Qwen3-Omni-Flash (modo de raciocínio), consulte Omni-modal .
  • OpenAI compatible
  • DashScope
Abaixo está o formato de resposta ao chamar o modo de raciocínio do modelo qwen-plus usando o SDK Python da OpenAI em modo streaming:
# Thinking stage
...
ChoiceDelta(content=None, function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content='Cover all key points while')
ChoiceDelta(content=None, function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content='remaining natural and fluent.')
# Response stage
ChoiceDelta(content='Hello! I am **Qwen', function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content=None)
ChoiceDelta(content='** (', function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content=None)
...
  • Se reasoning_content não for None e content for None, o estágio atual é de raciocínio.
  • Se reasoning_content for None e content não for None, o estágio atual é de resposta.
  • Se ambos forem None, o estágio permanece o mesmo do pacote anterior.
  • Python
  • Node.js
  • HTTP

Código de exemplo

from openai import OpenAI
import os

# Initialize the OpenAI client
client = OpenAI(
    # If you haven't configured an environment variable, replace with your Alibaba Cloud Model Studio API key: api_key="sk-xxx"
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

messages = [{"role": "user", "content": "Who are you"}]

completion = client.chat.completions.create(
    model="qwen-plus",  # Replace with other deep-thinking models as needed
    messages=messages,
    # The enable_thinking parameter enables the thinking process. This parameter has no effect on models qwen3-30b-a3b-thinking-2507, qwen3-235b-a22b-thinking-2507, and QwQ.
    extra_body={"enable_thinking": True},
    stream=True,
    # stream_options={
    #     "include_usage": True
    # },
)

reasoning_content = ""  # Full thought process
answer_content = ""  # Full response
is_answering = False  # Whether in the response stage
print("\n" + "=" * 20 + "Thought process" + "=" * 20 + "\n")

for chunk in completion:
    if not chunk.choices:
        print("\nUsage:")
        print(chunk.usage)
        continue

    delta = chunk.choices[0].delta

    # Collect only thinking content
    if hasattr(delta, "reasoning_content") and delta.reasoning_content is not None:
        if not is_answering:
            print(delta.reasoning_content, end="", flush=True)
        reasoning_content += delta.reasoning_content

    # Received content, start responding
    if hasattr(delta, "content") and delta.content:
        if not is_answering:
            print("\n" + "=" * 20 + "Full response" + "=" * 20 + "\n")
            is_answering = True
        print(delta.content, end="", flush=True)
        answer_content += delta.content

Resposta

====================Thought process====================

Okay, the user asked "Who are you," so I need to give an accurate and friendly answer. First, I should confirm my identity as Qwen, developed by Tongyi Lab under Alibaba Group. Next, explain my main functions, like answering questions, creating text, logical reasoning, etc. Keep the tone approachable and avoid overly technical terms so the user feels comfortable. Also, avoid complex jargon and ensure the answer is concise. Additionally, include some interactive elements to encourage further questions. Finally, check for any missing key information, such as my Chinese name "Tongyi Qianwen" and English name "Qwen," along with my company and lab. Make sure the response is comprehensive and meets user expectations.
====================Full response====================

Hello! I am Qwen, a large-scale language model independently developed by Tongyi Lab under Alibaba Group. I can answer questions, create text, perform logical reasoning, programming, and more, aiming to provide high-quality information and services. You can call me Qwen or simply Tongyi Qianwen. How can I help you?

Entrando em produção

  • Gerenciamento de desempenho e recursos: Em serviços de backend, manter uma conexão HTTP persistente para cada requisição em streaming consome recursos. Configure seu serviço com tamanho adequado de pool de conexões e valores de timeout. Em cenários de alta concorrência, monitore o uso de descritores de arquivos para evitar exaustão.
  • Renderização no lado do cliente: Em frontends web, utilize as APIs ReadableStream e TextDecoderStream para lidar e renderizar fluxos de eventos SSE de forma fluida, garantindo a melhor experiência ao usuário.
  • Model monitoring:
    • Métricas principais: Monitore o Tempo até o Primeiro Token (TTFT), a métrica central para a experiência em streaming. Acompanhe também a taxa de erros da API e o tempo médio de resposta.
    • Alertas: Configure alertas para taxas anormais de erros da API, especialmente erros 4xx e 5xx.
  • Configuração de proxy Nginx: Se utilizar o Nginx como proxy reverso, o buffer de saída padrão (proxy_buffering) compromete a natureza em tempo real das respostas em streaming. Para garantir que os dados sejam enviados aos clientes imediatamente, desative esse recurso definindo proxy_buffering off no arquivo de configuração do Nginx.

Códigos de erro

Se a chamada do modelo falhar e retornar uma mensagem de erro, consulte Error codes para resolução.

Perguntas frequentes

P: Por que não há informações de uso na resposta?

R: O protocolo OpenAI não retorna informações de uso por padrão. Defina o parâmetro stream_options para incluir informações de uso no último pacote retornado.

P: Ativar a saída em streaming afeta a qualidade da resposta do modelo?

R: Não. No entanto, alguns modelos suportam apenas saída em streaming, e chamadas sem streaming podem causar erros de timeout. Recomendamos o uso de saída em streaming.

P: Qual é a diferença entre chamadas sem streaming e com streaming?

R: Principais diferenças:
  • Limite de timeout: Para chamadas sem streaming, o timeout máximo é de pelo menos 300 segundos e varia conforme a região e o modelo. Se não for concluída a tempo, a requisição é encerrada.
  • Estrutura de saída: Chamadas sem streaming retornam a resposta completa (um único objeto JSON) de uma vez. Chamadas com streaming retornam chunks de dados progressivamente via protocolo SSE, com cada chunk contendo parte do conteúdo gerado. O cliente deve montar esses chunks.
  • Compatibilidade de recursos: Ambos suportam recursos como JSON Mode e Function Call, sem diferenças funcionais.
Recomendamos o uso de saída em streaming para evitar timeouts e melhorar a experiência do usuário.

P: A saída em streaming suporta JSON Mode (saída estruturada)?

R: Sim. Defina stream como true e response_format como {"type": "json_object"} na requisição. O modelo retornará fragmentos de conteúdo formatados em JSON progressivamente. A saída final montada será um JSON válido.
Plano de Tokens
Playground de Modelos
Inferência do Modelo
Avaliação
Compressão de Modelos
Estatísticas e Monitoramento
Suporte