AI・機械学習
Piにおけるコンパクションの仕組み
How Compaction Works in Pi (earendil.com)
要約
大規模言語モデル(LLM)は限られたコンテキストウィンドウを持つため、コーディングエージェントのような対話型アプリケーションでは、会話履歴が長くなるとコンテキストオーバーフローが発生します。Piは、この問題を解決するために「コンパクション」というプロセスを採用しています。これは、古い会話履歴をLLMに要約させることで、コンテキストウィンドウ内に収まるように圧縮し、新しいメッセージのためのスペースを確保する仕組みです。
全文翻訳
Piにおけるコンパクションの仕組み
日付: 2026年8月13日 木曜日
送信者: Earendil Engineering <rfc@earendil.com>
宛先: あなた
件名: Piにおけるコンパクションの仕組み
PiやClaude Code、Codexのようなコーディングエージェントで長いコーディングセッションを行ったことがあるなら、コンパクションをトリガーしたことがあるでしょう。この記事では、コンパクションがどのように機能し、Piがいつコンパクションを必要とするのかを説明します。
LLMの会話
大規模言語モデル(LLM)は、コンテキストウィンドウが限られています。コンテキストウィンドウとは、モデルが応答を生成する際に「見ることができる」範囲のことです。LLMで使用されるTransformerアーキテクチャは、処理できる入力の量に制限があります。
コーディングエージェントのセッションの入力には、すべての以前のメッセージとツール呼び出しが含まれ、作業が進むにつれてこれが増え続けます。コンテキストウィンドウを超えると、LLMはリクエストを拒否します。
Piのようなコーディングエージェントと対話しながら作業する場合、エージェントはLLMにリクエストを送信し、応答を受け取ります。各リクエストには、システムプロンプト、ロードされたファイル(AGENTS.mdなど)、ツール定義、および会話履歴が含まれます。
コーディングエージェントの最初のLLMリクエストには、この初期コンテキストと最初のユーザーメッセージが含まれます。
リクエスト1: [システム][ツール][ユーザー]
これは1ターンを開始します。LLMは最初にツール呼び出しを含むアシスタントメッセージを返すことがあります。エージェントプログラムはそれを実行し、完全な会話(ツール結果を含む)を含む新しいリクエストをLLMに送信します。別のアシスタントメッセージが返ってきます。アシスタントが出力生成を完了すると、ターンは終了します。
リクエスト1の後: [システム][ツール][ユーザー][アシスタント: ツール呼び出し][ツール結果][アシスタント]
<-------------------> ^ <---------> LLMによって返された | LLMによって返された | エージェントによって生成された
作業を続け、別のメッセージを送信します。
リクエスト2: [システム][ツール][ユーザー][アシスタント: ツール呼び出し][ツール結果][アシスタント][ユーザー]
^ 新しいユーザーメッセージ
各ターンで会話が拡張されます。最終的に、履歴がコンテキスト制限を超えます。次のリクエストは、「リクエストが最大サイズを超えています」のようなエラーを返します。
[システム][ツール][ユーザー][アシスタント][....][ツール結果][ユーザー]
^ コンテキストウィンドウを超えている
コンテキストオーバーフローの処理
既存の会話をそのまま続けられなくなった場合、2つの選択肢があります。1つは、蓄積されたコンテキストなしで、新しい空の会話を開始することです。これは履歴、以前の決定や未解決の作業をすべて破棄します。LLMの出力パフォーマンスはコンテキストサイズが増加するにつれて低下するため、これは依然として良い考えかもしれません。
もう1つは、会話コンテキストのより小さな表現を作成することです。これは、会話を続けたいからです。それがコンパクションが行うことです。
コンパクション
理論的には、コンパクションを実装する方法は数多くあります。例えば、会話の一部を保持し、残りを破棄する決定的な関数を記述することができます。しかし、実際には、コンパクションの実装はLLMリクエストを使用して会話履歴を要約します。
コンパクションは、履歴の一部を圧縮された表現に置き換えることで、追加のメッセージやツール呼び出しのためのスペースを残します。
[システム][ツール][コンパクション結果][ユーザー]
^ 新しいメッセージ
Piの実装
Piが具体的にどのようにコンパクションを実装しているか詳しく見てみましょう。会話が長くなりすぎると、Piは古いコンテンツを要約しながら最近の作業を保持するためにコンパクションを使用します。コンパクションは、コンテキスト制限がコンテキストウィンドウの総サイズに近づいているときにトリガーされます。また、/compactコマンドを使用して手動でトリガーすることもできます。
Piはターンの終了後に自動コンパクションをチェックします。それまでは、各リクエストは既存のプロンプトを拡張し、キャッシュされたプレフィックスを再利用できます。Piは、コンテキストオーバーフローエラーが発生した場合、ターン中にコンパクションを行うこともあります。
コンパクションを行う際、Piは最近のメッセージの数をいくつか変更せずに保持します。
コンパクション前: [システム + ツール][古いターン][最近保持されたメッセージ]
保持されるメッセージの数は変動します。これは、Piが設定可能なトークン予算を使用しているためです。Piの現在のデフォルトである2万トークンは、約5〜20ターンに相当します。このカットオフポイントより前のすべてのメッセージが抽出され、シリアライズされ、要約されます。
Piのコンパクションプロンプト
コーディングエージェントの良い要約の理想的な結果は、シフトからシフトへの引き継ぎブリーフィングのようなものです。Piのコンパクションプロンプトは、既存のコンテキストに、もはや関連性のないものがたくさんあるという事実に焦点を当てています。次のLLMリクエストにとってまだ重要なコンテキストであるものだけを保持する必要があります。
したがって、Piは通常の会話とは異なるリクエストをコンパクションのために送信します。スタンドアロンのコンパクションリクエストで使用されるシステムプロンプトは異なります。「あなたは専門のコーディングアシスタントです」とLLMに伝える代わりに、「あなたはコンテキスト要約アシスタントです」と伝えます。
コンパクションリクエストのユーザーメッセージも異なります。「後で戻ってきたときのコンテキストのために、この会話ブランチの構造化された要約」を要求します。
プロンプトは、目標、進捗、および主要な決定事項のセクションを指定します。これは既存の会話履歴を使用しないスタンドアロンのリクエストであり、異なるLLMモデルを使用しても不要なコストを発生させることなく使用できます。
コンパクションの結果は、コンパクションエントリとしてPiセッションに追加され、セッションは続行できます。コンパクションリクエストの後、コンテキストは圧縮されました。
コンパクション後: [システム][ツール][要約][最近のターン][新しいユーザーメッセージ]
これで、会話コンテキストにさらに多くのメッセージのためのスペースができました。Piはコンパクションの要約をセッションにプレーンテキストとして保存します。これにより、Piでモデルを切り替えても要約を引き続き使用できるため、コンパクションされたコンテキストは読みやすく、ポータブルになります。
コンパクションとプロンプトキャッシュ
プロンプトキャッシュは、LLMプロバイダーが同じ会話で繰り返し行われるリクエストをより安価にするために使用されます。アクティブなコーディングセッションでは、モデルによって既に生成されたコンテキストのコストが削減されます。このキャッシュは正確なプレフィックスマッチを必要とするため、セッションをコンパクションするとプロンプトキャッシュが壊れます。
コンパクション前のキャッシュ: [システム][ツール][古い履歴][最近保持されたターン]
<-------------------- キャッシュされたプレフィックス -------------------->
コンパクション後の最初の要求: [システム][ツール][要約][最近保持されたターン][新しいユーザーメッセージ]
<-- 再利用可能 -->^ | 最初の変更されたトークン |
+-- これ以降のすべては再計算する必要があります --+
保持されたターンは同じトークンを含みますが、それらは異なるプレフィックスに従います。したがって、それらの以前のキャッシュ状態は再利用できません。コンパクション後の新しいリクエストは、再びプロンプトキャッシュの恩恵を受けるようになります。
実験
Piは拡張可能で柔軟であるため、独自のコンパクションに置き換えることができます。異なるコンパクションメカニズムをテストするには、Piにカスタムコンパクションプロンプトを持つ拡張機能を作成するように依頼してください。