第13章 KVキャッシュ/プロンプトキャッシュ — 同じ前文を安く・速く
📖 この章のゴール:「プロンプトキャッシュ(KVキャッシュ)」で、同じ前置きの再送を安く・速くする考え方と、効かせる書き方が分かる。
📱 ChatGPTではこう見える
長い会話を続けていると、毎回これまでのやりとりを全部おさらいしているはずなのに、返事はサッと返ってきます。しかも「会話が長くなったら料金が一気にふくらんだ」という感じも、思ったほどありません。
実はこの裏で「同じ前置きの計算結果を、こっそり使い回す」しくみがはたらいています。それがこの章のテーマです。
🤔 なぜ「同じ前文の再送」が起きるの?(🟢 基礎)
第4章でやったとおり、LLM(大規模言語モデル=かしこい文章予測エンジン)には記憶がありません。だから毎回「全部送る」必要があります。
つまり毎回、同じ前置きを何度も送っているのです。
system(最初に決めた「あなたは親切なアシスタントです」などの設定)- これまでの会話(だんだん積み上がっていく長い文脈)
ここで登場するのがプロンプトキャッシュ(prompt cache=「前置きの計算結果を一時保存しておくしくみ」)です。LLMは送られてきた文章の前半を計算します。前半がまったく同じなら、その計算結果を取っておいて、2回目以降は使い回せます。だから2回目以降は安く・速くなります。
🔧 この内部で動いている技術が「KVキャッシュ」(Key-Value cache)と呼ばれるものです。名前は気にしなくて大丈夫。「前半の計算結果のメモ書き」くらいに思ってください。詳しくは付録C。
たとえ話:分厚い本を読むとき、毎回1ページ目から読み直すのは大変ですよね。しおりをはさんでおいて、続きから再開するイメージです。前半が変わらなければ、しおりの位置から始められます。
提供元による違いも知っておきましょう。
- OpenAIのGPT:長い共通の前置き(プレフィックス)があれば、自動的にキャッシュが効きます。こちらが何か書く必要はありません。
- Anthropic(Claude):「ここまでをキャッシュして」と明示的に指定します(やり方は付録C)。
🛠 こう作る(🟢 基礎)
ポイントはたった1つ。変わらない前半を安定させ、変わる部分を後ろに置くことです。
まずは「効きにくい」悪い例から見てみましょう。
const messages = [
{ role: "system", content: `現在時刻: ${new Date().toISOString()}\nあなたは親切なアシスタントです。` },
{ role: "user", content: userInput },
];
1行ずつ読むと:
const messages = [… LLMに送るメッセージの配列を作り始めます。{ role: "system", content: ... }… 一番先頭に設定文(system)を置いています。現在時刻: ${new Date().toISOString()}… ここが問題。毎回ちがう時刻が先頭に入ってしまいます。あなたは親切なアシスタントです。… 本来は固定したい文なのに、上の時刻のせいで前半全体が毎回変わります。{ role: "user", content: userInput }… ユーザーの入力。これは毎回変わって当然です。];… 配列を閉じます。
前半に毎回ちがう値(時刻)が入ると、「前半が同じ」という条件がくずれ、キャッシュが効きません。
次に「効きやすい」良い例です。
const messages = [
{ role: "system", content: "あなたは親切なアシスタントです。" },
...history,
{ role: "user", content: `現在時刻: ${now}\n${userInput}` },
];
1行ずつ読むと:
{ role: "system", content: "あなたは親切なアシスタントです。" }… 先頭をずっと同じ文に固定しました。...history… これまでの会話。前のほうほど内容が固まっているので、ここも安定した前半になります。{ role: "user", content: ... }… 毎回変わる部分はこの一番後ろにまとめます。現在時刻: ${now}\n${userInput}… 時刻のような「毎回変わる値」は、先頭ではなく後ろ側に置くのがコツです。
こうすると前半(system+これまでの会話)が安定し、キャッシュが効きやすくなります。具体的な料金やどれくらい安くなるかは付録Dを見てください。
⚠️ ハマりどころ
- 前半を毎回ちょっとでも変えると効かない:タイムスタンプ・乱数・ユーザー名などを先頭に入れない。1文字でもちがえば「別の前置き」とみなされます。
- キャッシュは入力(こちらが送る文)の話:LLMの出力(返事)は別に課金されます。キャッシュは入力側を安くするしくみで、出力代までは安くなりません。
- 万能ではない:短い文や、毎回まったく違う内容には効果が薄いです。「長くて同じ前置きを繰り返す」ときに一番効きます。
🤖 AIに頼むなら(Vibe codingのコツ)
🗣 プロンプト例:「TypeScript + OpenAI SDKのチャットで、systemと固定の長い文脈を先頭に固定して、毎回変わる部分(時刻やユーザー入力)を後ろに置く形に直して。プロンプトキャッシュが効きやすい並びにしてください。」
チェックリスト:
systemが毎回まったく同じ文になっている- タイムスタンプ・乱数・IDなど「毎回変わる値」を先頭に置いていない
- 変わる部分は配列の後ろ(最新のuserメッセージ側)にまとめている
- 出力は別課金だと理解している(入力だけが安くなる)
📝 ことばメモ
- プロンプトキャッシュ(prompt cache):同じ前置きの計算結果を一時保存して、2回目以降を安く・速くするしくみ。
- KVキャッシュ(Key-Value cache):プロンプトキャッシュを内部で支えている技術。名前だけ覚えればOK。
- プレフィックス(prefix):送る文章の「前半・先頭部分」のこと。ここが同じだとキャッシュが効く。
➡️ 次の章へ
次は第14章「本番で待ち受けるもの=スケールとコストの物語」。たくさんの人が同時に使い始めたとき、何が起きてどう向き合うかを物語として見ていきます。