BazaarLinkBazaarLink
ログイン
ドキュメントAPIリファレンスSDKリファレンスエージェント利用AIスキル
目次

ストリーミング

ストリーミング

設定: stream: true でServer-Sent Events(SSE)ストリームを受信します。各イベントにはレスポンスのチャンクが含まれます。

from openai import OpenAI

client = OpenAI(
    base_url="https://api.bazaarlink.ai/v1",
    api_key="sk-bl-YOUR_API_KEY",
)

stream = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[{"role": "user", "content": "Count to 10 slowly."}],
    stream=True,
)

for chunk in stream:
    content = chunk.choices[0].delta.content
    if content:
        print(content, end="", flush=True)

SSE形式

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":"Hello"},"index":0}]}

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":" world"},"index":0}]}

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{},"finish_reason":"stop","index":0}],"usage":{"prompt_tokens":10,"completion_tokens":4,"total_tokens":14}}

data: [DONE]
ストリーミングでの使用量
ストリーミング時、使用量データは[DONE]メッセージの前の最終チャンクに、空のdeltaとfinish_reason: "stop"を持つchoices配列とともに返されます。

Keep-alive と最終チャンク

ストリームにはSSEコメント行や未知またはpingのkeep-aliveイベントが含まれる場合があります。これらを無視してdataフレームを解析してください。最後のdataフレームにはdata: [DONE]の前にusageが含まれる場合があります。

: keepalive          <- SSE comment line — ignore, do NOT JSON.parse

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":"Hi"},"index":0}]}

data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{},"finish_reason":"stop","index":0}],"usage":{...}}

data: [DONE]

ストリームのキャンセル

クライアント接続を閉じることでストリーミングリクエストをキャンセルできます — 例えば AbortController.abort() を呼ぶ、または stream オブジェクトを閉じるなど。BazaarLink はキャンセルを受け取り次第、以降のチャンク転送を停止し、プロバイダーへのアウトバウンドリクエストを中止します。

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.bazaarlink.ai/v1",
  apiKey: "sk-bl-YOUR_API_KEY",
});

const controller = new AbortController();

const stream = await client.chat.completions.create(
  {
    model: "anthropic/claude-sonnet-4.6",
    messages: [{ role: "user", content: "Write a long story." }],
    stream: true,
  },
  { signal: controller.signal }
);

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

// e.g. on a "Stop" button click:
controller.abort();
中断されたストリームには課金されません
最後の usage チャンクが届く前にストリームが終了した場合 — クライアント側でのキャンセルを含む — そのリクエストには信頼できるトークン数の根拠がないため、BazaarLink は予約分を全額返金します。キャンセル前にすでにクライアントへ届いたコンテンツについて課金されることはありません。
プロバイダー側の即時停止は保証されません
接続を閉じると BazaarLink は以降のトークンの転送と課金を直ちに停止しますが、接続が切れた瞬間にアップストリームのプロバイダーが自社サーバー上で生成を停止するかどうかはそのプロバイダー次第です — 切断後もしばらく処理を続けるプロバイダーもあります。

ストリーム途中でのエラー

エラーフレームには choices フィールドがありません
ストリーミング開始後に失敗が発生した場合(例:アップストリーム接続の切断)、通常の {choices:[...]} ではなく {error:{message,type,code}} 形式の SSE データフレームが返されます — ヘッダーはすでに送信済みのため、HTTP ステータスの変化はありません。choices[0].delta を読む前に error キーの有無を確認してください。課金はそれまでにストリーミングされたトークン分のみです(部分課金が適用されます)。
data: {"id":"85e6f35c71a31f19-SJC","choices":[{"delta":{"content":"The capital of "},"index":0}]}

data: {"error":{"message":"The request could not be completed.","type":"upstream_error","code":502}}

data: [DONE]
サポート
こんにちは。どのようなご用件でしょうか?
メッセージをお送りください。担当者より返信します。
ストリーミング | BazaarLink