トークンとトークン化:モデルが消費する内容を理解する LLM
LLMは単語や文字ではなく、トークンを読みます。トークンとは、トークン化と呼ばれる処理でテキストを分割して得られる断片です。この目に見えない単位が、モデルがどれだけ記憶できるか、どれくらい速く応答するか、そして同じ内容でもフランス語のテキストが英語より「重く」なる理由まで、すべてを左右します。このガイドでは、トークンとは何か、LLMのトークン化がどのように機能するか、そしてローカルでモデルを動かす際にそれが何に影響するかを具体的に解説します。
#トークンについて話す理由
OllamaやLM Studioを使ってローカルLLMと会話するとき、入力するのは文章です。しかし、モデルがその文章をそのまま見ることはありません。最初の計算が行われる前に、テキストは数値の列に変換され、それぞれの数値が1つのトークンを表します。理解や生成など、モデルが行うすべての処理は、単語ではなく、これらのトークンの単位で行われます。
トークンを理解することは、単なる学術的な細部の話ではありません。非常に具体的な3つのことを理解する鍵になります。文書がコンテキストウィンドウに「収まる」かどうか、モデルがその速度で生成する理由(いわゆる毎秒トークン数)、そしてクラウドAPIの課金やコンテキストの上限が、単語ではなく常にトークン単位で数えられる理由です。
#トークンとは正確に何ですか
お使いのマシンで、プライベートかつ無料のChatGPTを1時間で構築 — LM Studio、Ollama、Open WebUI、ご自身のドキュメント、クラウド不要。
- 永久に利用できるオンラインスペース
- PDF + ファイル
- 生涯アップデート
トークンとはテキストの断片です。ときには単語全体、ときには単語の一部、あるいは単一の文字や記号です。これは文字や単語そのものではなく、テキストを最も効率的に表現するためにアルゴリズムが選択した統計的な単位です。
最も有用な経験則:英語では1トークン ≈ 4文字 ≈ 0.75語です。つまり、100トークンは約75語の英語に相当します。フランス語ではこの比率ははるかに不利であり、後ほど詳しく説明します。
- "chat"
- 頻出で短い単語:多くの場合、1つのトークンのみ。
- "anticonstitutionnellement"
- あまり使われない長い単語:複数のトークンに分割されます(anti / constitution / nelle / ment…)。
- " "(スペース)
- スペースは通常、単独のトークンにはならず、次のトークンの先頭に含まれます。
- "123456"
- 数字はしばしば桁ごとまたは小さなグループごとに分割されます。
- 😀
- 1つの絵文字だけで、複数のトークンを消費する場合があります。
非常によく使われる単語は、学習データの至る所に現れるため、1つのトークンが割り当てられます。珍しい単語や専門用語、学習データにあまり含まれていない言語の単語は、より小さな断片を組み合わせて再構成されるため、必要なトークン数が多くなります。
#テキストが実際にどのように分割されているか
現在のLLMの多くは、BPE(Byte Pair Encoding)と呼ばれるアルゴリズム群、またはその変種(WordPiece、Unigram)を使用しています。基本的な仕組みは、個々の文字から始め、学習コーパスで最も頻出する記号のペアを順次結合し、一定のサイズの語彙を作るというものです。語彙サイズはモデルによって異なりますが、通常は32,000〜200,000トークンです。
- 01初期分割テキストは、基本単位であるバイトまたは文字に分解されます。情報は失われず、どのような文字列でも表現できます。
- 02学習済みの結合トークナイザーは、学習時に得たマージのリスト(例:「t」+「ion」→「tion」)を頻度順に適用します。
- 03識別子への変換最終的な各トークンは、語彙内の対応する番号に置き換えられます。以降、モデルはこれらの整数だけを扱います。
重要な点として、語彙は学習時に固定されます。主に英語で学習したモデルは、英語向けに最適化された語彙を持ち、フランス語をより小さく、より多くの断片に分割します。これが、フランス語でコストが増える根本原因です。
#フランス語のコストが英語より高い理由
同等の内容において、フランス語のテキストは英語の翻訳に比べて、一般的に15〜30%多くのトークンを消費します。英語に特化した一部のモデルでは、この差は50%を超えることもあります。その理由として、三つの要因が重なります。
- 語彙の不均衡
- トークナイザーは主に英語データで訓練されています。頻出の英単語には専用のトークンが割り当てられますが、フランス語の単語にはそのような対応がありません。
- アクセントや特殊文字
- é、è、à、ç、œ などは語彙に含まれる頻度がより低く、複数のトークンに、場合によってはバイト単位に分割されることがあります。
- 語形変化がより豊富
- 動詞の活用、性・数などの一致、母音省略(l'、d'、qu')によって同じ単語に多くの語形が生じ、これらの語形は語彙で十分にカバーされにくくなります。
具体例として、英語の文「The cat is on the table」は約6トークンです。フランス語版の「Le chat est sur la table」は、モデルによって7〜8トークン程度になります。段落全体になると、この差は無視できなくなり、コンテキストウィンドウ内で占める容量と生成時間の両方に負担がかかります。
#トークンとコンテキストウィンドウ
モデルのコンテキストウィンドウは、単語数や文字数ではなく、トークン数で測ります。コンテキストが32,768トークンとされているモデルは、一度に英語約24,000語分の情報を「見る」ことができます。ただし、フランス語ではトークン化に必要なトークン数が増えるため、約18,000〜20,000語にとどまります。
このウィンドウにはすべてが含まれます:システムプロンプト、会話履歴、現在のメッセージ、貼り付けられたドキュメント、および生成中の回答です。総容量が上限を超えると、モデルは通常最も古い部分を切り捨て、「会話の初期部分を忘れる」ことになります。
- システムプロンプト
- 呼び出しのたびにカウントされます。冗長なシステムプロンプトは、毎回コンテキストの容量を消費します。
- 履歴
- 会話のやり取りは一回ごとに蓄積されます。会話が長くなると、やがてコンテキストウィンドウがいっぱいになります。
- ドキュメント(RAG、コピー&ペースト)
- 10ページのPDFでも、数千トークンになることは珍しくありません。
- 生成された回答
- 出力にも容量が必要です。回答を生成するための余裕を確保しておく必要があります。
#トークンとローカルでの速度
LLMの速度は、1秒あたりのトークン数(tok/s)で測定します。これはベンチマークで共通して使われる単位です。よく混同されますが、区別すべき段階が2つあります。
- プロンプト/プリフィル
- プロンプト全体を「読み込む」までの時間。入力トークンが増えるほど、最初の応答が遅延します。
- 生成 / デコード
- 応答トークンが1つずつ出力される速度です。画面上で観察されるtok/sのことです。
これはフランス語での利用に直接影響します。同じ内容でもトークン数が多くなるため、モデルがフランス語のプロンプトを処理し、同じ長さのフランス語の回答を生成するには、必然的により多くの時間がかかります。「フランス語だと遅い」という感覚は主観的なものではなく、トークン数に起因するものです。
デコード速度は主にモデルとハードウェア(トークンごとのアクティブパラメータ数、メモリ帯域幅、量子化)に依存します。ただし、ハードウェアが固定されている場合、入力トークンの数を減らす(システムプロンプトを短く、履歴を簡素化)ことで、最初のトークンまでの時間(time-to-first-token)が著しく短縮されます。
#テキスト内のトークン数を自ら数える
直感を得る最善の方法は、測定することです。最も簡単なものから最も正確なものまで、3つのアプローチをご紹介します。
#概算で推定
何もインストールせずに手早く見積もるには、英語なら文字数を4で、フランス語なら3〜3.5で割ってください。大まかな計算ですが、文書がコンテキストウィンドウに収まるかどうかを判断するには十分です。
#実際のトークナイザーを使ってPythonでトークン数を数える
正確なカウントを行うには、モデルのトークナイザーを使用してください。Hugging Faceのtokenizers / transformersライブラリは、オープンウェイトモデルの実際のトークナイザーを読み込みます。
自分の文章を使ってこのスクリプトを実行するのが、最も実感しやすい演習です。フランス語のどの単語が分割されるのか、英語がどれだけコンパクトになるのかを、自分の目で確認できます。
#Ollama APIからトークン数を読み取る
Ollamaは、応答にトークン数をすでに含めています。デーモンはデフォルトで http://localhost:11434 で待ち受けます。APIを呼び出すと、prompt_eval_count(プロンプトのトークン数)と eval_count(生成されたトークン数)が返されます:
そこには eval_duration も表示されます。eval_count をその時間で割ると、ご自身のマシンと量子化設定での実際の処理速度をトークン/秒で求められます。
#品質を落とさずにトークンを節約する
トークンが増えるほどコンテキスト容量を消費し、処理速度も低下するため、いくつかの簡単な習慣で大きな違いが生まれます。特にフランス語では効果があります。
- 簡潔なシステムプロンプト
- 呼び出しのたびに再送されます。余分な一文ごとに、毎ターンコストがかかります。
- 履歴を整理する
- 会話全体を毎回引き継ぐのではなく、古いやり取りを要約するか削除してください。
- すべてを貼り付ける代わりにRAGを使う
- ドキュメント全体ではなく、関連する箇所だけを入力してください。
- 出力長を指定
- 短い回答を要求するとトークン数が減り、結果としてより速く処理できます。
#さらに詳しく
トークンは、いくつかの基本概念をつなぐものです。このガイドの内容をさらに掘り下げる3つのガイドがあります。1つ目は、トークンが収まるコンテキストウィンドウについて詳しく説明します。2つ目は、1秒あたりのトークン数で測る速度に量子化がどう影響するかを説明します。3つ目は、Transformerがこれらのトークンを内部でどう処理するかを示します。
ご意見、誤りのご指摘、補足はありますか?ぜひお知らせください。皆さんにとってより良いガイドにするために役立ちます。