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

# トークン使用量

すべてのLLMレスポンスには、そのリクエストが消費したトークンを報告する`usage`オブジェクトが含まれます。Sunraは、呼び出したendpointのセマンティクスに従って使用量を報告します。Messagesのレスポンスは Anthropic の契約に従い、Chat Completions または Responses のレスポンスは OpenAI の契約に従います。

これらの形状が異なるのは意図的なものです。Chat Completionsのレスポンスを読むOpenAI SDKはOpenAIのセマンティクスを前提とし、Messagesのレスポンスを読むAnthropic SDKはAnthropicのセマンティクスを前提とします。各endpointは、単一の共通形状に押し込められるのではなく、それぞれの仕様が約束する内容を尊重します。

| Endpoint               | プロンプト数のフィールド    | キャッシュされたトークンはそこに含まれるか？                                     |
| ---------------------- | --------------- | ---------------------------------------------------------- |
| `/v1/messages`         | `input_tokens`  | いいえ — 3つの入力バケットは相互排他的です                                    |
| `/v1/chat/completions` | `prompt_tokens` | はい — キャッシュされたトークンは部分集合であり、`prompt_tokens_details`に詳細が示されます |
| `/v1/responses`        | `input_tokens`  | はい — キャッシュされたトークンは部分集合であり、`input_tokens_details`に詳細が示されます  |

<Warning>
  `/v1/messages`と`/v1/responses`はどちらも`input_tokens`というフィールド名を使用しますが、両者で意味は同じではありません。Messagesでは新規入力のみを指します。Responsesではキャッシュされたトークンを含むプロンプト全体を指します。
</Warning>

## Messages

`/v1/messages`では、3つの入力バケットは**相互排他的**です。同じトークンが二重に数えられることはないため、プロンプトの合計はそれらの和になります。

```
total prompt = input_tokens + cache_creation_input_tokens + cache_read_input_tokens
```

<ResponseField name="input_tokens" type="integer">
  新規の入力トークンのみ。両方のキャッシュバケットを除きます。
</ResponseField>

<ResponseField name="cache_creation_input_tokens" type="integer">
  このリクエストによってキャッシュに書き込まれたトークン。
</ResponseField>

<ResponseField name="cache_read_input_tokens" type="integer">
  キャッシュからこのリクエストに提供されたトークン。
</ResponseField>

<ResponseField name="output_tokens" type="integer">
  モデルが生成したトークン。
</ResponseField>

<ResponseField name="total_tokens" type="integer">
  3つの入力バケットと`output_tokens`の合計。非streamingのレスポンスに存在します。
</ResponseField>

存在しないバケットや`null`のバケットはゼロとして扱われます。

### 実例

同じ19,000トークンのプレフィックスを`claude-opus-4-8`に対して2回送信した場合。1回目のリクエストはキャッシュを書き込み、2回目はそれを読み取ります。

```json コールドリクエスト（キャッシュ書き込み） theme={null}
{
  "usage": {
    "input_tokens": 8,
    "cache_creation_input_tokens": 19349,
    "cache_read_input_tokens": 0,
    "output_tokens": 2,
    "total_tokens": 19359,
    "sunra_usage_semantics": "anthropic.exclusive.v1"
  }
}
```

```json ウォームリクエスト（キャッシュ読み取り） theme={null}
{
  "usage": {
    "input_tokens": 8,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 19349,
    "output_tokens": 2,
    "total_tokens": 19359,
    "sunra_usage_semantics": "anthropic.exclusive.v1"
  }
}
```

`input_tokens`は両方のリクエストで8のままです。8が毎回の真に新しい入力だからです。19,349トークンのプレフィックスは、作成バケットから読み取りバケットへ移動します。どちらのリクエストも合計は同じ19,359トークンになりますが、コストは同じではありません。キャッシュ書き込みとキャッシュ読み取りはそれぞれ独自のトークン単価で課金されるため、別々のバケットとして報告されています。

## Chat Completions と Responses

これらのendpointは、OpenAIのセマンティクスをそのまま報告します。プロンプト数は**プロンプト全体**であり、キャッシュされたトークンはその**部分集合**として別途報告されます。

```json /v1/chat/completions theme={null}
{
  "usage": {
    "prompt_tokens": 19357,
    "completion_tokens": 2,
    "total_tokens": 19359,
    "prompt_tokens_details": {
      "cached_tokens": 19349
    }
  }
}
```

`prompt_tokens`と`cached_tokens`を足し合わせると二重計上になります。これらのendpointで新規入力を求めるには、次のように引き算します。

```
fresh input = prompt_tokens - prompt_tokens_details.cached_tokens
```

同じルールが、`input_tokens`と`input_tokens_details.cached_tokens`を持つ`/v1/responses`にも適用されます。

## `sunra_usage_semantics`マーカー

Sunraが正規化したレスポンスには、`usage`の内部にマーカーが含まれます。

```json theme={null}
"sunra_usage_semantics": "anthropic.exclusive.v1"
```

このマーカーは**レスポンス**についての約束であり、個々のイベントやフィールドについての約束ではありません。非streamingのレスポンスではルートの`usage`オブジェクトに現れ、streamingのレスポンスでは入力バケットを運ぶイベントである`message_start`に現れます。この値とともに存在する場合、このページに記載された保証が成り立ちます。すなわち、3つの入力バケットは相互排他的であり、`total_tokens`は — 存在する場合 — それらの和に`output_tokens`を加えた値です。

**マーカーが存在しないことも、また約束です。** Sunraが正規化するのは、実測したレスポンス形状のみです。それ以外はアップストリームのプロバイダーからそのまま転送され、マーカーは付きません。マーカーのないレスポンスは、そのバケットについてSunraが保証しないレスポンスです。

レスポンスがどの規約に従っているかを数値から推測するのではなく、マーカーに対してアサートしてください。形状の推測こそ、このフィールドが置き換えるために存在するものです。「バケットの合計がプロンプト数を超えているのだから相互排他的に違いない」といったヒューリスティックは複数の規約で成立してしまい、いずれレスポンスを読み違えます。

```python theme={null}
usage = response["usage"]

if usage.get("sunra_usage_semantics") == "anthropic.exclusive.v1":
    total_prompt = (
        usage["input_tokens"]
        + usage.get("cache_creation_input_tokens", 0)
        + usage.get("cache_read_input_tokens", 0)
    )
else:
    # Not normalized by Sunra. Treat the upstream shape as unverified
    # and consult that provider's own documentation.
    total_prompt = None
```

マーカーが付くのは`/v1/messages`のレスポンスのみです。Chat CompletionsとResponsesはOpenAIの仕様に従っており、マーカーは付きません。

この値はバージョン管理されています。これらのフィールドの意味に破壊的変更が入る場合は新しい値で出荷されるため、`anthropic.exclusive.v1`との等価チェックが黙って別の契約を読み始めることはありません。

## Streaming

streamingのMessagesリクエストでは、使用量は2つのイベントに分かれて届きます。`message_start`が入力側とマーカーを運びます。終端の`message_delta`が運ぶのは`output_tokens`のみです。マーカーへのアサートは`message_start`で行い、そのうえで通常どおり2つのイベントをマージすれば — 後のイベントの使用量を先のイベントに上書きする — 上記に記載した値が得られます。

`total_tokens`はstreamingのレスポンスでは省略されます。入力側と出力側の両方を知っている単一のイベントは存在しないため、ストリームの途中で計算した合計はいずれも誤りになります。ストリームが完了してから、ご自身でバケットを合算してください。

## 以前の挙動からの移行

Sunraは以前、`/v1/messages`においてアップストリームの`usage`オブジェクトをそのまま転送していました。一部のプロバイダーの前段にある変換レイヤーは、キャッシュ作成トークンを`input_tokens`の**中に**畳み込みます。そのため、Anthropicの契約に従って3つのバケットを合算した呼び出し側は、キャッシュ作成トークンを二重に数えていました。

* **3つのバケットを合算している場合**、Anthropicの契約が記述するとおりであり、現在は正しい結果になります。お客様側での変更は不要です。
* **以前の挙動を補正していた場合** — `input_tokens`から`cache_creation_input_tokens`を自分で引いていた、あるいは畳み込みを何らかの形でリバースエンジニアリングしていた場合 — **やめてください**。その補正は、すでに除外済みのトークンを引くことになり、入力を過小に見積もります。
* **`total_tokens`を読んでいる場合**、これは引き続き全体の数を報告します。新規入力、両方のキャッシュバケット、そして出力です。

デプロイ日ではなくマーカーで変更を分岐させてください。そうすれば、マーカー付きのレスポンスと付いていないレスポンスの両方に対して、同じコードパスが正しく動作します。
