Skip to content

OpenRouter 支持对任意模型启用流式传输(SSE),只需在请求中设置 stream: true。本页说明流式传输的基本用法、SSE 注释处理、通过 AbortController 取消流,以及不同时机的错误处理方式。流式取消功能(立即停止计费)目前支持 OpenAI、Anthropic 等主流提供商,不支持 AWS Bedrock、Groq、Google 等。

OpenRouter API Streaming

OpenRouter 支持对任意模型启用流式传输,方便实时展示模型的生成过程。

基本用法

在请求中设置 stream: true

typescript
import { OpenRouter } from '@openrouter/sdk';

const openRouter = new OpenRouter({
  apiKey: '<OPENROUTER_API_KEY>',
});

const stream = await openRouter.chat.send({
  model: 'openai/gpt-4o',
  messages: [{ role: 'user', content: '如何建造世界上最高的建筑?' }],
  stream: true,
});

for await (const chunk of stream) {
  const content = chunk.choices?.[0]?.delta?.content;
  if (content) {
    process.stdout.write(content);
  }

  // 最后一个 chunk 包含用量统计
  if (chunk.usage) {
    console.log('\n用量:', chunk.usage);
  }
}

SSE 注释

OpenRouter 会偶尔发送 SSE 注释来防止连接超时,格式如下:

: OPENROUTER PROCESSING

按照 SSE 规范,这类注释可以安全忽略。你也可以利用它改善 UX,比如在等待时显示加载动画。

每个请求的 X-Generation-Id 响应头中会返回生成 ID,方便调试和追踪。

流式取消

通过 AbortController 可以取消正在进行的流式请求:

typescript
import { OpenRouter } from '@openrouter/sdk';

const openRouter = new OpenRouter({ apiKey: '<OPENROUTER_API_KEY>' });
const controller = new AbortController();

try {
  const stream = await openRouter.chat.send({
    model: 'openai/gpt-4o',
    messages: [{ role: 'user', content: '写一个故事' }],
    stream: true,
  }, {
    signal: controller.signal,
  });

  for await (const chunk of stream) {
    const content = chunk.choices?.[0]?.delta?.content;
    if (content) process.stdout.write(content);
  }
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('流已取消');
  } else {
    throw error;
  }
}

// 取消流:
controller.abort();

取消流后,支持的提供商会立即停止模型处理并停止计费;不支持的提供商会继续处理并照常收费。

支持流式取消的提供商

支持:OpenAI、Azure、Anthropic、Fireworks、Mancer、Recursal、AnyScale、Lepton、OctoAI、Novita、DeepInfra、Together、Cohere、Hyperbolic、Infermatic、Avian、XAI、Cloudflare、SFCompute、Nineteen、Liquid、Friendli、Chutes、DeepSeek

暂不支持:AWS Bedrock、Groq、Modal、Google、Google AI Studio、Minimax、HuggingFace、Replicate、Perplexity、Mistral、AI21、Featherless、Lynn、Lambda、Reflection、SambaNova、Inflection、ZeroOneAI、AionLabs、Alibaba、Nebius、Kluster、Targon、InferenceNet

流式传输中的错误处理

首个 token 前的错误

返回标准 JSON 错误,带对应 HTTP 状态码(400/401/402/429/502/503)。

已发送部分 token 后的错误

HTTP 状态码已确定(200 OK),错误以 SSE 事件形式返回,finish_reason"error"

typescript
async function streamWithErrorHandling(prompt: string) {
  try {
    const stream = await openRouter.chat.send({
      model: 'openai/gpt-4o',
      messages: [{ role: 'user', content: prompt }],
      stream: true,
    });

    for await (const chunk of stream) {
      // 检查 chunk 中的错误
      if ('error' in chunk) {
        console.error(`流错误: ${chunk.error.message}`);
        if (chunk.choices?.[0]?.finish_reason === 'error') {
          console.log('流因错误终止');
        }
        return;
      }

      const content = chunk.choices?.[0]?.delta?.content;
      if (content) process.stdout.write(content);
    }
  } catch (error) {
    // 处理首个 token 前的错误
    console.error(`错误: ${error.message}`);
  }
}

常见问题

Q: 哪些 SSE 客户端库兼容 OpenRouter 的流格式?

A: 部分 SSE 客户端不按规范解析非 JSON payload,会在处理注释时抛出异常。建议使用 OpenRouter SDK,或确认你的 SSE 库能正确处理注释行(以 : 开头的行)。

Q: 流式传输和非流式传输的收费方式一样吗?

A: 是的,都按实际的 prompt tokens + completion tokens 收费。取消流时,支持该功能的提供商会在取消点停止计费。

Q: X-Generation-Id 有什么用?

A: 可用于在 OpenRouter Activity 页面追踪单次请求的详细统计,也可通过 /api/v1/generation?id=<ID> 端点查询。