マガジン

長い会話でLLMの文脈が溢れる前に:履歴の切り詰めと要約の設計

AIを使いこなす

Claudeで執筆し、GPTで自動校閲・修正しています。

古い会話メモから要点を別紙にまとめる手元
記事の内容をもとに制作したAI生成イメージです。実際の製品画面や検証結果の写真ではありません。

結論から言うと、履歴は「全部送る」を出発点にし、入力トークンが自分で決めた予算の一定割合に達した時点で、古い部分だけを要約に置き換えるのが基本形です。直近のやり取りは原文のまま残し、数値・ID・決定事項のように一字でも違うと困る情報は、要約に任せず別枠で固定します。 窓の上限に当たってから慌てるのでは遅い理由は二つあります。一つは上限そのものです。Claude APIは、入力だけで窓を超えると400エラー(prompt is too long)を返すと説明しています。もう一つは精度とコストです。同じドキュメントは、トークンが増えると精度と再現性が落ちる「context rot」に触れ、窓に何を入れるかの選別が容量と同じくらい大事だと述べています(Claude: Context windows)。OpenAIのガイドでも、previous_response_id で会話をつないだ場合、チェーン内の過去の入力トークンはすべて入力トークンとして課金されるとされています(OpenAI: Conversation state)。履歴は送るほど毎回の請求に乗る、と考えて設計します。 この記事では、保持パターンの比較と、要約を挟む条件の決め方を扱います。確認日は2026年10月28日で、各社の仕様は変わりうるため、実装前に公式ドキュメントを見直してください。

この記事の目次
  1. 履歴保持の5パターンを比較する
  2. 要約を挟む条件の決め方
  3. 要約プロンプトとコードの例
  4. 運用前のチェックリスト

履歴保持の5パターンを比較する

以下は、公式資料の記述を踏まえた編集上の整理です。向き不向きは私の判断で、実測値ではありません。

  • A. 全履歴を送る、中身:毎回すべてのメッセージを送信、向く場面:短い会話、試作、弱点:長くなるほどコスト増・精度低下・上限超過
  • B. 直近N件だけ、中身:古いメッセージを捨てる、向く場面:一問一答に近い雑談、FAQ、弱点:初期の要件や決定事項が消える
  • C. 固定情報+直近N件、中身:要件・設定をシステムプロンプトに固定し、直近だけ履歴で送る、向く場面:目的が一定のサポート窓口、弱点:固定情報の更新の仕組みが要る
  • D. 要約+直近原文、中身:古い部分を要約に置換し、直近は原文のまま、向く場面:長い相談、作業の継続、弱点:要約の欠落・誤りが以後の前提になる
  • E. 外部保存+検索、中身:全履歴を自前で保存し、関連部分だけ取り出す、向く場面:数週間にわたる利用、複数セッション、弱点:検索設計と保存データの管理が必要

多くのサービスは、Cで固定すべき情報を決めたうえで、Dを閾値で発動させる構成に落ち着きます。Bだけで始めて、「最初に伝えた条件を忘れた」という不満が出てからCやDに移るのも現実的です。

ベンダーが用意する機能もあります。Claudeにはサーバー側の圧縮(compaction)があり、古いターンをサーバーで書いた要約に置き換える機能です。公式ページは、呼び出し側が時点を決める方式と、トークン閾値でAPIが自動で行う方式を区別しています。両方式ともベータです(Claude: Compaction)。対応モデルやヘッダーは変わるため、使うときは該当ページで確認してください。自前の要約を使う選択肢も公式の比較表に載っています。要約の指示文を自分で書きたいなら、自前実装が向きます。

要約を挟む条件の決め方

「何ターンで要約するか」より、トークン量と情報の性質で決める方が安定します。以下は判断メモです。

発動条件(どれか一つで可)

  1. 入力トークンが予算の約半分に達した。予算はモデルの窓いっぱいではなく、品質とコストを見て自分で決めた値にします。開始値は半分程度にして、自分の会話ログで見直します。
  2. ツール結果や貼り付け文書で急に肥大した。要約より、古いツール結果の削除のほうが安全な場合もあります。Claudeには古いツール結果や思考ブロックをルールで消す context editing もあります。
  3. 話題が切り替わった。前の話題を要約して閉じるのに適したタイミングです。
  4. セッションを再開する。保存済みの履歴をそのまま読み込まず、要約から始める運用です。

現在の使用量は、Claudeならレスポンスの usage で確認できます。送信前の見積もりにはトークンカウントAPIが使えると、同じ資料にあります。他社を使う場合は、各社のトークン数の取得方法を確認してください。

要約してはいけないもの

次は要約に混ぜず、構造化して別枠(システムプロンプトや専用メッセージ)に固定します。

  • 注文番号、金額、日付、型番などの正確な値
  • ユーザーが明示した制約・禁止事項
  • 確定済みの決定事項
  • コードやコマンドなど、一字の差が結果を変えるもの

要約しすぎない設計

  • 直近の数往復は原文で残します。Claudeの圧縮にも、直近ターンを原文のまま残す方式があります。
  • 要約は上書きし続けると、劣化がたまります。一定回数ごとに、固定情報と照合して直す運用にします。
  • 要約文は人が読めるように保存し、ログで追えるようにします。誤りが出たとき原因を特定できます。

要約プロンプトとコードの例

以下は説明用の例です。私の環境では実行しておらず、動作検証もしていません。llm() は各社のAPI呼び出しに置き換えてください。

要約を依頼する文(例)

以下は、サポート会話の古い部分です。後続の回答に必要な情報だけを、次の見出しで日本語にまとめてください。
推測は書かず、不明な項目は「不明」としてください。

## ユーザーの目的
## 確定した決定事項
## ユーザーが示した制約・禁止事項
## 未解決の質問
## 正確に保持すべき値(ID・金額・日付など。原文のまま)

会話:
{old_messages}

見出しを固定すると、「正確に保持すべき値」だけをプログラムで抜き出して固定枠へ移す処理も書きやすくなります。

閾値で切り替える骨組み(例)

python
KEEP_RECENT = 6          # 原文で残すメッセージ数(要調整)
BUDGET_TOKENS = 100_000  # 自分で決めた予算(要調整)
TRIGGER_RATIO = 0.5

def build_messages(summary, history):
    msgs = []
    if summary:
        msgs.append({"role": "user",
                     "content": f"【これまでの要約】\n{summary}"})
    return msgs + history

def maybe_compact(summary, history, count_tokens):
    used = count_tokens(build_messages(summary, history))
    if used < BUDGET_TOKENS * TRIGGER_RATIO:
        return summary, history
    old, recent = history[:-KEEP_RECENT], history[-KEEP_RECENT:]
    if not old:
        return summary, history
    prompt = SUMMARY_PROMPT.format(
        old_messages=render(summary, old))  # 前回の要約も材料に含める
    new_summary = llm(prompt)
    return new_summary, recent

count_tokens はプロバイダのトークンカウント機能か、直前レスポンスの使用量で代用します。メッセージの役割(role)の並び順などの制約はAPIごとに異なるため、実装時に確認してください。

運用前のチェックリスト

  • 要約の品質を確認する:実際の会話ログ(個人情報は置換したもの)から数件を選び、要約後に「最初の条件」を答えられるかを人が見て確かめます。
  • コストの出方を確認する:要約の呼び出しも課金されます。圧縮のたびに追加費用が出るため、頻度を上げすぎないようにします。キャッシュを使う場合、履歴の先頭を書き換えると再利用できる範囲が変わる可能性があるため、各社の仕様で確認します。Geminiの長文脈ガイドは、繰り返し使う大きな入力にはコンテキストキャッシュを主な最適化手段として挙げています(Gemini API: Long context)。
  • 保存する範囲を決める:履歴と要約は、ユーザーの発話内容を含む保存データです。保存期間と削除の手順を決め、削除時に要約も対象にします。
  • 失敗時の動作を決める:要約が失敗したときは、古い履歴を黙って捨てず、直近のみで続けて警告ログを残すなど、挙動を決めておきます。

最初の一歩は、既存の会話ログで「入力トークンが予算の半分を超える会話がどれだけあるか」を数えることです。ほぼゼロなら、パターンAかBで十分です。超える会話が目立つなら、固定情報の洗い出しから始めて、Dを導入します。

出典・参考資料