2026年には、100万トークンのコンテキストウィンドウを利用できます。Gemini、GPT-5、Claude(extended thinkingを使用)は、いずれもこれをサポートしています。デモでは、モデルが本を丸ごと一冊、一度に読んでいます。すべてをコンテキストに入れてモデルに判断させるという夢が、ついに現実になりました。
しかし、現実はいつものように、もう少し複雑です。100万トークンは技術上の容量であって、性能を保証するものではありません。現実のモデルが最高の性能を発揮するコンテキストは5~50Kトークンです。100Kを超えると微妙な品質問題が現れ、500Kを超えると重要な情報を安定して見落とすようになります。1Mではモデルが処理しきれません。
この「コンテキスト劣化」という現象は実在し、十分に文書化され、評価でも確認されています。つまり、すべてをコンテキストに投入するだけでは不十分です。何を含め、何を要約し、何を動的に検索し、得られたコンテキストをどのように構成するかを意図的に決める、コンテキストエンジニアリングが必要です。
この記事では、本格的な本番システムで効果的なコンテキストエンジニアリングを実践するためのパターンと規律を解説します。
コンテキスト劣化とは
「コンテキスト劣化」とは、技術的な上限以内であっても、コンテキストが増えるほどLLMの性能が低下するという経験的な観察結果です。
具体的な失敗モードは次のとおりです。
Lost-in-the-middle(Liu et al., 2023)。モデルはコンテキストの冒頭と末尾にある内容へより強く注意を向けます。中央の情報は安定して利用されません。100Kのうち50Kの位置に置かれた事実は、同じ事実を1Kまたは99Kの位置に置いた場合より見落とされやすくなります。
直近性バイアス。 モデルは新しい内容を過度に重視します。会話履歴では、古いコンテキストが実質的に見えなくなります。
妨害情報への感度。 コンテキスト内の無関係な内容は、その内容を必要としないタスクでも性能を低下させます。モデルは情報を選別する必要があり、その過程で一部のシグナルが失われます。
推論品質の低下。 コンテキストが増えるほど、多段階の推論は不安定になります。追跡すべき情報が増え、その精度が低下します。
コストとレイテンシー。 品質とは別に、大きなコンテキストは高コスト(トークン単位の料金)であり、低速です(多くのモデルではトークン数に対して線形に増えます)。
これらは理論上の懸念ではありません。大きなコンテキストを無造作に使う本番環境は、厳選したコンテキストを使う環境より一貫して低い性能を示します。
原則:少ないほど良い
中心となる洞察は、コンテキストは貴重で、増えるほど劣化する資源だということです。戦略的に使ってください。
厳選した内容を含む30Kトークンのコンテキストは、すべてを投入した300Kトークンのコンテキストより、通常は優れた性能を発揮します。品質、コスト、レイテンシーのすべてで、小さいコンテキストが有利です。
これによってエンジニアリングの焦点が変わります。「より多くをコンテキストに収める方法を探す」のではなく、「本当にコンテキストに必要なものを決め、適切に配置する」ことが課題になります。
コンテキスト予算
コンテキストを配分すべき予算として考えます。
カスタマーサポートエージェントの典型的な配分は、次のようになります。
コンテキスト予算の合計:30Kトークン
- システムプロンプト:1500トークン(5%)
- ツールの説明:1000トークン(3%)
- ユーザープロファイル / コンテキスト:500トークン(2%)
- 会話履歴の要約:1000トークン(3%)
- 直近の会話ターン(全文):4000トークン(13%)
- 検索した関連知識:12000トークン(40%)
- ユーザーの現在のメッセージ:500トークン(2%)
- 出力トークン予算(応答):10Kトークン(33%)
各要素は領域を奪い合います。コンテキストが増えるにつれて、トレードオフが必要になります。
重要なのは、配分を明示することです。どの要素も際限なく増やしてはいけません。
パターン1:階層化した会話メモリ
複数ターンの会話では、履歴全体が際限なく増えます。ほとんどの本番システムは、階層化したメモリを使用します。
階層1:直近のターンを全文で保持。 最後の5~10往復をそのまま保持します。
階層2:古いターンを要約。 会話の前半を短い要約へ圧縮します。
階層3:抽出した事実。 会話の重要情報(ユーザーの名前、好み、決定事項)を構造化した事実として保存します。
実装例:
各ターンで:
1. 会話履歴を取得します。
2. 直近の10ターンはそのまま保持します。
3. 11~30ターン目は200語に要約します(「以前、ユーザーはXについて話し、Yに合意しました」)。
4. 31ターン目以降は抽出した事実に縮約します(「ユーザーはPythonを好む。ユーザーはenterprise tierを利用している」)。
5. 会話の長さにかかわらず、メモリの合計は約2Kトークンです。
このパターンは、長期間続くあらゆる会話の基礎です。使用しなければ、会話が長くなるにつれて品質が低下します。
注意点として、要約ではエージェントが必要とする情報を保持しなければなりません。ユーザーが5ターン目に口座番号を伝えたのに、エージェントがそれを長期メモリへ移さなければ、50ターン目には失われます。
何を保持するかを明示した指示で要約を実行してください。
これまでの会話を要約してください。次の情報を保持します。
- ユーザーに関するすべての事実(名前、役割、好み、アカウント情報)。
- すべての決定事項。
- 未完了の約束またはフォローアップ。
- 会話の現在の目標。
次の情報は破棄します。
- あいさつや社交辞令。
- 重複する情報。
- 解決済みの詳細な推論。
パターン2:ジャストインタイム検索
コンテキストを事前に読み込む代わりに、必要になった時点で関連情報を検索します。
避けるべきパターンは、「モデルが必要とする場合に備えて」ユーザーの全ドキュメントをコンテキストへ詰め込むことです。ほとんどのクエリが必要とするのは、ごく一部です。コンテキストを浪費し、性能も低下します。
より良い方法は、現在のクエリに基づいてドキュメントを検索することです。クエリごとに異なるドキュメントを与えます。呼び出しごとのコンテキスト総量を小さく保ち、関連性を高く維持できます。
これは、規律をもって適用するRAGにほかなりません。重要なのは、「可能だからすべて含める」という誘惑に負けないことです。長いコンテキストを持つモデルを利用できると、経験豊富なチームでさえ誘惑されます。
パターン3:圧縮表現
コンテキスト内に保持する必要がある情報には、圧縮表現を使用します。
元の表現(冗長):
ユーザーはソフトウェアエンジニアリングに8年間従事しています。最初はAcme Corpという小規模なスタートアップでバックエンドシステムを担当しました。3年後、より大規模なBeta Incへ転職し、フロントエンド開発に携わりました。現在はGamma LLCで機械学習システムを担当しています。
圧縮後:
ユーザー:SWE、経験8年、現在はGamma LLCでMLを担当。以前はAcmeでバックエンド(3年)、Betaでフロントエンド。
圧縮版は、少ないトークンで関連する事実を保持します。ほとんどの目的では、モデルはどちらも同じように利用できます。
この手法を次のものに適用します。
- ユーザープロファイル。
- ドキュメントの要約。
- 過去の会話コンテキスト。
- ナレッジベースのエントリ(全文が不要な場合)。
トレードオフとして、圧縮すると細かなニュアンスが失われます。ニュアンスが重要なら全文を、重要でなければ圧縮版を使います。
パターン4:階層的検索
非常に大きなナレッジベースでは、階層的に検索します。
ステップ1: クエリに基づいて、広いカテゴリまたはドキュメント要約を検索します。
ステップ2: 最も関連するカテゴリの中から、特定のチャンクを検索します。
ステップ3: ステップ2で選ばれたチャンクだけを最終コンテキストに含めます。
これにより、「10K件のドキュメントがあるので、すべてをコンテキストに埋め込もう」という状況を避けられます。段階的に絞り込むことで、コンテキストを小さく保ちます。
派生パターンとして、メインの呼び出しへ含める前に、小規模なLLM呼び出しで最も関連するチャンクを選ぶ方法があります。少額のコストが加わりますが、コンテキストの肥大化を大幅に抑えられます。
パターン5:コンテキストの振り返り
長時間実行するタスクのエージェントでは、コンテキストに何があり、何を残すべきかを定期的に振り返ります。
10ステップごとに、エージェントは次を行います。
1. 現在のコンテキストを確認します。
2. 進行中の作業に関連するものを特定します。
3. 不要になったものを要約または削除します。
4. 追加すると役立つ可能性のあるコンテキストを記録します。
5. 古いコンテキストを厳選したバージョンで置き換えます。
これはコンテキストの「ガベージコレクション」です。これがなければ、エージェントは古い情報を蓄積し、新しい関連情報の領域を圧迫します。
実装にはカスタムのオーケストレーションが必要です。ほとんどのフレームワークは、この処理を標準では扱いません。各ステップの間に「メモリ統合」フェーズを設け、コンテキスト内の内容を調整します。
パターン6:動的なコンテキストウィンドウ
エージェント実行の各部分では、最適なコンテキストサイズが異なる場合があります。
- 意思決定ステップ: 小さなコンテキストで、直近の意思決定に集中します。
- 統合ステップ: 多数の情報源を含む、より大きなコンテキストを使います。
- 生成ステップ: スタイルや形式の参照を含む、中程度のコンテキストを使います。
エージェントワークフローの各ステップで異なる形のコンテキストを使い、どの内容をどのステップへ入れるかをオーケストレーションで管理します。
これには、エージェントの作業を一つの大きなループではなく、明示的なステップへ分割する必要があります。ここではフレームワークの選択が重要です(LangGraphは自然に処理できますが、直接APIでは手作業が必要です)。
パターン7:位置を考慮した配置
モデルはコンテキストの冒頭と末尾に強く注意を向けるため、重要な内容をそこに配置します。
効果が低い方法: 長いシステムプロンプトの中央に重要な指示を埋め込みます。
効果が高い方法: 重要な指示を冒頭に置き、末尾近くでもう一度記載します。
複数の検索済みドキュメントを使うRAGでは、最も関連するドキュメントを冒頭に、2番目に関連するものを末尾に、それより関連性の低いものを中央に置きます。
これは戦術的な最適化ですが、出力に測定可能な効果があります。
パターン8:選択的な要約
要約はどれも同じではありません。後続タスクのニーズに合わせて調整してください。
悪い例: ユーザーの好みが失われる汎用的な要約。
より良い例: 後続タスクに関連するユーザーの好みを明示的に保持する要約。
次の点に注目して、このドキュメントを要約してください。
- 決定された技術事項。
- 言及されたステークホルダー。
- 未解決の疑問またはリスク。
次の情報は除外してください。
- チームがすでに把握している一般的な背景。
- 重複する要点。
要約プロンプトは、後続用途に合わせて設計します。
パターン9:構造化コンテキスト
プレーンテキストは一つの選択肢です。構造化したコンテキスト(JSON、XML、特定のマークアップ)は、はるかに高密度にできる場合があります。
冗長な文章:
顧客の名前はJohn Smithです。2023年3月から顧客です。現在のプランはProで、月額$29を毎月請求しています。有効な統合はSlack、Notion、Linearの3つです。過去30日間の利用量は中程度で、API呼び出しは1,250回でした。
構造化した表現:
{
"customer": {
"name": "John Smith",
"since": "2023-03",
"plan": "Pro",
"billing": "monthly $29",
"integrations": ["Slack", "Notion", "Linear"],
"usage_30d": {"api_calls": 1250, "tier": "moderate"}
}
}
構造化版は短く、モデルにとっても多くの場合は使いやすくなります。モデルは特定の事実を素早く見つけられます。
ただし、すべてのモデルが構造化入力を同じように扱えるとは限りません。ユースケースに対して両方の形式をテストしてください。
パターン10:コンテキストのレイヤー化
優先度に応じてコンテキストをレイヤー化します。高優先度は常に含め、中優先度は関連する場合に含め、低優先度は必要に応じて検索します。
常に含めるレイヤー:
- システムプロンプト(アイデンティティ、振る舞い)。
- 現在のユーザーコンテキスト(必須の事実)。
- 直近の会話。
関連する場合:
- クエリに一致して検索されたドキュメント。
- 直近のステップから得られたツール出力。
必要に応じて:
- エージェントがツール呼び出しで要求する特定のデータ。
- 直近の範囲より古い履歴コンテキスト。
「必要に応じて」というパターンは、スケールさせるうえで不可欠です。すべてを事前に読み込むのではなく、エージェントが必要なときに必要なものを検索します。
パターン11:退避戦略
コンテキストが上限に近づいたとき、何を退避させるべきでしょうか。
- 直近性ベース: 最も古い内容から退避します。
- 関連性ベース: 現在のタスクとの関連性が最も低い内容から退避します。
- 重要度ベース: 重要度が低いと指定された内容から退避します。
実用的な方法は、コンテキスト項目に優先度を付けることです。退避が必要になったら、優先度順に削除します。
context_items = [
{"content": "...", "priority": "critical"}, # 退避しない
{"content": "...", "priority": "high"}, # 最後に退避
{"content": "...", "priority": "medium"}, # 必要なら退避
{"content": "...", "priority": "low"}, # 最初に退避
]
def evict_to_fit(items, budget):
items_by_priority = sorted(items, key=lambda x: priority_value(x.priority))
while total_tokens(items) > budget:
items.remove(items_by_priority.pop(0)) # 最も優先度が低い項目を削除
return items
パターン12:繰り返すコンテキストのキャッシュ
多くの呼び出しでは、同じシステムプロンプト、同じツールの説明、同じユーザープロファイルなど、同じコンテキストを再利用します。
現在、ほとんどのプロバイダーがプロンプトキャッシュをサポートしています。
- Anthropic:メッセージ内の明示的な
cache_controlマーカー。 - OpenAI:プレフィックスが一致するリクエストを自動でキャッシュ。
- Google:APIを介して明示的にキャッシュしたコンテンツ。
同じプレフィックスを再利用すると、キャッシュ版はより高速で安価になります(多くの場合、90%安くなります)。
1回のセッションで多数の呼び出しを行うエージェントでは、静的部分(システムプロンプト、ツール、ユーザーコンテキスト)をキャッシュ可能にしてください。動的な内容(現在のステップ、直近の結果)は、キャッシュ可能なプレフィックスの後に配置します。
これは、最もROIの高い最適化の一つです。10Kトークンの静的プレフィックスを1回のセッションで50回使う場合、最初の呼び出しは通常料金ですが、以降は90%割引になります。大幅な節約です。
パターン13:コンテキストを意識したプロンプト
プロンプトを使って、モデルによるコンテキストの適切な利用を促せます。
以下のドキュメントを参照して、ユーザーの質問に回答してください。必ず具体的なドキュメントを引用元として示し、関連する一節を引用してください。
提供されたドキュメント内に答えが見つからない場合は、その旨を明記してください。情報を捏造しないでください。
複数のドキュメントにある情報が関連する場合は、それらを統合し、意見の相違があれば示してください。
このようなプロンプトは、コンテキストに基づくタスクでハルシネーションを減らし、引用の品質を高めます。
長いコンテキストを採用すべき場面
コンテキスト劣化があっても、長いコンテキストの方が明確に優れているタスクもあります。
単一ドキュメントの分析。 「この契約書を分析する」というタスクでは、分割して検索するより、契約書全体をコンテキストに収める方が多くの場合は適しています。
多数の項目の比較。 10件の契約書を並べて比較する場合は、10件すべてをコンテキストに含めると効果的です。
コンテキスト内でのコード編集。 5K LOCのファイルにある関数を変更する場合、検索したスニペットより、ファイル全体をコンテキストに含める方が容易です。
会話全体の要約。 長い会話の要約は、ある程度までは全文を含むコンテキストの方が優れた結果になります。
基本パターンは、タスクが内容間の関係を理解することを本質的に必要とする場合には長いコンテキストが有効であり、ごく一部だけで実行できる場合には小さいコンテキストの方が適しているということです。
実用的な目安として、50Kトークンまでのコンテキストは通常問題ありません。50~200Kトークンも機能しますが、品質は低下します。200Kトークンを超えると、より短いコンテキストより性能が低くなる場合がよくあります。実測して確認してください。
評価の規律
コンテキストエンジニアリングが機能していることを、どう判断すればよいでしょうか。評価が必要です。
具体的な評価は次のとおりです。
再現率テスト。 長いコンテキストのさまざまな位置に重要な事実を埋め込み、モデルが利用するかをテストします。位置ごとの再現率を測定します。
妨害情報テスト。 同じクエリについて、無関係なコンテキストがある場合とない場合の性能を比較し、低下を測定します。
長いコンテキストとRAGの比較。 同じクエリへ、コンテキスト全体を使って回答した場合と、検索したチャンクを使って回答した場合の品質を比較します。
トークン効率。 1ドル当たりの品質を測ります。コンテキストが増えるほど支払額も増えますが、品質もそれに見合って向上しているでしょうか。
こうした評価により、コンテキストの選択が本当に役立っているかが分かります。評価がなければ推測にすぎません。
実例:リサーチアシスタント
現実の例として、小規模チーム向けのAIリサーチアシスタントを考えます。
タスク: 200件のドキュメント群(論文、社内資料、会議メモ)に関する質問へ回答します。
単純なアプローチ: 全ドキュメントをコンテキストへ埋め込みます(300Kトークン)。品質はまずまずですが、コストが高く、レイテンシーも長くなります。
設計されたアプローチ:
コンテキスト予算:25Kトークン
- システムプロンプト:1500トークン(キャッシュ済み)
- ツールの説明(search、fetch_docなど):800トークン(キャッシュ済み)
- 会話メモリ:1500トークン(直近の10ターン)
- 現在のクエリ向けに検索したチャンク:18000トークン(RAGによる上位12チャンク)
- ユーザーの現在の質問:200トークン
- 出力予算:約3000トークン
エージェントは質問に基づいてチャンクを動的に検索します。会話メモリが直近のコンテキストを保持し、静的要素はキャッシュされます。
結果:
- レイテンシー:2~3秒(300Kのコンテキストでは10~15秒)。
- コスト:約€0.01/クエリ(約€0.10から低下)。
- 品質:関連する内容へ適切に注意が向けられるため、評価セットで測定した品質が向上。
これが、規律あるコンテキストエンジニアリングです。一度だけ決めるのではなく、継続的に調整します。
よくある間違い
いくつかのパターンを挙げます。
間違い1:「コンテキストが多いほど良い」。 品質問題の解決策として長いコンテキストを選びます。実際には逆効果になることがよくあります。
間違い2:コンテキスト予算がない。 各要素が際限なく増えます。ユーザープロファイルのセクションが5Kトークン、検索チャンクのセクションが50Kトークンになります。規律がありません。
間違い3:位置を無視する。 重要な指示を中央に埋め込み、モデルが見つけることを期待します。見つかることもありますが、見つからないことも多々あります。
間違い4:事実を冗長な文章で表す。 構造化データで十分な箇所に長い文章を使い、トークンを浪費します。
間違い5:会話を要約しない。 会話が上限を超えるまで増え続けます。その後は、文脈が徐々に失われるか、システムが機能しなくなります。
間違い6:キャッシュしない。 静的なプレフィックスを繰り返し使うたびに通常料金を支払います。簡単に得られる節約効果を逃しています。
間違い7:コンテキスト選択を評価しない。 「優れたコンテキストエンジニアリング」が機能していると信じるだけです。実際には機能していないことがあります。
間違い8:汎用的な要約。 後続タスクのニーズを考えずに要約し、重要な情報を失います。
まとめ
長いコンテキストウィンドウは実在しますが、コンテキストエンジニアリングを無視してよい理由にはなりません。品質は技術的な上限に達するはるか前から低下します。コストとレイテンシーも現実の問題です。
コンテキストエンジニアリングの規律は、次のとおりです。
- コンテキストを予算として扱います。
- メモリを階層化します(直近はそのまま、古いものは要約、最も古いものは事実として保持)。
- 先回りせず、必要になった時点で検索します。
- 情報を保持できる場合は圧縮します。
- 重要な内容を注意が向きやすい位置に配置します。
- 優先度に応じてコンテキストをレイヤー化します。
- 静的なプレフィックスをキャッシュします。
- 継続的に評価します。
これらのパターンにより、「すべてをコンテキストへ投入する」という単純な方法よりも、高品質、高速、低コストなシステムを構築できます。
成熟した本番システムでは、コンテキストエンジニアリングは最も大きな効果が得られる領域の一つです。技術的なプリミティブは単純ですが、厳密に適用する規律が「デモが動く」と「本番環境で信頼できる」を分けます。
パターンへ投資し、規律を築いてください。その結果、扱うデータ、会話、複雑さが増えても、無理なくスケールするAIシステムを実現できます。



