Claude のプロンプトキャッシュの勘所と実プロジェクトでのコスト削減効果

記事タイトルとURLをコピーする

サーバーワークスの村上です。

当社ではお客様の Claude を使った業務効率化の支援を行っています。このブログでは支援の中で活用することが多いプロンプトキャッシュについて、実プロジェクトでの例を交えながらご紹介します。

プロンプトキャッシュとは

プロンプトキャッシュは生成AIモデルからの応答速度向上とコストを削減するために活用できる機能です。

これはモデルに入力したテキストの計算処理結果をキャッシュしておき、次回以降のリクエストで再利用することで計算コストを削減し実現します。

プロンプトキャッシュのイメージ

料金

執筆時点での Claude Sonnet 4.6 の料金を記載します。詳細は料金ページをご確認ください。

トークン種別 料金($/100 万トークン)
通常・キャッシュなし $3.00
Cache write(有効期限 5 分) $3.75(通常の 1.25 倍)
Cache write(有効期限 1 時間) $6.00(通常の 2.0 倍)
Cache read $0.30(通常の 1/10 のコスト)
出力 $15.00
  • キャッシュの有効期限は 5 分または 1 時間の2種類あります。
  • 当然、有効期限が長い方がキャッシュヒットの機会も多いですが、キャッシュに書き込む(Cache write)料金が割高になっています。
  • よってキャッシュに書き込んだものの、キャッシュヒットしない場合は単純に損をすることになります。ワークロードによっては敢えてキャッシュを使わないこともあります。

損益分岐点

どれだけキャッシュヒットすれば得になるのか、損益分岐の計算をします。

結論、有効期限5分の場合は1回、有効期限1時間の場合は2回キャッシュヒットすれば元が取れる計算になります。

以降は計算式ですので、適宜、読み飛ばしてください。

  • P_c(百万トークン):キャッシュ可能な静的部分(システムプロンプト・ツール定義など)
  • P_d(百万トークン):動的部分(ユーザーメッセージ・通話テキストなど)― 毎回通常単価として課金
  • N:リクエスト総数(1 write + N-1 reads を仮定)

キャッシュなしの場合

通常の入力トークン単価の 3 USDが計算根拠になります。

C_standard = N × 3.00 × (P_c + P_d)

キャッシュあり(有効期限 5 分)の場合

C_5min = 3.75 × P_c              # 1回目:キャッシュ書き込み
       + (N-1) × 0.30 × P_c      # 2回目以降:キャッシュ読み込みのため通常の1/10の単価
       + N × 3.00 × P_d          # 全件:キャッシュが効かない部分は毎回通常課金

損益分岐(C_5min = C_standard)を解くと、

3.75 P_c + (N-1) × 0.30 P_c + N × 3.00 P_d = N × 3.00 × (P_c + P_d)

P_d を含む項は両辺で完全に相殺されるため

3.75 P_c + (N-1) × 0.30 P_c = N × 3.00 P_c
3.75 + 0.30N - 0.30 = 3.00N
3.45 = 2.70N
N ≈ 1.28

よって、 2 回目のリクエスト(1 write + 1 read)から黒字となります

キャッシュあり(有効期限 1 時間)の場合

C_1h = 6.00 × P_c                # 1回目:キャッシュ書き込み(有効期限 1時間 の場合は通常の2倍の単価)
     + (N-1) × 0.30 × P_c        # 2回目以降:キャッシュ読み込み
     + N × 3.00 × P_d            # 全件:キャッシュが効かない部分は毎回通常課金

損益分岐(C_1h = C_standard)を解くと、

6.00 P_c + (N-1) × 0.30 P_c + N × 3.00 P_d = N × 3.00 × (P_c + P_d)
6.00 + 0.30N - 0.30 = 3.00N
5.70 = 2.70N
N ≈ 2.11

よって、 3 回目のリクエスト(1 write + 2 reads)から黒字となります

コスト削減率はキャッシュ可能な割合に応じて変動する

Anthropic のブログ Prompt caching with Claude では「最大 90% のコスト削減」と紹介されています。これは cache read の単価が通常の入力トークン単価の 10% であることに由来していると考えます。

ここでは「キャッシュ可能比率が高いシナリオ」と「中程度のシナリオ」の 2 例を比較してみます。

シナリオ A:キャッシュ可能比率が高い場合

ドキュメントや複雑な指示、Few shotなどを含むコンテキストを毎回入力する場合はキャッシュを効かせやすいシーンです。後述するサーバーワークスのお客様事例もこのケースです。

  • 前提
    • システムプロンプト + Few shot + ドキュメント(キャッシュ可能):10,000 トークン
    • ユーザークエリ(動的):200 トークン
    • キャッシュ可能比率 ≈ 98%(入力 10,200 トークンのうち 10,000 トークン)
    • ※計算をシンプルにするため、出力トークンは考慮しません。
N キャッシュなし キャッシュあり(5 分) 節約率 キャッシュあり( 1 時間) 節約率
1 $0.0306 $0.0381 ▲24.5%(コスト高) $0.0606 ▲98.0%(コスト高)
2 $0.0612 $0.0417 31.9% $0.0642 ▲4.9%(コスト高)
3 $0.0918 $0.0453 50.7% $0.0678 26.1%
10 $0.3060 $0.0705 77.0% $0.0930 69.6%
100 $3.0600 $0.3945 87.1% $0.4170 86.4%

結論、Anthropic のブログに記載されている90%に近いコスト削減が可能になります。

※計算例

N = 1(初回 write のみ)
  キャッシュなし: 3.00 × 0.0102          = $0.0306
  キャッシュ( 5 分): 3.75 × 0.010 + 3.00 × 0.0002 = $0.0381 
  キャッシュ( 1 時間): 6.00 × 0.010 + 3.00 × 0.0002 = $0.0606 

N = 2(1 write + 1 read)
  キャッシュ: 2 × $0.0306            = $0.0612
  キャッシュ( 5 分): $0.0381 + 0.30 × 0.010 + 3.00 × 0.0002 = $0.0417 
  キャッシュ( 1 時間): $0.0606 + 0.30 × 0.010 + 3.00 × 0.0002 = $0.0642

シナリオ B:キャッシュ可能比率が中程度の場合

このシナリオでは入力が動的に変わる部分が中程度ある場合を想定します。

  • 前提
    • システムプロンプト(キャッシュ可能):2,000 トークン
    • ユーザーメッセージ(動的):1,000 トークン
    • キャッシュ可能比率 ≈ 67%(入力 3,000 トークンのうち 2,000 トークン)
    • ※計算をシンプルにするため、出力トークンは考慮しません。
N キャッシュなし キャッシュあり( 5 分) 節約率 キャッシュあり( 1 時間) 節約率
1 $0.0090 $0.0105 ▲16.7%(コスト高) $0.0150 ▲ 66.7%(コスト高)
2 $0.0180 $0.0141 21.7% $0.0186 ▲3.3%(コスト高)
3 $0.0270 $0.0177 34.4% $0.0222 17.8%
5 $0.0450 $0.0249 44.7% $0.0294 34.7%
10 $0.0900 $0.0429 52.3% $0.0474 47.3%
100 $0.9000 $0.3669 59.2% $0.3714 58.7%

シナリオBではコスト削減率が約60%とシナリオAと比較して下がるという結果になりました。

注意点として、キャッシュが効かない部分が大きいことはコスト削減率を下げる要因になりますが、キャッシュを使わない理由にはなりません。先述した元を取るための損益分岐点は変わらないためです。

実際のプロジェクトでどれだけコスト削減できたか

サーバーワークスが支援させていただいたプロジェクトではキャッシュを使用しなかった場合と比較して約80%コストを削減できました。

要因は次の3点です。

  • 推論にリアルタイム性が不要だった(翌日に推論結果があれば良かった)ため、バッチ処理的にリクエストでき、5分以内にキャッシュヒットさせることができた
  • 毎回のリクエストで入力するコンテキストの大部分が共通でキャッシュ可能だった
  • リクエスト数が多かった(先述のとおり、リクエスト数Nが増えるほどコスト削減率は大きくなる)

キャッシュをより深く知る

キャッシュチェックポイントとはなんですか

キャッシュチェックポイントとは、入力トークンのうちどこまでをキャッシュに書き込むか指定するマーカーです。

キャッシュチェックポイントよりも前の部分がキャッシュに書き込まれる仕様です。

キャッシュチェックポイントのイメージ

よって、キャッシュチェックポイントよりも後のトークン計算結果はキャッシュ書き込みされず、以降の推論リクエストでキャッシュヒットすることはありません。

docs.aws.amazon.com

キャッシュヒットはツール定義→システム→メッセージの順番で評価される

Anthropicのドキュメントに下記の記載があります。

the cache follows the hierarchy: tools → system → messages. Changes at each level invalidate that level and all subsequent levels.
キャッシュは「ツール → システム → メッセージ」という階層構造に従います。各レベルでの変更は、そのレベルおよびそれ以降のすべてのレベルを無効にします。
Prompt caching - Claude API Docs

つまり、次のようにツール定義部分が同じであり、直後にキャッシュチェックポイントを入れていた場合、ツール定義部分はキャッシュヒットします。システムプロンプトは変更されているので、キャッシュミスになります。

ツール定義部分は同一のためキャッシュヒットする

一方で、次のようにシステムプロンプトは同じだが、ツール定義が異なっている場合、最初に評価されるツール定義がキャッシュミスであるため、以降のシステムプロンプトが同じでもキャッシュヒットすることはありません。

ツール定義が異なっているため、以降のシステムプロンプトが同一でもキャッシュミスになる

Amazon Bedrockの場合、キャッシュはAWSアカウント・リージョン間で共有されるのか?

キャッシュはAWSアカウント固有のものです(AWSアカウント間で共有されません)

公式ドキュメントに次の記載があります。

Your cache is specific to your account and comprises the internal model state representing your prompts.
キャッシュはアカウントごとに固有のものであり、プロンプトを表す内部モデル状態から構成されています。
Cache Prompts Between Requests - Amazon Bedrock Prompt Caching - AWS

キャッシュはリージョン間では共有されません

こちらについても公式ドキュメントに次の記載があります。「キャッシュへの書き込みが増加する場合がある」ということは裏を返すと、リージョン間でキャッシュヒットしないことと解釈できます。

プロンプトキャッシュは、リージョン間推論と組み合わせて使用​​できます。リージョン間推論は、推論リクエストを処理するために、お客様の地域内で最適なAWSリージョンを自動的に選択し、利用可能なリソースとモデルの可用性を最大化します。需要が高い時間帯には、これらの最適化によりキャッシュへの書き込みが増加する場合があります。

簡素化されたキャッシュ(Simplified Cache Management for Claude Models)

Claudeではキャッシュ管理の煩雑さを解消するための手法もあります。

AnthropicのドキュメントではAutomatic caching、Amazon Bedrock上でのClaudeでは簡素化されたキャッシュ管理(Simplified Cache Management for Claude Models)と呼ばれています。

例えばマルチターンの会話をする場合、生成AIモデルはステートレスのため以前の会話履歴も含めてリクエストを送ることになります。この場合、リクエストごとに含める会話履歴は不変のためキャッシュを効かせたいわけです。

このとき、静的なコンテンツの直後にキャッシュチェックポイントを1つ追加しておけば、キャッシュヒットをチェックしてくれます。

次の図では、末尾にキャッシュチェックポイントを入れておけば2回目のリクエストでは、1回目のリクエストでキャッシュ書き込みしたツール定義・システムプロンプト・ユーザーメッセージをキャッシュ読み込みしてくれます。

キャッシュが効かない!考慮すべき落とし穴

次のような場合はキャッシュが効かないため注意が必要です。

動的な値を含めている

キャッシュヒットするためには入力された値とキャッシュされた値が同一である必要があります。

以下のように動的な値を含めている場合はキャッシュヒットしません。

system_prompt = f"""
今日は {today} です。
あなたはコールセンターの...
"""

少なすぎるトークンをキャッシュしようとしている

モデルに応じてキャッシュできる最小のトークン数が定義されています。例えば Claude Sonnet 4.5 では 4,096です。

この値より少ないトークン数でキャッシュしようとしても、推論リクエスト自体は成功しますが、内部的にはキャッシュされず、以降のリクエストがキャッシュヒットすることはありません。

docs.aws.amazon.com

20ブロック以上遡ってキャッシュできない

ルックバックという仕様があります。

末尾のキャッシュチェックポイントから20ブロック遡った(Look backした)ブロックにキャッシュチェックポイントが存在していればキャッシュヒットするという仕様です。

簡易キャッシュ管理を有効にすると、システムは指定したブレークポイントから約20コンテンツブロックまで遡り、前のコンテンツブロック境界でキャッシュヒットを自動的にチェックします。
Prompt caching for faster model inference - Amazon Bedrock]

よって、明示的にキャッシュチェックポイントを作成しない限り、20ブロック以上遡ってキャッシュ読み込みされませんので注意が必要です。

20ブロック遡ってキャッシュ読み込みを探す仕様です

実際に手元でキャッシュ書き込みしていないブロックを以下のように21個追加してリクエストしたところ、キャッシュ読み込みは行われず、キャッシュ書き込みが行われました。

dummy_blocks = [
    {"text": f"【20ブロック上限テスト用ダミー {i+1:02d}/21】"
             "このテキストは過去キャッシュエントリを20ブロック圏外へ押し出すために挿入しています。"}
    for i in range(21)
]
miss_content = dummy_blocks + [{"cachePoint": {"type": "default"}}]

まとめ

  • キャッシュの損益分岐
    • 有効期限5分の場合は1回、有効期限1時間の場合は2回キャッシュヒットすれば元が取れる
  • キャッシュのコスト削減率
    • キャッシュヒットの割合が大きいほど、リクエスト数が多いほどコスト削減効果が大きい
  • キャッシュチェックポイントの仕様
    • キャッシュチェックポイントより前のトークンがキャッシュされる
    • キャッシュヒットするためには、入力トークンとキャッシュされたトークンが完全一致する必要がある

村上博哉 (執筆記事の一覧)

2020年4月入社。機械学習が好きです。