- 「プロンプトを送って返事が返ってくる」の裏で、文章がどうやって「トークン」という単位に分解され、どこまでが1回の処理の枠(コンテキストウィンドウ)に収まるのか
- モデルがなぜ回答を一気に返さず1トークンずつ生成するのか、そしてなぜ2つ目以降のトークンは速くなるのか
- 1回のやり取りが、実は「前回の会話を覚えていないAPI」への毎回まるごとの送信であること
- Anthropic・OpenAIのようなAPI型サービスを使う場合と、vLLMのような自前ホスティング型を使う場合とで、エンジニアが自分で管理するものがどう入れ替わるか
- これから読む10の質問が、この一連の流れのどこを指しているか
「AI開発」はトークンとコンテキストウィンドウから始まる
「AI開発してます」という一言が指す仕事の幅は広い。本書では、モデルをゼロから学習させることではなく、すでにできあがった大規模言語モデル(LLM。Large Language Modelの略。大量の文章を学習し、続きの文章を予測して生成するモデル)をAPI経由、あるいは自分でサーバーを立てて呼び出し、その入力と出力を設計・運用する仕事を指す。元になった投稿の10の質問——コンテキストの扱い方・キャッシング・レイテンシ(応答が返るまでの時間)・量子化・コンテキストウィンドウの調整・ツール呼び出し・監視・モデル選定・バッチ処理・プロンプトインジェクション防御——は、すべてこの「呼び出しをどう設計し運用するか」に関わる。まずはその土台になる、1回の呼び出しで何が起きているかを順番に見ていく。
LLMは文章をそのまま読んでいるわけではない。送った文章はまずトークンという最小単位に分解される。トークンは単語・単語の一部・文字、あるいは(文字コードUnicodeの都合で)バイト(= コンピュータがデータを扱う最小単位)のいずれにもなりうる、モデルが実際に扱う最小の単位だ。Anthropicの用語集は「Claudeの場合、1トークンはおよそ英語3.5文字に相当するが、正確な数は言語によって変わる」と説明している。公式のFAQでは英語で1トークン≒4文字、または0.75単語という目安も示されている。現行のトークナイザでは、100万トークンがおよそ英語55.5万語、Unicode文字数にして250万文字に相当するという換算も公式のモデル一覧ページが示している(2026-08時点)。ただしこの換算はClaude Opus 4.7以降の新しいトークナイザでの値で、Anthropicは「同じ文章で従来より約30%多くのトークンを生む」と明記している(旧トークナイザでは100万トークン≒75万語)。上の3.5文字・4文字という目安と数字が合わないのはこのためで、トークン数はモデルの世代によっても変わる。たとえばOpenAIが公開しているトークナイザtiktokenはBPE(Byte Pair Encoding)という方式を使う。BPEはトークン列から元の文章に戻せる可逆な方式で、学習データにない文字列にも対応でき、"encoding"を"encod"と"ing"に分けるように、よく出てくる部分文字列ごとに区切ることで圧縮する。料金はトークン数で決まり、レート制限(一定時間あたりに送れる量の上限)もリクエスト数と並んでトークン数を単位に設定される。
文章がトークンになった後、それがどこまで一度に「見える」かを決めるのがコンテキストウィンドウ(モデルの作業机の大きさ)だ。Anthropicは「コンテキストウィンドウとは、応答を生成する際にモデルが参照できるすべてのテキストを指し、生成される応答そのものも含む」と定義している。学習に使った膨大なデータとは別物で、いわば今回の作業のための一時的な記憶である。ここが誤解されやすい点で、コンテキストウィンドウは入力の上限ではない。システムプロンプト(モデルへの土台となる指示)・これまでの会話・ツール(= モデルが呼び出せる外部の機能。後の『1回のやり取りの中身』の節で説明)の定義とその実行結果・そしてこれから生成する出力まで、すべてを合算した1つの上限だ。図1-1は、その中身を示したものである。
モデルは1語ずつ返す — prefillとdecode、KVキャッシュ
LLMの生成は「自己回帰的(autoregressive)」と呼ばれる方式で進む。Hugging Faceの説明によれば、モデルは「これまでのプロンプトと、自分がここまで生成した出力」をもとに次の1トークンを予測する、という処理を、あらかじめ決めた長さに達するか、文の終わりを示す特別なトークン(EOSトークン)が出るまで繰り返す。つまり応答は一括で作られるのではなく、1トークンずつ、モデルへの呼び出しを何度も繰り返して積み上げられる。
この処理はさらに2つの段階に分かれる。最初にプロンプト全体をまとめて読み込み、最初の1トークンを作るまでの段階がprefill(読み込み段階)、そこから先、出力トークンを1つずつ生成し続ける段階がdecode(書き出し段階)だ。prefillは入力全体が最初から分かっているため並列に計算しやすく、GPU(= 大量の計算を同時にこなす演算装置。LLMの計算はほぼこれで行う)の計算能力を使い切りやすい。一方decodeは1回ごとに1トークン分の計算しかしないため、計算そのものより「必要なデータをメモリから読み出す速さ」がボトルネックになりやすい。最初の1トークン(≒最初の文字)が出るまでの時間を指す「TTFT(Time to First Token)」はこのprefillの長さ(混雑時は処理の順番待ちの時間も加わる)にほぼ対応し、応答全体が終わるまでの時間はTTFTとdecodeの合計になる。図1-2はこの2段階を時間軸で示したものだ。
decodeが1トークンごとに何度もモデルを呼び出すにもかかわらず致命的に遅くならないのは、KVキャッシュという仕組みがあるからだ。Hugging Faceの説明では、各トークンの注意計算(attention。どのトークンにどれだけ注目するかを計算する仕組み)に使うキー・バリューという中間値をメモリに保存しておき、次のトークンを生成するときに再計算せず使い回す。キャッシュが無ければ、ステップが進むたびにそれまでの全トークン分のキー・バリューを毎回計算し直すことになり、計算量はステップ数の二乗で増える。キャッシュがあれば、そのステップで新しく出てきたトークンの分だけを計算すればよく、計算量はステップ数にほぼ比例するだけで済む(メモリの使用量は増え続ける)。図1-3はこの違いを示している。この「直前までの計算結果を保存して使い回す」という発想は、次章以降で扱う「プロンプトキャッシュ」という機能の土台にもなっている。
1回のやり取りの中身 — 覚えていないAPI・役割・ツール呼び出し
実際にLLMを呼び出すAPIの多くはステートレス、つまり前回のやり取りを覚えていない。Anthropicは「Messages APIはステートレスであり、常に会話の全履歴を送信する」と明記しており、OpenAIも「各テキスト生成リクエストは独立してステートレスだが、追加のメッセージをパラメータとして渡すことで複数ターンの会話を実現できる」と説明する。つまり2回目のやり取りでも、1回目の内容をこちらがすべて含めて送り直す。会話が長くなるほど、毎回送るトークン数、つまりコンテキストウィンドウの消費量も増えていく。
送る内容には「役割(ロール)」がある。指示を与える立場としてsystem(またはOpenAIのdeveloper)、実際の利用者からの入力としてuser、モデル自身の応答としてassistantがある。developerが規則を決め、userがその規則を当てはめる具体的な入力を渡す、という優先順位の階層だ。OpenAIはこれを「プログラミング言語における関数と引数のようなもの」にたとえている。
もう1つ重要なのがツール呼び出し(tool calling、function callingとも呼ぶ。モデルが外部の機能を使えるようにする仕組み)だ。Anthropicの説明では、モデルは呼び出したいツールと引数を「構造化された呼び出し」として返し、それをアプリ側(client tools)またはAnthropic側(server tools)が実行する。つまりモデル自身はツールを実行しない。流れはこうだ。①アプリがモデルにツールの一覧を渡してリクエストする、②モデルが「このツールをこの引数で呼びたい」という応答を返す、③アプリ側(またはAnthropic/OpenAI側)が実際にそのツールを実行する、④実行結果を次のリクエストでモデルに返す、⑤モデルが最終的な応答を返す。モデルは関数を「呼ぶ」のではなく「呼んでほしいと言っているだけ」であり、実行と結果の検証はアプリ側の責任だ。この点は後の章(ツール呼び出しの信頼性)で詳しく扱う。
応答を一気に受け取るのではなく、生成されるトークンをその都度クライアント(= APIを呼び出す側のアプリ)に送るストリーミングという方式もよく使われる。1トークンずつしか生成されないという性質をそのままクライアントに見せる仕組みで、ユーザーが待たされる体感の時間を減らす効果がある。
API型と自前ホスティング型 — 誰が何を管理するか
トークン数やコンテキストウィンドウの上限はAPI利用者にも料金・エラーとして見えるが、その裏側の実装——prefill/decodeの実行、KVキャッシュの管理、複数リクエストの同時処理(バッチング)、量子化——は、AnthropicやOpenAIのようなAPI型サービスを使う限り利用者からは見えない。これらはすべてサービス側が内部で管理し、利用者は入力を送って出力を受け取るだけでよい。
一方、vLLMのようなサーバーソフトウェアを使って自分でモデルをホスティングする場合、これらは自分で設定する対象になる。たとえばvLLMは、複数のリクエストを同時に処理する仕組み、メモリを効率よく使う仕組み、共通する接頭辞(= プロンプトの先頭部分)のKVキャッシュを使い回す仕組み、メモリを減らす量子化(= 重み〈モデル内部の膨大な数値〉の精度を落として軽くする手法)などを自分の設定項目として持ち、OpenAI互換のAPIサーバーとして起動できる。つまり同じアプリのコードでも、呼び出す相手をAPI型から自前ホスティング型に切り替えると、それまでサービス側に任せていた実装が、自分でチューニングしなければならない設定値に変わる。図1-4はこの違いを示している。なお、レート制限や課金の条件はAPI型ではサービス側が決めるものであり、自前ホスティングでは自分で別途用意する必要がある。10の質問のうち、量子化やバッチ処理を扱うものは、主にこの自前ホスティング側の実務を指している。
cache_controlというパラメータでキャッシュしたい範囲を指定できるが、KVをどう保存し再利用するかの実装はサービス側にある。vLLMのような自前ホスティング型では、同じ機能がそれぞれ自分で設定するパラメータになる。この流れに10の質問を重ねる
ここまで見てきた「トークン化 → コンテキストウィンドウ → prefill/decode(KVキャッシュ) → API呼び出し(ロール・ツール・ストリーミング) → API型/自前ホスティング型の分担」という流れの、どこを指しているのかを整理すると、元投稿の10の質問は次のように対応する。
| 質問 | この流れの中の位置 | 詳しく扱う章 |
|---|---|---|
| Q1 コンテキストの扱い方 | コンテキストウィンドウに何をどう詰めるか(入力側の設計) | 第2章 |
| Q2 キャッシングの使い分け | プロンプトキャッシュ(KVキャッシュをサービスとして使い回す)と、応答そのものを使い回すセマンティックキャッシュ | 第3章 |
| Q3 推論レイテンシの改善 | prefillとdecodeのどちらが遅いかの切り分け | 第5章 |
| Q4 量子化の導入判断 | 自前ホスティング側でモデルの重みやKVを軽くする手段 | 第6章 |
| Q5 コンテキストウィンドウの調整 | 上限に近づいたとき何を残すか(入力側の運用) | 第4章 |
| Q6 ツール呼び出しの信頼性 | モデルの呼び出し要求をアプリがどう実行・検証するか | 第8章 |
| Q7 LLMの監視・運用 | 1回のやり取りごとの使用量・停止理由をどう見るか | 第9章 |
| Q8 モデル選定の判断基準 | この一連の処理をどのモデルに任せるか | 第10章 |
| Q9 バッチ処理とスループット | 複数の「1語ずつ返す」処理を自前ホスティング側でどう同時に捌くか | 第7章 |
| Q10 プロンプトインジェクション防御 | 外部由来のテキストも区別なくコンテキストウィンドウに入ることの危険 | 第11章 |
つまずきポイント
「トークン数=文字数」だと思っていた。トークンは単語でも文字でもない。英語ならおおよそ4文字で1トークンという目安があるが、これは英語での目安であり、言語やモデルの世代によって変わる。実際、Claude 4.7以降の新しいトークナイザは同じ文章で旧世代より約30%多くのトークンを生む。画像・ファイル・ツール定義には「文字数÷4」は使えないとOpenAIも明記している。正確に知りたければトークン数を数えるAPI(Anthropicのcount_tokensは無料)を使う。
「コンテキストウィンドウ=入力の上限」だと思っていた。「大きなモデルだから、大きな資料を入れても大丈夫」と思いがちだが、コンテキストウィンドウは入力だけでなく、モデルが生成する出力(考える過程を含む)も同じ枠を消費する。入力だけでほぼ埋まっていれば、出力の途中で上限に達して応答が途切れることもある。
「APIは前回の会話を覚えている」と思っていた。チャット画面で会話が続いているように見えても、APIの多くは前回のやり取りを保存していない。アプリ側が毎回、これまでの会話をすべて含めて送り直しており、会話が長引くほど毎回のリクエストで送るトークン数が増えていく。
「大きいモデル・大きいウィンドウを使えば全部解決する」と思っていた。コンテキストウィンドウを大きくしても、詰め込む情報を増やすほど良い結果が出るとは限らない。トークン数が増えるほどモデルが情報を正確に思い出す精度が落ちる「context rot」という現象が知られており、Anthropicも、コンテキストは足せば足すほど1トークンあたりの効果が小さくなる有限の資源(Anthropicの表現では「限界効用が逓減する有限資源」)と位置づけている。この点は次章以降で詳しく扱う。
理解度チェック
Q1. トークンとは何ですか?単語や文字と何が違いますか?
トークンはモデルが実際に扱う最小単位で、単語・単語の一部・文字・バイトのいずれにもなりうる。英語ではおよそ4文字、または0.75単語で1トークンという目安があるが、言語やモデルの世代によって変わる。
Q2. コンテキストウィンドウには、入力以外に何が含まれますか?
システムプロンプトや会話履歴、ツールの定義・実行結果に加えて、モデルが生成する出力(考える過程も含む)も同じ枠に数えられる。
Q3. decode(2トークン目以降の生成)は、なぜprefillに比べて1ステップあたりの効率が悪いのですか?
prefillは入力全体をまとめて並列処理できるが、decodeは1トークンずつしか処理できない。計算そのものより、必要なデータをメモリから読み出す速さがボトルネックになるためだ。
Q4. KVキャッシュがあると何がどう変わりますか?
各ステップで過去のトークンすべてを再計算する必要がなくなり、新しく出てきたトークンの分だけ計算すればよくなる。計算量はステップ数の二乗ではなく、ほぼ比例で済むようになる。
Q5. 同じアプリのコードで、呼び出す相手をAPI型から自前ホスティング型(vLLMなど)に切り替えると、何が変わりますか?
それまでサービス側が内部で管理していたバッチ処理・キャッシュ・量子化・ストリーミングといった機能が、自分で設定・チューニングする対象に変わる。
まとめ
- プロンプトはまず「トークン」という単位に分解され、料金もレート制限もこの単位で決まる
- コンテキストウィンドウは入力だけでなく出力までを含む1つの上限であり、大きければよいわけではない
- 生成はprefill(読み込み)とdecode(1トークンずつの書き出し)の2段階からなり、KVキャッシュのおかげでdecodeの計算量は積み上がらずに済む
- APIの多くはステートレスで、毎回の会話全体を送り直している。ツール呼び出しも、モデルは実行を「依頼するだけ」で、実行と検証はアプリ側の役割になる
- API型サービスと自前ホスティング型では、同じ機能でも「サービスに任せるもの」と「自分で設定するもの」が入れ替わる
次章では、この流れの入力側にあたる「コンテキストの扱い方(Q1)」を、実務でどう設計しているかを見ていく。
参考リンク
- Claude Developer Platform: Glossary
- Claude Developer Platform: Models overview
- Claude Developer Platform: Token counting
- OpenAI tiktoken: README(BPEの説明)
- OpenAI API Docs: Token counting
- NVIDIA Developer Blog: LLM Benchmarking — Fundamental Concepts
- Claude Developer Platform: Context windows
- Claude Developer Platform: Working with messages
- Claude Developer Platform: Tool use overview
- Anthropic Engineering: Effective context engineering for AI agents
- Hugging Face Transformers: KV cache explanation
- vLLM Documentation
- NVIDIA Developer Blog: Mastering LLM Techniques — Inference Optimization
- OpenAI Platform Docs: Latency optimization
- OpenAI API Docs: Function calling