cd ../back to blog
$Trust//June 4, 2026//6 min read

トークン水増しの実態 — ゲートウェイが請求を5〜25倍にする手口と、20行でできる検証テスト

AIゲートウェイは usage のトークン数をこっそり水増しして請求を5〜25倍に膨らませられます。隠れたシステムプロンプト注入などの手口、どのゲートウェイにも使える20行のPythonテスト、結果の読み方を解説します。

どの AI API もトークン単位で課金します。あなたはゲートウェイが返す usage オブジェクト — prompt_tokens completion_tokens — が本当のトークン数だと信じています。 ところがこの数値こそ、リセラーが完全にコントロールできる唯一の項目であり、 こっそり上乗せ請求するのに最も都合のよい場所です。これを上品に言い換えたのが トークン水増し(token inflation)です。ゲートウェイは 実際に送受信したよりも多いトークン数を報告し、あなたは正直なコストの 5 倍、10 倍、ときに 25 倍を払わされます — 本物のモデルかどうかとは無関係に。

これは Brievio がそもそも対抗するために作られた失敗パターンなので、 ありのまま説明する価値があります。どう水増しが行われるのか、どんな ゲートウェイ(当社を含む)にも実行できる 20 行のテスト、そして結果の読み方です。

トークン水増しとは実際に何なのか

正直なトークン数とは、プロバイダー自身があなたのメッセージ — あなたのシステムプロンプト、あなたのユーザー入力、モデルの返信 — に対して数える数のことです。信頼できるゲートウェイはそれをそのまま素通しします。 水増しするゲートウェイはそこに詰め物をします。同じリクエストでも、請求は まるで別物です。

usage.json
# 正直なトークン数 — 送ったテキストの量にほぼ一致し、上乗せは
# チャットテンプレートのわずかなオーバーヘッドだけ(role マーカーや整形用トークン):
{"prompt_tokens": 24, "completion_tokens": 2, "total_tokens": 26}

# 水増し — テキストは約 20 トークンしか送っていないのに 1,840 トークン分を請求:
{"prompt_tokens": 1840, "completion_tokens": 2, "total_tokens": 1842}
#   ^ あなたが書いてもいない約 1,800 トークンのシステムプロンプトがリクエストに
#     注入され、そのぶんが請求に乗っている。一語の質問でも。毎回。

最もよくある手口が隠れたシステムプロンプトの注入です。 リセラーは数百〜数千トークンの自前のテキスト —「安全のための」前置き、 ルーティング用のラッパー、偽のペルソナ — をすべての呼び出しの先頭に 差し込みます。あなたは書いてもいないし見えもしませんが、リクエストごとに 必ず請求されます。Sonnet の入力レートでは、1,800 トークンの幽霊プレフィックスは 一語の質問でも約 $0.0055 の純粋なマージンになります。これに 月間 100 万回の呼び出しを掛けてみてください。

20 行のテスト

誰の言葉も — 当社の言葉さえも — 鵜呑みにする必要はありません。サイズが 分かっているプロンプトを送り、ゲートウェイが請求した量と、あなたの テキストが自分のマシンで実際にトークン化される量を突き合わせるだけです。

token_inflation_test.py
# token_inflation_test.py
# あなたのゲートウェイは正直なトークン数を報告しているか? サイズが分かっている
# プロンプトを送り、ゲートウェイが報告した prompt_tokens を、実際に送った
# まさにそのメッセージをローカルのトークナイザーで数えた値と比較する。
import tiktoken
from openai import OpenAI

client = OpenAI(api_key="sk-brievio-...", base_url="https://api.brievio.com/v1")

messages = [
    {"role": "system", "content": "You are a terse assistant."},
    {"role": "user", "content": "Reply with the single word: ok."},
]

# 1. ゲートウェイが課金してくる量:
resp = client.chat.completions.create(
    model="claude-sonnet-4-6", messages=messages, max_tokens=5,
)
reported = resp.usage.prompt_tokens

# 2. 自分のメッセージを実際にローカルでトークン化した量:
enc = tiktoken.get_encoding("cl100k_base")   # あくまで近似値 — 下の注意書きを参照
local = sum(len(enc.encode(m["content"])) for m in messages)

print(f"gateway reported prompt_tokens: {reported}")
print(f"local token count of your text: {local}")
print(f"ratio: {reported / local:.1f}x")

# 正常    → 比率 約 1.1〜1.6 倍(role マーカー + チャットテンプレートのオーバーヘッド)
# 水増し  → 比率 2倍 / 5倍 / 25倍(隠れたプロンプトが入力に詰め込まれている)

読み方: わずかな固定オーバーヘッドは正常です。チャット フォーマットは role マーカーやメッセージの区切りのために数トークンを 追加するので、小さなプロンプトで 1.1〜1.6 倍 程度の比率なら 問題なく、プロンプトが大きくなるほど 1.0 倍 に近づきます。 これに対し 2 倍5 倍25 倍 という 比率は丸め誤差ではありません — 詰め物です。

正直な注意点が 1 つ。tiktokencl100k_base は OpenAI のトークナイザーであり、Claude や Gemini はトークン化の仕方が 少し異なります(通常は 10〜20% の範囲)。なのでローカルの数値は近似値として扱い、1 トークン単位の厳密な監査とは考えないでください。 この近似が 2 倍の差を、まして 25 倍の差を説明することは決してありません — 正確な数字が欲しいなら、プロバイダー自身のトークナイザーや count-tokens エンドポイントを使ってください。このテストは水増しを 捕まえるためのもので、1 トークンの細かい違いを論じるためのものではありません。

出力とキャッシュもチェックする

入力が常套の標的ですが、同じ詰め物は出力トークンやキャッシュにも 潜みます。さらに手早くできるチェックを 2 つ。

output_and_cache.py
# 出力とキャッシュも水増しされうる。さらに 30 秒でできるチェックを 2 つ:
#
# (a) 出力: ちょうど 1 トークンだけ返すよう求め、上限もかける。
resp = client.chat.completions.create(
    model="claude-sonnet-4-6",
    messages=[{"role": "user", "content": "Reply with only: ok"}],
    max_tokens=2,
)
print(resp.usage.completion_tokens)   # 正直なら 約 1〜2。水増しなら 50、200、…
#
# (b) キャッシュ: 同じ長いプレフィックスを約 5 分以内に 2 回送る。2 回目は入力の
#     大部分が割引されたキャッシュ読み取り料金で請求されるはず。"cached" フィールドが
#     常に 0 なら、キャッシュヒットでも全額を払わされている。
print(resp.usage.prompt_tokens_details.cached_tokens)

1 トークンしか求めていないのに 50 トークン請求されたり、同一内容の 繰り返し呼び出しでも cached_tokens が 0 のまま動かないなら、 メーターは間違っています。

水増しはどこから来るのか

  • 注入されたシステムプロンプト。 すべてのリクエストに 追加されるラッパーの前置き — 最もよくある発生源です。大きく、見えず、 そして請求される。
  • 再ラップされた「テンプレートプロキシ」モデル。 あなたのプロンプトは、モデルに届く前に大きな固定テンプレートへ 詰め込まれます。テンプレートのトークンは — モデルにとっても請求にとっても — 本物のトークンですが、あなたのものではありません。
  • でっち上げられた usage の数値。 最も雑なやり方です。 usage オブジェクトが単純に現実と一致していない。上のテストで すぐに見抜けます。
  • 幽霊の出力水増し。 報告される completion_tokens が、実際に返ってきた語数を上回ります。

これらのどれにも偽のモデルは必要ありません。ゲートウェイは本物の Claude を 提供しつつ、メーターだけ水増しすることもできます — モデルが本物であることと 請求が正直であることは別々の 2 つの約束であり、両方を確かめるべきです。

正直なベースライン

Brievio はプロバイダー自身のトークン数を改変せずに素通しし、あなたの リクエストに何も注入せず、呼び出しごとに実際の入力・出力トークンと正確な コストを記録します。これは 使用状況ダッシュボードで確認できます。 上のテストを Brievio に対して実行すれば、reported ≈ local + わずかな オーバーヘッド が見えるはずです — 本来どこでもこう読めるべき形です。 当社の料金ページは各モデルを公式の基準レートと 並べて表示しているので割引が検証可能であり、 使用状況ドキュメントには返すフィールドが 正確に明記されています。

あるゲートウェイが定価の 80% 引きなら、最初に問うべきは「モデルは本物か」 ではありません —「メーターは何と言っているか」です。20 行を走らせてください。 1 セントもかかりませんし、ベンダーに対してできる最も安いデューデリジェンスです。