LLMにデータを渡すとき、つい JSON.stringify(data, null, 2) の結果をそのまま貼り付けていませんか。これがトークン的にどれくらい高くつくのか測ったことがなかったので、同じデータをフォーマットだけ変えて数えてみました。
結論から言うと、インデント付きJSONはCSVの約3倍のトークンを使います。
測定方法
商品テーブルを1つ用意しました。20行、フィールドは5つ(ID、商品名、価格、在庫有無、カテゴリ)です。CSVだと1行はこうなります。
1001,Wireless Mouse,9.99,false,electronics
同じデータを7つのフォーマットで書き、GPT-4o以降のOpenAIモデルが使う o200k_base トークナイザーで数えました。
import { getEncoding } from "js-tiktoken";
const enc = getEncoding("o200k_base");
const count = (s) => enc.encode(s).length;
count(csv); // 300
count(JSON.stringify(rows)); // 525
count(JSON.stringify(rows, null, 2)); // 884
結果
| フォーマット | トークン | CSV比 |
|---|---|---|
| TSV | 296 | 0.99倍 |
| CSV | 300 | 1.00倍 |
| Markdownの表 | 373 | 1.24倍 |
| JSON(空白なし) | 525 | 1.75倍 |
| YAML | 649 | 2.16倍 |
| JSON(2スペースインデント) | 884 | 2.95倍 |
| XML | 1,088 | 3.63倍 |
旧トークナイザー(cl100k_base)でも、どのフォーマットも差は2%以内でほぼ同じでした。
なぜこんなに差が出るのか
-
キーが行ごとに繰り返される。 JSON・YAML・XMLは
"name":や"price":を20回書きます。CSVはヘッダーに1回だけです。 - 記号もトークン。 引用符、波かっこ、コロンがすべてトークンを消費します。XMLは値ごとに開始タグと終了タグが付くので最も高くなります。
- インデントは人間のため。 モデルは改行やインデントがなくても問題なく読めます。今回、整形だけで359トークン(+68%)増えていました。
面白いのはYAMLです。文字数は空白なしJSONより少ないのに、トークンは多い。フィールドごとに改行してキーを書き直すからです。
コードも測ってみた
コーディングエージェントには大量のコードが送られるので、コードについてもいくつか測りました。
| 実験 | 結果 |
|---|---|
| Python 16行:4スペース / 2スペース / タブ | 135 / 135 / 133 トークン、ほぼ差なし |
| 同じファイルから1行のdocstringを削除 | 135 → 123(−9%) |
| JSの関数10行をminify | 92 → 47(−49%) |
| UUID 1つ | 18トークン |
- インデントはほぼタダ。 最近のトークナイザーは連続した空白を1トークンにまとめます。トークン節約のためにコード整形を変える必要はありません。
-
minifyでトークンは半分になるが、やめておく。
subtotalやtaxRateのような名前が消えると、モデルがコードを理解しにくくなります。 - UUIDは意外と高い。 プロンプトに長いIDが並ぶなら行番号に置き換えて送り、応答を受け取ってからコード側で戻すほうが得です。
使い分け
- 入力として渡すフラットな表: CSVかTSV。値にカンマが含まれるならTSVにすれば引用符の処理が不要です。
- モデルに返させるデータ: スキーマを指定した空白なしJSON。パースの安定性のほうが数トークンより大事です。構造化出力(structured output)に対応したAPIならそれを使いましょう。
- ネストしたデータ: 空白なしJSON。無理にCSVへ平坦化すると、かえって増えることが多いです。
- 人も一緒に見る表: Markdown。CSVより24%多いだけです。
- プロンプトに整形済みJSONとXMLは避ける。 ツールが要求する場合を除いて。
さらに、不要なフィールドや null のフィールドを削り、数値を丸めるだけでもかなり減ります。
コストにすると
20行の表をリクエストごとに付けて、1日1,000回、月3万回送るとします。入力100万トークンあたり$2のモデルの場合です。
| フォーマット | 月のトークン | 月のコスト |
|---|---|---|
| CSV | 900万 | $18 |
| JSON(空白なし) | 1,580万 | $32 |
| JSON(インデント) | 2,650万 | $53 |
| XML | 3,260万 | $65 |
1リクエストでは気づきませんが、サービスとして動かすとそのまま積み上がります。RAGの検索結果や長いAPIレスポンスを入れる場合は、差がさらに大きくなります。
注意点
- 表1つ、トークナイザー1つでの結果です。ClaudeやGeminiはトークナイザーが違うので、数値そのものは変わります。ただ「キーを繰り返すフォーマットほど高い」という順位はフォーマットの構造から来るものなので、大きくは変わらないはずです。
- フォーマットが回答の精度に影響するなら、両方試してください。安くても回答が悪くなるなら意味がありません。
自分のデータで測る
自分のデータで比べたくて、トークンカウンターを作りました。同じ o200k トークナイザーがブラウザ内で動くので、貼り付けたデータはどこにも送信されません。2つのフォーマットを交互に貼り付ければ、トークン数とモデルごとの料金がすぐに出ます。
より詳しい測定結果は JSON vs YAML vs CSV のトークン比較(英語)にまとめています。