Claude Media
Claude Citationsのトークンコストの仕組み — cited_textが出力トークンに数えられない理由

Claude Citationsのトークンコストの仕組み — cited_textが出力トークンに数えられない理由

Citationsは入力トークンをわずかに増やす一方、応答に含まれるcited_textは出力トークン・再送信時の入力トークンのどちらにも数えられません。課金ロジックと自前プロンプトとの費用差を検算します。

Citationsを有効にすると入力トークンはどう変わるか

Citationsは、Claudeの回答に文書中の該当箇所を具体的な引用として添える機能です。ドキュメントブロックにcitations.enabled: trueを指定すると、Claudeが述べた主張に、根拠となる文書内の位置情報が付いたテキストブロックで応答が返ります。稼働中のすべてのモデルが対応し、Claude API本体のほか、Amazon Bedrock、Google Cloud、Microsoft Foundryでも提供されています。

コストへの影響はまず入力側に出ます。Citationsを有効にすると、システムプロンプトへの追加分と、ドキュメントの内部的なチャンク分割(文単位への区切り)のぶんだけ、入力トークンがわずかに増えます。Citationsのドキュメントには、増加は「わずか」とあるだけで、割合の数値は載っていません。自分の文書での実際の増加は、リクエストの前にToken Counting APIで測れます(手順は後半の節で扱います)。

入力側の増加は小さく、出力側の削減が本題です。

curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 1024,
    "messages": [{
      "role": "user",
      "content": [
        {
          "type": "document",
          "source": {
            "type": "text",
            "media_type": "text/plain",
            "data": "The grass is green. The sky is blue."
          },
          "title": "My Document",
          "citations": {"enabled": true}
        },
        {"type": "text", "text": "What color is the grass and sky?"}
      ]
    }]
  }'

cited_textが出力トークンに数えられない仕組み

Citationsを有効にした応答では、モデルが標準化された形式で引用位置を出力します。それをAPIがパースし、cited_text(引用元テキスト本体)と文書内の位置情報に分けてレスポンスへ載せます。

ここが課金上の分岐点です。cited_textは応答を読みやすくするために添えられる項目で、出力トークンとしてカウントされません。応答は1つの長い文章ではなく、textブロックの連なりとして返ります。

{
  "content": [
    { "type": "text", "text": "According to the document, " },
    {
      "type": "text",
      "text": "the grass is green",
      "citations": [
        {
          "type": "char_location",
          "cited_text": "The grass is green.",
          "document_index": 0,
          "document_title": "My Document",
          "start_char_index": 0,
          "end_char_index": 20
        }
      ]
    },
    { "type": "text", "text": " and " }
  ]
}

Claudeが書いた本文は各textブロックのtextにあり、根拠の抜粋はcitations配列のcited_textにあります。抜粋がどれだけ長くても、cited_textのぶんはusage.output_tokensに加わりません。モデルが出力するのは標準形式の引用で、cited_textはそこからAPIが組み立てて添える項目です。長い引用を何箇所も返す用途ほど、非課金の効果は相対的に大きくなります。

ストリーミングでは、引用はcontent_block_deltaイベントの中でcitations_deltaという種別で届きます。1つのデルタが1件の引用で、現在のtextブロックのcitationsリストに追加されます。地の文はtext_deltaで流れるため、クライアントでは両者を別々に扱います。

会話を続けてもcited_textは入力トークンに戻らない

もう一段効くのが複数ターンの会話です。前の応答をそのまま次のターンの入力に含めると、通常はその全文が入力トークンとして再び課金されます。

Citationsはここでも例外です。前のターンのcited_textを含む応答を次のリクエストに載せても、cited_textは入力トークンとして数えられません。長い文書から引用を重ねながら対話するRAG(検索拡張生成)型のアプリでは、この差がターンごとに積み上がります。

差の大きさは、引用の量とターン数の掛け算で決まります。次の数字は検算用に置いた仮定です。1回の応答に300トークン分の引用が5箇所あり、10ターン続くとします。

数字

逐語引用で10ターン続けたときの引用ぶんのトークン

  • 出力トークン

    15,000

    1,500トークン×10ターン

  • 再送される入力トークン

    67,500

    1,500×(0+1+…+9)=1,500×45

  • 引用ぶんの合計

    82,500

    出力と入力は単価が違うので、合計は規模の目安

仮定: 1回300トークン×5箇所の引用、履歴を毎ターン全文再送。Citationsでは、このうち引用の抜粋ぶんがどちらも数えられません

入力側の67,500トークンは、履歴をPrompt Cachingで読み出している構成なら再送ぶんの単価が下がるため、実際の金額は構成で変わります。それでも、出力と再送の両方から引用が外れる点は変わりません。

プロンプトで逐語引用させる方法と何が違うか

Citationsを使わなくても、「該当箇所を引用してください」とプロンプトで指示すれば似た出力は得られます。公式は3つの観点でCitationsを推しています。

くらべる

逐語引用の指示とCitations

自前

プロンプトで逐語引用

引用文がそのまま出力トークンになります。Claudeが原文を書き写すので、引用が文書内の実在の位置を指す保証はありません。

API任せ

Citations機能

cited_textは出力トークンに数えられません。APIが文書から直接抽出するため、引用は提供した文書内の有効な位置を必ず指します。Anthropicの評価では、関連性の高い箇所を引く傾向がプロンプト方式より明らかに強いとされています。

正確性の違いは、書き写しの仕組みから生まれます。プロンプト方式では、Claudeが引用符の中へ原文を再生成するので、1文字ずれれば「正確な引用」ではなくなります。Citationsではcited_textをAPIが文書から取り出すため、ずれが入り込みません。引用が正しいかを確かめる後処理を、アプリ側で減らせる可能性があります。

Citationsのドキュメントには、コスト差の数値は載っていません。引用が長く頻度が高いほど恩恵が大きく、文書が短く一問一答で終わる用途では、入力側のわずかな増加のほうが目立ちます。

入力側で課金されるもの: titleとcontextの扱い

入力側には、見落としやすい点があります。ドキュメントブロックのtitleとcontextは、モデルに渡されますが、引用の対象にはなりません。引用できるのは、sourceの中のテキストだけです。

ここで勘違いしやすいのが、「引用元として無料になる」という読み方です。titleとcontextはモデルに渡されるフィールドなので、入力として処理されます。無料扱いになると明記されているのは、応答側のcited_textだけです。

titleには長さの上限があります。文書のメタデータ(作成日、版、管理番号など)を持たせたいときは、contextにテキストか文字列化したJSONとして入れる使い方が想定されています。引用の対象にしたくない補足を渡す場所として使えるわけです。

{
  "type": "document",
  "source": { "type": "text", "media_type": "text/plain", "data": "…本文…" },
  "title": "就業規則",
  "context": "{\"version\": \"2026-04\", \"owner\": \"人事部\"}",
  "citations": { "enabled": true }
}

引用の粒度を選ぶ場面もあります。プレーンテキストとPDFは、既定で文単位に自動分割されます。箇条書きや書き起こしのように粒度を自分で決めたいときは、カスタムコンテンツ文書を使います。RAGのチャンクを文単位で引用させたいなら、チャンクごとに1つのプレーンテキスト文書として渡します。追加の分割をしたくないときは、チャンクをカスタムコンテンツ文書に載せます。引用位置の形式も文書の種類で変わります。PDFはページ範囲(1始まり)、プレーンテキストは文字位置(0始まりで終端は含まない)、カスタムコンテンツは元のコンテンツリストのブロック番号(0始まり)です。文書番号は、リクエスト全体の文書ブロックを通した0始まりの番号になります。粒度の違いは、ドキュメント種別ごとの引用形式に詳しくあります。

導入前にトークン増加を測る手順

Citationsを有効にしたときの入力側の増加は、リクエストを送る前にToken Counting APIで比べられます。同じメッセージ構造を、citations.enabledの有無だけ変えて2回数えます。

手順

導入前の見積もり

  1. 1

    文書をテキストかbase64で用意する

    Token Counting APIは、urlやfileを指定したdocumentブロックをinvalid_request_errorで返します。Files APIのファイルやURL指定のPDFは、base64で渡し直して数えます。

  2. 2

    citationsの有無だけ変えて2回数える

    /v1/messages/count_tokensへ、文書とメッセージが同じでcitationsだけ異なる2つのリクエストを送り、input_tokensの差を見ます。

  3. 3

    文書ごとに差を並べる

    文書の長さや形式(プレーンテキストかPDFか)で、チャンク分割のぶんの差も変わります。代表的な文書を数点選んで差を出すと、見積もりの精度が上がります。

curl https://api.anthropic.com/v1/messages/count_tokens \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-5-5",
    "messages": [{
      "role": "user",
      "content": [
        {
          "type": "document",
          "source": {"type": "text", "media_type": "text/plain", "data": "The grass is green."},
          "citations": {"enabled": true}
        },
        {"type": "text", "text": "What color is the grass?"}
      ]
    }]
  }'

citationsの行を外した同じリクエストを送り、返ってくるinput_tokensを比べます。返る値は推定で、実際にメッセージを作成したときの入力トークン数とは少しずれることがあります。

Agent SDKで動くアプリのように、リクエストが自動で何度も発生する構成では、見積もりだけでなく実際の消費量を継続的に追う仕組みも必要です。Agent SDKのコスト集計では、total_cost_usdやモデル別使用量の取得方法を扱っています。

併用できる機能と、併用できない機能

CitationsはPrompt Caching、Token Counting、バッチ処理と併用できます。ただし対象が非対称な機能と、そもそも併用できない機能があります。

Prompt Cachingは文書側にだけ効く

応答に含まれる引用ブロックはキャッシュできません。キャッシュできるのは、引用元の文書側だけです。最上位のドキュメントブロックにcache_controlを付けると、同じ文書に繰り返し質問するワークフローで、文書側をキャッシュしながら応答では引用を使えます。Prompt Cachingの仕組みは別記事にまとめています。

Citationsの有効・無効を切り替えると、キャッシュにも影響します。システムプロンプトが変わるため、ツール定義のキャッシュは残りますが、システムプロンプトとメッセージのキャッシュは無効になります。運用の途中でオンとオフを行き来させると、キャッシュが効かずに入力コストが跳ねる原因になります。

バッチ処理とも併用できる

大量の文書に非同期でリクエストを投げるバッチ処理とも組み合わせられます。件数が数千・数万に達する構成では、1件あたりの引用の分量が小さくても、出力側から外れるぶんが積み上がります。

構造化出力とは併用できない

Citationsと構造化出力は互換性がありません。ユーザーが渡した文書(documentブロックまたはsearch_resultブロック)でCitationsを有効にしたうえで、output_config.format(非推奨のoutput_formatも同じ)を指定すると、APIは400エラーを返します。引用ブロックをテキストに差し込む形式が、構造化出力の厳密なJSONスキーマの制約と両立しないためです。両者の関係はCitationsと構造化出力の記事で詳しく扱っています。

有効化は全文書か、まったくなしか

1つのリクエストの中では、Citationsを全文書で有効にするか、どの文書でも有効にしないかのどちらかです。一部の文書だけ有効にする使い方はできません。

Citationsのコスト効果はどんな用途で効くか

効き方は、引用の頻度、文書の長さ、会話やバッチの件数で決まります。

用途コスト面での効果理由
長文文書に対する複数ターンのRAG対話コスト面での効果大きい理由cited_textが毎ターンの再送コストから外れ続ける
大量文書を非同期でバッチ処理コスト面での効果大きい理由1件あたりは小さくても件数分が積み上がる
短い一問一答・単発の要約コスト面での効果小さい理由入力側のわずかな増加のほうが相対的に目立つ
スキャンPDFのみの文書コスト面での効果適用不可理由抽出可能なテキストがなく、そもそも引用対象にできない

カスタマーサポートのFAQ検索や社内ナレッジベースへの質問応答のように、同じ文書セットに繰り返し問い合わせる構成は、表の上2行の条件に近づきます。

引用の正確性そのものが目的なら、コストとは別にCitationsを選ぶ理由があります。引用が提供した文書内の有効な位置を指すという性質は、Citationsの仕組みが持つものだからです。

まとめ

Citationsは入力側で少しだけ増える代わりに、cited_textが出力トークンと再送時の入力トークンの両方から外れます。得をするのは、文書が長く、引用が多く、ターンや件数が積み上がる用途です。短い一問一答なら、入力の増加のほうが目立ちます。

導入するかどうかは、自分の文書でcitationsの有無を変えて2回数えた差で判断できます。構造化出力を使う設計なら、Citationsとは併用できない点を先に押さえます。スキャンPDFがCitationsで引用できない理由も、文書側の手戻りを減らす手がかりになります。

この記事を共有:XはてブLinkedIn