AIエージェントのメモリは、短期記憶・長期記憶・エピソード記憶の3層で設計するのが定石です。短期は会話コンテキスト、長期はユーザーの好みや事実情報、エピソードは過去のタスク実行経験を司ります。この区別を曖昧にすると、LLMのコンテキストウィンドウがすぐに溢れ、かつ過去の学びが活用できない「記憶喪失のエージェント」が生まれます。
なぜAIエージェントにメモリが必要か
LLMは原則として「前回の会話を覚えていない」存在です。各リクエストは独立しており、コンテキストウィンドウに含まれない情報は一切参照できません。そのため、AIエージェントが継続的なやり取りを行うには、外部にメモリを持たせる必要があります。さらに、コンテキストウィンドウには上限があり、すべての履歴を詰め込むのは不可能です。重要な情報を抽出し、適切な形で保持する戦略が必要になります。
【AIエージェントのメモリ3種類】
短期記憶(Working Memory)
[現在の会話]
└── 直近N発話を保持
└── セッションごとにリセット
長期記憶(Long-term Memory)
[ユーザー情報・事実知識]
└── ベクトルDBに永続保存
└── 類似度検索で呼び出し
エピソード記憶(Episodic Memory)
[過去のタスク実行経験]
└── 成功・失敗パターンを保存
└── 類似タスクに再利用
この3層はそれぞれ役割が異なり、使い分けが重要です。関連する基礎知識として、AIエージェントの基本構造、ベクトルDB、エンベディング、RAGの記事を併せて参照してください。
短期記憶(Working Memory)
短期記憶は、現在の会話セッション中に参照される直近の文脈を保持する役割を持ちます。これが機能しないと、「先ほど話した件ですが」という参照が通じなくなります。もっとも素朴な実装は、会話履歴をすべて配列に蓄積し、毎回LLMへ渡す方式です。しかし、トークン消費が際限なく膨らむため、実用的にはN発話のみ保持するバッファ方式や、古い発話を要約して圧縮する方式が採用されます。
from collections import deque
from openai import OpenAI
client = OpenAI()
class ShortTermMemory:
def __init__(self, max_turns=10):
self.buffer = deque(maxlen=max_turns)
def add(self, role, content):
self.buffer.append({"role": role, "content": content})
def messages(self):
return list(self.buffer)
memory = ShortTermMemory(max_turns=10)
memory.add("user", "東京の人口は?")
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=memory.messages()
)
memory.add("assistant", response.choices[0].message.content)
より洗練された設計では、バッファが溢れる前に古い履歴を要約する「Summary Memory」を重ねます。LangChainのConversationSummaryBufferMemoryはその代表例です。
長期記憶(Long-term Memory)
長期記憶は、セッションを跨いで保持される情報を扱います。ユーザーの好み、名前、過去に言及した事実、業務上の重要な文脈などが対象です。典型的な実装は、情報をエンベディングに変換してベクトルDBへ保存し、必要に応じて類似度検索で呼び出す形式です。RAGと同じ仕組みですが、扱う対象がドキュメントではなく「個別のメモリ単位」である点が異なります。
from openai import OpenAI
import chromadb
client = OpenAI()
chroma = chromadb.Client()
collection = chroma.create_collection(name="long_term_memory")
def embed(text):
return client.embeddings.create(
model="text-embedding-3-small",
input=text
).data[0].embedding
def save_memory(user_id, fact):
collection.add(
embeddings=[embed(fact)],
metadatas=[{"user_id": user_id}],
documents=[fact],
ids=[f"{user_id}-{hash(fact)}"]
)
def recall_memory(user_id, query, k=3):
return collection.query(
query_embeddings=[embed(query)],
n_results=k,
where={"user_id": user_id}
)["documents"][0]
save_memory("u001", "好きな食べ物はピザ")
print(recall_memory("u001", "食事の好みは?"))
長期記憶には、情報の重要度や鮮度をメタデータとして付与するのが実務的です。古くなった情報を削除するか、信頼度を下げる仕組みを入れないと、古い情報が誤った応答を生む原因になります。
エピソード記憶(Episodic Memory)
エピソード記憶は、過去のタスク実行の「経験」を保存する領域です。どんな問題を、どんな手順で解き、結果としてどうだったかを記録し、将来同じような問題に遭遇した際に参照できるようにします。人間が過去の失敗から学ぶのと同じで、エージェントに経験を蓄積させる仕組みです。
from datetime import datetime
import json, chromadb
from openai import OpenAI
client = OpenAI()
chroma = chromadb.Client()
episodes = chroma.create_collection(name="episodes")
def embed(text):
return client.embeddings.create(
model="text-embedding-3-small", input=text
).data[0].embedding
def save_episode(task, steps, outcome):
doc = json.dumps({"task": task, "steps": steps, "outcome": outcome}, ensure_ascii=False)
episodes.add(
embeddings=[embed(task)],
documents=[doc],
metadatas=[{"outcome": outcome, "ts": datetime.utcnow().isoformat()}],
ids=[f"ep-{datetime.utcnow().timestamp()}"]
)
def recall_similar_episodes(task, k=3):
return episodes.query(
query_embeddings=[embed(task)],
n_results=k
)["documents"][0]
save_episode("月次レポート作成", ["データ取得", "集計", "グラフ化"], "success")
print(recall_similar_episodes("四半期レポート作成"))
エピソード記憶の本質は「再利用可能な知恵」です。失敗パターンの記録が特に価値を持ちます。同じ失敗を繰り返さないためのブロッカーとして機能するからです。
メモリ設計のベストプラクティス
| 種別 | 保存先 | 保持期間 | 検索方法 | 主な用途 | 実装難易度 |
|---|---|---|---|---|---|
| 短期記憶 | インメモリ/Redis | セッション中 | 順次参照 | 会話文脈 | 低 |
| 長期記憶 | ベクトルDB | 永続 | 類似度検索 | ユーザー情報・事実 | 中 |
| エピソード記憶 | ベクトルDB+RDB | 永続 | 類似度+メタ検索 | タスク経験再利用 | 高 |
| ユースケース | 短期 | 長期 | エピソード | 理由 |
|---|---|---|---|---|
| カスタマーサポートBot | 必須 | 必須 | 推奨 | 過去の問い合わせ履歴を活かす |
| 社内ナレッジ検索 | 推奨 | 必須 | 不要 | 知識検索が主目的 |
| 業務自動化エージェント | 必須 | 推奨 | 必須 | 過去の手順を再利用 |
| コーディング補助 | 必須 | 推奨 | 必須 | プロジェクトごとの文脈 |
| 単発Q&A | 不要 | 不要 | 不要 | 文脈継承不要 |
メモリは入れれば入れるほど良いわけではありません。必要以上に情報を詰め込むと、検索ノイズが増え、かえって応答品質が落ちます。「何を覚え、何を忘れるか」の判断こそが設計の核心です。
まとめ――メモリはAIエージェントの「経験」
- メモリは短期・長期・エピソードの3層で設計するのが基本
- 短期記憶はインメモリ、長期記憶はベクトルDB、エピソード記憶はベクトルDB+RDBの組み合わせが定石
- 情報の重要度・鮮度・信頼度をメタデータで管理する
- 「何を覚え、何を忘れるか」の判断が応答品質を決める
よくある質問
AIエージェントのメモリとは
AIエージェントが過去の対話や実行結果を記憶し、将来のタスクに活用するための仕組みです。短期記憶(現在の会話)、長期記憶(過去の知識・好み)、エピソード記憶(過去の経験パターン)の3種類があります。
メモリなしのエージェントでも動作しますか
動作しますが、毎回の対話が独立してしまい、文脈の継続や過去の経験の活用ができません。1回限りのタスク実行ならメモリなしでも十分ですが、継続的な対話やパーソナライズが必要な場合はメモリが必須です。
エージェントのメモリはどこに保存すべきですか
短期記憶はインメモリ(Redis等)、長期記憶はベクトルDB(Qdrant、Pinecone等)、エピソード記憶はベクトルDB+RDB(PostgreSQL等)の組み合わせが一般的です。データの永続性とアクセス速度のバランスで選定してください。