業務活用事例

Claudeのプロンプトキャッシュ:APIコストを最大90%削減する方法

Claudeのプロンプトキャッシュ:APIコストを最大90%削減する方法

この記事の要点

Claude APIのプロンプトキャッシュ機能の仕組みと設計方法を解説。キャッシュの対象・有効時間・コスト構造・システムプロンプトの設計パターンまで、APIコストを大幅に削減する実践的な方法を紹介します。

結論

Claude APIのプロンプトキャッシュを使うと、同じシステムプロンプトや大きなドキュメントを繰り返し送信する場合のAPIコストを最大90%削減できます。設計は単純で、キャッシュしたいコンテンツの末尾にcache_controlマーカーを追加するだけです。

特にチャットボット・文書処理システム・コードレビューツールのように、多数のリクエストで同じ大きなプロンプトを繰り返し送信するシステムで効果が大きいです。


プロンプトキャッシュの仕組み

通常のAPI呼び出しでは、システムプロンプトとユーザーメッセージを合わせた全てのトークンを毎回処理します。1,000トークンのシステムプロンプトを1日1,000回使うと、100万トークン分の処理コストが発生します。

プロンプトキャッシュを使うと、最初のリクエストでキャッシュが作成され(キャッシュ書き込みコスト)、以降のリクエストではキャッシュから読み込まれます(キャッシュ読み込みコスト)。キャッシュ読み込みは処理コストの約10分の1です。

処理種別コスト比率
通常のトークン処理1.0(基準)
キャッシュ書き込み1.25(初回のみ割高)
キャッシュ読み込み0.1(約90%削減)

初回だけキャッシュ書き込みコストが発生しますが、2回目以降はキャッシュ読み込みになるため、繰り返し使うほどコストが下がります。


キャッシュの対象になるコンテンツ

全てのコンテンツがキャッシュの対象になるわけではありません。会話をまたいで変化しない大きなコンテンツがキャッシュ効果を最大化します。

キャッシュに向いているもの

  • システムプロンプト(特に詳細な指示・コーディング規約・ペルソナ定義)
  • 大きな参照ドキュメント(マニュアル・FAQ・規約集)
  • ツール定義(MCPツールのスキーマ)
  • Few-shot例文(判断基準の例)

キャッシュに向いていないもの

  • ユーザーごとに変わる情報(名前・過去の購入履歴)
  • リアルタイムデータ(現在時刻・在庫状況)
  • セッションごとに変わる会話履歴

キャッシュの設定方法

キャッシュしたいコンテンツのブロックの末尾にcache_controlを追加します。

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": """あなたはECサイトの顧客サポートエージェントです。
            
[ここに詳細なシステムプロンプト - 数千トークン]
- 返金ポリシー: 購入から30日以内
- エスカレーション基準: 5万円以上の案件
...""",
            "cache_control": {"type": "ephemeral"}  # ← これだけ追加
        }
    ],
    messages=[
        {"role": "user", "content": "注文#12345の返金をお願いします"}
    ]
)

cache_controltypeは現在ephemeralのみです。このマーカーが付いたブロックの先頭から末尾までがキャッシュの対象になります。


キャッシュプレフィックスの設計

キャッシュは「プレフィックスの一致」で機能します。リクエストの先頭から「キャッシュマーカーまでの内容が完全に一致」している場合にキャッシュがヒットします。

重要: 変化する内容はキャッシュマーカーより後に置く

# 正しい設計: 変化しない内容を先に、変化する内容を後に

system=[
    {
        "type": "text",
        "text": "不変のシステムプロンプト(数千トークン)",
        "cache_control": {"type": "ephemeral"}  # ここまでキャッシュ
    }
],
messages=[
    # ユーザーごとの情報はここに(キャッシュされない)
    {"role": "user", "content": f"顧客名: {customer_name}\n質問: {question}"}
]
# 誤った設計: ユーザー情報がシステムプロンプトに混入

system=[
    {
        "type": "text",
        "text": f"""顧客: {customer_name}  ← ユーザーごとに変わる
        不変のシステムプロンプト...""",
        "cache_control": {"type": "ephemeral"}
    }
]
# customer_nameが変わるたびにキャッシュミス → 効果ゼロ

マルチターン会話でのキャッシュ設計

チャットボットのようにマルチターンの会話を扱う場合、会話履歴が増えるにつれてコンテキストも増えます。

会話の各ターンでキャッシュを活用する

# 長い会話履歴に対してキャッシュを適用

conversation_history = [
    {"role": "user", "content": "最初の質問"},
    {"role": "assistant", "content": "最初の回答"},
    # ... 多くの会話ターン
    {"role": "user", "content": "長い会話の途中の質問", 
     "content": [{"type": "text", "text": "...", "cache_control": {"type": "ephemeral"}}]},
]

長い会話履歴をキャッシュすることで、会話が長くなるほどコスト効果が上がります。


大きな文書処理でのキャッシュ活用

100ページの技術マニュアルに対してユーザーが質問するQ&Aシステムを例に考えます。

キャッシュなしの場合

リクエストごとのコスト:
システムプロンプト(500トークン) + マニュアル全文(50,000トークン) + 質問(100トークン)
= 50,600トークン × リクエスト数

100件のリクエストで506万トークン処理。

キャッシュありの場合

1件目: キャッシュ書き込み
  - 通常処理: 50,600 × 1.0 + キャッシュ書き込み: 50,000 × 0.25 = 約63,100相当

2〜100件目: キャッシュ読み込み
  - 通常処理: 600 × 1.0 + キャッシュ読み込み: 50,000 × 0.1 = 5,600相当 × 99件

100件合計: 63,100 + 5,600 × 99 ≈ 618,500相当(88%削減)


キャッシュのTTL管理

キャッシュのTTL(有効時間)は5分です。使い方によっては意図せずキャッシュが切れることがあります。

TTLに関する設計の注意点

アクティブなチャットボット: ユーザーが頻繁に質問するシステムでは5分以内に次のリクエストが来るため、キャッシュが持続します。

バッチ処理: 1時間に1回まとめてリクエストを送るシステムでは、各バッチの最初のリクエストは必ずキャッシュミスになります。バッチ処理の場合はキャッシュの恩恵が限定的です。

夜間の低負荷時間帯: トラフィックが少ない時間帯は5分の間隔でリクエストが来ない可能性があり、キャッシュが切れやすくなります。


キャッシュ効果を測定する

APIレスポンスにはキャッシュの状態を示す情報が含まれます。

response = client.messages.create(...)

# キャッシュの統計情報を確認
usage = response.usage
print(f"入力トークン: {usage.input_tokens}")
print(f"キャッシュ書き込みトークン: {usage.cache_creation_input_tokens}")
print(f"キャッシュ読み込みトークン: {usage.cache_read_input_tokens}")

# キャッシュヒット率を計算
cache_hit_rate = usage.cache_read_input_tokens / (
    usage.input_tokens + usage.cache_read_input_tokens
) * 100
print(f"キャッシュヒット率: {cache_hit_rate:.1f}%")

キャッシュヒット率が低い(20%未満)場合は、次を確認します。

  • システムプロンプトにユーザーごとの情報が混入していないか
  • cache_controlマーカーの位置が正しいか
  • リクエストの間隔が5分を超えていないか

ツール定義のキャッシュ

MCPツールのスキーマ定義が多数ある場合も、キャッシュが有効です。

tools = [
    {
        "name": "get_customer",
        "description": "顧客情報を取得する...",
        "input_schema": {...}
    },
    # ... 他のツール定義(多数ある場合は数千トークンになる)
]

response = client.messages.create(
    model="claude-opus-4-8",
    tools=tools,
    # ツール定義にもcache_controlを適用できる
    ...
)

ツール定義は通常変化しないため、キャッシュによるコスト削減効果が大きい領域です。

MCPツールの設計についてはMCPツール設計のベストプラクティスも参考になります。


プロンプトキャッシュが特に効果的なシステム

システム種別効果の大きさ理由
カスタマーサポートボット非常に大きい詳細なシステムプロンプトを全員で共有
技術文書Q&Aシステム非常に大きい大きな文書を全リクエストで共有
コードレビューツール大きいレビュー基準・ルールを全PRで共有
汎用チャットボット中程度システムプロンプトが比較的短い場合
One-shot処理小さい同じコンテンツを繰り返さない

最新のコスト情報は公式ドキュメントで確認してください(モデルや地域によって異なります)。


まとめ

プロンプトキャッシュの実践ポイントをまとめます。

  • キャッシュは「変化しない大きなコンテンツ」に適用する。変化する情報はキャッシュマーカーの後に置く
  • cache_control: {"type": "ephemeral"}をシステムプロンプトや大きな参照文書の末尾に追加するだけで有効になる
  • TTLは5分。頻繁なリクエストがあるシステムほど効果が大きい
  • キャッシュヒット率を測定して設計が正しく機能しているか確認する
  • ツール定義・Few-shot例文・マニュアル文書など、変化しない大きなコンテンツほど削減効果が高い

適切な設計をするだけでAPIコストが大幅に削減でき、同じ予算でより多くのリクエストをこなせるようになります。

よくある質問

プロンプトキャッシュとは何ですか?

一度処理した長いプロンプト(システムプロンプト・大きなドキュメントなど)の処理結果をAnthropicのサーバーが5分間保持し、同じ内容が再送信された場合にキャッシュから返す機能です。キャッシュヒット時はトークン処理コストが約90%削減されます。

キャッシュはどれくらいの時間保持されますか?

キャッシュのTTL(保持時間)は5分です。5分以内に同じキャッシュプレフィックスが使われると有効時間がリセットされます。5分間アクセスがないとキャッシュは破棄されます。

どんなコンテンツをキャッシュするのが効果的ですか?

会話をまたいで変わらない大きなコンテンツが対象です。具体的にはシステムプロンプト・大きな参照ドキュメント・ツール定義・few-shot例文などです。ユーザーごとに変わる情報はキャッシュの対象外です。