Skip to main content

コンテキストキャッシュ

大規模モデルの推論リクエストには、マルチターン対話や同じ書籍に関する一連の質問など、重複する入力が含まれることがよくあります。コンテキストキャッシュは、これらのリクエストの共通プレフィックスをキャッシュすることで、冗長な計算を削減します。これにより、応答品質に影響を与えることなく、応答速度の向上と利用コストの削減を実現します。

さまざまなシナリオをサポートするために、コンテキストキャッシュには 2 つのモードが用意されています。利便性、確実性、コストの要件に基づいてモードを選択してください:
  • 明示的キャッシュ:手動で有効にするモードです。特定のコンテンツに対してキャッシュを作成し、5 分間の有効期間内に確定的なヒットを保証します。キャッシュの作成に使用されるトークンは、標準入力トークン価格の 125% で課金されますが、その後のキャッシュヒットは、その価格のわずか 10% で課金されます。
  • 暗黙的キャッシュ:この自動モードは追加の構成を必要とせず、無効にすることもできません。利便性を優先するシナリオに最適です。システムはリクエストの共通プレフィックスを自動的に識別してキャッシュしますが、ヒット確率は保証されません。キャッシュから提供された入力部分は、標準入力トークン価格の 20% で課金されます。

項目

明示的キャッシュ

暗黙的キャッシュ

応答品質への影響

なし

なし

キャッシュ作成トークンの課金

標準入力トークン価格の 125%

標準入力トークン価格の 100%

キャッシュされた入力トークンの課金

標準入力トークン価格の 10%

標準入力トークン価格の 20%

キャッシュの最小トークン数

1024

256

キャッシュ有効期間

5 分 (ヒット時にリセット)

不確定。システムは古くて未使用のキャッシュデータを定期的にクリアします。

明示的キャッシュと暗黙的キャッシュは相互排他的です。
プロビジョニング済みスループットユニット (PTU) デプロイメントもコンテキストキャッシュをサポートしています。キャッシュヒットが発生すると、システムはキャッシュ割引係数を使用して PTU 使用量を計算します。詳細については、「PTU のための長い入力とキャッシュ」をご参照ください。
OpenAI Chat Completions、DashScope、および Anthropic 互換インターフェイスでは、Responses API とセッションキャッシュを使用して推論レイテンシとコストを削減します。詳細については、「セッションキャッシュ」をご参照ください。

明示的キャッシュ

暗黙的キャッシュとは異なり、明示的キャッシュは明示的な作成が必要でオーバーヘッドが発生しますが、より高いキャッシュヒット率と低いアクセスレイテンシを提供します。

仕組み

"cache_control": {"type": "ephemeral"} マーカーを messages 配列に追加します。その後、システムは各 cache_control マーカーから後方に検索し、最大 20 個の先行する content ブロックを調べてキャッシュヒットを探します。
1 つのリクエストで最大 4 つのキャッシュマーカーをサポートします。
  • キャッシュミス キャッシュミスが発生した場合、システムは messages 配列の先頭と cache_control マーカーの間のコンテンツから新しいキャッシュブロックを作成します。新しいキャッシュブロックの有効期間は 5 分です。
    システムは、モデルが応答を生成した後にキャッシュを作成します。そのキャッシュにヒットさせるには、作成リクエストが完了するまで待ってください。
    キャッシュブロックには、少なくとも 1,024 トークンが含まれます。
  • キャッシュヒット キャッシュヒットが発生した場合、システムは最長一致プレフィックスを選択し、対応するキャッシュブロックの有効期間を 5 分にリセットします。
次の例は、この仕組みを示しています:
  1. 最初のリクエストを送信:テキスト A (1,024 トークン以上) を含むシステムメッセージを送信し、キャッシュマーカーを追加します:
[{"role": "system", "content": [{"type": "text", "text": A, "cache_control": {"type": "ephemeral"}}]}]
システムは最初のキャッシュブロックを作成し、それをキャッシュブロック A と呼びます。 2. 2 番目のリクエストを送信:次の構造でリクエストを送信します:
[
    {"role": "system", "content": A},
    <Other messages>
    {"role": "user","content": [{"type": "text", "text": B, "cache_control": {"type": "ephemeral"}}]}
]
  • 「その他のメッセージ」が 20 以下の場合、リクエストはキャッシュブロック A にヒットし、その有効期間が 5 分にリセットされます。システムはまた、A、その他のメッセージ、および B に基づいて新しいキャッシュブロックを作成します。
  • 「その他のメッセージ」が 20 を超える場合、リクエストはキャッシュブロック A をミスします。システムは引き続き、完全なコンテキスト (A、その他のメッセージ、および B) に基づいて新しいキャッシュブロックを作成します。

サポート対象モデル

  • シンガポール
  • 中国 (北京)
  • ドイツ (フランクフルト)
  • 香港 (中国)
  • 日本 (東京)
  • 米国 (バージニア)
以下のモデルは、国際デプロイ範囲で利用可能です。
Qwen Max: qwen4-max-preview (Token Plan 限定), qwen3.8-max, qwen3.7-max, qwen3.7-max-2026-05-20, qwen3.7-max-2026-06-08Qwen Open-source: qwen3.8-2.4t-a95b, qwen3.8-27bQwen Plus: qwen3.7-plus, qwen3.7-plus-2026-05-26, qwen3.6-plus, qwen3.5-plus, qwen3.5-plus-2026-04-20, qwen-plusQwen Flash: qwen3.8-flash, qwen3.7-flash, qwen3.7-flash-2026-07-15, qwen3.6-flash, qwen3.5-flash, qwen-flashQwen Coder: qwen3-coder-flashQwen VL: qwen3-vl-plus

クイックスタート

以下の例は、OpenAI 互換、DashScope、および Anthropic 互換プロトコルにおけるキャッシュブロックの作成とキャッシュヒットのメカニズムを示しています。
  • OpenAI 互換
  • DashScope
  • Anthropic 互換
from openai import OpenAI
import os

client = OpenAI(
    # 環境変数が設定されていない場合は、次の行を api_key="sk-xxx" に置き換えます
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 中国 (北京) のモデルを使用する場合は、base_url を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 に置き換えます
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# モックコードリポジトリのコンテンツ。キャッシュ可能な最小プロンプト長は 1,024 トークンです。
long_text_content = "<Your Code Here>" * 400

# リクエストを行う関数
def get_completion(user_input):
    messages = [
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": long_text_content,
                    # ここに cache_control マーカーを配置します。これにより、messages 配列の先頭からこの時点までのすべてのコンテンツを含むキャッシュブロックが作成されます。
                    "cache_control": {"type": "ephemeral"},
                }
            ],
        },
        # ユーザーの質問はリクエストごとに異なります。
        {
            "role": "user",
            "content": user_input,
        },
    ]
    completion = client.chat.completions.create(
        # 明示的キャッシュをサポートするモデルを選択します。
        model="qwen3.8-max",
        messages=messages,
    )
    return completion

# 最初のリクエスト
first_completion = get_completion("What is the content of this code?")
print(f"First request cache creation tokens: {first_completion.usage.prompt_tokens_details.cache_creation_input_tokens}")
print(f"First request cached tokens: {first_completion.usage.prompt_tokens_details.cached_tokens}")
print("=" * 20)
# 2 番目のリクエスト。コードの内容は同じですが、質問が異なります。
second_completion = get_completion("How can this code be optimized?")
print(f"Second request cache creation tokens: {second_completion.usage.prompt_tokens_details.cache_creation_input_tokens}")
print(f"Second request cached tokens: {second_completion.usage.prompt_tokens_details.cached_tokens}")
cache_control マーカーを追加すると、モックコードリポジトリのコンテンツに対して明示的キャッシュが有効になります。このコンテンツを照会する後続のリクエストでは、システムはキャッシュブロックを再利用し、再計算を排除します。これにより、キャッシュにヒットしたリクエストは、最初のキャッシュ作成リクエストよりも高速かつ安価になります。
First request cache creation tokens: 1605
First request cached tokens: 0
====================
Second request cache creation tokens: 0
Second request cached tokens: 1605

複数のキャッシュマーカーによる詳細な制御

複雑なシナリオでは、プロンプトはしばしば再利用頻度が異なる複数の部分で構成されます。複数のキャッシュマーカーを使用して、詳細な制御を実現できます。 例えば、インテリジェントなカスタマーサービスエージェントのプロンプトには、通常、以下が含まれます:
  • システムペルソナ:非常に安定しており、めったに変わりません。
  • 外部ナレッジ:これはナレッジベースから、またはツールクエリを通じて取得され、1 回の対話中に変更されない場合があります。
  • 対話履歴:動的に増加します。
  • 現在の質問:リクエストごとに異なります。
プロンプト全体を単一のユニットとしてキャッシュすると、外部ナレッジの更新などのわずかな変更でもキャッシュミスが発生する可能性があります。 リクエストに最大 4 つのキャッシュマーカーを追加して、プロンプトの異なる部分に対して個別のキャッシュブロックを作成できます。これにより、キャッシュヒット率が向上し、詳細な制御が可能になります。

課金

明示的キャッシュは、入力トークンの課金方法にのみ影響します。ルールは次のとおりです:
  • キャッシュ作成:新しいキャッシュの作成に使用されるコンテンツは、標準入力トークン価格の 125% で課金されます。新しいキャッシュのコンテンツに既存のキャッシュがプレフィックスとして含まれている場合、増分部分のみがキャッシュ作成として課金されます (つまり、新しいキャッシュトークンの数から既存のキャッシュトークンの数を引いたもの)。 例えば、既存の 1,200 トークンのキャッシュ (キャッシュ A) があり、新しいリクエストで 1,500 トークンのコンテンツ (コンテンツ AB) をキャッシュする場合、最初の 1,200 トークンはキャッシュヒットとして標準価格の 10% で課金されます。新しい 300 トークンは、キャッシュ作成として標準価格の 125% で課金されます。
    cache_creation_input_tokens パラメーターは、キャッシュ作成に使用されるトークンの数を指定します。
  • キャッシュヒット:標準入力トークン価格の 10% で課金されます。
    cached_tokens パラメーターは、キャッシュされたトークンの数を指定します。
  • その他のトークン:キャッシュヒットでもキャッシュ作成に使用されたものでもないトークンは、標準入力トークン価格で課金されます。
  • 例外:qwen3.8-max、qwen3.8-flash、および qwen3.8-2.4t-a95b の明示的キャッシュヒット価格は、標準入力トークン価格の 10% ではありません。具体的な価格については、Model Studio コンソールをご参照ください。(キャッシュ作成価格は標準価格の 125% のままです。)

キャッシュ可能なコンテンツ

messages 配列内の以下のメッセージタイプのみがキャッシュマーカーの追加をサポートしています:
  • システムメッセージ
    関数呼び出しの場合、リクエストに tools パラメーターが含まれていると、ツール定義はキャッシュ計算のためにシステムメッセージに含まれます。ツール定義は独立してキャッシュすることはできません。キャッシュマーカーはメッセージのコンテンツにのみ追加できるため、ツール定義に追加されたキャッシュマーカーは無視されます。
  • ユーザーメッセージ
    qwen3-vl-plus モデルでキャッシュを作成する場合、cache_control マーカーをマルチモーダルコンテンツまたはテキストの後に配置できます。その位置は、ユーザーメッセージ全体がどのようにキャッシュされるかには影響しません。
  • アシスタントメッセージ
  • ツールメッセージ (ツール実行の結果)
例えば、システムメッセージの場合、content フィールドを配列に変更し、cache_control フィールドを追加する必要があります:
{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "<your specified prompt>",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ]
}
この構造は、messages 配列内の他のメッセージタイプにも適用されます。

キャッシュの制限事項

  • キャッシュ可能な最小プロンプト長は 1,024 トークンです。
  • キャッシュは後方プレフィックスマッチング戦略を使用します。一致するコンテンツと cache_control マーカーを持つメッセージが 20 個以上の content ブロックで区切られている場合、キャッシュミスが発生します。
  • type は ephemeral にのみ設定でき、これにより 5 分間の有効期間を持つキャッシュが作成されます。
  • 1 つのリクエストで最大 4 つのキャッシュマーカーをサポートします。
    4 つ以上のキャッシュマーカーが提供された場合、最後の 4 つのみが有効になります。

関数呼び出しのキャッシュ最適化

ツール定義は、キャッシュのために JSON 文字列にシリアル化されます。キャッシュの無効化を防ぐため、この定義はすべてのリクエストで同一でなければなりません。以下に注意してください:
  • 一貫したツール順序:tools 配列内のツールの順序は、すべてのリクエストで一貫している必要があります。
  • 一貫したフィールド順序:同じツール内の JSON フィールドの順序は、すべてのリクエストで一貫している必要があります。
  • 一貫したフィールド構造:フィールドが空またはオプションであっても、フィールドを省略したり追加したりしないでください。

並列ツール呼び出しのためのメッセージ構造の最適化

並列ツール呼び出しを使用すると、モデルは 1 回の応答で複数の tool_calls を返します。各ツール結果を個別の tool メッセージとして送信すると、messages 配列内の content ブロックの数が急速に増加します。cache_control マーカーと以前のコンテンツの間に 20 を超える content ブロックがあると、後方ルックバックウィンドウがそれらの以前のブロックに到達できず、キャッシュミスが発生します。 これを解決するには、次のリクエストを送信する前に、連続する同じロールのツールメッセージを複数の content ブロックを持つ単一の tool メッセージにマージします。これにより、総 content ブロック数が減り、キャッシュしたいコンテンツが 20 ブロックのルックバックウィンドウ内に収まります。 最適化前 (個別のツールメッセージ — キャッシュヒット率が低い):
# モデルが並列 tool_calls を返した後、各結果を個別のメッセージとして送信します
messages.append(assistant_message)  # 並列 tool_calls を含むアシスタントメッセージ
# 各ツール結果は独自のメッセージです — content ブロック数を N 個増やします
messages.append({"role": "tool", "tool_call_id": "call_1", "content": "result_1"})
messages.append({"role": "tool", "tool_call_id": "call_2", "content": "result_2"})
最適化後 (マージされたツールメッセージ — キャッシュヒット率が高い):
# モデルが並列 tool_calls を返した後、すべての結果を 1 つのメッセージにマージします
messages.append(assistant_message)  # 並列 tool_calls を含むアシスタントメッセージ
# すべてのツール結果を複数の content ブロックを持つ単一のメッセージにマージします
messages.append({
    "role": "tool",
    "tool_call_id": "call_1",
    "content": [
        {"type": "text", "text": "result_1"},
        {"type": "text", "text": "result_2", "tool_call_id": "call_2"},
    ],
})
キャッシュヒット率をさらに向上させるには、cache_control マーカーを messages 配列の安定した位置 (例えば、システムメッセージや他の頻繁に変更されないコンテンツ) に配置します。1 つのリクエストで最大 4 つのキャッシュマーカーをサポートします。

使用例

from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # これはシンガポールリージョンの base_url です。呼び出しを行う際は、{WorkspaceId} を実際の WorkspaceId に置き換えてください。URL はリージョンによって異なります。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# モックコードリポジトリのコンテンツ
long_text_content = "<Your Code Here>" * 400

# リクエストを送信する関数
def get_completion(user_input):
    messages = [
        {
            "role": "system",
            "content": [
                {
                    "type": "text",
                    "text": long_text_content,
                    # ここに cache_control マーカーを配置して、プロンプトの先頭からこの content オブジェクトの末尾 (モックコードリポジトリのコンテンツ) までをキャッシュします。
                    "cache_control": {"type": "ephemeral"},
                }
            ],
        },
        {
            "role": "user",
            "content": user_input,
        },
    ]
    completion = client.chat.completions.create(
        # 明示的キャッシュをサポートするモデルを選択します
        model="qwen3.8-max",
        messages=messages,
    )
    return completion

# 最初のリクエスト
first_completion = get_completion("What is the content of this code?")
created_cache_tokens = first_completion.usage.prompt_tokens_details.cache_creation_input_tokens
print(f"First request - Cache creation tokens: {created_cache_tokens}")
hit_cached_tokens = first_completion.usage.prompt_tokens_details.cached_tokens
print(f"First request - Cache hit tokens: {hit_cached_tokens}")
print(f"First request - Uncached tokens: {first_completion.usage.prompt_tokens-created_cache_tokens-hit_cached_tokens}")
print("=" * 20)
# 同じコードコンテンツで質問が異なる 2 番目のリクエスト
second_completion = get_completion("What are some possible optimizations for this code?")
created_cache_tokens = second_completion.usage.prompt_tokens_details.cache_creation_input_tokens
print(f"Second request - Cache creation tokens: {created_cache_tokens}")
hit_cached_tokens = second_completion.usage.prompt_tokens_details.cached_tokens
print(f"Second request - Cache hit tokens: {hit_cached_tokens}")
print(f"Second request - Uncached tokens: {second_completion.usage.prompt_tokens-created_cache_tokens-hit_cached_tokens}")
この例では、コードリポジトリのコンテンツをプレフィックスとしてキャッシュします。後続のリクエストでは、同じリポジトリについて異なる質問をします。
First request - Cache creation tokens: 1605
First request - Cache hit tokens: 0
First request - Uncached tokens: 13
====================
Second request - Cache creation tokens: 0
Second request - Cache hit tokens: 1605
Second request - Uncached tokens: 15
モデルのパフォーマンスを確保するため、システムはいくつかの内部トークンを追加します。これらのトークンは標準の入力価格で課金されます。詳細については、「よくある質問」をご参照ください。
関数呼び出しのためにシステムメッセージをキャッシュする場合、tools パラメーターはシステムメッセージの一部としてキャッシュされます。ツール定義がすべてのリクエストで同一であること (ツールの順序、フィールドの順序、フィールドの構造を含む) を確認し、messages 内の最後の content に cache_control フラグを追加します。以下に完全なフローを示します:最初のリクエストでキャッシュが作成され、2 番目のリクエストでキャッシュにヒットします。
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

# モックコードリポジトリのコンテンツ。明示的キャッシュの最小しきい値である 1,024 トークンを超えるようにします。
long_text_content = "<Your Code Here>" * 400

# ツール定義:すべてのリクエストで同一であることを確認します (ツールの順序、フィールドの順序、フィールドの構造)。
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "指定された都市の現在の天気情報を取得します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "都市名。例:北京、上海、ニューヨーク。"
                    },
                    "unit": {
                        "type": "string",
                        "description": "温度の単位。「celsius」または「fahrenheit」。デフォルトは「celsius」。",
                        "enum": ["celsius", "fahrenheit"]
                    }
                },
                "required": ["city"],
                "additionalProperties": False
            },
            "strict": True
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "指定されたタイムゾーンの現在の日時を取得します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "timezone": {
                        "type": "string",
                        "description": "IANA タイムゾーン名。例:「Asia/Shanghai」または「America/New_York」。デフォルトは「Asia/Shanghai」。"
                    }
                },
                "required": [],
                "additionalProperties": False
            },
            "strict": True
        }
    },
    {
        "type": "function",
        "function": {
            "name": "convert_currency",
            "description": "リアルタイムの為替レートに基づいて通貨額を換算します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "from_currency": {
                        "type": "string",
                        "description": "換算元通貨の ISO 4217 コード。例:CNY、USD、EUR。"
                    },
                    "to_currency": {
                        "type": "string",
                        "description": "換算先通貨の ISO 4217 コード。"
                    },
                    "amount": {
                        "type": "number",
                        "description": "換算する金額。"
                    }
                },
                "required": ["from_currency", "to_currency", "amount"],
                "additionalProperties": False
            },
            "strict": True
        }
    }
]

def get_completion(user_input, messages=None):
    if messages is None:
        messages = [
            {
                "role": "system",
                "content": [
                    {
                        "type": "text",
                        "text": long_text_content,
                        # ここに cache_control マーカーを配置します。これにより、messages 配列の先頭から現在の content オブジェクトまでのすべてのコンテンツを含むキャッシュブロックが作成されます。
                        # cache_control マーカーはメッセージの 'content' に配置する必要があり、'tools' には配置できません。
                        "cache_control": {"type": "ephemeral"},
                    }
                ],
            }
        ]

    messages.append({"role": "user", "content": user_input})

    completion = client.chat.completions.create(
        # 明示的キャッシュをサポートするモデルを選択します
        model="qwen3.7-plus",
        messages=messages,
        tools=tools,
        # 思考モードを無効にします
        extra_body={"enable_thinking": False},
    )
    return completion

# 最初のリクエスト:キャッシュを作成
print("=== First request (Create cache) ===")
first_completion = get_completion("What's the weather like in Beijing now?")
usage = first_completion.usage
print(f"Prompt Tokens: {usage.prompt_tokens}")
print(f"Cache creation tokens: {usage.prompt_tokens_details.cache_creation_input_tokens}")
print(f"Cache hit tokens: {usage.prompt_tokens_details.cached_tokens}")
print(f"Model selected tool(s): {[t.function.name for t in first_completion.choices[0].message.tool_calls or []]}")
print()

# 2 番目のリクエスト:同じシステムメッセージで質問が異なるため、キャッシュにヒットします
print("=== Second request (Cache hit) ===")
messages = [
    {
        "role": "system",
        "content": [
            {
                "type": "text",
                "text": long_text_content,
                "cache_control": {"type": "ephemeral"},
            }
        ],
    }
]
second_completion = get_completion("What's the weather like in Shanghai now?", messages=messages)
usage = second_completion.usage
print(f"Prompt Tokens: {usage.prompt_tokens}")
print(f"Cache creation tokens: {usage.prompt_tokens_details.cache_creation_input_tokens}")
print(f"Cache hit tokens: {usage.prompt_tokens_details.cached_tokens}")
print(f"Model selected tool(s): {[t.function.name for t in second_completion.choices[0].message.tool_calls or []]}")
コードを実行すると、次のような出力が生成されます:
=== First request (Create cache) ===
 Prompt Tokens: 2174
 Cache creation tokens: 2156
 Cache hit tokens: 0
 Model selected tool(s): ['get_weather']

 === Second request (Cache hit) ===
 Prompt Tokens: 2174
 Cache creation tokens: 0
 Cache hit tokens: 2156
 Model selected tool(s): ['get_weather']
典型的なマルチターン対話シナリオでは、各リクエストの messages 配列の最後の content オブジェクトにキャッシュマーカーを追加します。2 ターン目以降、各リクエストは前のターンのキャッシュにヒットしてリフレッシュし、現在のターンの新しいキャッシュブロックを作成します。
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # これはシンガポールリージョンの base_url です。呼び出しを行う際は、{WorkspaceId} を実際の WorkspaceId に置き換えてください。URL はリージョンによって異なります。
    base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)

system_prompt = "You are a witty person." * 400
messages = [{"role": "system", "content": system_prompt}]

def get_completion(messages):
    completion = client.chat.completions.create(
        model="qwen3.8-max",
        messages=messages,
    )
    return completion

while True:
    user_input = input("User: ")
    messages.append({"role": "user", "content": [{"type": "text", "text": user_input, "cache_control": {"type": "ephemeral"}}]})
    completion = get_completion(messages)
    print(f"[AI Response] {completion.choices[0].message.content}")
    messages.append(completion.choices[0].message)
    created_cache_tokens = completion.usage.prompt_tokens_details.cache_creation_input_tokens
    hit_cached_tokens = completion.usage.prompt_tokens_details.cached_tokens
    uncached_tokens = completion.usage.prompt_tokens - created_cache_tokens - hit_cached_tokens
    print(f"[Cache Info] Cache creation tokens: {created_cache_tokens}")
    print(f"[Cache Info] Cache hit tokens: {hit_cached_tokens}")
    print(f"[Cache Info] Uncached tokens: {uncached_tokens}")
コードを実行して、大規模言語モデルとの対話を開始します。後続の各質問は、前のターンで作成されたキャッシュにヒットします。

暗黙的キャッシュ

サポート対象モデル

  • 中国 (北京)
  • シンガポール
  • 米国 (バージニア)
  • ドイツ (フランクフルト)
  • 中国 (香港)
  • 日本 (東京)
  • テキスト生成モデル
    • Qwen Max: qwen3.8-max, qwen3.7-max, qwen3.7-max-2026-05-20, qwen3.7-max-2026-06-08, qwen-max
    • Qwen Plus: qwen3.7-plus, qwen3.7-plus-2026-05-26, qwen-plus
    • Qwen Flash: qwen3.8-flash, qwen3.7-flash, qwen3.7-flash-2026-07-15, qwen-flash
    • Qwen Coder: qwen3-coder-flash
    • Qwen Open-source: qwen3.8-2.4t-a95b, qwen3.8-27b
    • DeepSeek: deepseek-v4-pro, deepseek-v4.1-flash-1017
    • Kimi: kimi-k3.1-pro, kimi-k2.7-code, kimi-k2.6, kimi-k2.5
    • GLM: glm-5.2, glm-5.2-fast-preview, glm-5.1, glm-5
    • MiniMax: MiniMax-M2.5
  • 視覚理解モデル
    • Qwen VL: qwen3-vl-plus

仕組み

暗黙的キャッシュ機能は、サポートされているモデルにリクエストが送信されると自動的に有効になります。システムの動作は次のとおりです:
  1. 検索:リクエストを受信した後、システムはプレフィックスマッチングを使用して、リクエストの messages 配列のコンテンツの共通プレフィックスをキャッシュで確認します。
  2. 決定:
    • キャッシュヒットが発生した場合、システムは残りの推論にキャッシュされた結果を使用します。
    • キャッシュミスが発生した場合、システムはリクエストを通常どおり処理し、将来のリクエストのためにプロンプトのプレフィックスをキャッシュに保存します。
システムは、長期間使用されていないキャッシュデータを定期的にクリアします。コンテキストキャッシュのヒット確率は 100% ではありません。リクエストのコンテキストが同一であっても、キャッシュミスが発生する可能性があります。システムが特定のヒット確率を決定します。
暗黙的キャッシュをトリガーするために必要な最小トークン数は、Qwen3.7 モデルでは約 2000、その他のモデルでは 256 です。

キャッシュヒット確率の向上

暗黙的キャッシュヒットは、異なるリクエストのプレフィックスに重複するコンテンツがある場合に発生します。ヒット確率を高めるには、重複するコンテンツをプロンプトの先頭に、一意のコンテンツを末尾に配置します。
  • テキストモデル:例えば、システムが「ABCD」をキャッシュしたとします。「ABE」のリクエストは「AB」の部分にヒットする可能性がありますが、「BCD」のリクエストはヒットしません。
  • 視覚理解モデル:
    • 同じ画像または動画について複数の質問をするには、画像または動画をテキストの前に配置します。
    • 異なる画像または動画について同じ質問をするには、テキストを画像または動画の前に配置します。

課金

暗黙的キャッシュモードを有効にしても、追加料金は発生しません。 リクエストがキャッシュにヒットすると、キャッシュヒットからの入力トークンは cached_token として課金されます。これらのトークンの割引率は、モデルによって異なります。キャッシュにヒットしなかった入力トークンは、標準の input_token として課金されます。出力トークンは元の価格で課金されます。
  • deepseek-v4.1-flash、deepseek-v4.1-flash-1017、deepseek-v4-pro、qwen3.8-max、qwen3.8-flash、および qwen3.8-2.4t-a95b 以外のモデルの場合:cached_token の単価は、input_token 単価の 20% です。
  • deepseek-v4-pro:cached_token の単価は、input_token 単価の 20% ではありません。具体的な価格については、Model Studio コンソールをご参照ください。
  • deepseek-v4.1-flash および deepseek-v4.1-flash-1017:cached_token は固定単価で課金され、すべてのリージョンで 100 万トークンあたり $0.003(オフピーク時間帯)、$0.006(ピーク時間帯)です。
  • qwen3.8-max、qwen3.8-flash、および qwen3.8-2.4t-a95b:cached_token の単価は、input_token 単価の 20% ではありません。具体的な価格については、Model Studio コンソールをご参照ください。
  • GLM (Alibaba Cloud Model Studio にデプロイ):glm-5.2 および glm-5.2-fast-preview は 25%、その他のすべての GLM シリーズモデルは 20% です。
例:リクエストに 10,000 の入力トークンが含まれ、そのうち 5,000 がキャッシュヒットしたとします。コストは次のように計算されます:
  • 非キャッシュヒットトークン (5,000):単価の 100% で課金されます。
  • キャッシュヒットトークン (5,000):単価の 20% で課金されます。
総入力コストは、非キャッシュモードのコストの 60% です:(50% × 100%) + (50% × 20%) = 60%。
image.png
キャッシュヒットしたトークンの数は、応答の cached_tokens 属性から取得できます。
OpenAI 互換 - バッチ (ファイル入力) メソッドを使用して行われた呼び出しは、キャッシュ割引の対象外です。

キャッシュヒットの例

  • テキスト生成モデル
  • 視覚理解モデル
  • OpenAI 互換
  • DashScope
  • Anthropic 互換
OpenAI 互換メソッドを使用してモデルを呼び出し、暗黙的キャッシュがトリガーされると、応答は usage.prompt_tokens_details.cached_tokens フィールドでキャッシュにヒットしたトークンの数を示します。この値は usage.prompt_tokens の一部です。
{
    "choices": [
        {
            "message": {
                "role": "assistant",
                "content": "I am a large-scale language model developed by Alibaba Cloud. My name is Qwen."
            },
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null
        }
    ],
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 3019,
        "completion_tokens": 104,
        "total_tokens": 3123,
        "prompt_tokens_details": {
            "cached_tokens": 2048
        }
    },
    "created": 1735120033,
    "system_fingerprint": null,
    "model": "qwen-plus",
    "id": "chatcmpl-6ada9ed2-7f33-9de2-8bb0-78bd4035025a"
}

ユースケース

リクエストが共通のプレフィックスを共有している場合、コンテキストキャッシュは推論速度を大幅に向上させ、推論コストを削減し、最初のパケットのレイテンシを短縮できます。この機能は、特に以下のユースケースで役立ちます:
  1. 長文テキストの質疑応答 小説、教科書、法的文書など、同じ長文テキストについて複数のリクエストを送信する場合にこのパターンを使用します。 最初のリクエストメッセージ
messages = [{"role": "system","content": "You are a language teacher who can help students with reading comprehension."},
          {"role": "user","content": "
後続のリクエストの messages 配列
messages = [{"role": "system","content": "You are a language arts teacher. You can help students with reading comprehension."},
          {"role": "user","content": "<Article content> Please analyze the third paragraph of this text."}]
質問は異なりますが、すべて同じ記事に基づいています。同じシステムプロンプトと記事の内容が大量の反復的なプレフィックス情報を構成し、キャッシュヒットの確率が高くなります。 2. コード自動補完 コード自動補完シナリオでは、モデルは周囲のコードをコンテキストとして使用して後続のコードを生成します。記述するにつれて、コードファイルの先頭は同じままです。コンテキストキャッシュはこのプレフィックスを保存して、コード補完を高速化できます。 3. マルチターン対話 マルチターン対話の場合、各ターンを messages 配列に追加します。これにより、各新しいリクエストが前のターンと共通のプレフィックスを共有し、キャッシュヒットの可能性が高まります。 最初のターンの messages
messages=[{"role": "system","content": "You are a helpful assistant."},
          {"role": "user","content": "Who are you?"}]
2 番目のターンの messages
messages=[{"role": "system","content": "You are a helpful assistant."},
          {"role": "user","content": "Who are you?"},
          {"role": "assistant","content": "I am Qwen, developed by Alibaba Cloud."},
          {"role": "user","content": "What can you do?"}]
対話が長くなるにつれて、推論速度とコストに対するキャッシュの利点がより顕著になります。 4. ロールプレイングまたはフューショット学習 ロールプレイングまたはフューショット学習シナリオでは、モデルの出力形式をガイドするために、プロンプトに広範な指示を含めることがよくあります。これにより、複数のリクエストにわたって大きな共有プレフィックスが作成されます。 例えば、モデルにマーケティングの専門家として行動するよう指示する場合、システムプロンプトには広範なテキストが含まれます。以下は 2 つのリクエスト例です:
system_prompt = """You are an experienced marketing expert. Provide detailed marketing suggestions for different products in the following format:

1. Target audience: xxx

2. Main selling points: xxx

3. Marketing channels: xxx
...
12. Long-term development strategy: xxx

Ensure your suggestions are specific, actionable, and highly relevant to the product features."""

# 最初のリクエストのユーザーメッセージはスマートウォッチについて尋ねます。
messages_1=[
  {"role": "system", "content": system_prompt},
  {"role": "user", "content": "Provide marketing suggestions for a newly launched smartwatch."}
]

# 2 番目のリクエストのユーザーメッセージはラップトップについて尋ねます。system_prompt が同じであるため、キャッシュヒットの可能性が非常に高いです。
messages_2=[
  {"role": "system", "content": system_prompt},
  {"role": "user", "content": "Provide marketing suggestions for a newly launched laptop."}
]
コンテキストキャッシュを使用すると、リクエストの製品を頻繁に変更しても (例えば、スマートウォッチからラップトップへ)、長いシステムプロンプトがキャッシュされるため、システムはより速く応答できます。 5. 動画理解 動画理解シナリオでは、同じ動画について複数の質問をする場合、video を text の前に配置するとキャッシュヒットの確率が高まります。異なる動画について同じ質問をする場合、text を video の前に配置するとキャッシュヒットの確率が高まります。次の例は、同じ動画に対する 2 つのリクエストを示しています:
# 最初のリクエストのユーザーメッセージは、この動画の内容について尋ねます。
messages1 = [
    {"role":"system","content":[{"text": "You are a helpful assistant."}]},
    {"role": "user",
        "content": [
            {"video": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250328/eepdcq/phase_change_480p.mov"},
            {"text": "What is the content of this video?"}
        ]
    }
]

# 同じ動画に関する 2 番目のリクエストでは、動画をテキストの前に配置するとキャッシュヒットの可能性が高まります。
messages2 = [
    {"role":"system","content":[{"text": "You are a helpful assistant."}]},
    {"role": "user",
        "content": [
            {"video": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250328/eepdcq/phase_change_480p.mov"},
            {"text": "Describe the series of events in the video. Output the start time (start_time), end time (end_time), and event (event) in JSON format. Do not include the ```json``` code block."}
        ]
    }
]

よくある質問

Q:コンテキストキャッシュはどのくらいの期間保持されますか (有効期間)?

A:コンテキストキャッシュの有効期間は、キャッシュの種類によって異なります:
  • 明示的キャッシュ:有効期間は 5 分で、キャッシュヒットごとにさらに 5 分にリセットされます。キャッシュブロックが 5 分以内にヒットしない場合、システムは自動的にクリアします。
  • 暗黙的キャッシュ:システムによって自動的に管理され、固定の有効期間はありません。システムは、長期間使用されていないキャッシュデータを定期的にクリアします。
この有効期間は、API 呼び出し中のコンテキストキャッシュのライフサイクルを指します。コンソールのモデル体験またはモデルデバッグページに表示される対話履歴と同じ機能ではありません。

Q:暗黙的キャッシュを無効にするにはどうすればよいですか?

A:無効にすることはできません。暗黙的キャッシュは、応答品質に影響を与えないため、すべての適用可能なモデルリクエストで有効になっています。キャッシュヒットが発生すると、コストが削減され、応答速度が向上します。

Q:明示的キャッシュがミスしたのはなぜですか?

A:キャッシュミスは、以下の理由で発生する可能性があります:
  • システムは、5 分の有効期間内にヒットしない場合、キャッシュブロックをクリアします。
  • 最後の content と既存のキャッシュブロックの間隔が 20 content ブロックを超える場合、キャッシュヒットは発生しません。新しいキャッシュブロックを作成することをお勧めします。

Q:キャッシュヒットで有効期間はリセットされますか?

A:はい。各ヒットで、キャッシュブロックの有効期間が 5 分にリセットされます。

Q:明示的キャッシュはアカウント間で共有されますか?

A:いいえ。暗黙的キャッシュと明示的キャッシュの両方のデータは、アカウントレベルで分離されています。

Q:明示的キャッシュはモデル間で共有されますか?

A:いいえ。キャッシュデータはモデル間で分離されています。

Q:なぜusageのinput_tokensがcache_creation_input_tokensとcached_tokensの合計と等しくないのですか?

A:モデルの出力品質を確保するため、バックエンドサービスはプロンプトに少数のトークン (通常は 10 以下) を追加します。これらのトークンは cache_control マーカーの後に配置されるため、キャッシュの作成や読み取りにはカウントされませんが、合計の input_tokens には含まれます。