LLMはテキストをどう見ているか:i18nシステムが教えてくれたトークンエコノミクスの実態
サイトのi18n翻訳システムを構築した際、1,500語の英語ブログ記事を韓国語に翻訳すると、英語ソースの2.8倍のトークンを消費することがわかりました。同じ意味内容、同じセマンティクスなのに、APIコストは2.8倍です。日本語は2.4倍、繁体字中国語は2.1倍、スペイン語は1.15倍でした。多言語コンテンツのトークンエコノミクスに不意を突かれたのは、トークナイザーの仕組みを理解していなかったからです。1
TL;DR
トークナイゼーションとは、人間が読めるテキストを言語モデルが処理する数値トークンに変換するプロセスです。27件のブログ記事を6言語に翻訳した結果、実際のコストデータが得られました。非ラテン文字は、英語と比べてセマンティック単位あたり2〜3倍のトークンを消費します。以下のインタラクティブビジュアライザーでは、任意の言語のテキストを貼り付けてトークンの内訳を確認できます。トークナイゼーションを理解したことで、翻訳パイプラインのコストを正確に見積もれるようになり、プロンプトを最適化してコストを35%削減し、韓国語翻訳でMarkdown構造が崩れるフォーマットの問題もデバッグできました。この問題は、トークナイザーが脚注マーカーをトークン境界をまたいで分割していたことが原因でした。
i18nトークンコストの実測データ
27件のブログ記事をClaudeを使って6言語に翻訳しました。翻訳品質を確保するにはOpusレベルのモデルが必要でした(安価なモデルは使いません——Haikuで生成した翻訳が機械的な出力のように読めてしまった経験からの教訓です)。言語ごとのトークン消費量は驚くべきものでした。
| 言語 | 平均トークン数/記事 | 英語比 | 文字体系 |
|---|---|---|---|
| 英語(ソース) | 1,850 | 1.0x | ラテン文字 |
| スペイン語 | 2,128 | 1.15x | ラテン文字 |
| ドイツ語 | 2,220 | 1.20x | ラテン文字 |
| フランス語 | 2,090 | 1.13x | ラテン文字 |
| 韓国語 | 5,180 | 2.80x | ハングル |
| 日本語 | 4,440 | 2.40x | CJK混合 |
| 繁体字中国語 | 3,885 | 2.10x | CJK |
ラテン文字の言語(スペイン語、ドイツ語、フランス語)は英語の20%以内に収まりました。CJKとハングルの言語は2〜3倍に跳ね上がります。このコスト差は27記事 × 6言語 = 162件の翻訳全体に複利的に効いてきます。2
なぜこの差が生まれるのか
多くのトークナイザー(ClaudeとGPT-4の両方が採用しているBPE)は、主に英語テキストで学習されています。英語の単語は、学習データに他のどの言語よりも多くの英語が含まれているため、最適化されたトークン表現を持っています。一般的な英語の単語(「the」「and」「is」)は単一トークンにマッピングされます。韓国語の音節ブロック、日本語の漢字、中国語の文字は、学習時に出現頻度が低かったため、2〜3個のバイトレベルトークンに分割されることがよくあります。3
この効果はランダムではなく、体系的です。韓国語の翻訳は常に英語の約2.8倍のコストがかかります。この倍率は一貫しているため、正確にコストを見積もることができます。
トークナイゼーションのバグ
韓国語翻訳の最初のバッチで、翻訳された記事からすべてのMarkdownフォーマットが失われました。脚注参照([^1])が消え、コードブロックの言語タグがなくなり、見出しマーカー(##)が本文に結合してしまったのです。
原因の特定に1時間かかりました。根本原因は、翻訳プロンプトが「このブログ記事を韓国語に翻訳してください」とだけ指示しており、フォーマットの保持を明示していなかったことです。トークナイザーは、韓国語のコンテキストでは英語のコンテキストとは異なる位置でMarkdown構文をトークン境界で分割していました。モデルは[^1]を構造的なマークアップではなく、翻訳対象のコンテンツとして扱ったのです。
修正方法として、翻訳プロンプトに明示的な制約を追加しました。
Preserve all markdown formatting exactly:
- Keep [^N] footnote references unchanged
- Keep ``` code fences with language tags unchanged
- Keep ## heading markers unchanged
- Keep **bold** and *italic* markers unchanged
各制約が特定の不具合モードを排除しました。制約リストは翻訳指示そのものよりも長くなりました——これはOODAプロンプトエンジニアリングフレームワークで解説しているパターンです。4
トークンとは何か
文字からトークンへ
テキスト処理への素朴なアプローチは、各文字を入力単位として扱うことです。「Hello world」は11文字になります。文字レベルの処理はあらゆる詳細を捉えますが、非常に長いシーケンスを生成します。1,000語のドキュメントは約5,000文字になります。5
単語レベルの処理はシーケンス長を短縮しますが、未知の単語に対応できません。50,000エントリの単語レベル語彙では、「unfathomability」という単語が学習に出現していない限り処理できません。
サブワードトークナイゼーションはその中間を見つけます。一般的な単語(「the」「and」)は単一トークンのままです。まれな単語はサブワードの断片に分割されます。「Unfathomability」は[“un”, “fath”, “om”, “ability”]に分割され、各断片は学習済みの表現を持つのに十分な頻度で出現しています。
Byte-Pair Encoding(BPE)
ClaudeとGPT-4が使用するBPEは、個々のバイトから始めて、最も頻出する隣接ペアを反復的にマージします。6
- 個々の文字から開始:
[l, o, w, e, r] - 最頻出ペア:
(l, o)→ マージして[lo, w, e, r] - 最頻出ペア:
(e, r)→ マージして[lo, w, er] - 最頻出ペア:
(lo, w)→ マージして[low, er] - 最頻出ペア:
(low, er)→ マージして[lower]
最終的な語彙には、すべての元のバイトとマージされた全トークンが含まれ、通常50,000〜100,000エントリになります。学習データにおいて英語が支配的であるため、マージされたトークンも英語の単語が大半を占めます。
プロンプトの最適化方法
トークンコストの差を発見した後、翻訳パイプラインを最適化してコストを35%削減しました。
最適化1:言語ファミリーごとのバッチ処理
ラテン文字の言語(スペイン語、フランス語、ドイツ語)は構造的に類似しています。ソース記事が十分に短く、3言語分の出力とともにコンテキストウィンドウに収まる場合、1回のAPI呼び出しで3言語すべての翻訳を生成するようにバッチ処理しています。共有コンテキスト(英語ソース)のコストは3回ではなく1回だけで済みます。7
最適化2:制約の重複排除
元の翻訳プロンプトでは、言語ごとに制約を繰り返していました。最適化版では、制約を一度定義してすべての出力に適用します。
# Constraints (apply to ALL translations below):
- Preserve markdown structure, footnotes, code blocks
- Keep proper nouns in English
- Adapt idioms, don't transliterate
# Translate the following post into: Spanish, French, German
制約セクションのトークン消費は1回だけです。代替案(言語ごとに制約を繰り返す)では3倍消費します。
最適化3:簡潔な指示
元のプロンプトは340トークンの指示を使用していました。最適化後は180トークンです。47%の削減が162件の翻訳全体に複利的に効きます。
| 指標 | 最適化前 | 最適化後 | 削減率 |
|---|---|---|---|
| 指示トークン数 | 340 | 180 | 47% |
| ラテン語バッチ合計 | 6,780 | 4,438 | 35% |
| CJK言語あたり合計 | 5,520 | 5,180 | 6% |
CJK言語はプロンプト最適化の恩恵が少なくなります。出力トークン(翻訳そのもの)がコストの大部分を占めるためです。指示をいかに簡潔にしても、出力はトークン換算で本質的に長くなります。8
実践的な応用
コストの見積もり
英語テキストのおおよその目安として、1トークンは約0.75語、または約4文字に相当します。1,000語のドキュメントは約1,333トークンを消費します。英語以外のコンテンツには、上記の表の言語倍率を適用してください。9
コードのトークナイゼーション
コードは散文とは異なるトークナイゼーションが行われます。一般的なキーワード(def、return、if)は単一トークンにマッピングされます。変数名は出現頻度に基づいて分割されます。
# "def calculate_total(items):" splits approximately as:
# ["def", " calculate", "_total", "(", "items", "):", ]
一貫した命名規則はトークン数を削減します。私のフックインフラストラクチャではverb-noun.shの規則(git-safety-guardian、recursion-guard、blog-quality-gate)を使用しています。この一貫したパターンにより、トークナイザーは一般的なサブワードを効率的に予測・マージできます。
予期しない動作のデバッグ
モデルが予期しない出力を生成した場合、トークナイゼーションがその理由を説明できることがあります。韓国語のフォーマットバグは、トークナイザーが韓国語コンテキストでは英語とは異なる方法で[^1]を分割していたために発生しました。分割パターンを理解したことが、修正(明示的な保持制約)に直結しました。
重要なポイント
LLM APIを使用するエンジニアの方へ: - 多言語対応に着手する前に、言語ごとのトークンコストを計測してください。CJK言語は英語に比べてセマンティック単位あたり2〜3倍のコストがかかります - プロンプト指示の最適化(簡潔な表現、制約の重複排除)により、大量の翻訳パイプラインで30〜50%のコスト削減が可能です - 本番デプロイ前に、ドメイン固有の用語やMarkdown構文のトークナイゼーションをテストしてください。予期しない分割がフォーマットのバグを引き起こします
AI機能の予算を策定するプロダクトマネージャーの方へ: - 英語以外の言語サポートは、英語に比べてAPI呼び出しあたり1.5〜3倍のコストがかかります。多言語AI機能の予算は、言語あたり一律の見積もりではなく、言語倍率を使用して策定してください - コンテキストウィンドウの制限はCJK言語に不均衡な影響を与えます。200Kトークンのウィンドウには、英語と比べて韓国語のコンテンツは40%少なくしか収まりません
参考文献
-
著者のi18n翻訳パイプライン。27記事を6言語に翻訳。言語ごとのトークン消費量を計測し、韓国語の2.8倍の倍率が判明。 ↩
-
著者の翻訳コストデータ。言語ごとの平均トークン数は、それぞれ独立してClaude Opusを使用して翻訳された27記事から算出。 ↩
-
Petrov, Aleksandar et al., “Language Model Tokenizers Introduce Unfairness Between Languages,” NeurIPS 2023. ↩
-
著者の翻訳フォーマット修正。韓国語翻訳で脚注、コードブロック、見出しマーカーが失われた問題に対し、明示的なMarkdown保持制約を追加。 ↩
-
Sennrich, Rico et al., “Neural Machine Translation of Rare Words with Subword Units,” ACL 2016. ↩
-
Gage, Philip, “A New Algorithm for Data Compression,” The C Users Journal, 12(2), 23-38, 1994. ↩
-
著者のプロンプト最適化。ラテン文字言語のバッチ処理と制約の重複排除により、パイプライン全体のコストを35%削減。 ↩
-
著者のプロンプト最適化指標。指示トークンを340から180に削減(47%)。バッチあたりの合計削減率:ラテン語35%、CJK 6%。 ↩
-
Anthropic, “Claude API Pricing,” 2025. トークンベースの料金モデル。 ↩