💾

Azure OpenAIのプロンプトキャッシュの挙動検証

に公開

背景

MCPサーバーを使うなら Prompt Caching が大切だと思い知った話という記事を読んで、プロンプトキャッシュの重要さを知り、興味を持ったため調べてみました。
 プロンプトキャッシュを使用せず、LLMに毎回同じようなプロンプトを入力すると、LLMは毎回ゼロから回答を生成して出力してしまいます。これでは毎回回答生成にかかる時間のロスが発生するだけでなく、同じような内容のプロンプトであるにもかかわらずトークンも毎回消費されるためコストがかかってしまいます。
 したがって、プロンプトキャッシュは生成AIにおいて余分なコストを削減し、効率よく処理するのに必要な技術要素です。たとえばMCPツール連携をする際、毎回LLMに1000文字規模のMCPツールの説明を渡すのは効率的ではありません。このような事態を避けるためにプロンプトキャッシュは有効な手法となっています。
 今回の記事ではプロンプトキャッシュの有無によるキャッシュトークン数を比較検証しようと思います。

検証内容

  • 2025/06/30時点のこちらの記事によると、Azure OpenAIでは次のモデルのみがプロンプトキャッシュをサポートしていると書かれていました。

    • o3-mini-2025-01-31
    • o1-2024-12-17
    • o1-preview-2024-09-12
    • o1-mini-2024-09-12
    • gpt-4o-2024-11-20
    • gpt-4o-2024-08-06
    • gpt-4o-mini-2024-07-18
    • gpt-4o-realtime-preview (バージョン 2024-12-17)
    • gpt-4o-mini-realtime-preview (バージョン 2024-12-17)
    • gpt-4.1-2025-04-14
    • gpt-4.1-nano-2025-04-14
  • なお、以下の条件を満たすとプロンプトキャッシュが自動で効きます

    • トークンの長さが1024以上 かつ 先頭1024トークンが同じ
  • キャッシュトークンにかかるコストは通常のトークンの1/4の費用です

  • キャッシュは通常、非アクティブな状態から5~10分以内にクリアされ、最後に使用されてから1時間以内に削除されます

  • プロンプトキャッシュをサポートするモデルgpt-4.1-nanoとサポートしていないモデルgpt-4.1-miniで同じプロンプトを複数回実行した場合、キャッシュトークン数にどのような違いがでるか検証します

  • また、プロンプトキャッシュをサポートしないgpt-4.1-miniにおいてもトークンのキャッシュをする方法を考え、実装したいと思いました

検証環境

項目 バージョン
OS Windows11
ランタイム Node.js v22.14.0
主要ライブラリ @azure/openai: "^2.0.0"
モデル Azure OpenAI (gpt-4.1-nano, gpt-4.1-mini)
リージョン japaneast

ソースコード

トークン数が1024以上になるように、ループによりシステムプロンプトの長さを盛っています。

import { config } from "./config.js"
import { AzureOpenAI } from "openai";

const openai =new AzureOpenAI( { 
    apiKey: config.apiKey,
    apiVersion: config.apiVersion,
    endpoint: config.endpoint,
    deployment: config.deploymentName,
});

const userMessage = "10+20はいくつですか?";

let systemPrompt;
for (let i = 0; i < 250; i++) {
  systemPrompt += "You are a helpful assistant.";
}

for (let i = 0; i < 5; i++) {
  const response = await openai.chat.completions.create ({
      model: "",
      messages: [
        { role: "system", content: systemPrompt },
        { role: "user", content: userMessage }
      ],
  });
  console.log(response.usage);
}

結果

console.log(response.usage)により、以下のようなログが出力されました。

# 一部抜粋

{
  completion_tokens: 11,
  completion_tokens_details: {
    accepted_prediction_tokens: 0,
    audio_tokens: 0,
    reasoning_tokens: 0,
    rejected_prediction_tokens: 0
  },
  prompt_tokens: 1272,
  prompt_tokens_details: { audio_tokens: 0, cached_tokens: 0 },
  total_tokens: 1283
}
{
  completion_tokens: 11,
  completion_tokens_details: {
    accepted_prediction_tokens: 0,
    audio_tokens: 0,
    reasoning_tokens: 0,
    rejected_prediction_tokens: 0
  },
  prompt_tokens: 1272,
  prompt_tokens_details: { audio_tokens: 0, cached_tokens: 1152 },
  total_tokens: 1283
}

completion_tokensはユーザが入力したプロンプトである10+20はいくつですか?、prompt_tokensはシステムプロンプトYou are a helpful assistant.....にあたります。
消費されたトークンの量total_tokensはいずれのLLMも1283でした。

そのうちキャッシュされたトークンの量cached_tokensはそれぞれ以下のようになっていました。
なお、ユーザープロンプトはキャッシュされません。

モデル名 1回目 2回目 3回目 4回目 5回目
gpt-4.1-nano 0 0 1152 1152 1152
gpt-4.1-mini 0 0 1152 0 1152

2025/07/09時点で実行するとgpt-4.1-miniもプロンプトキャッシュが効いているみたいでした....
なお、gpt-4.1-miniは3回目の実行でキャッシュが効いたにもかかわらず、4回目の実行ではキャッシュが効いていません。原因はわかりませんが実際の動作ではキャッシュが常に効くとは限らないようです。

キャッシュが効かないとされていたgpt-4.1-miniにおいても、何の追加実装も設定もない状態でキャッシュが効くという嬉しい誤算となりました。gpt-4.1-miniにおいてキャッシュを効かせる方法を考えるという構想は頓挫しましたが、ユーザーとしては何の手間もなくコストを抑えることができ、ありがたい結果となりました。

このような細かい仕様は日々アップデートされているため注意が必要です。

まとめ

  • gpt-4.1-nanogpt-4.1-miniでキャッシュトークンの比較をしたかったのですが、いずれもキャッシュが効く結果となりました
  • システムプロンプトやツールの説明など、常に固定で渡されるものに対してプロンプトキャッシュは有効です
セリオ株式会社 テックブログ

Discussion