Lovely Routerドキュメント
キーを取得
モデル API

ストリーミング

3 つの API 形式のいずれでも、生成されたトークンを順次ストリーミングできます。ゲートウェイが早期の失敗をどう隠すか、停止やストリーム途中のエラーがどう現れるか、キャンセルしたストリームの料金について説明します。

ストリームは、各ベンダー独自の形式による Server-Sent Events を使います。受け取るバイト列はモデルが生成したバイト列そのものです。ゲートウェイは使用量の計測と、失敗からの保護のためにそれを監視するだけです。

ストリーミングを有効にする#

APIストリーミングの方法ストリームの終わり
Anthropic Messages本文に "stream": trueevent: message_stop
OpenAI Chat Completions本文に "stream": truedata: [DONE]
GeminiPOST /v1beta/models/{model}:streamGenerateContent?alt=ssecandidate に finishReason を含むイベント

コードは各 SDK のガイドにあります:Anthropic、OpenAI、Gemini。

ストリームの例#

SSE
event: message_start
data: {"type":"message_start","message":{"id":"msg_01HCz7","type":"message","role":"assistant","model":"claude-sonnet-5-5","content":[],"stop_reason":null,"usage":{"input_tokens":14,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":1}}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"One, two, three."}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":8}}

event: message_stop
data: {"type":"message_stop"}

早期の失敗は自動で再試行される#

チャネルがリクエストを受け付けた後、出力を生成する前に失敗することがあります。たとえば、message_start を送った直後に過負荷エラーを返すケースです。ゲートウェイは、コンテンツの最初のトークン(テキスト、思考、ツール呼び出し)が届くまで、すべてのストリームの冒頭を保留します。その前にチャネルが失敗した場合、まだ何もクライアントに届いていないため、ゲートウェイは別のチャネルでリクエストを再試行し、クライアントは最初から正常なストリームを受け取ります。

立ち上がりが遅いだけのチャネルも同様です。拡張思考を使わない Claude モデルでは、10 秒以内(プロンプト 1 万トークンごとに 1 秒追加)に最初のトークンを生成しないチャネルは、利用できる最後のチャネルでない限り、別のチャネルに切り替えます。思考を有効にしたリクエストは、モデルが思考する間そのまま待ちます。非ストリーミングのリクエストにも同じルールが適用されます。

クライアント側への影響は次のとおりです。

  • HTTP ステータスとヘッダーは最初のトークンと一緒に届きます。そのため、最初のバイトまでの時間は最初のトークンまでの時間と同じになります。
  • 最初のトークンより前にすべてのチャネルが失敗した場合は、壊れたストリームではなく、お使いの API のエラー形式による通常の HTTP エラーレスポンスが返ります。
  • 保留は最長 15 秒です。それより長く無言で思考するモデルは、その時点でストリーミングを開始し、以降そのリクエストはそのチャネルに確定します。
  • レスポンスが始まるまで、少なくとも 30 秒は待てるようにしてください。リクエストは、その前に容量の空きを数秒待つこともあります。レート制限とフェイルオーバーを参照してください。

ストリーム途中の停止とエラー#

トークンが流れ始めると、リクエストは 1 つのチャネルに確定し、移動できなくなります。それでも、次の 2 つの理由でストリームが途中で終わることがあります。

停止。 チャネルが 3 分間何も送らなかった場合、ゲートウェイはお使いの API の形式によるエラーイベントでストリームを終了し、接続を閉じます。

SSE
event: error
data: {"type":"error","error":{"type":"api_error","message":"Upstream stopped responding mid-stream"}}

チャネルからのエラー。 チャネルは、実行中のストリームの中でエラーを報告することがあります(モデルの過負荷など)。その場合は、チャネル独自のテキストではなく、お使いの API の形式による汎用的なエラーイベントを受け取ります。チャネルが混雑している場合は overloaded_error(OpenAI では rate_limit_exceeded、Gemini では RESOURCE_EXHAUSTED)、それ以外の場合は api_error(Gemini では UNAVAILABLE)で、メッセージは The model provider returned an error. Please retry. です。

どちらの場合も、ストリームは通常の最終イベント(message_stop、data: [DONE]、または finishReason)なしで終わります。最終イベントなしで終わったストリームは不完全なものとして扱ってください。部分的な出力を残すか破棄するかを決め、完全な回答が必要ならリクエスト全体を再試行します。Anthropic SDK と OpenAI SDK は、エラーイベントを受け取ると例外を送出します。

ストリームをキャンセルする#

生成を止めるには接続を閉じます。たとえば、ループを抜けるか、stream.close() / controller.abort() を呼び出します。ゲートウェイはモデルを停止し、その時点までに生成された分を課金します。

  • 入力には、ストリームがすでに報告したトークン数を使います(Anthropic は開始時に報告します)。報告がなかった場合は、リクエストの約 4 文字を 1 トークンとして見積もります。
  • 出力は、ストリームがそれまでに報告したトークン数と、送信済みのテキストを約 4 文字 1 トークンとして見積もった値の、大きいほうになります。途中で打ち切られたストリームが最終的な出力トークン数を報告することはまれなため、通常は見積もりの値が使われます。

停止エラーで終わったストリームも、同じ方法で、受け取った分が課金されます。キャンセルまたは停止したストリームは、すべて請求額とともにログに表示されます。モデルと料金を参照してください。