🤖

AIエージェントはどう「記憶」するのか——短期・長期・ファクトベースの仕組みを解説

に公開

AIエージェントはどう「記憶」するのか

自律稼働するAIエージェントを実装する際、意外と見落とされるのが記憶の仕組みだ。今この瞬間に何をしているのか。過去に何をしたのか。そして何が事実なのか。この3つを区別して管理できるかどうかで、エージェントの動きは大きく変わる。

多くの開発者はLLMの記憶機構を曖昧なままに組み立ててしまい、後になってスケーラビリティの壁や判断の一貫性の欠如に直面する。3つの記憶レイヤーの役割と実装方法を見ていこう。

3つの記憶レイヤー

1. 短期メモリ(コンテキストウィンドウ)

短期メモリはLLMのコンテキストウィンドウそのものである。会話履歴、直近の観測結果、実行中のタスク説明がここに入る。リアルタイム性は高いが、トークン制限があり、明示的に保存しない限り自動的には残らない。

実装の基本形:

class Agent:
    def __init__(self):
        self.context_window = []
    
    def add_to_context(self, role, content):
        self.context_window.append({
            "role": role,
            "content": content
        })
    
    def get_context(self):
        # コンテキスト制限内で保持する
        return self.context_window[-20:]  # 直近20メッセージ

ただ短期メモリだけに頼ると、数時間後には過去の判断を忘れてしまう。そこで長期メモリが活躍する。

2. 長期メモリ(エピソード記憶)

長期メモリはエージェント自身が実行した行動やイベントの記録だ。ベクトルデータベースやテキスト検索システムで実装され、セッション間を超えて保持される。過去のタスク履歴を検索可能にすることで、スケーラビリティが飛躍的に向上する。

from datetime import datetime

class EpisodicMemory:
    def __init__(self, vector_db):
        self.vector_db = vector_db
    
    def store_episode(self, task, action, result, timestamp=None):
        episode = {
            "timestamp": timestamp or datetime.now().isoformat(),
            "task": task,
            "action": action,
            "result": result
        }
        # ベクトル化して保存
        self.vector_db.add(episode)
    
    def retrieve_similar_episodes(self, query, limit=5):
        # 類似したタスク履歴を検索
        return self.vector_db.search(query, limit=limit)

「過去に類似の顧客問い合わせをどう処理したか」といった検索が活躍する。経験が蓄積されるにつれ、エージェントの判断精度は上がっていく。

3. ファクトベース(セマンティック記憶)

ファクトベースは事実・知識・ルールの永続的な記録層だ。顧客情報、企業ポリシー、プロダクト仕様など、変更頻度が低く検索されやすい情報に最適である。構造化・非構造化情報の両方に対応でき、複数エージェント間での共有も容易だ。

class FactStore:
    def __init__(self, db_connection):
        self.db = db_connection
    
    def store_fact(self, category, key, value, metadata=None):
        fact = {
            "category": category,
            "key": key,
            "value": value,
            "metadata": metadata or {}
        }
        self.db.insert("facts", fact)
    
    def query_fact(self, category, key):
        result = self.db.query(
            "facts",
            where={"category": category, "key": key}
        )
        return result[0]["value"] if result else None
    
    def get_facts_by_category(self, category):
        # カテゴリーごとに関連ファクトを一括取得
        return self.db.query("facts", where={"category": category})

複数エージェント間で判断の一貫性を保つには、ファクトストアが唯一の情報源として機能する必要がある。

3つの記憶を統合する設計

現場実装では、3つの記憶レイヤーを明確に役割分担させることが欠かせない。

記憶検索の流れ

ユーザー入力

【短期】コンテキストウィンドウを確認

【長期】類似の過去タスク履歴を検索

【ファクト】必要な知識・ルールを取得

意思決定&実行

具体例:カスタマーサポートエージェント

ユーザーから「以前の注文について質問があります」という連絡が来たとしよう。

  1. 短期メモリが今回の会話の流れを把握する
  2. 長期メモリからこのユーザーの過去の問い合わせ処理を検索し、解決方法を参考にする
  3. ファクトストアで現在の返金ポリシーと商品のサポート対象期間を確認する

3つを組み合わせることで、エージェントは一貫性を保ちながら個別対応ができるようになる。

実装時の注意点

トレードオフ1:レイテンシ vs 精度

短期メモリは高速だが精度に欠ける場合がある。長期・ファクトベース検索は正確だが遅延が増す。ユースケースに応じた設計を求められる。

トレードオフ2:保持 vs プライバシー

エピソード記憶の保持期間を定めないと、個人情報やセンシティブなデータが際限なく蓄積される。定期的なクリーンアップ戦略を組み込む必要がある。

トレードオフ3:更新頻度 vs コスト

ファクトストアを常に最新に保つのはコストがかかる。変更頻度と更新タイミングを事前に定義しておくことが重要だ。

さらに詳しく学ぶなら

AIエージェントの設計・実装をより詳しく学びたい方は、Zenn Bookの『AIエージェントが自律稼働するまで』をご覧ください。記憶設計に加えて、マルチステップの推論、エラーハンドリング、スケーリング戦略など、実運用に必要な全体像を解説しています。

まとめ

AIエージェントの記憶はコンテキストウィンドウだけでは成り立たない。短期・長期・ファクトベースの3レイヤーを意識的に設計することで、真に自律稼働するエージェントが実現する。短期メモリでリアルタイム性を確保し、長期メモリで学習と改善を積み重ね、ファクトベースで判断の一貫性を保つ。3つの役割分担を明確にしたエージェント設計が、本番環境での信頼性向上につながる。

Discussion