ストリーミングレスポンス

Server-Sent Events を使用したトークンごとのリアルタイムレスポンス。

概要

AllToken は Server-Sent Events (SSE) によるストリーミングレスポンスをサポートしています。stream: true を設定すると、API は完全なレスポンスを待つのではなく、トークンを生成しながら逐次返します。

これによりリアルタイム UI が実現できます — テキストが一文字ずつ表示され、ユーザーが体感する遅延が大幅に改善されます。

基本的な使い方

Chat Completions リクエストに stream: true を追加してください:

TypeScript
1import OpenAI from 'openai';
2
3const client = new OpenAI({
4 apiKey: process.env.ALLTOKEN_API_KEY,
5 baseURL: 'https://api.alltoken.ai/v1',
6});
7
8const stream = await client.chat.completions.create({
9 model: 'claude-sonnet-4',
10 messages: [{ role: 'user', content: '量子コンピューティングを説明してください' }],
11 stream: true,
12});
13
14for await (const chunk of stream) {
15 const content = chunk.choices[0]?.delta?.content;
16 if (content) process.stdout.write(content);
17}

SSE レスポンスフォーマット

各 SSE イベントは data: プレフィックスの付いた JSON オブジェクトです:

レスポンスストリーム
1data: {"choices":[{"delta":{"content":"こんにちは"},"index":0}]}
2data: {"choices":[{"delta":{"content":"世界"},"index":0}]}
3data: [DONE]

ストリームは data: [DONE] で終了します。その後にコスト注釈が続く場合があります:

コスト情報
1: {"cost":"0.0012","input_price":"0.0003","output_price":"0.0009","prompt_tokens":15,"completion_tokens":42}

思考モード(拡張推論)

一部のモデルは拡張推論をサポートしています。有効にすると、モデルは最終的な回答の前に内部の推論プロセスを出力します:

TypeScript
1const stream = await client.chat.completions.create({
2 model: 'deepseek-reasoner',
3 messages: [{ role: 'user', content: '√2 が無理数であることを証明してください' }],
4 stream: true,
5});
6
7for await (const chunk of stream) {
8 // 推論プロセス(思考チェーン)
9 const thinking = chunk.choices[0]?.delta?.reasoning_content;
10 if (thinking) process.stderr.write(thinking);
11
12 // 最終的な回答
13 const content = chunk.choices[0]?.delta?.content;
14 if (content) process.stdout.write(content);
15}

reasoning_content フィールドにはモデルの段階的な推論プロセスが含まれ、content には最終的な回答が含まれます。

エラー処理

ストリーミング中のエラーは SSE イベントの error フィールドで渡されます:

エラーレスポンス
1data: {"error":{"message":"Rate limit exceeded","type":"rate_limit_error","code":429}}

ストリーミングでよくあるエラー:

  • 401 — API Key が無効または期限切れです。AllToken は自動的にトークンのリフレッシュを 1 回試みます。
  • 429 — レート制限を超えました。バックオフしてリトライしてください。
  • 500 — 上流プロバイダーエラー。リクエストは自動的に別のプロバイダーに再試行される場合があります。

リクエストのキャンセル

AbortController を使用して進行中のストリーミングリクエストをキャンセルできます:

TypeScript
1const controller = new AbortController();
2
3const stream = await client.chat.completions.create(
4 {
5 model: 'deepseek-chat',
6 messages: [{ role: 'user', content: '長い文章を書いてください' }],
7 stream: true,
8 },
9 { signal: controller.signal }
10);
11
12// 5秒後にキャンセル
13setTimeout(() => controller.abort(), 5000);