23 分で読了 #ai #models-and-context
このページの目次

コンテキストエンジニアリング

モデルはステートレスです——モデルが「知っている」ことはすべて、リクエストごとのコンテキストウィンドウ内にあります。ウィンドウを予算として管理してください: 安定したプレフィックスをキャッシュし、古い履歴を圧縮し、ツールを必要に応じて読み込み、無秩序に詰め込まないでください。ウィンドウ管理はエージェント性能の最も重要な変数です。

概要

大規模言語モデル(LLM)は、1つのリクエストに対してステートレスです: 前回の会話を覚えておらず、隠れた「記憶」も持っていません。モデルが世界について知っていることはすべて、そのリクエストに詰め込まれたテキスト——⁠コンテキストウィンドウ(context window)——のみです。「コンテキストエンジニアリング(context engineering)」とは、この有限で高価、かつ位置に敏感なウィンドウ内で、より正確で、速く、安価な出力を得るために、何を、どこに、どのように再利用するかを決定することです。

この作業が重要な理由は、LLM に対する直感がしばしばずれているからです: 「より多くの資料を投げ込めば、答えは良くなるはずだ」と思われがちです。実際にはウィンドウには上限があり(Claude Opus 4.8 は 1M トークン)、注意機構の計算量は長さに対して ~O(n²) で増加し、さらにモデルはウィンドウの中間にある情報を「見落とし」がちです。ウィンドウを底なしのゴミ箱ではなく、⁠予算として管理することが、現代のモデルを効果的に使うための第一原則です。

歴史的に見れば、これは「プロンプトエンジニアリング(prompt engineering: どのように表現するか)」から進化してきました: 単発の短いプロンプトの時代には、表現がすべてでした。しかし、長いコンテキスト、ツール呼び出し、マルチターンエージェントの時代に入ると、⁠ウィンドウに何が、どのような順序で、どれほどキャッシュできるかが支配的な要因となりました。Anthropic は 2024–2026 年にかけて、プロンプトキャッシュ、コンパクション、コンテキスト編集、適応的思考などを API プリミティブとして順次実装しましたが、これらは本質的にコンテキストエンジニアリングのツールです。

モデルが1リクエストで「知っている」のはコンテキストウィンドウのみ

/v1/messages へのリクエストごとに、モデルは以下のように連結されたテキストを見ます(レンダリング順序は tools → system → messages で固定です):

1つのリクエストのコンテキストウィンドウ: tools → system → messages を連結してモデルに入力 コンテキストウィンドウ(レンダリング順序は固定) tools ツール定義(name / description / JSON schema) system システムプロンプト(ロール、ルール、安定した指示) messages 履歴(user/assistant のターン、過去の tool_use/tool_result を含む) 検索結果(RAG でヒットしたドキュメント断片) 今回の user 入力 モデル(ステートレス) output(thinking / text / tool_use) モデルが前回のターンを「覚えている」のは、呼び出し元が履歴全体を再送信したからです——API 自体はステートレスです。 「記憶」は呼び出し側が管理し、ウィンドウ内の内容と順序こそが、モデルにとってのそのターンにおける「認知」のすべてです。

重要な結論: モデルが前回のターンを「覚えている」のは、⁠呼び出し元が履歴全体を再送信したからです。API はステートレスであり、「記憶」は呼び出し側が管理します。これにより、長い対話ほど高価になる理由も説明できます——各ターンで履歴全体を再送信しなければならないためです。

トークンと注意機構: なぜ長くすると高価で遅くなるのか

テキストはまずトークナイザー(tokenizer)⁠によってトークンに分割されます(Claude のトークンは OpenAI のトークンとは異なり、tiktoken で Claude を推定しないでください。15–20% 少なく見積もられます。正確にするには count_tokens を使用してください)。課金、レートリミット、ウィンドウ上限の単位はすべてトークンです。

長さには2つのコストが生じます:

  • 計算量 ~O(n²): 自己注意機構(self-attention)により、各トークンは他のすべてのトークンに注意を払います。シーケンスが2倍になると、計算量は約4倍になります。これが「長くすると遅くなる」根本原因です。
  • KV キャッシュのVRAM: 各トークンを生成するたびに履歴を再計算しないよう、推論エンジンは履歴の各層の Key/Value をキャッシュします。VRAM はコンテキストの長さに対して線形に増加します。ローカル展開では特にリソースが逼迫します——ローカル LLM 展開を参照してください: 64k コンテキストの f16 KV キャッシュには約 5.37 GB 必要で、24GB のカードには収まりません。Q8_0 に量子化して約 2.85 GB に圧縮する必要があります。クラウド API ではこの VRAM が直接見えませんが、これが「長いコンテキストほど高価になる」物理的な理由です。

KV キャッシュ(推論エンジンが高速化のためにキャッシュするテンソル)と、以下の プロンプトキャッシュ⁠(API がコスト削減のためにキャッシュするプレフィックス)は、異なる階層の「キャッシュ」です。混同しないでください。前者は単一の生成内の高速化であり、後者はリクエスト間でプレフィックスを再利用することです。

コンテキスト予算: 誰がウィンドウを奪い合うのか

ウィンドウを予算として配分してください。同じウィンドウは以下の要素によって分けられ、どれを削ってもパフォーマンスに影響します:

占用元典型サイズ管理手法
ツール定義 tools数十〜数千トークン/ツールツールが多い場合はツール検索で必要に応じて読み込み; 一度にすべて詰め込まない
システムプロンプト system固定凍結する(キャッシュ参照); タイムスタンプを挿入しない
履歴 messages対話に応じて線形に増加コンパクション / コンテキスト編集
検索結果 RAG制御可能検索を硬貼付けより優先: ヒットした断片のみを配置し、データベース全体を詰め込まない
出力 outputmax_tokens で予約ストリーミング + 適切な max_tokens
thinkingeffort で決定effort で調整し、硬貼付けしない

よくある誤解として、知識ベース全体をシステムプロンプトに貼り付けることが挙げられます。正しいアプローチは RAG です: まず検索し、関連する断片のみをウィンドウに配置します。検索の精度が、コンテキストの長さよりも答えの品質をより決定します——この点は RAG と検索強化 で詳しく展開します。

プロンプトキャッシュ: 安定したプレフィックスをキャッシュする

マルチターン対話やエージェントループでは、リクエストごとのプレフィックス(ツール定義 + システムプロンプト + 長い履歴)が高度に重複します。⁠プロンプトキャッシュはこの安定したプレフィックスをサーバーサイドでキャッシュし、その後のヒットは約 0.1x の価格で課金されます(書き込み後 5 分間の TTL は 1.25x、1 時間 TTL は 2x)。

その動作はすべて、以下の不変量から導き出されます:

プロンプトキャッシュはプレフィックスマッチ(prefix match)です。プレフィックス内のバイトが1つでも変わると、その位置以降のキャッシュはすべて無効になります。

レンダリング順序は tools → system → messages であるため、キャッシュの境界は「安定/可変」の境界で切る必要があります:

プロンプトキャッシュの境界: cache_control ブレークポイント前後で価格が激変 cache_control ブレークポイント 安定プレフィックス ツール定義(順序固定)+ 凍結されたシステムプロンプト 可変サフィックス 今回の可変する質問 キャッシュヒット、約 0.1x 課金 フル価格課金 ブレークポイント前のバイトは1つたりとも変えてはならず、キャッシュにヒットします。ブレークポイント後は今回の新規可変内容であり、 キャッシュマッチの対象外でフル価格課金——したがって、安定したものを前に、可変するものを後ろに配置します。

実務上のポイント:

  • 安定したものを前に、可変するものを後ろに。 システムプロンプト内に now()、UUID、ユーザーID、ランダムIDを挿入しないでください⁠。これらがプレフィックス内にあると、以降すべてが無効になります。動的な情報は messages の後ろの位置に配置してください。
  • ブレークポイント⁠: 安定プレフィックスの最後のブロックに cache_control: {type: "ephemeral"} を設定します(またはトップレベルの自動キャッシュを使用)。リクエストあたり最大4つのブレークポイントまで。
  • 最小キャッシュ可能プレフィックスはモデルに依存します: Opus 4.8 は 4096 トークン、Sonnet 4.6 / Fable 5 は 2048 トークン——プレフィックスが短すぎると静かにキャッシュされず⁠、エラーは出力されません。
  • ヒット確認⁠: 応答 usage.cache_read_input_tokens を確認してください。同じプレフィックスのリクエストを複数回送ってもこれが常に 0 である場合、「静かな無効化要因」(システムプロンプト内のタイムスタンプ、ソートされていない JSON、変動するツールセット)があります。2つのリクエストのプレフィックスをバイト単位で diff して特定してください。
変更内容ツールキャッシュシステムキャッシュメッセージキャッシュ
ツール定義(追加/削除/並べ替え)、モデル変更
システムプロンプト内容✅保持
メッセージ内容、tool_choice、thinking 切替

(✅=その層のキャッシュが有効のまま)。結論:⁠ツールセットやモデルを途中で変更しないでください⁠——そうするとキャッシュ全体が最初から無効になります。

対話がウィンドウを超える場合: コンパクション vs コンテキスト編集

長いエージェントを実行していると、履歴がウィンドウに近づき、甚至い超えることがあります。2つの API プリミティブは逆方向の操作であり、しばしば組み合わせて使用されます:

コンパクション (圧縮)コンテキスト編集 (切り捨て)
動作初期履歴を要約してコンパクションブロックにする古い tool_result / thinking を削除する
情報要約して保持直接削除
使用時ウィンドウ上限に近づいた場合、対話を継続したい場合古いツール出力が関係なくなり、サイズを縮小したい場合
重要な注意点response.content(コンパクションブロックを含む)⁠全体を再送信する必要があります。text のみだと状態が失われますtool_use/thinking のみを削除し、対話構造は変更しない
Beta ヘッダーcompact-2026-01-12context-management-2025-06-27

両者の違いを覚えておいてください: コンパクションは「要約」であり、コンテキスト編集は「削除」です。セッションを跨ぐ永続的な記憶は別の話です(要点をファイルやメモリベースに書き込む)。これは単一のウィンドウ内で解決されるものではなく——詳細は 記憶と状態 を参照してください。

thinking / effort / task_budget: モデルに予算を管理させる

現代の Claude (Opus 4.6+) は 適応的思考(adaptive thinking) (thinking: {type: "adaptive"}) を使用し——モデルが自らいつ、どの深さまで考えるかを決定し、手動で budget_tokens を入力する必要がなくなりました(Opus 4.7/4.8/Fable 5 では手動入力は 400 エラーになります)。深さを制御するマスタースイッチは effort です:

output_config: { effort: "low" | "medium" | "high" | "xhigh" | "max" }

effort が低いほど、ツール呼び出しは少なく集約され、前置きが短くなります。high/xhigh はコーディングやエージェントに適しています。これは1リクエストでの thinking + ツール + 出力のトークン消費を直接決定します——これがコンテキスト予算を調整する最も直接的なノブです。

また タスク予算⁠(beta task-budgets-2026-03-13): エージェントループ全体にトークン予算(最小 20000)を与え、モデルはカウントダウンを見て自ら收尾できます。これは max_tokens と異なります: max_tokens は単一応答のハード上限であり、モデルは見えません。task_budget はモデルが知覚可能な「支出ガイドライン」です。

「真ん中で失われる(lost in the middle)」とコンテキストローテーション: 多=良ではない

モデルのウィンドウへの注意は不均一です: 始まりと終わりはよく覚えているが、真ん中は「見えない」傾向があります(研究界では "lost in the middle" と呼ばれます)。さらに、弱く関連するコンテンツを多く詰め込むとシグナルが希釈され——より長いコンテキストがかえって精度を低下させるのが、「コンテキストローテーション(context rot)」です。

実装可能な2つの対策:

  • 最も重要な指示を、モデルの注意が強い位置に配置する⁠(前方の system、または後方の user)、そして明確な区切り文字 / XML タグで重要なブロックを囲む。
  • 硬貼付けより検索を優先。 50ページのドキュメントをすべて貼り付けてモデルが自分で探すのを待つよりも、まず RAG でヒットさせてから2ページを配置する方がよい(RAG と検索強化 参照)。

ベストプラクティス

  • ウィンドウを予算として管理し、ゴミ箱にしない。 何を、どこに、どのように再利用するかを決定し、無闇に詰め込まない——これが現代のモデルを効果的に使うための第一原則です。
  • 安定プレフィックスを固定し、可変内容を後方に配置。 システムを凍結し、ツール順序を固定し、動的情報(タイムスタンプ/ID/検索断片)はすべて後ろに配置——これがキャッシュヒットのほぼすべての秘密です。
  • effort は high で始め、評価でスキャン。 反射的に xhigh/max に引き上げない——関係は単調ではなく、エージェントでは高 effort の方がむしろ節約になることが多い。
  • 検索を硬貼付けより優先。 RAG でヒットした2ページが、50ページを硬貼付けするより優れている(RAG と検索強化 参照)。
  • 重要な指示は強い位置に配置 + 区切り文字で囲む。 前方の system または後方の user に配置し、XML タグで区切り、中間に埋め込まない。
  • 長い対話は積極的に管理し、3つのことを区別する。 コンパクションは要約、コンテキスト編集は削除、記憶 はセッションを跨ぐ永続化——1つの手段で3つのことをやろうとしない。

トレードオフと失敗パターン

  • ウィンドウへの硬貼付け⁠: 越多しいほど正確だと思い込むが、実際にはコンテキストローテーションを引き起こし、注意が希釈され、精度が低下する → 検索を硬貼付けより優先し、ヒットした断片のみを配置。
  • キャッシュの静かな無効化⁠: システム内に now()/UUID/ソートされていない JSON を挿入し、cache_read_input_tokens が長期間 0 のまま → プレフィックスを凍結し、動的情報を後方に配置し、2つのリクエストをバイト単位で diff して調査。
  • 1つのリクエスト内でのツールセット変更またはモデル変更⁠: 全体のプレフィックスキャッシュが無効化され、コストが数倍に → ツールセットとモデルは同じループ内で不変に保つ。
  • 2種類の「キャッシュ」の混同⁠: KV キャッシュは単一生成内の VRAM 高速化、プロンプトキャッシュはリクエスト間でのプレフィックス再利用 → 階層を区別してから最適化する。
  • 反射的な effort の最大値設定⁠: 単純なタスクで高 effort を使用するとトークンを無駄に消費する → high で始め、評価でスキャン(推論と thinking 参照)。

最前線: コンテキストは「世界」そのもの

コンテキストウィンドウを極限まで押し広げると、興味深い方向——⁠ワールドモデル(world model)——に至ります。アリババの Qwen チームの Qwen-AgentWorld-35B-A3B は、256K コンテキストの MoE(35B 総パラメータ / 3B 活性化)ですが、これはチャット用ではなく、⁠コンテキスト内でエージェントが置かれている環境(ターミナル、Web、OS……)をシミュレートするためのものです。このようなモデルは、「コンテキスト」を「資料を詰め込む場所」から「対話可能な世界の状態を担うもの」へと変えます——コンテキストエンジニアリングの究極は、ウィンドウを1台のステートマシンとして管理することです。この点は エージェントループとツール使用 の最前線セクションで詳しく展開します。

参考文献

  • Anthropic 公式ドキュメント⁠: プロンプトキャッシュ、コンパクション、コンテキスト編集、適応的思考とエフォート(platform.claude.com、実装前は公式を優先)
  • ローカル実戦⁠: ローカル LLM 展開(KV キャッシュ量子化、VRAM 戦術)
  • 研究⁠: "Lost in the Middle: How Language Models Use Long Contexts" (Liu et al., 2023)
  • 下流⁠: エージェントループとツール使用MCP とスキル

Keywords: context window, token, tokenizer, KV cache, attention O(n²), prompt caching, prefix match, cache_control, TTL, compaction, context editing, adaptive thinking, effort, task budget, lost in the middle, context rot, RAG, world model