【AIエージェントの解剖学:第6回】思い出と忘却の調和:Memory & RAG Engineeringの実践
【新連載:AIエージェントの解剖学】
※本連載は、何も話せない空っぽの「チャットボット」の前に立ち、彼に命を吹き込みながら、自分の意志で動く「AIエージェント」へとパーツごとに作り上げていく開発ドキュメンタリーです。
1. プロローグ:次のパーツ「時間と経験を蓄積する記憶の書庫」
前回、私たちはロボットのシステムに「Loop Control(安全ヒューズ)」と「サンドボックス(無菌の実験室)」を装着し、彼が自分でコードを実行してもホストPCや本番環境を絶対に破壊させない「安全性」を実装しました。
しかし、安全に稼働し始めた彼には、まだ致命的な欠落があります。
それは「昨日ユーザーと何を話したか」「10分前にツールを実行して何がわかったか」を覚えておくための、持続的な記憶装置がないことです。
会話の往復が増えるにつれて、彼は古い対話をコンテキストウィンドウの限界からこぼし落とし、綺麗さっぱり忘れてしまいます。
今回は、限られた脳のスペースを消費することなく、過去の出来事や得られた知識をデータベースに保管し、必要に応じて引き出す脳の記憶貯蔵庫、「Memory & RAG Engineering」のアーカイブブロックをロボットの頭部スロットに装着します。
時間と言葉の壁を越えて、彼に「経験から学ぶ知恵」を授けましょう。
2. 短期メモリと長期メモリのハイブリッドアーキテクチャ
人間と同じように、自律的に動くAIエージェントにも「短期メモリ(チャット履歴)」と「長期メモリ(外部知識ベース)」の2つを組み合わせたハイブリッドな設計が必要です。

※図:短期メモリ(チャット履歴)と長期メモリ(Vector DB)が合流し、古い履歴を要約(Consolidation)で圧縮維持するハイブリッド構造(AI生成ダイアグラム)
-
短期メモリ(Short-Term Memory):
今まさに行っている会話の流れ(直近のチャットの応酬)をそのまま覚えておくための一時記憶。これは、LLMのプロンプトのコンテキストウィンドウに直接バッファとして詰め込まれます。 -
長期メモリ(Long-Term Memory / RAG):
過去の会話の全履歴、または共有ファイルなどの知識。これらはすべて「ベクトルデータ(数値化された意味の塊)」に変換され、外部のデータベース(Vector DB)に保管されます。
3. Memory Consolidation(記憶の圧密化と自動要約)
チャットが長くなると、短期メモリのデータ量が膨れ上がり、LLMを動かすための利用料金(トークン消費量)が爆発的に高まります。
これを防止し、エージェントを長期的に活動させるための最も重要なパターンが、「Memory Consolidation(記憶の要約・圧密化)」です。
【Memory Consolidationの実行サイクル】
1. チャット履歴の往復数が一定(例:5往復)を超える。
2. プログラムの裏側で、「これまでの会話の重要な論点を1文に要約してください」とLLMに個別に命令を投げる(非同期の要約処理)。
3. 取得した「要約文」をシステムプロンプトの直下に【これまでの要約記憶】として再挿入する。
4. 古い5往復分の生テキスト履歴をパージ(削除)する。
この「不要な古い生テキストを忘れ、本質的な要約だけを残す」という忘却の調和により、エージェントのコンテキスト使用量は極めて低いレベルで一定に保たれ、何千回チャットを繰り返してもフリーズしない長寿のエージェントが完成します。
4. 【体験】会話の自動要約(Memory Consolidation)を動かそう
チャットの履歴が一定量を超えた際、古いログを消去して1文の「記憶のダイジェスト」に変換し、会話の文脈を軽量に保ち続けるミニプログラムです。
手元の環境で実行してみてください。
# エージェントの短期メモリ(直近のチャット履歴)
chat_history = [
{"role": "user", "content": "私の名前は太郎です。"},
{"role": "assistant", "content": "太郎さん、こんにちは!何をお手伝いしましょうか?"},
{"role": "user", "content": "明日、東京のオフィスに10時に行く予定があります。"},
{"role": "assistant", "content": "承知しました。明日の東京オフィスですね。"},
{"role": "user", "content": "そこでの会議用の資料を準備しておいてほしいです。"}
]
# 記憶の要約(本来はLLMに要約を依頼して取得します)
def mock_llm_summarize(history: list) -> str:
# 過去の会話をぎゅっと1文にまとめる
return "ユーザーの名前は太郎で、明日の10時に東京オフィスでの会議用資料の準備を求めている。"
# 短期メモリを軽量化する関数
def consolidate_memory(history: list, threshold: int) -> tuple:
summary_state = ""
if len(history) >= threshold:
print("⚡ システム: 短期メモリの閾値を超えました。記憶の圧密化を開始します...")
# 1. 過去の会話から「要約」を作成
summary_state = mock_llm_summarize(history)
# 2. 古い生履歴をパージし、直近の1件だけ残す
cleaned_history = [history[-1]]
return summary_state, cleaned_history
return summary_state, history
# 閾値を「5メッセージ」に設定して圧密化を実行
summary, active_history = consolidate_memory(chat_history, threshold=5)
print(f"\n🧠 【保管された長期記憶(要約)】:\n -> {summary}\n")
print("💬 【軽量化された直近の会話バッファ】:")
for msg in active_history:
print(f" -> {msg['role']}: {msg['content']}")
このコードを実行すると、過去の雑多な会話履歴が消去されて1つの「要約テキスト(summary)」に変換され、コンテキストに渡すバッファが大幅にクリーニングされる動作が分かります。
5. エピローグ:歴史と向き合い始めたロボット

※画像:ロボットの脳ブロックに、過去のログや経験をカプセル状に整理・格納するアーカイブユニットを挿入するイメージ(AI生成画像)
これで、ロボットに「Memory & RAG Engineering」のアーカイブスロットが取り付けられ、過去の対話やツールの結果から学び、知能の歴史を永遠に蓄積する「記憶」が実装されました。
しかし、記憶とツールを持った彼には、まだ「自分で複雑な状況を判定し、実行ルートを網の目のように分岐させて進む」ためのシステムとしての地図がありません。
彼が自分の意志で「エラーが出たらこのステップに戻る」「成功したらあの承認ステップへ進む」という複雑なワークフローを制御できるようにしなければ、高度な実務はこなせません。
次回、第7回。
一本道の単純な処理フローを脱し、グラフ構造によって意思決定ルートを自由自在に条件分岐・制御する、「State & Graph Routingの制御技術」の脳内マップを彼に装着します。
知能の行動経路が、直線から網の目(ネットワーク)へと拡張する瞬間へと進みましょう。