大規模言語モデル(LLM)は、テキスト生成、翻訳、質問応答などの複雑なタスクを可能にし、AIとのインタラクションの革命をもたらしました。しかし、特に洗練されたプロンプトを用いてこれらの強力なモデルと対話することは、かなりの計算コストとレイテンシを伴う場合があります。多くのアプリケーションでは、似たようなまたは部分的に同一のプロンプトを何度も送信することが含まれます。固定されたシステムプロンプトを持つチャットボット、同じ指示でチャンクを処理する文書分析ツール、または一貫したツール定義を使用するエージェントを想像してみてください。これらのシナリオでは、LLMが同じ初期情報(プロンプトのプレフィックス)を繰り返し処理し、計算を無駄にし、応答時間を増加させます。
プロンプトキャッシングは、この非効率性に対処するための強力な最適化手法として浮上しました。これにより、LLMプロバイダーは、プロンプト(プレフィックス)の初期部分に関連する中間計算状態を保存できます。その後のリクエストが同じプレフィックスを使用する場合、モデルはこのキャッシュされた状態を再利用でき、冗長な計算をスキップして新しい動的部分(サフィックス)のみを処理します。これにより、レイテンシとコストの両方で大幅な改善がもたらされ、LLMアプリケーションがより迅速かつ経済的になります。
このガイドでは、プロンプトキャッシングの包括的な概要、その動作方法、利点、実装の詳細(特にAnthropicのAPIに焦点を当てており、AWS Bedrock上のClaudeモデルにも関連しています)、価格に関する考慮事項、制限事項、およびベストプラクティスを提供します。
開発チームが最大の生産性で協力できる統合型のオールインワンプラットフォームが欲しいですか?
Apidogはあなたのすべての要求を満たし、Postmanをはるかに手頃な価格で代替します!

button
プロンプトキャッシングの仕組み: メカニズム
プロンプトキャッシングは、LLMとの多くのインタラクションの反復的な性質を利用しています。LLMにプロンプトを送信すると、モデルが入力トークンを順番に処理して内部表現または状態を生成します。プロンプトキャッシングはこのプロセスを介入します。
- キャッシュミス(最初のリクエスト / 変更されたプレフィックス): 最近見られていない、または既存のキャッシュエントリと一致しないプロンプトプレフィックスを持つリクエストが到着すると、LLMは通常通りプロンプト全体を処理します。ただし、特定のプレフィックス境界に対してキャッシングが有効になっている場合、システムはそのプレフィックスに対応する内部モデル状態を処理後に保存します。これは通常、キャッシュ書き込みと呼ばれます。この保存された状態には、プレフィックスの内容(システムプロンプト、ツール定義、およびキャッシュポイントまでのメッセージを含む)の暗号化ハッシュなどの一意の識別子が関連付けられ、キャッシュキーとして機能します。
- キャッシュヒット(その後のリクエスト): 後続のリクエストがキャッシュの有効期限(TTL)の範囲内で到着し、そのプレフィックスが保存されたキャッシュキーに関連付けられた内容と完全に一致している場合、システムは保存された内部状態を取得します。LLMは効果的にプレフィックスの終わりに早送りし、再処理なしで新しいプロンプト部分(サフィックス)のみを処理する必要があります。これをキャッシュ読み取りまたはキャッシュヒットと呼びます。
キャッシュされたプレフィックス:
「プレフィックス」を構成する具体的な内容はAPIやリクエストの構造によります。一般的に、呼び出しの中で再利用することを意図したプロンプトの静的な部分が含まれます。たとえば、AnthropicのAPI構造を参照として使用すると:
- ツール: 使用可能なツール/関数の定義。
- システムプロンプト: モデルのための高レベルの指示やコンテキスト。
- メッセージ: 初期のユーザー/アシスタントメッセージ、例えば数ショットの例や会話の履歴。
通常、順序が重要です(例: Anthropicはtools
、次にsystem
、その後messages
を処理します)。キャッシュ可能なプレフィックスの終わりを特定のAPIパラメータを使用して指定します。
キャッシュ特性:
- ライフタイム(TTL): キャッシュは永続的ではありません。TTLがあります。たとえば、Anthropicのキャッシュには最低5分のTTLがあり、キャッシュエントリがアクセスされるたびに更新されます(キャッシュヒット)。TTL内で使用されないキャッシュエントリは期限切れとなり、次の関連リクエストで再作成が必要です。現在、大部分の実装では比較的短いライフタイムの「一時的」キャッシングを提供しています。
- スコープとプライバシー: キャッシングはプライバシーを考慮して設計されています。キャッシュは通常、組織またはアカウントレベルで分離されます。異なる二つの組織が完全に同じプロンプトプレフィックスを送信しても、キャッシュエントリを共有することはありません。組織内では、同一のプレフィックスを送信するユーザーがキャッシュエントリを共有する可能性があり、チームアプリケーションの効率を向上させます。キーとして暗号学的ハッシュを使用することで、同一のプレフィックスを持つリクエストだけが特定のキャッシュにアクセスできることが保証されます。
- 完全一致: キャッシングはプレフィックス内容の完全な一致に依存します。指定されたプレフィックス内でのわずかな変更(ホワイトスペースを含む)でもキャッシュミスを引き起こし、新しいキャッシュ書き込みを必要とします。
プロンプトキャッシングを使用する理由は何ですか?
プロンプトキャッシングを導入することで、主にパフォーマンスとコスト効率に焦点を当てた重大な利点が得られます。
- レイテンシの削減: これはしばしば最も即時的な利益です。数千のプレフィックストークンの再処理をスキップすることで、LLMは関連する新しい情報(プロンプトサフィックス)の処理をはるかに早く開始できます。これは最終ユーザーへの応答時間の短縮に直接的に繋がります。チャットボットやコードアシスタントのようなリアルタイムインタラクションが必要なアプリケーションでは、この速度向上は重要です。AWS Bedrockは、対応するモデルで最大85%のレイテンシ削減を報告しています。
- コストの削減: LLM APIは通常、処理された入力および出力トークンの数に基づいて課金されます。キャッシュヒットが発生すると、キャッシュから読み取られたトークンに対して通常よりも大幅に低い料金が請求されます。サフィックスの新しいトークンに対してのみ標準入力料金がかかります(そして初期キャッシュ書き込みに対してわずかに高い料金がかかる場合があります)。多くの呼び出しで大きく静的なプレフィックスを使用する場合、これは大幅なコスト削減に繋がります。AWS Bedrockは最大90%のコスト削減が可能だと示唆しています。
- 一般的なユースケースのための最適化されたパフォーマンス: キャッシングは、本質的にプロンプトの繰り返しを含むアプリケーションにとって特に影響力があります:
- 取得強化生成(RAG)/文書Q&A: 大きな文書やコンテキストスニペットが、ユーザーの問いが変わるだけでプロンプトの一部として繰り返し入力されることがよくあります。文書コンテキストをキャッシュすることで、その文書に対するQ&Aが大幅にスピードアップします。
- 数ショットプロンプト: プロンプト内で複数の例を提示すること(数ショット学習)はモデルのパフォーマンスを向上させますが、プロンプトの長さが増加します。これらの静的な例をキャッシュすることで、すべての新しいクエリのために再処理する必要を避けることができます。
- エージェンティックワークフロー: AIエージェントは、複雑なシステムプロンプト、詳細な指示、固定されたツール定義のセットに依存することがよくあります。これらの定数要素をキャッシュすることで、特に多段階プロセスでのタスクの実行が加速されます。
- チャットボット/マルチターン会話: 会話履歴が増え続ける一方で、初期のシステムプロンプトと指示は通常同じままです。システムプロンプトをキャッシュし、場合によっては会話のターンを段階的にキャッシュすることで、コンテキストウィンドウがいっぱいになってもインタラクションをスナッピーに保つことができます。
- コードアシスタント: 静的なコードコンテキスト、ライブラリのドキュメント、または雛形の指示をキャッシュすることで、アシスタントがユーザーの特定のコーディングクエリに計算を集中させることができます。
- シームレスな統合: プロンプトキャッシングは他のLLM機能と連携して機能するように設計されています。たとえば、AWS Bedrockのエージェントやガードレールなどの機能と統合されているため、繰り返しの要素による完全なレイテンシペナルティを受けることなく、複雑なセットアップを活用できます。
プロンプトキャッシングを有効にする方法
プロンプトキャッシングを有効にするための正確な方法は、LLMプロバイダーやそのAPIによって若干異なります。ここでは、AnthropicのMessages APIを使用した実装に焦点を当てます。これはAnthropicを介して直接、またはAWS Bedrockなどのプラットフォームを通じてClaudeモデルに適用されます。
一般的な原則: プロンプトを構造化する
重要なのは、API呼び出しの構造を設定し、静的で再利用可能なコンテンツが最初に表示され、動的コンテンツがその後に続くようにすることです。
+-------------------------+--------------------------+
| 静的プレフィックス | 動的サフィックス |
| (システムプロンプト、ツール、| (新しいユーザークエリ、最新 |
| 数ショットの例、 | 会話ターンなど) |
| 初期コンテキスト) | |
+-------------------------+--------------------------+
^
|
キャッシュのブレークポイントがここに
Anthropic APIの実装(cache_control
)
Anthropicは、キャッシングを有効にして管理するために、Messages APIリクエストボディ内でcache_control
パラメータを使用します。
- 有効化: キャッシュ可能なプレフィックスの終わりとして含めたいブロックのいずれかに
cache_control
オブジェクトを含めます。現在、サポートされているtype
は、"ephemeral"
のみです。 - 配置:
cache_control
ブロックを次のいずれかに配置できます: system
プロンプトメッセージ。- 特定の
message
オブジェクト(ユーザーまたはアシスタントのターン)。 - ツール定義ブロック(あまり一般的ではありませんが、可能です)。
- キャッシュ作成順序: キャッシュプレフィックスは、キャッシュコントロールでマークされたブロックまでの内容に基づいて構築され、標準の順序(
tools
→system
→messages
)に従います。 - 複数のブレークポイント: 複数のブロックに
cache_control
を追加することで、単一のリクエストで最大4つのキャッシュブレークポイントを定義できます。システムは、これらの潜在的なブレークポイントに基づいて最長の一致キャッシュプレフィックスを見つけようとします。
例(Anthropic Python SDK):システムプロンプトのキャッシング
import anthropic
client = anthropic.Anthropic(api_key="YOUR_API_KEY")
# 最初のリクエスト(キャッシュ書き込み)
response1 = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=1024,
system=[
{
"type": "text",
# このシステムプロンプトはキャッシュしたいコンテンツです
"text": "あなたは天体物理学を専門とした有用なアシスタントです。あなたの知識は、恒星の進化、宇宙論、惑星科学に関する詳細な情報を含みます。正確かつ簡潔に応答してください。",
"cache_control": {"type": "ephemeral"} # キャッシング用にマーク
}
],
messages=[
{
"role": "user",
# これは動的な部分で、プレフィックスにはキャッシュされません
"content": "チャンドラセカール限界とは何ですか?"
}
]
)
print("最初の応答:", response1.content)
print("使用状況(書き込み):", response1.usage)
# 使用状況の出力例は次のようになる可能性があります:
# Usage(Write): Usage(input_tokens=60, output_tokens=50, cache_creation_input_tokens=60, cache_read_input_tokens=0)
# その後のリクエスト(キャッシュヒット - TTL内、例: < 5分後)
response2 = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=1024,
system=[
{
"type": "text",
# 前回と全く同じシステムプロンプト
"text": "あなたは天体物理学を専門とした有用なアシスタントです。あなたの知識は、恒星の進化、宇宙論、惑星科学に関する詳細な情報を含みます。正確かつ簡潔に応答してください。",
"cache_control": {"type": "ephemeral"} # 再びマーク
}
],
messages=[
{
"role": "user",
# 新しい動的なクエリ
"content": "ダークエネルギーの概念を説明してください。"
}
]
)
print("\\\\n二回目の応答:", response2.content)
print("使用状況(ヒット):", response2.usage)
# 使用状況の出力例は次のようになる可能性があります:
# Usage(Hit): Usage(input_tokens=8, output_tokens=75, cache_creation_input_tokens=0, cache_read_input_tokens=60)
この例では:
- 最初の呼び出しでは、システムプロンプトの60トークンとユーザーメッセージの8トークンが処理されます。システムプロンプトをキャッシュします(
cache_creation_input_tokens: 60
)。 - 二回目の呼び出しは、同一のシステムプロンプトのキャッシュヒットを見つけます(
cache_read_input_tokens: 60input_tokens: 8
)。
例(会話におけるインクリメンタルキャッシング):
会話履歴をキャッシュするには、次のターンのためにキャッシュに含めたい最後のメッセージにcache_control
を置くことができます。
# ターン1(ユーザーが質問、アシスタントが応答 - キャッシュシステム + ターン1)
response_turn1 = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=500,
system=[{"type": "text", "text": "フレンドリーな人格を維持してください。"}], # これもキャッシュ
messages=[
{"role": "user", "content": "こんにちは、クロード!"},
{"role": "assistant", "content": "こんにちは!今日はどうお手伝いできますか?", "cache_control": {"type": "ephemeral"}} # ここまでキャッシュ
]
)
# ユーザーがターン2のためにさらにメッセージを追加すると仮定します
# ターン2(システム+ターン1のキャッシュヒット、ターン2のキャッシュ書き込み)
response_turn2 = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=500,
system=[{"type": "text", "text": "フレンドリーな人格を維持してください。"}], # 同じシステムプロンプト
messages=[
{"role": "user", "content": "こんにちは、クロード!"}, # 現在キャッシュされたプレフィックスの一部
{"role": "assistant", "content": "こんにちは!今日はどうお手伝いできますか?"}, # 現在キャッシュされたプレフィックスの一部
{"role": "user", "content": "面白い事実を教えてください。"}, # 新しい動的コンテンツ
{"role": "assistant", "content": "ハチ蜜は腐らないことを知ってましたか?", "cache_control": {"type": "ephemeral"}} # ターン2の終わりまでキャッシュ
]
)
# ターン2の使用状況には、システム+ターン1のためのcache_read_input_tokensが表示されます
# およびターン2の新しいユーザー/アシスタントメッセージのためのcache_creation_input_tokensが含まれます。
キャッシュパフォーマンスの追跡:
APIの応答には、キャッシュがどのように利用されたかを明らかにする使用状況メトリックが含まれています:
input_tokens
: 処理された非キャッシュ入力トークンの数(動的サフィックス)。output_tokens
: 応答で生成されたトークンの数。cache_creation_input_tokens
: このリクエストで処理され、アクティブにキャッシュに書き込まれた入力トークンの数(キャッシュミスで発生)。cache_read_input_tokens
: このリクエストでキャッシュから取得された入力トークンの数(キャッシュヒットで発生)。
これらのフィールドのモニタリングは、あなたのキャッシング戦略が効果的かどうかを理解するために重要です。時間の経過とともにcache_read_input_tokens
がcache_creation_input_tokens
に対して高いことは、成功したキャッシングを示します。
AWS Bedrock:
AWS Bedrock経由でアクセスされたAnthropic Claudeのようなモデルでは、キャッシングメカニズムは通常、モデル呼び出しリクエストボディ(application/json
形式でInvokeModel
またはInvokeModelWithResponseStream
に渡される)内で同じcache_control
パラメータを使用して有効化されます。特定のモデルの要件に従ってJSONボディを構造化し、上記のようにcache_control
フィールドを含めます。使用しているモデルプロバイダーの特定のBedrockドキュメントを確認してください。
プロンプトキャッシングの価格はどのくらいですか?
プロンプトキャッシングは、標準トークンコストに比べてより細分化された価格構造を導入します。全体的には有益ですが、関与する異なるトークンのタイプを理解することが重要です:
- 基本入力トークン: これらはキャッシュプレフィックスの一部ではない標準的な入力トークンです(すなわち、キャッシュヒットシナリオの動的サフィックス、またはキャッシングが使用されない場合やミスした場合の全プロンプト)。これらはモデルの標準入力トークンレートで課金されます。
- キャッシュ書き込みトークン (
cache_creation_input_tokens
): プレフィックスが初めて処理されたとき(またはキャッシュミスの後)にキャッシュに書き込まれると、そのプレフィックスに関連付けられているトークンは通常プレミアム料金で課金されます。たとえば、Anthropicはキャッシュ書き込みで基本入力トークンレートの25%増しで請求します。これは、キャッシュエントリの処理および保存コストを反映しています。 - キャッシュ読み取りトークン / キャッシュヒットトークン (
cache_read_input_tokens
): キャッシュヒットが発生した場合、キャッシュからロードされたプレフィックスに対応するトークンは、著しく割引された料金で課金されます。たとえば、Anthropicはキャッシュ読み取りで基本入力トークンレートのわずか10%(90%割引)を請求します。これは計算のコスト削減を反映しています。 - 出力トークン: LLMが応答で生成したトークンは、入力に対してキャッシングが使用されていたかどうかに関わらず、モデルの標準出力トークンレートで請求されます。
価格表の例(Anthropic Claudeモデル - 参考料金):
モデル | 基本入力 (/MTok) | キャッシュ書き込み (/MTok) (+25%) | キャッシュ読み取り (/MTok) (-90%) | 出力 (/MTok) |
---|---|---|---|---|
Claude 3.5 ソネット | $3.00 | $3.75 | $0.30 | $15.00 |
Claude 3 ハイク | $0.25 | $0.30 | $0.03 | $1.25 |
Claude 3 オーパス | $15.00 | $18.75 | $1.50 | $75.00 |
(注意:最新の料金については、AnthropicおよびAWS Bedrockの公式料金ページを常に確認してください。)
コスト効率は、特定のプレフィックスに対するキャッシュヒットとミスがどれほど頻繁に発生するかに大きく依存します。大きなプレフィックスが何度も再利用される場合、キャッシュ書き込みの初期コストは、次のキャッシュ読み取りから得られる大幅な節約によってすぐに相殺されます。
プロンプトキャッシングの制限
強力ですが、プロンプトキャッシングには限界と考慮すべき要素があります:
最小キャッシュ可能長さ: モデルには、プレフィックスがキャッシングの対象となるために必要な最小トークン数があります。この制限よりも短いプロンプトは、cache_control
でマークされていてもキャッシュできません。
- Anthropic Claude 3.7/3.5 ソネット・オーパス: 最小1024トークン。
- Anthropic Claude 3.5/3 ハイク: 最小2048トークン。
キャッシュ無効化(キャッシュバスティング): キャッシュはプレフィックス内の変更に非常に敏感です。いかなる変更もキャッシュを壊し、新しい書き込みを強制します:
system
、tools
、またはプロンプトのプレフィックスの一部として指定されたmessages
ブロック内のいかなるテキストコンテンツを変更すること。tool
の定義の順序または数を変更すること。tool_choice
パラメータを変更すること(例:auto
から特定のツールに切り替えるなど)。- プロンプト内の画像を追加、削除、または変更すること(マルチモーダルモデル用)。
- 初期処理に影響を与える他のモデルパラメータを変更するとキャッシュが壊れる可能性があります(例: Anthropicの拡張思考設定はメッセージキャッシュを無効にする場合があります)。
キャッシュの寿命(TTL): キャッシュは一時的であることを忘れないでください(例: Anthropicの最小TTLは5分で、使用されるたびに更新されます)。TTL内で再利用されないプレフィックスは期限切れになります。現在、キャッシュを手動でクリアまたは延長する方法はありません。
同時実行性: 初めてのリクエストが完了し、エントリをキャッシュに書き込む前に、プレフィックスを対象とする多くの同一リクエストを同時に送信すると、以後のリクエストがキャッシュミスになる可能性があります。並行シナリオでキャッシュヒットを保証するには、他のリクエストを送信する前に最初の応答を待つ必要があります。
サポートされているモデル: プロンプトキャッシングは全てのモデルやプロバイダで普遍的に利用できるわけではありません。使用を予定している特定のモデルのドキュメントを常に確認してください。(現在、さまざまなClaude 3および3.5モデルで確認されています)。
デバッグ: キャッシュミスを引き起こす微妙な変更を特定することは時には難しいことがあります。呼び出し間で正確なプレフィックス内容を慎重に比較する必要があります。
効果的なキャッシングのためのベストプラクティス
プロンプトキャッシングの利点を最大限に引き出すために:
- プロンプトを賢く構造化する: 最も安定して再利用可能な情報(システムプロンプト、指示、ツール定義、コンテキスト文書、数ショットの例)をプロンプトシーケンスの最初に配置します。動的で頻繁に変わる情報(ユーザークエリ、最新の会話ターン)はキャッシュブレークポイントの後に配置します。
- 最適なブレークポイントを特定する:
cache_control
(または同等のメカニズム)を意図的に使用します。真に静的なコンテンツの最大可能ブロックの終わりをマークします。複数のブレークポイントを使用する場合(Anthropicが許可するように)、プロンプト構造内の安定性の異なるレベルを考慮してください。 - キャッシュ使用状況をモニターする: API応答内で定期的に
cache_creation_input_tokens
およびcache_read_input_tokens
を確認します。時間の経過とともに高い読み取り対書き込みの比率を目指します。書き込みがほとんどの場合、プレフィックスが頻繁に変更されすぎているか、最小キャッシュ可能長さを下回っている可能性があります。 - 不必要な変更を避ける: プレフィックス内容のわずかな、見えにくい変更(空白を追加する、句読点を変更するなど)でもキャッシュを壊すことに留意してください。プレフィックスの生成方法の一貫性を確保します。
- コストのトレードオフを考慮する: キャッシングは、長いおよび頻繁に再利用されるプレフィックスに最も効果的です。非常に短いプレフィックスはキャッシュしても、潜在的な節約は最小限で、複雑さが上回ることがあるためキャッシングを避けます。変動が激しいユーザー入力のキャッシングも避けます。
- テストと反復: 特定のアプリケーションのワークロードと使用パターンに最適な戦略を見つけるために、さまざまなプロンプト構造およびキャッシュブレークポイントを試してみてください。
結論
プロンプトキャッシングは、大規模言語モデルに基づくアプリケーションを構築するための重要な最適化技術です。静的プロンプトプレフィックスの計算状態を賢く保存し再利用することで、長いまたは繰り返しのプロンプトに関連するレイテンシとコストの課題に直接取り組みます。キャッシングの動作方法、選択したLLMプロバイダー(Anthropicのcache_control
など)の特定の実装詳細、関連する料金のニュアンス、および制限を理解することで、より効率的で応答性が高く経済的なAIアプリケーションの設計が可能になります。LLMの使用例が複雑さと規模で増加するにつれて、プロンプトキャッシングのような機能を活用することが、性能の高い持続可能なソリューションを構築するためにますます重要になります。
開発チームが最大の生産性で協力できる統合型のオールインワンプラットフォームが欲しいですか?
Apidogはあなたのすべての要求を満たし、Postmanをはるかに手頃な価格で代替します!
button
