プレフィックス共有キャッシング(プレフィックスキョウユウキャッシング)
LLM推論において、複数リクエスト間で共通するプロンプトの先頭部分(プレフィックス)のKVキャッシュを共有・再利用する最適化手法。
プレフィックス共有キャッシングとは
プレフィックス共有キャッシング(Prefix Sharing / Prefix Caching)は、LLM の推論サービングにおいて、複数のリクエストが同一のプロンプトプレフィックスを持つ場合に、そのプレフィックス部分の KV キャッシュを共有して再利用する技術である。商用 LLM API で「プロンプトキャッシング」と呼ばれる機能の多くは、この原理に基づいている。
従来のLLMサービングでは、各リクエストは独立して処理され、同一のシステムプロンプトであっても毎回KV計算が行われていた。プレフィックス共有では、トークン列の先頭からの一致部分を検出し、既にメモリ上に存在するKVキャッシュを再利用することで、冗長な計算を排除する。
プレフィックスマッチングのアルゴリズム
プレフィックス共有の核心は、新規リクエストのトークン列と既存のキャッシュエントリとの間でプレフィックス一致長を効率的に特定するアルゴリズムにある。
Radix Tree ベースの管理
vLLM や SGLang で採用されているアプローチでは、Radix Tree(基数木)データ構造を用いてKVキャッシュを管理する。
Root
├── [System Prompt A: 2048 tokens] ─── KV Block 0-15
│ ├── [User Query 1: 256 tokens] ─── KV Block 16-17
│ ├── [User Query 2: 512 tokens] ─── KV Block 16-19
│ └── [User Query 3: 128 tokens] ─── KV Block 16
└── [System Prompt B: 4096 tokens] ─── KV Block 20-51
└── [User Query 4: 256 tokens] ─── KV Block 52-53
この構造により、同一システムプロンプトを共有する複数のリクエストが効率的にキャッシュを共有できる。新規リクエスト到着時にはRadix Treeを走査して最長一致プレフィックスを検出し、一致部分のKVブロックを参照する。
ハッシュベースの管理
OpenAI の自動キャッシングやDeepSeekの実装では、トークン列のハッシュ値を用いたルックアップが採用されている。プレフィックスを一定長のチャンクに分割し、各チャンクのハッシュ値をキーとしてKVキャッシュを管理する。
| 管理方式 | 検索計算量 | メモリ効率 | 実装例 |
|---|---|---|---|
| Radix Tree | O(プレフィックス長) | 高(共有ノード) | SGLang, vLLM |
| ハッシュテーブル | O(チャンク数) | 中(チャンク単位) | OpenAI, DeepSeek |
| LRU リスト | O(エントリ数) | 低(全エントリ保持) | 初期実装 |
商用APIでのプレフィックス共有
Anthropic Claude のプレフィックスキャッシング
Anthropic は cache_control パラメータで最大4つのブレークポイントを設定でき、各ブレークポイントまでのプレフィックスがキャッシュ対象となる。キャッシュのTTLは最終使用から5分間で、使用のたびにリセットされる。最小キャッシュ単位は1,024トークンで、Claude 3.5 Sonnet / Claude 3.5 Haiku / Claude 3 Opus の全モデルで利用可能。
キャッシュヒット時の入力トークン料金は通常の10%に割引され、キャッシュ書き込み時は通常の125%の料金が発生する。損益分岐点は、キャッシュ対象プレフィックスが2回以上使用される場合で、実際のエージェントシステムでは10回以上の再利用が一般的であるため、大幅なコスト削減が実現する。
OpenAI の自動プレフィックスキャッシング
OpenAI は2024年10月から GPT-4o および o1 シリーズで自動プレフィックスキャッシングを提供開始した。開発者側の設定は一切不要で、1,024トークン以上の共通プレフィックスが自動的にキャッシュされる。キャッシュヒット時は入力トークン料金が50%割引となる。
キャッシュ状態は API レスポンスの usage フィールド内 prompt_tokens_details.cached_tokens で確認できる。
プレフィックス共有の設計パターン
システムプロンプト固定パターン
最も基本的かつ効果の高いパターン。全リクエストで共通のシステムプロンプトを先頭に配置し、プレフィックスキャッシュのヒット率を最大化する。
Few-shot例示固定パターン
Few-shot プロンプティングにおいて、例示部分を固定プレフィックスとして配置する。例示の順序が一定であることが重要で、順序が変わるとプレフィックスが不一致となりキャッシュミスが発生する。
マルチターン会話パターン
会話履歴が蓄積されるチャットシステムでは、前回のリクエスト内容がそのまま次回のプレフィックスとなる。ターンが進むほどキャッシュ対象のプレフィックスが長くなり、計算の節約量も増大する。
プレフィックス共有の制約
- 先頭一致限定: プロンプトの途中や末尾が一致してもキャッシュは効かない
- トークン単位の厳密一致: 1トークンでも異なるとプレフィックスマッチが途切れる
- バージョン管理: システムプロンプトを更新するとキャッシュが全て無効化される
- マルチテナント分離: セキュリティ上、異なるユーザー間でのキャッシュ共有は原則禁止
よくある質問(FAQ)
Q1: プレフィックスの順序を変えるとキャッシュが効かなくなるのはなぜですか?
A1: プレフィックスキャッシングはトークン列の先頭からの厳密一致で判定されるためです。システムプロンプトとツール定義の順序を入れ替えると、先頭のトークンから異なるため、全く別のプレフィックスとして扱われます。キャッシュ効率を最大化するには、プロンプトの構成要素の順序を固定し、可変部分は必ず末尾に配置してください。
Q2: vLLM の Prefix Caching はどのように有効化しますか?
A2: vLLM 0.4.0以降では --enable-prefix-caching フラグを指定して起動します。内部的に Radix Tree ベースのKVキャッシュ管理が有効化され、同一プレフィックスを持つリクエスト間で自動的にKVキャッシュが共有されます。SGLang ではデフォルトで有効です。
Q3: プレフィックス共有はバッチ処理にも適用できますか?
A3: はい、バッチ処理はプレフィックス共有と特に相性が良いです。同一テンプレートで異なるデータを処理するバッチジョブでは、テンプレート部分がプレフィックスとしてキャッシュされ、2件目以降のリクエストでは変数部分の計算のみで済みます。大量の顧客メールに同一トーンで返信する、複数の契約書を同一基準でレビューする、といったユースケースで効果的です。