Tech Learning Daily

2026-07-25 (Sat) — 第 7 号
AI が毎朝届ける、ソフトウェア技術の基礎解説
AI 🌿 基礎 ⏱ 約 7 分

「トークン」「推論」「コンテキストウィンドウ」、LLM の中で結局何が起きているのか?

Claude や ChatGPT の API を叩けば、リクエストボディに max_tokens を指定し、レスポンスには使用トークン数が返ってくる。会話が長くなるとレスポンスがじわじわ遅くなり、ある日突然「コンテキストが長すぎる」というエラーに当たる。これらの挙動は全て、LLM が文章をどう読み、どう次の一語を選んでいるかという 1 つの仕組みから説明できる。

🎯 3 行まとめ
  • LLM は文章をそのまま読むのではなく、BPE で分割した「トークン」という数値の列に変換してから処理する
  • 推論とは「これまでのトークン列の続きとして最も確率が高いトークンを 1 つ選び、末尾に足す」を繰り返す操作にすぎない
  • コンテキストウィンドウに上限があるのは、Attention の計算量とキャッシュのメモリ量がどちらも入力の長さに応じて増えていくからだ

トークン化 — 文字ではなく「トークン」を単位に見ている

LLM は文字列をそのままニューラルネットワークに渡せない。ネットワークが扱えるのは数値だけなので、まず文章をトークン(モデルが処理する最小単位で、単語より細かい部分文字列のことが多い)の列に変換し、それぞれに語彙表上の ID を割り当てる。この変換に使われる代表的な方式がBPE(Byte Pair Encoding、頻出する文字の並びを繰り返しマージしてサブワード単位の語彙を作るアルゴリズム)で、OpenAI や多くのオープンモデルの語彙構築に使われている。

「トークン=単語」ではない点が重要だ。encodingencoding のように単語の一部で分割されることがあり、逆に短い単語は 1 トークンに収まる。この語彙は学習データに含まれる文字の並びの頻度から機械的に作られるため、学習データの主流を占める言語(多くの場合英語やコード)ほど 1 トークンでまとまる範囲が広く、それ以外の言語や絵文字は 1 文字あたりのトークン数が増えやすい。

推論 — 「次の一語」を確率で選び続けているだけ

トークン列に変換された入力は Transformer に通され、各位置について「語彙表の中のどのトークンが次に来そうか」という確率分布を出力する。仕組みとしては、最終層の出力ベクトルを線形変換してから softmax にかけ、語彙表全体に対する確率を作っているだけだ。この確率分布から 1 つのトークンをサンプリングし、生成済みの列の末尾に追加し、それを含めた列を再びモデルに入力する。これを 1 トークンずつ繰り返す方式を自己回帰生成と呼ぶ。

「意味を理解してから答えを組み立てている」ように見えるが、モデルの出力インターフェースはあくまで「次の 1 トークンの確率」であり、文全体の答えを先に確定してから言葉にしているわけではない。API の temperature パラメータはこのサンプリングの分散を調整するもので、0 に近いほど最も確率が高いトークンを毎回選びやすくなり、出力が決定的に近づく。

┌──────────────┐
│  入力テキスト  │
└──────┬───────┘
       ▼
┌──────────────┐
│ トークン化(BPE)│
└──────┬───────┘
       ▼
┌──────────────┐
│ Transformer   │
│ + Attention   │
└──────┬───────┘
       ▼
  次トークンの確率分布
       ▼
   1 つサンプリング
       │
       ▼
 列の末尾に追加して
    最初から繰り返す
🍱 たとえるなら

同時通訳者を思い浮かべてほしい。話者の発言をまるごと録音し直して毎回頭から聞き返すのではなく、それまで自分が書き留めた要点メモを手元に置いたまま、次の一言だけを組み立てる。メモのページが増えるほど(=コンテキストが長くなるほど)目を通す量も机に広げておく分量も増えていく。机の広さに限りがある以上、メモのページ数を無限には増やせない——これがコンテキストウィンドウに上限がある理由と同じ構造だ。

コンテキストウィンドウ — なぜ無限に伸ばせないのか

Transformer の中核であるAttention(自己注意機構。各トークンが、それ以前の全トークンとの関連度を計算して次の予測に反映する仕組み)は、入力長 N に対して計算量が N の 2 乗で増える。トークンが増えるほど、参照しなければならない過去のトークンの組み合わせが掛け算的に増えるためだ。これがコンテキストウィンドウ(一度に入力できるトークン数の上限)が有限である根本的な理由になる。

とはいえ生成のたびに全トークンの Attention を毎回ゼロから計算し直しているわけではない。各トークンが 1 度計算した Key・Value のベクトルは以降変わらないため、これをKVキャッシュとして保持しておき、新しいトークンを生成するたびにその 1 個分だけ Key・Value を追加計算する。これにより 1 トークン生成あたりの計算量は入力長に対してほぼ線形まで抑えられる。ただしキャッシュ自体のメモリ量はトークン数に比例して増え続けるため、コンテキストが長くなるほどメモリ使用量が膨らみ、GPU のメモリ容量がもう一つの上限として効いてくる。

💼 実務でどう出会うか

API 課金がトークン単位なのは、計算コストがトークン数にほぼ比例するからだ。チャットボットで会話が長引くほど最初の応答が出るまでの待ち時間(プロンプト全体の Attention を計算する prefill フェーズ)が延びるのも同じ理由による。コンテキストウィンドウを超えるとエラーになったり、古い発言が自動で切り捨てられたりするのは、モデルが「忘れている」のではなく、そもそも入力として渡せる範囲に物理的な上限があるからだ。長い会話を要約してから渡す設計や、関連する部分だけを検索して渡す RAG は、この上限を回避するための実務上の工夫にあたる。

⌨️ 手を動かす(5 分)

同じ意味の英語と日本語で、実際に何トークンに分割されるかを比較する。OpenAI のトークナイザ実装 tiktoken を使う。

pip install --quiet tiktoken
python3 - <<'PY'
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4o")
en = "The quick brown fox jumps over the lazy dog."
ja = "素早い茶色の狐がのろまな犬を飛び越える。"
print("EN:", len(en), "文字 ->", len(enc.encode(en)), "トークン")
print("JA:", len(ja), "文字 ->", len(enc.encode(ja)), "トークン")
PY

文字数はほぼ同じなのに、トークン数は言語によって差が出るはずだ。これは学習データにおける文字の並びの出現頻度に応じて BPE の語彙が作られているため、語彙の「主流」から外れた言語ほど 1 文字あたりのトークン数が増えやすいことを示している。

🙅 よくある誤解
  • LLM は質問の意味を理解してから、答え全体を決めて話し始める — モデルの出力は常に「次の 1 トークンの確率分布」であり、生成は 1 トークンずつ逐次的に進む。文全体の結論を先に確定してから言葉にしているわけではない。
  • コンテキストウィンドウが大きいほど、それだけ多くの情報を"記憶"しておける — ウィンドウを超えた古い発言は次のリクエストの入力から物理的に切り捨てられる。「記憶」ではなく、その回のリクエストで一緒に読める範囲の上限にすぎない。
  • トークンはだいたい単語と同じ — 実際はサブワード単位で、英語の一般的な単語は 1 トークンに収まりやすい一方、日本語・絵文字・専門用語などは 1 語が複数トークンに分割されることが多い。
📖 用語ミニ辞典
トークン
LLM が処理する最小単位。単語より細かいサブワードであることが多い。
BPE(Byte Pair Encoding)
頻出する文字の並びを繰り返しマージしてサブワード語彙を作るトークン化アルゴリズム。
自己回帰生成
直前までのトークン列から次の 1 トークンを予測し、末尾に追加する処理を繰り返すことで文章を生成する方式。
Attention(自己注意機構)
各トークンがそれ以前の全トークンとの関連度を計算し、次の予測に反映する Transformer の中核機構。
KVキャッシュ
各トークンの Key・Value ベクトルを再利用のために保持し、生成のたびに全体を再計算しなくて済むようにする仕組み。
コンテキストウィンドウ
1 回の推論でモデルに入力できるトークン数の上限。
🔗 もっと深く