コンテキスト 5 層圧縮戦略
概要
長い会話シーンでは、コンテキストの token 数が徐々にモデルのコンテキストウィンドウ制限に近づいていきます。システムは3 層アーキテクチャ・5 つの圧縮戦略によるカスケード方式を採用し、会話品質を保証したうえでコンテキスト長をインテリジェントに管理します。
戦略の全体像

| 番号 | 層 | 戦略名 | トリガー条件 | 処理方法 |
|---|---|---|---|---|
| ① | Layer 1 | 単一ツール結果の切り詰め | 単一のツール結果がコンテキストの 50% を超過 | 予算まで切り詰め、改行境界で分断 |
| ② | Layer 1 | 旧ツール結果の圧縮 | 総入力がコンテキストの 75% を超過 | ホワイトリストのツール結果をプレースホルダーに置換 |
| ③ | Layer 2 | メッセージ履歴の剪定 | LLM がコンテキストオーバーフローエラーを返す | 重要メッセージを保持し、中間履歴を剪除 |
| ④ | Layer 3 | LLM 全量要約 | Layer 2 では緩和が不十分 | チャンク要約 + 統合、9 節構造化フォーマット |
| ⑤ | Layer 3 | 部分要約フォールバック | LLM 要約が失敗 | 超大メッセージを除外して再試行、最終的にプレーンテキスト通知へフォールバック |
Layer 1:予防的なツール結果の切り詰め
トリガータイミング:各 LLM 呼び出しの前に自動実行(予防的で、オーバーフローの発生を待たない)。
戦略 ① — 単一ツール結果の切り詰め
単一のツール結果がコンテキストウィンドウの 50% を超えた場合、予算まで切り詰めます:
元のツール出力(超長)
│
├── 先頭 N 文字を保持(改行境界で分断)
└── マーカーを追加: [truncated: output exceeded context limit]
重要な定数:
SINGLE_TOOL_RESULT_CONTEXT_SHARE = 0.5(単一ツール上限の占有率)
戦略 ② — 旧ツール結果の圧縮
総入力がコンテキストウィンドウの 75% を超えた場合、最も古いツール結果から圧縮を行います:
ツール呼び出し履歴(時系列)
│
├── 最新のツール結果 → 完全な内容を保持
├── 比較的新しいツール結果 → 完全な内容を保持
├── 比較的古いツール結果 → [compacted: tool output removed to free context]
└── 最も古いツール結果 → [compacted: tool output removed to free context]
ホワイトリスト方式:以下の高出力ツールに対してのみ圧縮を実行します:
- Read File、Bash、Grep、Glob、Search Files、Web Fetch、Edit
Write/Create 系ツールの出力は常に保持されます。その出力は後続の操作の根拠となるためです。
重要な定数:
CONTEXT_INPUT_HEADROOM_RATIO = 0.75(総入力上限の占有率)
Layer 2:オーバーフロー検出とメッセージ履歴の剪定
トリガータイミング:LLM がコンテキストオーバーフローエラーを返したときに受動的にトリガーされます。
戦略 ③ — メッセージ履歴の剪定
中間の履歴メッセージを剪除し、重要なメッセージを保持します:
メッセージ履歴
│
├── System Prompt ← 常に保持
├── 最初のユーザーメッセージ ← 常に保持
├── _pin: true のメッセージ ← 常に保持
├── ........ 中間履歴 ........ ← 剪除(通知に置換)
├── [context compacted: X earlier messages removed]
├── 最新 N 件のメッセージ ← 保持(N = min(6, ⌊総数/3⌋))
└── 現在のメッセージ ← 保持
剪定後、孤立したツールペア(対応する tool_result のない tool_use、またはその逆)を自動的に修復し、メッセージフォーマットの正当性を保証します。
Layer 3:LLM インテリジェント要約
トリガータイミング:Layer 2 の剪定後もコンテキスト圧力の緩和に不十分な場合にトリガーされます。
戦略 ④ — 全量要約
独立した LLM 呼び出しを使用して、履歴メッセージを構造化して要約します:
9 節要約フォーマット:
- ユーザーの意図と目標
- 主要な概念と用語
- 関与するファイルとパス
- 発生したエラーと解決策
- 問題解決のアプローチ
- ユーザーの重要メッセージ
- 未完了タスク
- 現在の作業進捗
- 次のステップの計画
チャンク戦略:メッセージが 50,000 文字を超えた場合、最大 4 チャンクに分割してそれぞれ要約し、最終要約へ統合します。
戦略 ⑤ — 部分要約フォールバック
全量要約が失敗した場合、3 段階のフォールバックを実行します:
| フォールバックレベル | 処理方法 |
|---|---|
| Level 1 | 超大メッセージ(>50,000 文字)を除外し、残りのメッセージに対して要約を再試行 |
| Level 2 | 注釈 [Note: X oversized message(s) were excluded] を追加 |
| Level 3 | プレーンテキスト通知 [Summary unavailable — X messages could not be summarized] を返す |
重要な定数の一覧
| 定数 | 値 | 説明 |
|---|---|---|
CONTEXT_INPUT_HEADROOM_RATIO |
0.75 | Layer 1 総入力上限の占有率 |
SINGLE_TOOL_RESULT_CONTEXT_SHARE |
0.5 | Layer 1 単一ツール上限の占有率 |
MAX_OVERFLOW_COMPACTION_ATTEMPTS |
5 | 最大圧縮再試行回数 |
COMPACT_MAX_OUTPUT_TOKENS |
20,000 | 要約 LLM 呼び出しの出力上限 |
COMPACT_BUFFER_TOKENS |
13,000 | 圧縮閾値のバッファ |
CHARS_PER_TOKEN |
4 | 通常テキストの token あたり文字数 |
TOOL_RESULT_CHARS_PER_TOKEN |
2 | ツール結果(より密)の token あたり文字数 |
EMA Token 校正
システムは指数移動平均を使用して chars-per-token 推定を動的に校正します:
| 段階 | 校正方法 |
|---|---|
| 初期 | 3.0 chars/token(保守的、中国語 + コードに対応) |
| 最初の 3 回の LLM 呼び出し | 平均値に収束 |
| 以降 | EMA α=0.15 で平滑追跡 |
| 異常値フィルタ | 0.5 < observed < 8 の範囲外は無視 |
圧縮フローチャート
各 LLM 呼び出しの前
│
├── Layer 1: enforceToolResultBudget()
│ ├── 単一ツール切り詰め(>50% コンテキスト)
│ └── 旧ツール圧縮(総入力 >75% コンテキスト)
│
├── shouldPreemptiveCompact() ?
│ └── はい → compact()(Layer 2 剪定)
│
└── LLM 呼び出し
│
├── 成功 → 継続
└── オーバーフローエラー → getRetryStrategy()
│
├── compact()(Layer 2)
│ │
│ └── なお不十分 → compactWithSummary()(Layer 3)
│ ├── summarizeMessagesFull()(戦略 ④)
│ ├── 失敗 → summarizeMessagesPartial()(戦略 ⑤ Level 1-2)
│ └── 全て失敗 → bare notice(戦略 ⑤ Level 3)
│
└── LLM 呼び出しを再試行(最大 5 回)
ユーザーにとっての意味
コンテキスト圧縮は、長い会話で感じるかもしれない「Agent が以前の内容を忘れた」という現象の原因です。 これはバグではなく、システムが限られたコンテキストウィンドウ内で情報をインテリジェントに管理する仕組みです。
観察されるかもしれない現象:
- 長い会話で、Agent が突然、冒頭で述べた要望を「覚えていない」→ これは Layer 2/3 が初期のメッセージを圧縮したためです
- Agent が「以前の議論によると…」と言うが、詳細が完全には正確でない場合がある → 圧縮後は要約のみが保持されているためです
- ツール呼び出しの履歴結果が
[compacted]になった → これは Layer 1 が古いツール出力を圧縮したためです
次のように対応できます:
- 重要な情報には「覚えておいて」と伝える:メモリシステムの保存をトリガーし、コンテキスト圧縮の影響を受けません
- 重要な要望を再度述べる:長い会話では、あなたの中心的な要望を定期的に述べ直しましょう
- 大きなコンテキストのモデルを選ぶ:GPT-4.1(1M)や Claude(200K)は DeepSeek(64K)よりも多くのコンテキストを保持できます
- 新しい会話を開始する:会話がすでに非常に長く混乱している場合、新しい会話を開始する方が続けるよりも効率的な場合があります
関連ドキュメント
- Agent ループエンジン — ループ内でのコンテキスト管理の位置づけ
- モデル設定 — 各モデルのコンテキストウィンドウのサイズ
- サポートされているモデル一覧 — モデル能力マトリクス
