> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arouter.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# プロンプトキャッシング

> 繰り返されるプロンプトのプレフィックスをキャッシュしてコストとレイテンシを削減します。OpenAI、Anthropic、DeepSeek、Google Gemini で対応しています。

プロンプトキャッシングにより、プロバイダーは以前に処理したプロンプトコンテンツを再利用できます。プロンプトの先頭が以前にキャッシュされたプレフィックスと一致する場合、プロバイダーはそれらのトークンの再処理をスキップします——コストとレイテンシの両方を大幅に削減します。

## キャッシュ使用状況の確認

キャッシュの使用状況はすべてのレスポンスの `usage` オブジェクトに反映されます：

```json theme={null}
{
  "usage": {
    "prompt_tokens": 1500,
    "completion_tokens": 100,
    "total_tokens": 1600,
    "prompt_tokens_details": {
      "cached_tokens": 1024,
      "cache_write_tokens": 476
    },
    "completion_tokens_details": {
      "reasoning_tokens": 0
    }
  }
}
```

| フィールド                                      | 説明                                     |
| ------------------------------------------ | -------------------------------------- |
| `prompt_tokens_details.cached_tokens`      | キャッシュから読み取られたトークン（キャッシュヒット——安い）        |
| `prompt_tokens_details.cache_write_tokens` | このリクエストでキャッシュに書き込まれたトークン（一回限りの書き込みコスト） |

## OpenAI 自動キャッシング

OpenAI はプロンプトプレフィックスを自動的にキャッシュします。特別なリクエスト設定は不要です。

**仕組み：**

* キャッシングは OpenAI のサーバー側で、プロンプトが十分長い場合に自動的にトリガーされます
* 最小プロンプト長：1,024 トークン
* キャッシュエントリは約 1 時間の非アクティブ後に期限切れになります
* キャッシュされたトークンは割引料金で課金されます（通常 50% 割引）

```python theme={null}
from openai import OpenAI

client = OpenAI(
    base_url="https://api.arouter.ai/v1",
    api_key="lr_live_xxxx",
)

# 繰り返し呼び出すと、長いシステムプロンプトは自動的にキャッシュされる
response = client.chat.completions.create(
    model="openai/gpt-5.4",
    messages=[
        {
            "role": "system",
            "content": "You are an expert assistant. " + "<long context>" * 100,
        },
        {"role": "user", "content": "Summarize the above."},
    ],
)

print(response.usage.prompt_tokens_details)
# PromptTokensDetails(cached_tokens=1024, audio_tokens=0)
```

## Anthropic Claude プロンプトキャッシング

Anthropic は 2 つのキャッシングモードをサポートしています：

* **自動キャッシング**（デフォルト）：Claude がシステムプロンプトを自動的にキャッシュします。最低 1,024 トークン。
* **明示的キャッシング**（`cache_control`）：`"cache_control": {"type": "ephemeral"}` で特定のコンテンツブロックをマークして、キャッシュする内容を正確に制御します。

### キャッシュ TTL

| キャッシュタイプ         | TTL                                |
| ---------------- | ---------------------------------- |
| 自動               | 5 分                                |
| 明示的（`ephemeral`） | 1 時間（Claude 3.5+）または 5 分（Claude 3） |

### サポートされるモデル

| モデル                           | 最小トークン（テキスト） | 最小トークン（画像） |
| ----------------------------- | ------------ | ---------- |
| `anthropic/claude-sonnet-4.6` | 1,024        | 1,024      |
| `anthropic/claude-opus-4.5`   | 1,024        | 1,024      |
| `anthropic/claude-haiku-3.5`  | 2,048        | 2,048      |
| `anthropic/claude-3-5-sonnet` | 1,024        | 1,024      |

### 明示的キャッシングの例

`cache_control` を使用してコンテンツブロックレベルでキャッシングを制御します：

```json theme={null}
{
  "model": "claude-sonnet-4.6",
  "system": [
    {
      "type": "text",
      "text": "You are a helpful assistant with access to the following reference document:\n\n<document>...</document>",
      "cache_control": { "type": "ephemeral" }
    }
  ],
  "messages": [
    { "role": "user", "content": "What does the document say about pricing?" }
  ],
  "max_tokens": 1024
}
```

OpenAI 互換エンドポイントでは、`extra_body` を通じて渡します：

<Tabs>
  <Tab title="Python (OpenAI)">
    ```python theme={null}
    from openai import OpenAI

    client = OpenAI(
        base_url="https://api.arouter.ai/v1",
        api_key="lr_live_xxxx",
    )

    long_document = "<document content here>" * 50  # 1024 トークン以上を確保

    response = client.chat.completions.create(
        model="anthropic/claude-sonnet-4.6",
        messages=[
            {
                "role": "system",
                "content": [
                    {
                        "type": "text",
                        "text": f"Reference document:\n\n{long_document}",
                        "cache_control": {"type": "ephemeral"},
                    }
                ],
            },
            {"role": "user", "content": "Summarize the key points."},
        ],
    )

    print(response.usage)
    # Usage(prompt_tokens=1500, completion_tokens=80, total_tokens=1580,
    #   prompt_tokens_details=PromptTokensDetails(cached_tokens=1024, cache_write_tokens=476))
    ```
  </Tab>

  <Tab title="Node.js (OpenAI)">
    ```typescript theme={null}
    import OpenAI from "openai";

    const client = new OpenAI({
      baseURL: "https://api.arouter.ai/v1",
      apiKey: "lr_live_xxxx",
    });

    const longDocument = "<document content here>".repeat(50);

    const response = await client.chat.completions.create({
      model: "anthropic/claude-sonnet-4.6",
      messages: [
        {
          role: "system",
          content: [
            {
              type: "text",
              text: `Reference document:\n\n${longDocument}`,
              // @ts-ignore — cache_control は Anthropic 固有
              cache_control: { type: "ephemeral" },
            },
          ],
        },
        { role: "user", content: "Summarize the key points." },
      ],
    });

    console.log(response.usage?.prompt_tokens_details);
    // { cached_tokens: 1024, cache_write_tokens: 476 }
    ```
  </Tab>

  <Tab title="Anthropic SDK">
    ```python theme={null}
    import anthropic

    client = anthropic.Anthropic(
        base_url="https://api.arouter.ai",
        api_key="lr_live_xxxx",
    )

    long_document = "<document content here>" * 50

    response = client.messages.create(
        model="claude-sonnet-4.6",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": f"Reference document:\n\n{long_document}",
                "cache_control": {"type": "ephemeral"},
            }
        ],
        messages=[
            {"role": "user", "content": "Summarize the key points."}
        ],
    )

    print(response.usage)
    # Usage(input_tokens=1500, output_tokens=80,
    #   cache_creation_input_tokens=1024, cache_read_input_tokens=0)

    # 2 回目の呼び出し——書き込みではなくキャッシュから読み取り
    response2 = client.messages.create(
        model="claude-sonnet-4.6",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": f"Reference document:\n\n{long_document}",
                "cache_control": {"type": "ephemeral"},
            }
        ],
        messages=[
            {"role": "user", "content": "What's the main topic?"}
        ],
    )

    print(response2.usage)
    # Usage(input_tokens=476, output_tokens=40,
    #   cache_creation_input_tokens=0, cache_read_input_tokens=1024)
    ```
  </Tab>
</Tabs>

## DeepSeek 自動キャッシング

DeepSeek は OpenAI と同様に、プロンプトプレフィックスを自動的にキャッシュします。設定は不要です。

```python theme={null}
client = OpenAI(
    base_url="https://api.arouter.ai/v1",
    api_key="lr_live_xxxx",
)

# DeepSeek は同じプレフィックスで繰り返し呼び出すと自動的にキャッシュ
response = client.chat.completions.create(
    model="deepseek/deepseek-v3.2",
    messages=[
        {"role": "system", "content": "<long context>" * 100},
        {"role": "user", "content": "Analyze the above."},
    ],
)

# usage でキャッシュヒットを確認
print(response.usage.prompt_tokens_details.cached_tokens)
```

## xAI（Grok）自動キャッシング

Grok モデルはリクエスト間で同じプレフィックスを再利用する際に、プロンプトプレフィックスを自動的にキャッシュします。特別な設定は不要です。

```python theme={null}
client = OpenAI(
    base_url="https://api.arouter.ai/v1",
    api_key="lr_live_xxxx",
)

# Grok は同じプレフィックスで繰り返し呼び出すと自動的にキャッシュ
response = client.chat.completions.create(
    model="x-ai/grok-4.20",
    messages=[
        {"role": "system", "content": "<long system prompt>" * 100},
        {"role": "user", "content": "Answer the question."},
    ],
)

# キャッシュヒットは usage に反映される
print(response.usage.prompt_tokens_details)
```

## Groq 自動キャッシング

Groq の推論インフラは対応モデルのプロンプトプレフィックスを自動的にキャッシュします。キャッシュヒットはレイテンシを削減し、レスポンスの usage オブジェクトに反映されます。

```python theme={null}
client = OpenAI(
    base_url="https://api.arouter.ai/v1",
    api_key="lr_live_xxxx",
)

# Groq は繰り返し呼び出すと自動的にキャッシュ
response = client.chat.completions.create(
    model="groq/meta-llama/llama-4-maverick",
    messages=[
        {"role": "system", "content": "<long context>" * 100},
        {"role": "user", "content": "Analyze the above."},
    ],
)

print(response.usage.prompt_tokens_details.cached_tokens)
```

## Google Gemini プロンプトキャッシング

Gemini は暗黙的（自動）および明示的キャッシングの両方をサポートしています。

### 暗黙的キャッシング

Gemini 2.5 Flash と Pro は追加コストなしで大きなコンテキストを自動的にキャッシュします。キャッシュヒットはレスポンスの usage に表示されます。

### ネイティブ Gemini API による明示的キャッシング

細かい制御のためには、ネイティブの Gemini `cachedContents` API を使用します。キャッシュオブジェクトを作成し、後続のリクエストで参照します：

```json theme={null}
{
  "model": "models/gemini-2.5-flash",
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "What are the key points in this document?"
        }
      ]
    }
  ],
  "cachedContent": "cachedContents/abc123"
}
```

ARouter のプロバイダープロキシを経由してネイティブ Gemini エンドポイントを使用してキャッシュされたコンテンツを操作します：

```bash theme={null}
# キャッシュされたコンテンツを作成
curl https://api.arouter.ai/google/v1beta/cachedContents \
  -X POST \
  -H "Authorization: Bearer lr_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "models/gemini-2.5-flash",
    "contents": [
      {
        "role": "user",
        "parts": [{"text": "<large document content>"}]
      }
    ],
    "ttl": "3600s"
  }'
```

レスポンスには後続のリクエストで参照する `name` フィールド（例：`cachedContents/abc123`）が含まれます：

```bash theme={null}
curl https://api.arouter.ai/google/v1beta/models/gemini-2.5-flash:generateContent \
  -X POST \
  -H "Authorization: Bearer lr_live_xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{"role": "user", "parts": [{"text": "Summarize"}]}],
    "cachedContent": "cachedContents/abc123"
  }'
```

キャッシュ使用状況はレスポンスに表示されます：

```json theme={null}
{
  "usageMetadata": {
    "promptTokenCount": 200,
    "cachedContentTokenCount": 1500,
    "candidatesTokenCount": 50,
    "totalTokenCount": 250
  }
}
```

## プロバイダースティッキールーティング

キャッシュヒット率を最大化するには、繰り返しのリクエストが**同じプロバイダーインスタンス**に届く必要があります。ARouter はスティッキールーティングをサポートして、必要なプロバイダーにこれを保証します。

リクエストに Anthropic の `cache_control` ブロックが含まれている場合、ARouter は同じプレフィックスを持つ後続のリクエストを自動的に同じプロバイダーエンドポイントにルーティングし、キャッシュの有効性を維持します。

### スティッキールーティングの仕組み

1. `cache_control` ブロックを含む最初のリクエストがプロバイダーで処理されキャッシュされます
2. ARouter はリクエストを処理したプロバイダーインスタンスを記録します
3. 同じキャッシュプレフィックスを持つ後続のリクエストが同じインスタンスにルーティングされます
4. キャッシュヒットによりコストが下がり（読み取りは書き込みより安い）レイテンシが減少します

### キャッシュヒットの確認

`usage` オブジェクトを確認してリクエスト間のキャッシュヒットを確認します：

```python theme={null}
# 最初のリクエスト——キャッシュミス、コンテンツが書き込まれる
response1 = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[
        {"role": "system", "content": [{"type": "text", "text": long_doc, "cache_control": {"type": "ephemeral"}}]},
        {"role": "user", "content": "Question 1"},
    ],
)
# prompt_tokens_details.cache_write_tokens > 0
print(response1.usage.prompt_tokens_details)

# 2 回目のリクエスト——キャッシュヒット
response2 = client.chat.completions.create(
    model="anthropic/claude-sonnet-4.6",
    messages=[
        {"role": "system", "content": [{"type": "text", "text": long_doc, "cache_control": {"type": "ephemeral"}}]},
        {"role": "user", "content": "Question 2"},
    ],
)
# prompt_tokens_details.cached_tokens > 0（キャッシュヒット！）
print(response2.usage.prompt_tokens_details)
```

## プロバイダーキャッシュサポートの概要

| プロバイダー        | キャッシュタイプ | 最小トークン   | TTL               | 設定                   |
| ------------- | -------- | -------- | ----------------- | -------------------- |
| OpenAI        | 自動       | 1,024    | 約 1 時間            | 不要                   |
| Anthropic     | 自動 + 明示的 | 1,024    | 5 分（自動）、1 時間（明示的） | `cache_control` ブロック |
| DeepSeek      | 自動       | 1,024    | プロバイダー定義          | 不要                   |
| Google Gemini | 自動 + 明示的 | 32,768   | デフォルト 1 時間        | `cachedContents` API |
| xAI（Grok）     | 自動       | プロバイダー定義 | プロバイダー定義          | 不要                   |
| Groq          | 自動       | プロバイダー定義 | プロバイダー定義          | 不要                   |
