🐶

Roo CodeでGemini2.5 proを使う際のPrompt Cacheについて調べてみた

に公開

きっかけ:Roo CodeのPromptCacheとGeminiのImplicit Cachingがかち合っているのではないかと思い調べてみた。

(結論、↑は誤認識みたいでした。)

🔽 Gemini2.5のImplicit Caching (5/8)
https://developers.googleblog.com/en/gemini-2-5-models-now-support-implicit-caching/

🔽 Roo Code 3.14のGemini 2.5 Caching (4/25)
https://docs.roocode.com/update-notes/v3.14

Prompt Cacheの定義

Prompt Cacheは、AIプロバイダーのキャッシュ機能を利用して、過去に送信したプロンプトや会話の一部を記憶し、同じ内容が再度必要になった場合に完全に再処理せずに再利用する仕組みです。

Roo Code内で対応しているモデル

  • Anthropic Claude 3.7/3.5シリーズ
  • Google Gemini 2.5/2.0/1.5の一部モデル
  • OpenAI GPT-4.1シリーズ、o3、o4シリーズ
  • Amazon Bedrockの一部のモデル

https://github.com/RooVetGit/Roo-Code/blob/7bef4f0fa64512adb79a912b906891bc590fc954/src/shared/api.ts#L26-L37

https://github.com/RooVetGit/Roo-Code/blob/main/src/shared/api.ts#L505-L513

https://github.com/RooVetGit/Roo-Code/blob/main/src/shared/api.ts#L863-L871

Gemini APIのImplicit CachingとExplicit Caching

私はこの辺からちょっと誤認していました。

GeminiAPIには明示的キャッシュ(Explicit Caching)と暗黙的キャッシュ(Implicit Caching)があり今回追加されたのは暗黙的キャッシュである。

Roo Codeは、内部のメカニズムで
明示的キャッシュ(Explicit Caching)を管理するロジックがある。

Implicit Cachingは、Gemini側の話なのでGeminiサイドのサーバで勝手に処理される。

ざっくりまとめ

  • Gemini APIには2つのキャッシュメカニズムがある
    - 明示的キャッシュ
    - 明示的にキャッシュしたコンテンツを事前にモデルに渡して、このキャッシュを使うように以後はリクエストする必要がある
    - キャッシュのTTLを設定できる(デフォルトは1時間)
    - キャッシュヒットを制御できるため、コスト削減が保証される
    - 暗黙的キャッシュ
    - 設定などは不要でデフォルトで自動適用
    - 最小入力トークン数。これ以下はキャッシュされない。
    - Gemin 2.5 Flash: 1024
    - Gemini 2.5 Pro: 2048
    - キャッシュヒットするかどうかはリクエスト次第

引用元:
https://zenn.dev/link/comments/3ed30a2e399579

Roo Code内のGeminiの実際のロジック

Roo Code の GeminiHandler が明示的に caches.create / cachedContent を使って管理する仕組みがありました。

基本

https://github.com/RooVetGit/Roo-Code/blob/main/src/api/providers/gemini.ts#L23-L30

  • キャッシュのTTLは5分
  • キャッシュ書き込み頻度は、10回に1回
    • データ読み取り10回につき1回だけキャッシュを更新する
  • 4096トークン以上の場合のみキャッシュ対象。

管理体制

  • ローカルの NodeCache

    • 役割: 「どのセッションがどの cacheId を持っているか」を参照する
  • Gemini サーバーの Cache

    • 役割: プロンプトの長い共通プレフィックス を保存し、次回以降の請求を割引。

🟦 A. 明示的キャッシュ(Roo Code による管理)

Roo Code の GeminiHandler が明示的に caches.create / cachedContent を使って管理する仕組み。

1. NodeCache を使って明示キャッシュを探索

  • cacheKey をもとに、Roo側の NodeCache(TTL 5分)からキャッシュID (cacheId) を取得。

  • ヒットすれば未キャッシュ分だけ Gemini に送信し、cachedContent: cacheId を添える。

2. 明示的キャッシュIDを指定して送信

  • Gemini 側は cacheId に対応するプレフィックスを展開。

  • そのトークンは75%割引で課金される(明示的キャッシュ適用)。

3. writeCache による新規キャッシュ作成

  • キャッシュが無い or 10件以上追加 → writeCache() をバックグラウンド実行。

  • caches.create で新しいプレフィックスを Gemini に保存(TTL: 5分)。

  • 新しい cacheId を NodeCache に保存。

4. 古いキャッシュを削除

  • 古い cacheId があれば caches.delete で Gemini 側から削除。

https://github.com/RooVetGit/Roo-Code/blob/main/src/api/providers/gemini.ts#L89-L98

  1. Gemini が「明示的キャッシュ」をサポートするモデルか確認。

  2. 4,096token 超の長文でないとキャッシュを作らない(Gemini の制限)。

  3. NodeCache にヒットすれば「未キャッシュ分だけ」送信する準備をする。

  4. 10 メッセージ分追記されたら、あとで新しいキャッシュを作成するフラグを立てる。

https://github.com/RooVetGit/Roo-Code/blob/main/src/api/providers/gemini.ts#L123-L138

  1. cachedContent を渡すと Gemini サーバーは対応する prefix を展開し、当該トークンを 75% 割引で計上。

  2. キャッシュを使うときは再送不要な systemInstruction を外して帯域節約。

  3. レスポンスはストリームで逐次受信し、usage metadata からトークン数を後で計算。

https://github.com/RooVetGit/Roo-Code/blob/main/src/api/providers/gemini.ts#L140-L142

https://github.com/RooVetGit/Roo-Code/blob/main/src/api/providers/gemini.ts#L320-L391

  1. caches.create で リモート(Gemini サーバー) に最新 prefix をスナップショット。

  2. 返ってきた cacheId を ローカル NodeCache に保存。

  3. もし旧 ID があれば caches.delete で削除し、サーバー側のゴミを残さない。

  4. isCacheBusy で多重呼び出しを抑止。

暗黙的キャッシュはGemini 側が自動判定

これはRoo Code外で起こっていること

1. 同じ prefix を再送する

  • 前回と同じ内容のプレフィックスを含んだプロンプトを送るだけで OK。

2. Gemini 側で自動検出

  • 同じ先頭部分が見つかると、そのトークンに 75% 割引を自動適用。

  • usageMetadata の cachedContentTokenCount に反映される。

3. 開発者は何も設定しなくてもいい

  • cachedContent や caches.create は一切不要。

結論

  • Roo Codeは、内部のメカニズムで明示的キャッシュ(Explicit Caching)を管理している。

  • Implicit Caching(暗黙的キャッシュ)は、Gemini側の話なのでGeminiサイドのサーバで勝手に処理される。

  • コードを読む限り、Roo Codeはそれを明確に分け、キャッシュ利用条件やトリガーを制御することで安全に両立させていそう

    • cachedContent (明示的キャッシュ) は Gemini 側に「prefix これね」と明示して渡す。
    • implicit caching はこの指定と無関係に、トークン内容だけを見て勝手にかかる
      • 動作レイヤーが明確に異なる
  • なので、結論、以下のdisableはしなくても良さそう

Xのフォローお願いします!

AIエージェントやAIを用いたプログラミングについて発信しています。
気が向いたらフォローよろしくお願いします
しば田 | Programming x AI

Discussion