今回の論文
今回取り上げるのは、In Gim、Guojun Chen、Seung-seob Lee らによる 2024 年の論文「Prompt Cache: Modular Attention Reuse for Low-Latency Inference」です。公開元は The 7th Annual Conference on Machine Learning and Systems(MLSys 2024)で、研究分野は LLM サービング、推論最適化、キャッシュ設計です。URL は https://proceedings.mlsys.org/paper_files/paper/2024/file/a66caa1703fe34705a4368c3014c1966-Paper-Conference.pdf です。なお、arXiv では 2023 年 11 月に初版が公開されています。
この論文を選んだ理由は、モデル自体を学習し直さずに、推論サーバー側の設計だけで大きな速度改善を狙えるからです。特に、RAG、社内検索、エージェント、コード生成のように「毎回かなり似た長いプロンプトを投げる」アプリでは、そのまま開発のヒントになります。
どんな技術か
Prompt Cache は、LLM に渡すプロンプトのうち、何度も出てくる共通部分をあらかじめ計算しておき、その attention state を次のリクエストで再利用する技術です。たとえば、毎回同じシステムプロンプト、同じ指示テンプレート、同じ参照文書を含むなら、その部分を最初から毎回計算し直すのは無駄です。
通常の KV キャッシュは、1 回の生成の途中で過去トークンを再利用する仕組みですが、Prompt Cache はこの再利用を「リクエストの外側」まで広げます。しかも単純な prefix キャッシュではなく、プロンプトをモジュールとして分解し、同じ位置関係を保てるようにして再利用する点が特徴です。
要するに Prompt Cache は、「長いプロンプトを毎回読むのが遅いなら、共通部分は一度だけ読ませて使い回そう」という発想を、Transformer の位置情報まで考慮して実装可能にした技術です。
課題
この技術が解決しようとしているのは、LLM の推論では最初の 1 トークンを返すまでの時間、いわゆる TTFT(time-to-first-token)が長くなりやすいという問題です。特に長いコンテキストを含むアプリでは、ユーザーが質問を 1 行しか変えていなくても、モデルはその前にある大量のプロンプトを毎回最初から読み直します。
難しいのは、共通テキストがあるからといって、そのまま別リクエストへ KV キャッシュを流用できないことです。Transformer の attention state は、テキスト内容だけでなく、トークンが入力列のどこに置かれていたかという位置情報にも依存します。同じ文章でも、プロンプト中の位置がずれると、そのまま再利用すると整合しません。
既存の方法では、単純な prefix caching のように「先頭が完全一致する場合だけ使う」手法が中心でした。しかし実際のアプリでは、共通部分が必ずしも一つの固定 prefix とは限りません。システムメッセージ、テンプレート、参照資料、ユーザー属性、関数定義、コードファイルなど、複数の部品が組み合わさって 1 つのプロンプトになります。
なぜこの課題を解く必要があるかというと、長いプロンプトが価値になるアプリほど TTFT が悪化しやすいからです。RAG では複数文書を突っ込みますし、エージェントではツール定義や履歴が増えます。コード生成では複数ファイルを文脈に入れたくなります。これらはユーザー価値を上げる一方で、「文脈を増やすほど待ち時間が伸びる」という構造的な問題を抱えます。
用語解説
- KV キャッシュ
- Transformer の自己注意で計算した key と value を保持し、次のトークン生成で再利用する仕組みです。Prompt Cache はこの考え方を 1 リクエスト内だけでなく、複数リクエスト間へ拡張したものとして理解すると読みやすくなります。
- TTFT(Time-to-First-Token)
- ユーザーがリクエストしてから最初の 1 トークンが返るまでの時間です。チャットや検索系の体感速度を強く左右する指標で、Prompt Cache は特にこの TTFT を下げることを狙っています。
- Prefix Caching
- リクエストの先頭部分が完全一致するときだけ、その prefix の計算結果を再利用する方法です。実装は比較的単純ですが、共通部分が途中に散らばる複雑なプロンプトには弱いため、Prompt Cache はそこを一般化しています。
- Attention State
- ここでは各層で保持される key と value の状態を指します。単なる文字列キャッシュではなく、この状態そのものを保存して再利用するので、モデルの重みを変えずに前計算の恩恵を受けられます。
- Prompt Module
- Prompt Cache が定義する再利用単位です。システムプロンプト、文書、テンプレート、属性セットなどをモジュールとして切り出し、それぞれの位置関係を保ったまま組み合わせることで、再利用と柔軟性を両立します。
技術の仕組み
Prompt Cache の肝は、「共通テキストをただ保存する」のではなく、「どの位置で使われる attention state なのか」まで含めて管理するところです。そのために論文では prompt module、schema、PML という仕組みを導入しています。
基本アイデア
基本アイデアは、プロンプトをいくつかの再利用可能な部品に分け、部品ごとの attention state を保存することです。次のリクエストでは、その部品を再計算せずに呼び出し、未キャッシュ部分だけを新しく計算します。
たとえば RAG なら、よく使うシステム指示、FAQ 文書、社内規定、出力フォーマットをそれぞれ module にしておき、今回の質問文だけを未キャッシュ部分として追加するイメージです。こうすると、長い文脈を全部処理し直さずに済みます。
なぜ位置合わせが必要なのか
Transformer では、各トークンの attention state は位置埋め込みの影響を受けます。そのため、同じ文書でも「プロンプトの先頭にある場合」と「後ろに置かれた場合」では、そのまま同じ state を使い回せません。
Prompt Cache はここを schema で解決します。schema は、各 prompt module が全体プロンプトのどこに置かれるかを定義する設計図です。module の開始位置を固定し、その位置に基づいて position ID を割り当てたうえで attention state をエンコードしておけば、次のリクエストでも同じ位置関係のまま安全に再利用できます。
Prompt Module と Schema
論文では、再利用可能なテキスト断片を prompt module と呼びます。schema はそれらの module の並びや階層関係を定義するものです。ユーザーは schema から必要な module を import するようにプロンプトを組み立てます。
この構成の利点は、単なる 1 本の prefix ではなく、複数の部品を組み合わせられることです。たとえば「共通のシステムプロンプト + 商品カテゴリ別テンプレート + 地域ごとの説明文 + 今回の質問」といった構成も扱えます。つまり、プロンプトをアプリケーションの UI コンポーネントのように分解し、それぞれをキャッシュ可能にしているわけです。
PML で再利用可能な構造を記述する
論文では PML(Prompt Markup Language)という記法を使って、schema と prompt を記述します。<module> で再利用単位を定義し、<prompt> 側では必要な module を参照しつつ、キャッシュしない追加指示を書きます。
この方式の重要な点は、未キャッシュのユーザー入力だけを後から足せることです。共通部分を毎回丸ごと prefix として固定する必要がないので、実アプリのプロンプト設計にかなり近い形で扱えます。
パラメータ化で再利用率を上げる
Prompt Cache は静的な文字列だけをキャッシュするわけではありません。module 内にパラメータを置けるので、テンプレートの可変部分を限定しながら再利用を最大化できます。
たとえば「3日間の旅行プランを作る」の 3日間 の部分だけが可変なら、テンプレート全体を毎回別物として扱うのではなく、そのパラメータだけ差し替えます。これにより、似たプロンプトを大量に扱う業務アプリでキャッシュ効率を上げやすくなります。
エンコードと保存の流れ
Prompt Cache で module を初めて使うときは、その module の token 列を取り出し、schema 内の絶対位置に基づく position ID を付与して LLM へ通し、各層の key/value を計算して保存します。以後は同じ module を再利用するとき、その attention state を読み出して接続します。
保存先は CPU メモリにも GPU メモリにも置けます。GPU メモリに置けば再利用時の読み出しは速いですが容量が限られます。CPU メモリに置くとホストから GPU へのコピーは必要になるものの、非常に大きなモジュール群を保持しやすくなります。論文はこの二層構成を採り、CPU 側の大容量メモリも活用しています。
推論時の流れ
推論時は、プロンプト全体を 0 から prefill する代わりに、使える module の attention state を読み込み、未キャッシュ部分だけを計算します。つまり「プロンプトの共通部分はメモリコピー、差分部分だけは実計算」という形です。
このとき重要なのが、self-attention の計算コストは系列長に対して重くなりやすい一方、キャッシュ済み state の読み出しは主にメモリ転送コストだという点です。論文は、長い prompt ほど通常の prefill 計算との差が広がるので、Prompt Cache の利得も大きくなると説明しています。
既存の推論最適化との関係
Prompt Cache は、FlashAttention や PagedAttention のような既存の最適化と競合するというより、かなり直交する技術です。モデルを変えずにサービング層へ足せるため、既存の efficient attention カーネルやバッチ実行と組み合わせやすいのが実務上の魅力です。
特に論文では、同じ prompt module を複数リクエストで共有できるため、PagedAttention のような block 単位の共有とも相性がよく、バッチ推論時のメモリ重複削減にもつながると述べています。
実験と結果
論文の評価は、単に「速い」という話ではなく、GPU と CPU の両方で TTFT を測り、さらに出力品質が壊れないかも LongBench で確かめています。ここが実務的に重要です。速度だけ上がって回答品質が崩れるなら、本番導入しづらいからです。
何を検証したのか
主に検証しているのは次の 3 点です。
- Prompt Cache で TTFT がどれだけ短くなるか
- CPU メモリ格納と GPU メモリ格納でどれくらい差が出るか
- attention state の再利用で回答品質が落ちないか
加えて、コード生成、パーソナライズド教育、パラメータ付きテンプレートといった具体的なユースケースでも、再利用の柔軟性を確認しています。
どんなデータセットや評価指標を使ったのか
レイテンシ評価では、Llama 7B を使い、LongBench の 8 つのデータセットで TTFT を測定しています。GPU は NVIDIA RTX 4090、A40、A100 を使用し、CPU は Intel i9-13900K と AMD Ryzen 9 7950X を使っています。
品質評価では、Llama2 7B、Llama2 13B、MPT 7B、Falcon 7B の 4 系統で LongBench を評価しています。指標はタスクに応じて F1、Rouge-L、Accuracy を使っています。つまり、1 モデルの特殊ケースではなく、複数アーキテクチャで再利用可能性を見ている点が強みです。
TTFT はどれだけ改善したのか
論文の要点はここです。Prompt Cache は、GPU 推論で最大 8 倍、CPU 推論で最大 60 倍の TTFT 改善を報告しています。特に、長い文書を含む LongBench 系タスクや、共通文脈が大きいユースケースで効果が大きく、CPU 側での改善幅が目立ちます。
この差が大きい理由は、長い prompt の prefill は attention 計算が重く、CPU ではその負担がより強く出やすいからです。Prompt Cache にすると、その部分が主にメモリコピーへ置き換わるため、計算資源が限られる環境ほど恩恵が目立ちます。
品質は落ちなかったのか
LongBench の評価では、Prompt Cache ありとなしで、ほとんどの条件で精度は同等でした。論文でも「across all datasets, the accuracy of output with Prompt Cache is comparable to the baseline」という結論を示しています。
個別の数値を見ると、たとえば GovReport の Rouge-L は Llama2 7B で 24.67 から 25.37、Llama2 13B で 28.13 から 28.18 とほぼ同等です。QMSum や MultiNews も近い値で、再計算を省いても品質が大きく崩れていないことがわかります。一方で TriviaQA や Passage Retrieval など一部には上下があるので、タスク次第で個別検証は必要です。
なぜ長いプロンプトほど効くのか
論文は、通常の prefill 計算は系列長に対して二次的に重くなりやすい一方、Prompt Cache のオーバーヘッドは主に線形なメモリコピーだと説明しています。つまり、prompt が長くなるほど「計算し直すコスト」と「読み出すコスト」の差が拡大します。
この点は実装者にとって重要です。短いチャットの往復では利得が小さくても、長文 RAG、巨大 system prompt、複数ファイルを読むコード補助、属性の多いエージェントでは一気に効く可能性があります。
ユースケース実験が示すこと
論文の図では、コード生成の例で複数ソースファイルをそれぞれ module 化し、必要ファイルだけ import する構成を示しています。ここでも TTFT は大きく短縮されており、単なるベンチマーク上の最適化ではなく、実際のアプリ構成でも効果が出ることを示しています。
また、パーソナライズ用途では、学年、習熟度、学習履歴、学習スタイルなどを module 化しています。これは業務システムでいう「顧客属性」「部署別ルール」「商品カテゴリ別説明」を分割する設計にかなり近く、テンプレート化された実務アプリへの応用をイメージしやすい結果です。
何に使える?
Prompt Cache は、単にベンチマークを速くする技術ではありません。共通文脈が多い LLM アプリなら、かなり広く使えます。
RAG と社内検索
RAG では、固定のシステム指示、検索結果の整形テンプレート、よく参照される基礎文書が繰り返し入ります。これらを module 化すれば、毎回の問い合わせで大半を読み直す必要がなくなります。特にヘルプセンターや社内規程検索のように、似た質問が何度も来る用途で効きやすいです。
AI エージェント
エージェントは、ツール仕様、ロール定義、行動ルール、履歴要約など、長くて再利用可能な文脈を抱えがちです。これらをモジュールとして切り分ければ、毎ターン全てを prefill し直す負担を減らせます。ツール定義が多い業務エージェントほど効果が出やすいでしょう。
コード生成・開発支援
論文でも、各ソースファイルを module として扱うコード生成例を出しています。実務でも、共通ライブラリ、API 定義、DB スキーマ、型定義、設計ガイドラインをキャッシュしておき、今回編集したいファイルや指示だけ追加する設計が考えられます。大きなリポジトリをまたぐ開発支援では特に有効です。
パーソナライズドな業務アプリ
営業支援、学習支援、FAQ、自動応答などでは、ユーザー属性やプラン別ルールがある程度固定されています。属性ごとに module を切り分けておけば、毎回全文を差し込むより効率的です。属性の組み合わせが多い場合でも、schema ベースなら部品を差し替えて再利用できます。
CPU や小規模 GPU での運用
論文の結果からは、Prompt Cache は CPU 環境や GPU リソースが限られた環境で特に価値があります。高価な GPU を増やす前に、既存ハードウェアで TTFT を下げたいケースでは、かなり優先度の高い設計候補になります。
開発や事業へのヒント
Prompt Cache から得られる学びは、「プロンプトはただの文字列ではなく、再利用可能なアプリ資産として設計できる」という点です。これは単なる高速化テクニック以上に、AI プロダクトの作り方に影響します。
プロンプトを部品として管理する
多くの AI アプリでは、巨大なプロンプトを 1 本のテンプレート文字列として管理しがちです。しかし Prompt Cache 的に考えると、システム指示、業務ルール、文書群、ユーザー属性、出力フォーマットを明確に分割したほうが、保守もしやすく再利用もしやすいです。これは prompt engineering を構成管理の問題として扱う発想でもあります。
速度改善をモデル変更だけに頼らない
体感速度を上げたいとき、すぐに小型モデルへ落とす、量子化する、GPU を増やす、という議論になりがちです。Prompt Cache は、モデル品質を落とさずに、推論サーバー側の工夫だけで改善できる余地を示しています。特に既存モデルを変えたくない本番システムでは実用的です。
キャッシュヒットしやすい業務を狙う
事業視点では、「どの業務が prompt module を共通化しやすいか」を見ると、収益化しやすい用途のヒントになります。社内規程検索、契約レビュー補助、医療文書補助、カスタマーサポート、教育支援など、共通文書とテンプレートが強い領域は Prompt Cache と相性がよいです。
小規模プロダクトでも応用できる
大規模な serving 基盤がなくても、発想自体は小規模プロダクトで使えます。たとえば「毎回同じ system prompt を付ける」「毎回同じ資料セットを参照する」「ユーザー属性に応じた固定ルールがある」といった箇所を洗い出すだけでも、将来の最適化しやすさが変わります。最初から prompt の再利用単位を意識して設計しておく価値があります。
今後注目すべき方向性
今後は、Prompt Cache 単体よりも、prefix caching、PagedAttention、長文最適化、RAG の文書管理と一体で設計される流れが重要になりそうです。特に、頻出文書を単にベクトル検索するだけでなく、「検索されやすい文書は attention state まで前計算しておく」という運用は、実務で十分ありえます。
限界
Prompt Cache には明確な注意点もあります。まず、どのテキストでも無条件に再利用できるわけではありません。schema で位置関係を保てること、ある程度共通部分が繰り返し使われることが前提です。毎回まったく異なる短い質問ばかりなら、利得は小さくなります。
また、キャッシュ管理の実装は簡単ではありません。どの module を CPU に置くか GPU に置くか、どれをいつ追い出すか、更新時にどう無効化するか、マルチテナント環境でどう分離するかといった問題が出ます。論文でも、将来の serving system では cache replacement や module management の改善余地があると述べています。
データ依存性にも注意が必要です。LongBench では概ね品質維持が確認されていますが、すべてのタスクで完全一致ではありません。特に、module の切り方や共通文脈の設計が変わると挙動も変わりうるので、実運用のデータで検証すべきです。
さらに、メモリ消費はゼロではありません。attention state を保存する以上、長大な module を大量に保持するなら、それなりのストレージとメモリ管理が必要です。どの module を CPU に置き、どれを GPU に残すか、eviction をどう設計するかは実装上の重要課題です。
最後に、これは API レベルの「レスポンスキャッシュ」とは別物です。Prompt Cache はモデル内部の attention state を再利用するので、推論基盤にかなり近い層で実装する必要があります。SaaS 利用側がすぐ再現できるとは限らない点は認識しておくべきです。
よくある質問
Q. Prompt Cache は普通の prefix caching と何が違うのですか?
A. Prefix caching は、プロンプト先頭が完全一致するときにだけ使えることが多いです。Prompt Cache は、プロンプトを module に分割し、schema で位置関係を固定することで、途中にある共通部分や組み合わせ可能な部品も再利用できるようにしています。
Q. どんなアプリで特に効果が出やすいですか?
A. 長い system prompt、テンプレート、参照文書、属性情報を毎回含むアプリです。具体的には RAG、社内検索、FAQ、エージェント、コード生成、教育支援などが向いています。短い一問一答だけのチャットでは効果は相対的に小さくなります。
Q. 出力品質は本当に落ちないのですか?
A. 論文の LongBench 評価では、全体としてベースラインと同等でした。ただし一部タスクでは上下があるため、実サービスでは自分たちのデータで検証したほうが安全です。品質を壊さない前提で導入するなら、A/B テストやオフライン評価は必須です。
Q. API を使うだけのアプリ開発者でも取り入れられますか?
A. 推論サーバー内部で attention state を扱えるなら取り入れやすいですが、外部 API だけでは同じレベルの制御は難しいです。ただし、プロンプトを module 単位で設計する考え方自体は API 利用でも有効で、将来 provider 側の caching 機能を活かしやすくなります。
Q. RAG の代わりになりますか?
A. いいえ、役割が違います。RAG は必要な文書を探して持ってくる技術で、Prompt Cache は持ってきた文脈のうち共通部分を速く読むための技術です。よく使う文書群がある RAG では、むしろ併用すると相性がよいです。
今日の学び
この論文は、長いプロンプトを使う LLM アプリで TTFT が伸びやすく、同じ共通文脈を毎回計算し直しているという課題を扱いました。そこに対して Prompt Cache は、プロンプトを module に分解し、位置情報を保った attention state をリクエスト間で再利用する仕組みで解こうとしました。
ここから得られるヒントは、AI アプリの性能改善はモデル変更だけではなく、プロンプトの構造設計とサービング設計でも大きく変わるということです。特に、共通文脈が多い RAG やエージェントでは、プロンプトを再利用可能な部品として扱う発想そのものがプロダクト改善につながります。