0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

トークン数はコストの代理変数にならない ― 自分のログ25,574ターンで測り直したら、他の人と結論が分かれた

0
Posted at

3日前、私は「1ターンあたり23万トークンを読み直していた」という記事を書きました。

**その書き方に不足がありました。**この記事は、その訂正と、
訂正しようとして測り直したら、別の人と結論が分かれた話です。

何が不足していたか

トークンのを測って、それをコストの大きさとして語っていました。

単価が違います。

入力(非キャッシュ)   1.0     ← これを基準にすると
キャッシュ書込        1.25
キャッシュ読出        0.1     ← **1/10**
出力                 5.0

キャッシュ読出は入力の1/10、出力に対しては1/50の単価です。
量で何倍あっても、金額はその比では効きません。

この点は、@Tsutomu_eng さんが
「キャッシュ読出がトークンの81倍」はコストの話ではなかった
で明示的に指摘されています。トークンで81倍のものが、金額では1.62倍だったという測定です。

私はこの型を踏んでいました。

自分のログで測り直した

Claude Code はセッションごとの usage を手元に保存しています。推測せずに数えられます。

対象   ~/.claude/projects/**/*.jsonl   167ファイル
       usage を持つターン **25,574**(claude-opus-5 / claude-sonnet-5)

結果です。

種別                    トークン        量の%     額の%
入力(非キャッシュ)          51,126     0.0%     0.0%
キャッシュ書込         224,263,066     3.4%    **27.7%**
キャッシュ読出       6,402,387,834    96.3%    **63.2%**
出力                  18,607,112     0.3%     9.2%

キャッシュ読出は、出力の344倍(トークン量)。金額比では6.88倍。

344倍 → 6.88倍   **50倍の開きがある**

「344倍」を根拠に何かを削っていたら、50分の1の効果しか出ない場所を削っていました。

そして、結論が分かれた

同じ測定を、別の環境でやると、こうなります。

                読出(額)   書込(額)   その人の結論
@Tsutomu_eng     41.6%      32.7%      「コストの話ではなかった」
こちら           63.2%      27.7%      **読出が依然として最大**

**どちらの計算も正しいはずです。**環境が違うだけです。

分かれた理由は、使い方だと考えています。

長いセッションを少数   読み直す量が積み上がる  → **読出が効く**
短いセッションを多数   毎回書き直しが発生する  → **書込が効く**

キャッシュ書込は、assistant のターンのほぼ毎回発生します。
セッションを短く切れば書込の回数が増え、長く続ければ読出の量が増える。
どちらが効くかは、その人の回し方で決まります。

だから、両方に共通することだけが持ち出せる

環境をまたいで成り立ったのは、この2つでした。

1  **トークン量の構成比 ≠ 金額の構成比**
   こちら 96.3% → 63.2% / 向こう 81倍 → 1.62倍
   **どちらも、量で見ると大きく外す**

2  **キャッシュ書込は、量に対して金額が重い**
   こちら 量3.4% → 額27.7%(**8倍**)
   向こう 量6.3%(読出比) → 額32.7%

「どちらが最大か」は環境依存です。「量では測れない」は環境依存ではありません。

手元で測る

外部データを使いません。自分のログを読むだけです。

# -*- coding: utf-8 -*-
"""自分のセッションログから、トークンの内訳と金額の構成比を出す。"""
import collections, io, json, os, sys

sys.stdout.reconfigure(encoding="utf-8", errors="replace")

ROOT = os.path.expanduser("~/.claude/projects")
KEYS = ("input_tokens", "cache_creation_input_tokens",
        "cache_read_input_tokens", "output_tokens")
LABEL = {"input_tokens": "入力(非キャッシュ)",
         "cache_creation_input_tokens": "キャッシュ書込",
         "cache_read_input_tokens": "キャッシュ読出",
         "output_tokens": "出力"}
# **単価は「比」だけを使う。**絶対額はモデルとプランで変わる
RATIO = {"input_tokens": 1.0, "cache_creation_input_tokens": 1.25,
         "cache_read_input_tokens": 0.1, "output_tokens": 5.0}

tot, turns, files = collections.Counter(), 0, 0
for root, _dirs, names in os.walk(ROOT):
    for n in names:
        if not n.endswith(".jsonl"):
            continue
        files += 1
        for line in io.open(os.path.join(root, n), encoding="utf-8", errors="ignore"):
            if '"usage"' not in line:
                continue
            try:
                o = json.loads(line)
            except Exception:
                continue
            u = (o.get("message") or {}).get("usage") or o.get("usage")
            if not isinstance(u, dict):
                continue
            turns += 1
            for k in KEYS:
                tot[k] += int(u.get(k) or 0)

S = sum(tot[k] for k in KEYS)
cost = {k: tot[k] * RATIO[k] for k in KEYS}
C = sum(cost.values())
print(f"ファイル {files} / usage を持つターン {turns}\n")
print(f"{'種別':<18}{'トークン':>16}{'量の%':>9}{'額の%':>9}")
for k in KEYS:
    print(f"{LABEL[k]:<18}{tot[k]:>16,}{100*tot[k]/S:>8.1f}%{100*cost[k]/C:>8.1f}%")
print(f"\n読出は出力の {tot['cache_read_input_tokens']/max(tot['output_tokens'],1):.1f} 倍(量)"
      f" / {cost['cache_read_input_tokens']/max(cost['output_tokens'],1):.2f} 倍(額)")

**単価は比だけを使っています。**絶対額はモデルとプランで変わるうえ、
この記事の主張に絶対額は要らないからです。構成比だけで結論が出ます。

定額プランを使っている場合、この金額比はそのまま請求額にはなりません。
測っているのは消費の構成であって、課金の仕組みではありません。
それでも「どこを削ると効くか」の判断には、量ではなく額の構成比を見る必要があります。

訂正したこと

前の記事に追記を入れました。

残した   結論の向き ―― **読出が金額でも最大(63.2%)**。これは自分の環境では正しかった
直した   倍率の書き方 ―― 344倍ではなく **6.88倍**
足した   量と額は別物である、という但し書き

結論が間違っていたのではなく、根拠の単位が間違っていました。
そして単位が間違っていると、たまたま結論が合っていても、次で外します。

まとめ

1  トークン数はコストの代理変数にならない。**単価が50倍違うものを足している**
2  自分のログで測ると、量96.3% のものが額では63.2% だった
3  **同じ測定でも、環境が違えば結論が分かれる**(読出が最大か、書込が重いか)
4  環境をまたいで成り立つのは「**量では測れない**」のほうだけ
5  代理変数を、本体として語らない

5番目が、この件で足した検査です。
トークン数を根拠に何かを主張するときは、必ず単価を掛けてから書く。


この連載は、実際に測った数字だけで書いています。
同じことを試す人の役に立ちそうなら、ストックしておいてください。

この連載

AIエージェントを実際に回して、かかった費用と壊れた箇所を測って書いています。推測は書きません。実測値だけです。

  1. Claude Code のトークン使用量を実測したら1ターン23万 ― 節約に効いたのは「セッションを切る」だった
    https://qiita.com/manabu49-ai/items/2598a30d5140e4445ab6
  2. 57分間、死んだジョブを誰も見ていなかった ― AIエージェントの見張りを機械に渡す
    https://qiita.com/manabu49-ai/items/5c7506c94b5be58c040e
  3. AIに100通り試させたら、効果ゼロなのに5個が「有意」だった
    https://qiita.com/manabu49-ai/items/397a018948e1ab7ef29e
  4. 仕様書は2日前から手元にあった ― 読まずに実装した対処が、データを永久に失う設計だった
    https://qiita.com/manabu49-ai/items/9b947604d3dc4958fa36
  5. AIを触り始めて3日で24時間動くものを作った ― そして8回間違えた
    https://qiita.com/manabu49-ai/items/acd01b13abe9c8cbea16
  6. 同じデータを2つのAIに測らせたら、中央値が5通り出た ― 全部、計算は正しかった
    https://qiita.com/manabu49-ai/items/dc699a8458b129d6be39
  7. 本記事 ― トークン数はコストの代理変数にならない
  8. 次 ― 「できました」の的中率を測り続けた結果(未公開)

番外 ― Qiitaで何が読まれるかを3,478本から探した ― 106通り掃いて、残ったのは6つだけだった
https://qiita.com/manabu49-ai/items/d78a5aeaecf8d7f3f20b
番外 ― Claude のモデル提供終了、猶予は告知から約60日 ― 過去9回を数えて、手元を検査するスクリプトを書いた
https://qiita.com/manabu49-ai/items/bc2a7be2a6ee4ceb6185

**無料記事は結論まで全部書きます。**出し惜しみはしません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?