Context Rot徹底解説 — なぜ長いコンテキストで性能が落ちるのか
Chromaの研究論文を基に、Context Rot(コンテキスト腐敗)の原因、18モデルの比較データ、3つの劣化メカニズム、実践的な対策を解説します。
Context Rotとは
Context Rot(コンテキスト腐敗)とは、LLMに渡す入力トークン数が増えるにつれて出力品質が劣化する現象です。Chroma社の研究チームが18のフロンティアモデルを対象に体系的に検証し、「すべてのモデルで性能が低下する」ことを実証しました。
重要なのは、コンテキストウィンドウが満杯に近づいたときだけでなく、容量に余裕がある段階でもトークンを追加するだけで性能が落ちるという点です。
Chroma研究の概要
実験設計
従来のベンチマークでは、長い入力ほどタスクの難易度も上がるため、「入力長の増加」と「タスクの複雑化」を分離できませんでした。Chroma研究はタスクの複雑さを一定に保ちながら、入力長のみを変化させる方法論で、この問題を解決しています。
テスト対象モデル(18モデル)
| ファミリー | モデル |
|---|---|
| Claude | Opus 4、Sonnet 4、Haiku 3.5 |
| GPT | GPT-4.1、GPT-4.1 mini、GPT-4.1 nano |
| Gemini | 2.5 Pro、2.5 Flash |
| Qwen | Qwen3-235B、Qwen3-32B、Qwen3-8B |
4つの実験
- ニードル-質問類似度: 質問と回答の意味的類似度を変化させた場合の影響
- ディストラクタの影響: 無関係な類似情報を混入させた場合の影響
- ニードル-ヘイスタック類似度: 検索対象と周囲テキストの類似度の影響
- ヘイスタック構造: テキストの論理的一貫性 vs シャッフルの影響
3つの劣化メカニズム
Context Rotは単一の原因ではなく、3つのメカニズムが複合的に作用して発生します。
1. Lost-in-the-Middle効果
LLMはコンテキストの冒頭と末尾に対する注意力が高く、中間部分への注意力が低下します。
注意力の分布イメージ:
高 ████ ████
████ ████
████ ████
████ ██ ██ ████
低 ████ ████ ██ ██ ██ ██ ████ ████
─────────────────────────────────────
先頭 ← コンテキストの位置 → 末尾
重要な情報がコンテキストの中間に配置されると、モデルがそれを見落とす確率が高くなります。
2. 関連情報の識別負荷
入力が長くなるほど、モデルは多くの候補からタスクに必要な情報を識別する必要があります。注意重みを単純にトークン数で割った値では説明できませんが、類似情報、古い指示、無関係な履歴が増えると、取得と指示追従が難しくなることがあります。
3. ディストラクタ干渉
意味的に類似しているが回答に無関係な情報(ディストラクタ)が、正しい情報の検索を妨害します。
Chromaの研究では、無関係な情報や意味的に似た情報を加えると、複数モデルで性能が変化しました。低下幅はモデル、質問、情報の位置によって異なるため、固定値ではなく自分の評価セットで確認します。
モデル別の差はスナップショットとして扱う
長文入力に対する回答拒否、誤答、位置依存性はモデルごとに異なります。ただし、特定バージョンを比較した研究結果は、モデル更新やAPI設定の変更で陳腐化します。「Claudeは保守的」「GPTは積極的」のような製品単位の性格へ一般化せず、使用するモデルIDと設定を固定して評価します。
実用的なインパクト
LongMemEval実験の結果
集中的な短いプロンプト(約300トークン)とフルコンテキスト(約113Kトークン)を比較した実験で、すべてのモデルで顕著な性能ギャップが確認されました。
これは実運用のRAGシステムに直接的な示唆を与えます。検索した情報をすべてコンテキストに詰め込むよりも、本当に必要な情報だけを厳選して渡すほうが高精度になります。
ニードル-質問類似度の影響
質問と回答の意味的類似度が低いほど、入力長増加による性能劣化が急激になります。実際のユースケースでは質問と回答が完全一致することは稀であるため、Context Rotの影響は研究で示された以上に深刻である可能性があります。
対策と緩和戦略
1. コンテキストの情報密度を最大化する
# 悪い例: 検索結果をすべて投入
context = "\n".join(all_retrieved_chunks) # 50チャンク = 25,000トークン
# 良い例: リランクして上位のみ投入
ranked = reranker.rank(query, all_retrieved_chunks)
context = "\n".join(ranked[:5]) # 5チャンク = 2,500トークン
2. 重要情報の配置を制御する
Lost-in-the-Middle効果を考慮し、最も重要な情報をコンテキストの先頭または末尾に配置します。
def arrange_context(
system_prompt: str,
critical_info: str,
supporting_info: str,
user_query: str
) -> str:
"""重要情報を先頭と末尾に配置"""
return f"""{system_prompt}
{critical_info}
{supporting_info}
重要な前提(再掲): {critical_info}
{user_query}"""
3. ディストラクタを除去する
セマンティック重複排除とリランキングで、関連度の低いチャンクを積極的に除外します。
4. コンテキストを分割する
大量の情報を1回で処理させるのではなく、Map-Reduceパターンで分割処理します。
Step 1: 各チャンクを個別に要約(Map)
Step 2: 要約を統合して最終回答を生成(Reduce)
5. 構造化テキストの活用
Chroma研究の意外な発見として、シャッフルされたコンテキストのほうが論理的に一貫したコンテキストよりも性能が高いケースがありました。これは、論理的な文章がディストラクタとして機能しうることを示唆しています。箇条書きや表形式など、意味的に独立したフォーマットが有効です。
実践ポイント
- 「長いコンテキスト = 高性能」ではない: トークン数を減らすことが性能向上に直結する場合がある
- リランキングの効果を測る: 不要な情報を減らせるか、費用と待ち時間を含めて比較する
- モデルの特性を実測する: 製品名で固定的に性格付けせず、利用中の版と実タスクで評価する
- 情報の配置を設計する: 先頭と末尾に重要情報、中間にサポート情報
- 定期的に検証する: Context Rotの影響はモデルアップデートで変化するため、継続的なベンチマークが必要