Re Reference AI

技術

ストリーミングとは

Streaming

LLMが生成したトークンを、完成を待たずに逐次クライアントへ送信する応答方式

LLMAPI

ひとことで言うと

AIが答えを全部作り終える前に、できた分から順番に届ける方式。

概要

ストリーミング(Streaming)とは、LLMがテキストを生成する際、全ての出力が完成するのを待ってから一括で返すのではなく、生成されたトークンを1つずつ、あるいは小さなまとまりごとに逐次クライアントへ送信していく応答方式。 ユーザーは、モデルが実際に生成している様子をリアルタイムに近い形で確認できるため、長い応答を待つ際の体感的な待ち時間を減らせる。 ChatGPTやClaude等のチャットUIで回答が少しずつ表示されていく挙動は、多くの場合このストリーミングによるもの。 実装上はサーバー送信イベント(SSE)などの技術を用いて、生成の都度トークンを送り出す形が一般的で、対話型アプリケーションにおける標準的な応答方式になっている。

背景

LLMによる長い応答は生成に数秒〜数十秒かかることがあり、生成完了まで何も表示しないと、ユーザーは応答が止まっているように感じてしまう。 ストリーミングは、生成済みの部分から順次表示することで、この体感待ち時間の問題を緩和するため採用されている。

アーキテクチャ

サーバー側は、トークンが生成されるたびにそれをクライアントへ送信し、クライアント側はSSE(Server-Sent Events)等の技術を用いて受信したトークンを順次画面へ追記していく。 総生成時間(最後のトークンが出力されるまでの時間)自体はストリーミングの有無によって変わらないが、最初のトークンが返ってくるまでの体感時間(First Token Latency)を短く感じさせる効果がある。

ワークフロー

クライアントがストリーミング対応のリクエストを送信 → サーバーがトークンを生成するたびに順次送信 → クライアントがSSE等で受信したトークンを画面へ逐次追記 → 生成完了を示すイベントで終了する。

コード例

OpenAI APIでストリーミング応答を受け取る

from openai import OpenAI

client = OpenAI()
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "AIについて説明してください。"}],
    stream=True,
)

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

利点

  • 応答の完成を待たずに内容の表示を始められ、体感的な待ち時間を減らせる
  • 長い応答や、途中で処理を打ち切りたい場合にも柔軟に対応しやすい
  • チャットUIのように、生成過程を見せること自体が価値を持つ用途に適する

欠点

  • 実装がリクエスト・レスポンス型のシンプルなAPI呼び出しより複雑になる
  • Function Calling等、構造化された完全な出力が必要な処理では追加の工夫を要する場合がある
  • クライアント側もストリーミング受信に対応した実装が必要で、単純なリクエスト・レスポンスより開発コストが増える

比較

  • 推論ストリーミングは、推論結果を返す際の配信方式であり、推論そのものの計算量を減らすものではない
  • バッチ推論ストリーミングが個々のリクエストへの応答性を重視するのに対し、バッチ推論は複数リクエストをまとめて処理しスループットを重視する

関連用語

推論バッチ推論LLM

よくある質問

ストリーミングを使うと生成は速くなる?

総生成時間自体は変わらないが、最初のトークンが返ってくるまでの体感待ち時間が短くなり、ユーザー体験としては速く感じられる。

ストリーミングはAPIコストに影響する?

課金は通常、生成されたトークン数に基づくため、ストリーミングの有無自体が課金額に影響することは少ない。

参考文献

関連Zenn記事