はじめに: 知性の基盤としての記憶
記憶のない大規模言語モデルは、記憶喪失の専門家のようなものです。単一の質問に見事に答えます。 しかし、継続的な関係を構築したり、過去のやり取りから学んだり、蓄積したりすることができない 時間の経過とともに知識が得られます。そこには メモリ それがステートレス LLM を エージェント しつこい、あなたが誰であるか、何を話し合ったのか、一緒にどのような決定を下したのかを思い出すことができます。
記憶システムがなければ、すべての対話はゼロから始まります。エージェントはあなたが昨日バグを修正したことを知りません 認証モジュールでは、JavaScript よりも Python を好むかどうかは覚えておらず、どのプロジェクトがどのプロジェクトに属しているのかもわかりません。 あなたは仕事をしていて、2週間後に締め切りがあります。しかし、記憶があれば、エージェントは真の協力者になります。 コンテキストを蓄積し、繰り返し発生するパターンを認識し、時間の経過とともにその応答を改善します。
この記事では、AI エージェントの記憶システムを、次のような最も単純な戦略から検討していきます。 会話履歴からベクトル埋め込み、ナレッジ グラフ、ハイブリッド パターンを使用した高度なアプローチまで 2026 年のベスト プラクティスとして浮上している Mem0。完全性とコストのトレードオフを分析します。 精度とレイテンシの間で、各アプローチを実装するための疑似コードと具体的なアーキテクチャを提供します。
この記事で学べること
- AI エージェントの 4 種類の記憶: 感覚記憶、短期記憶、長期記憶、エピソード記憶
- 会話履歴の管理戦略: スライディング ウィンドウ、要約、重要度のサンプリング
- ベクトル埋め込みと RAG (検索拡張生成) パターンの仕組み
- Neo4j を使用したリレーショナル推論のためのナレッジ グラフ
- Mem0 ハイブリッド パターン: ベクトル ストア + ナレッジ グラフの組み合わせ
- コンテキスト ウィンドウの最適化とトークン バジェット
- 異なるメモリアプローチ間のベンチマークとトレードオフ
AI エージェントのメモリの種類
AI エージェントの記憶システムの研究は人間の認知心理学からインスピレーションを得て、概念を適応させています 言語モデルのコンテキストに対する短期および長期の記憶として。 4つ特定できます 基本的なタイプのメモリであり、それぞれに異なる特性と使用例があります。
4 種類の記憶
| タイプ | 説明 | 間隔 | Esempio |
|---|---|---|---|
| 感覚記憶 | 即時入力: 現在のプロンプトと実行したばかりのツールの結果 | 単一の反復 | ユーザーのメッセージ、SQL クエリの出力 |
| 短期記憶 | 現在のセッションのコンテキスト: 蓄積された会話履歴 | 単一セッション | チャット内の以前のメッセージ、下された決定 |
| 長期記憶 | 外部ストレージに保存された、異なるセッション間での永続的な知識 | 永続 | ユーザー設定、ビジネス文書、ソースコード |
| エピソード記憶 | 関係コンテキストとの過去のやり取りの特定の記憶 | 永続 | 「JSON パーサーのバグを修正したとき」 |
感覚記憶: 即時入力
感覚記憶は、エージェントが現時点で「知覚」するすべてのもの、つまりメッセージを表します。 ユーザーの、実行したばかりのツールの結果、呼び出された API の応答。最高レベルだよ ループの 1 回の反復中にのみ存在する、少量の一時的なメモリ エージェント。完全に現在のプロンプト内に存在するため、永続化メカニズムは必要ありません。
実際には、感覚記憶は、単一のパラメータでモデルに渡されるパラメータに対応します。 call: システム プロンプト、ユーザーとアシスタントのメッセージ、およびツール呼び出しの結果。 これは、処理できるトークンの最大数を定義するモデルのコンテキスト ウィンドウによって制限されます。 一つの推論で。
短期記憶: セッションの背景
短期記憶は、単一の会話セッション内のコンテキストを維持します。 ユーザーとエージェント間で交換されたメッセージのリスト (結果を含む) として実装されます。 中間ツール呼び出しの数。このメモリにより、エージェントは何を参照できるようになります。 文脈上の曖昧さを解決し、対話の一貫性を維持するためであると以前にも言われています。
短期記憶に関する主な問題は、 直線的な成長: 多ければ多いほど 会話が続くと、より多くのトークンが消費されます。コンテキスト ウィンドウを持つモデルの場合 128,000 ~ 200,000 トークン、激しい技術的な会話では、数時間の作業で限界に達する可能性があります。 このため、圧縮と優先順位付けの戦略を実装することが不可欠になります。
長期記憶: 永続的な知識
長期記憶により、エージェントは異なるセッション間で情報を記憶することができます。 会話の中に残る短期記憶とは異なり、長期記憶には必要なものがあります。 外部ストレージ: ベクトル データベース、リレーショナル データベース、構造化ファイル システム。 エージェントは対話中に関連情報を保存し、必要に応じてそれを取得します。 今後のセッション。
長期記憶の例には以下が含まれます: ユーザーの好み (プログラミング言語) 推奨、コード スタイル、命名規則)、インデックス付きの会社文書、知識 プロジェクトの基礎、技術仕様と要件。このタイプの記憶は変化します エージェントが一般的なアシスタントから、パーソナライズされ、状況に合わせたコラボレーターに変わります。
エピソード記憶: 特定の記憶
エピソード記憶は最も洗練されたタイプであり、単に事実を記憶するだけではなく、 覚えておいてください 具体的な経験 関係的なコンテキストとともに。エージェントは覚えています 「パーサーにバグがある」だけでなく、「1 月 15 日にパーサーにバグがあると診断しました」 不正なエンコードが原因で発生した JSON パーサー。ユーザーが検証を追加することで解決しました。 前処理では UTF-8」。
エピソード記憶は通常、ナレッジ グラフを使用して実装されます。 プロジェクト、バグ、決定など)はノードであり、それらの間の関係(解決済み、原因あり、 depend_on) は円弧です。これにより、エージェントはイベント間の接続をナビゲートできるようになります。 そして、豊富で関連性のあるコンテキストを提供します。
会話履歴の管理
会話履歴は、最も直接的な記憶の形式です。つまり、メッセージの完全なリストです。 現在のセッションで取引されました。効率的に管理することが非常に重要です。 ウィンドウには固定制限があり、それを超えると情報が失われるか、最悪の場合は受信することになります。 モデルからのエラー。主要な戦略は 3 つあり、それぞれに独自のトレードオフがあります。
戦略 1: スライディング ウィンドウ
最も単純なアプローチ: 最後のものだけを保持する N メッセージを削除し、古いメッセージを破棄します。 実装が簡単で、トークンの消費量が予測可能であり、追加のモデル呼び出しは必要ありません。 欠点は、会話の最初のコンテキストが完全に失われることです。 エージェントが対話の開始時に下された決定に言及するときの矛盾。
class SlidingWindowMemory:
def __init__(self, max_messages: int = 20):
self.max_messages = max_messages
self.messages: list[dict] = []
def add_message(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
# Mantieni sempre il system prompt (indice 0)
if len(self.messages) > self.max_messages:
system = self.messages[0]
self.messages = [system] + self.messages[-(self.max_messages - 1):]
def get_context(self) -> list[dict]:
return self.messages.copy()
def token_count(self) -> int:
return sum(len(m["content"]) // 4 for m in self.messages)
戦略 2: 段階的な要約
古いメッセージを破棄するのではなく、段階的に要約していきます。会話のとき トークンのしきい値を超えると、古いメッセージは保存された要約に圧縮されます 重要な情報: 下された決定、重要な事実、表明された好み。概要 アクティブな会話を担当し、トークンをあまり消費せずにコンテキストを維持します。
この戦略では、サマリーを生成するために追加のモデル呼び出しが必要です。 コストと遅延が増加します。ただし、コンテキストをより効果的に保存します。 スライディング ウィンドウと比較すると、重要な情報が完全に失われることはないためです。
class SummarizationMemory:
def __init__(self, max_tokens: int = 4000, summary_threshold: int = 3000):
self.max_tokens = max_tokens
self.summary_threshold = summary_threshold
self.summary: str = ""
self.active_messages: list[dict] = []
def add_message(self, role: str, content: str):
self.active_messages.append({"role": role, "content": content})
if self._count_tokens(self.active_messages) > self.summary_threshold:
self._compress()
def _compress(self):
# Prendi i messaggi più vecchi (prima meta)
half = len(self.active_messages) // 2
old_messages = self.active_messages[:half]
self.active_messages = self.active_messages[half:]
# Genera un riassunto dei messaggi vecchi
prompt = f"Riassumi i punti chiave di questa conversazione:\n"
for msg in old_messages:
prompt += f"{msg['role']}: {msg['content']}\n"
new_summary = llm_call(prompt) # Chiamata al modello
self.summary = f"{self.summary}\n{new_summary}".strip()
def get_context(self) -> list[dict]:
context = []
if self.summary:
context.append({
"role": "system",
"content": f"Riassunto conversazione precedente:\n{self.summary}"
})
context.extend(self.active_messages)
return context
戦略 3: 重要度のサンプリング
最も洗練されたアプローチ: 各メッセージは独自に評価されます。 重要性 関連するものだけがコンテキスト内に保持されます。重要性は次のように判断できます。 いくつかの要因: 明示的な決定の存在、プロジェクトの主要なエンティティへの言及、 好みの表現、制約や要件の定義。
この戦略はコンテキストの品質の点で最良の結果をもたらしますが、 実装が最も複雑です。重要性を評価するにはモデル (またはヒューリスティック) が必要です 各メッセージの内容、および一見無関係に見えるが重要な情報が削除されるリスク そして常に存在します。
class ImportanceSamplingMemory:
def __init__(self, max_tokens: int = 4000):
self.max_tokens = max_tokens
self.messages: list[dict] = []
self.importance_scores: list[float] = []
def add_message(self, role: str, content: str):
score = self._evaluate_importance(content)
self.messages.append({"role": role, "content": content})
self.importance_scores.append(score)
self._prune()
def _evaluate_importance(self, content: str) -> float:
score = 0.5 # Base score
# Decisioni esplicite
if any(kw in content.lower() for kw in ["deciso", "scelta", "usero", "implemento"]):
score += 0.3
# Vincoli e requisiti
if any(kw in content.lower() for kw in ["deve", "requisito", "vincolo", "deadline"]):
score += 0.2
# Errori e bug
if any(kw in content.lower() for kw in ["errore", "bug", "fix", "problema"]):
score += 0.2
# Messaggi recenti hanno un bonus
score = min(score, 1.0)
return score
def _prune(self):
while self._count_tokens() > self.max_tokens:
# Rimuovi il messaggio con l'importanza più bassa
# (escludi system prompt e ultimo messaggio)
min_idx = min(
range(1, len(self.importance_scores) - 1),
key=lambda i: self.importance_scores[i]
)
self.messages.pop(min_idx)
self.importance_scores.pop(min_idx)
戦略間のトレードオフ
| 戦略 | 複雑 | 追加費用 | 品質のコンテキスト | 使用事例 |
|---|---|---|---|---|
| 引き違い窓 | 低い | ゼロ | 平均 | 短い会話、プロトタイプ |
| まとめ | 平均 | 1 ~ 2 回の LLM コール | 高い | 長いセッション、複雑なタスク |
| 重要度のサンプリング | 高い | ヒューリスティックまたはLLM | 非常に高い | 専門代理店・制作 |
ベクトルの埋め込みと検索拡張生成
I ベクトル埋め込み それらは空間内のテキストの密な数値表現です。 多次元。各文、段落、または文書は数値のベクトルに変換されます。 (通常は 768 または 1536 次元) ベクトル間の幾何学的距離は、 対応するテキスト間の意味上の類似性。似た意味を持つ 2 つの文にはベクトルが含まれます たとえ全く違う言葉を使っていたとしても、空間的には近い。
埋め込みの仕組み
埋め込みプロセスでは、特殊なニューラル モデル (たとえば、 text-embedding-3-small
OpenAI または all-MiniLM-L6-v2 Sentence Transformers の) は文字列を入力として受け取ります
テキストのデータを抽出し、数値ベクトルを生成します。これらのモデルは膨大な量のテキストでトレーニングされています
意味的に類似した文をベクトル空間内に近接して配置することを目的としています。
類似性検索は、 少し似ている または ユークリッド距離 クエリ ベクトルとインデックス付きドキュメント ベクトルの間。 距離が最も小さい (または類似性が最も高い) ドキュメントがクエリに最も関連しています。
import numpy as np
def cosine_similarity(vec_a: np.ndarray, vec_b: np.ndarray) -> float:
"""Calcola la similarità coseno tra due vettori."""
dot_product = np.dot(vec_a, vec_b)
norm_a = np.linalg.norm(vec_a)
norm_b = np.linalg.norm(vec_b)
return dot_product / (norm_a * norm_b)
# Esempio: embedding di due frasi
embedding_1 = embed("Come risolvere un bug nel parser JSON")
embedding_2 = embed("Fix di un errore nel parsing di file JSON")
embedding_3 = embed("Ricetta per la torta al cioccolato")
# Le prime due frasi avranno alta similarità (~0.85-0.95)
# La terza sarà molto distante (~0.05-0.15)
print(cosine_similarity(embedding_1, embedding_2)) # ~0.91
print(cosine_similarity(embedding_1, embedding_3)) # ~0.08
ベクター データベース: 主なオプション
ベクトル データベースは、ベクトルの保存と検索に最適化されたストレージ システムです。 高次元。 B ツリー インデックスを使用するリレーショナル データベースとは異なり、ベクトル データベースでは次のようなアルゴリズムが使用されます。 ニューサウスウェールズ州 (階層型ナビゲート可能なスモールワールド) o 体外受精 (反転ファイル インデックス) を使用して、サブリニア時間で近似検索を実行します。
ベクターデータベースの比較
| データベース | タイプ | 強みポイント | 使用事例 |
|---|---|---|---|
| 松ぼっくり | マネージド (クラウド) | スケーラビリティ、ゼロオペレーション、サーバーレスインデックス | 大規模な生産、インフラのないチーム |
| ウィアビエイト | セルフホスト型 / クラウド型 | ハイブリッド検索 (ベクター + BM25)、GraphQL API | フィルターによる高度な検索、電子商取引 |
| 彩度 | 組み込み / セルフホスト型 | 軽量、ネイティブ Python API、ローカル開発 | プロトタイプ、ローカルアプリケーション、開発 |
| クドラント | セルフホスト型 / クラウド型 | パフォーマンス、高度なフィルター、豊富なペイロード | 高性能アプリケーション |
| ベクター | PostgreSQL 拡張機能 | 既存のスタック、SQL との統合 | すでに PostgreSQL を使用しているチーム |
RAG パイプライン: 検索拡張生成
パターン ラグ (検索拡張生成)は、 長期記憶を AI エージェントに統合します。考え方はシンプルです。質問に答える前に、 質問があると、エージェントはナレッジ ベースで最も関連性の高いドキュメントを検索し、それらをプロンプトに含めます。 追加のコンテキストとして。これにより、モデルは情報に基づいて応答を行うことができます 具体的かつ最新のもので、幻覚を軽減します。
class RAGPipeline:
def __init__(self, vector_db, embedding_model, llm):
self.vector_db = vector_db
self.embedding_model = embedding_model
self.llm = llm
def ingest(self, documents: list[str], metadata: list[dict] = None):
"""Indicizza documenti nella knowledge base."""
for i, doc in enumerate(documents):
# 1. Chunking: dividi il documento in frammenti
chunks = self._chunk_document(doc, chunk_size=512, overlap=50)
for chunk in chunks:
# 2. Embedding: genera il vettore
vector = self.embedding_model.embed(chunk)
# 3. Store: salva nel vector database
self.vector_db.upsert(
id=f"doc_{i}_{hash(chunk)}",
vector=vector,
text=chunk,
metadata=metadata[i] if metadata else {}
)
def query(self, question: str, top_k: int = 5) -> str:
"""Rispondi a una domanda usando RAG."""
# 1. Embedding della query
query_vector = self.embedding_model.embed(question)
# 2. Retrieval: cerca i documenti più simili
results = self.vector_db.search(
vector=query_vector,
top_k=top_k,
threshold=0.7 # Soglia minima di similarità
)
# 3. Context assembly: costruisci il contesto
context = "\n\n---\n\n".join([r.text for r in results])
# 4. Generation: genera la risposta
prompt = f"""Rispondi alla domanda basandoti SOLO sul contesto fornito.
Se il contesto non contiene la risposta, dillo esplicitamente.
Contesto:
{context}
Domanda: {question}
Risposta:"""
return self.llm.generate(prompt)
def _chunk_document(self, doc: str, chunk_size: int, overlap: int) -> list[str]:
"""Dividi un documento in chunk con overlap."""
words = doc.split()
chunks = []
for i in range(0, len(words), chunk_size - overlap):
chunk = " ".join(words[i:i + chunk_size])
chunks.append(chunk)
return chunks
チャンク化のベスト プラクティス
- チャンクサイズ: 256 ~ 1024 トークン。小さすぎるとコンテキストが失われ、大きすぎるとノイズが発生します
- オーバーラップ: 途中でコンセプトが崩れることを避けるため、チャンク サイズの 10 ~ 20%
- セマンティックチャンキング: 文字数ではなく、段落または論理セクションで分割することを好みます。
- メタデータ: ソース、日付、ドキュメント タイプを各チャンクに関連付けて、結果をフィルタリングします。
- 再ランキング: 取得後、クロスエンコーダー モデルを使用して、関連性によって結果を並べ替えます。
リレーショナル メモリのナレッジ グラフ
I ナレッジグラフ 知識をエンティティ (ノード) のネットワークとして表現します。 関係 (円弧) によって接続されており、それぞれが関連するプロパティを持ちます。ベクトルデータベースとは異なります 意味的類似性検索に優れたナレッジ グラフは、 関係推論: エンティティがどのように相互に接続されているかを理解してください。 関係の連鎖を調べ、既存のつながりから新しい知識を推測します。
ナレッジグラフの構造
ナレッジ グラフは、次の 3 つの基本要素で構成されます。
- ノード (エンティティ): ドメイン オブジェクトを表します。各ノードには、プロパティのセットであるタイプ (ラベル) があります。例:
(:User {name: "Federico", role: "developer"}) - 文字列 (関係): 2 つのノードを接続し、タイプと方向を持ちます。各円弧はプロパティを持つことができます。例:
[:RESOLVED {date: "2026-01-15", time_spent: "2h"}] - 財産: ノードまたはエッジに関連付けられたキーと値のペア。詳細とコンテキストを追加します。
Neo4j は暗号言語です
Neo4j 宣言型クエリ言語を備えた、最も人気のあるグラフ データベースです。
呼ばれた サイファー これにより、グラフのナビゲーションが直感的になります。サイファーが使用するのは、
グラフの構造を反映する視覚的な構文: ノードは括弧で表されます。
丸い () 角括弧内の関係 [] 方向を示す矢印付き。
// Creare nodi e relazioni per la memoria episodica
CREATE (u:User {name: "Federico", role: "developer"})
CREATE (p:Project {name: "E-commerce API", language: "Python"})
CREATE (b:Bug {id: "BUG-142", description: "Parser JSON crash on UTF-8"})
CREATE (s:Session {date: "2026-01-15", duration: "45min"})
// Relazioni con proprietà
CREATE (u)-[:WORKS_ON {since: "2025-11-01"}]->(p)
CREATE (b)-[:FOUND_IN]->(p)
CREATE (u)-[:RESOLVED {method: "UTF-8 validation", time: "2h"}]->(b)
CREATE (s)-[:DISCUSSED]->(b)
CREATE (s)-[:INVOLVED]->(u)
// Query: Trova tutti i bug risolti da Federico con il contesto
MATCH (u:User {name: "Federico"})-[r:RESOLVED]->(b:Bug)-[:FOUND_IN]->(p:Project)
RETURN b.description, r.method, r.time, p.name
// Query: Ricostruisci la timeline di una sessione
MATCH (s:Session {date: "2026-01-15"})-[:DISCUSSED]->(topic)
MATCH (s)-[:INVOLVED]->(participant)
RETURN s.date, collect(topic.description), collect(participant.name)
// Query: Trova bug correlati per progetto e tipo
MATCH (b1:Bug)-[:FOUND_IN]->(p:Project)<-[:FOUND_IN]-(b2:Bug)
WHERE b1 <> b2 AND b1.description CONTAINS "parser"
RETURN b1.description, b2.description, p.name
記憶に関するナレッジグラフの利点
ナレッジ グラフは、ベクトル データベースよりも AI エージェントの記憶に独自の利点をもたらします。 彼らは答えることができません:
- 関係推論: エージェントはエンティティ間の関係をナビゲートして、明白ではない接続を発見できます。 「Federico は電子商取引プロジェクトにあったバグ BUG-142 を修正しましたが、同じプロジェクトには別の同様のバグ BUG-198 があります。」
- 効率的なコンテキスト: プロンプトに履歴全体を含める代わりに、エージェントは現在のクエリに関連するサブグラフのみを抽出し、トークンを節約します
- 推論: 既存の関係から新しい知識を引き出す推論ルールを定義できます。 A が B に依存し、B が C に依存する場合、A は推移的に C に依存します。
- 増分更新: 新しい情報は、インデックス全体を再構築することなく、新しいノードおよびエッジとして追加されます。
- 説明可能性: エージェントはグラフを通じて推論パスを追跡し、透明性のある説明を提供できます。
ハイブリッド アプローチ: Mem0 パターン
Mem0 パターン: ベスト プラクティス 2026
2026 年の AI エージェントの記憶システムの新たなパターンは次のことを組み合わせたものです ベクトルストア e ナレッジグラフ 一つのまとまったシステムに。 「Mem0」(「メムゼロ」と発音)という名前は、同じ名前のオープンソース プロジェクトを指します。 そして、それが導入したアーキテクチャパターン:ゼロから始まり成長していく記憶 それぞれの相互作用で有機的に。
Mem0 パターンのアーキテクチャ
基本的な考え方はシンプルです。エージェントが新しい情報を受け取ると、それを保存します。 同時に 両方のストレージ システムで。彼が回復しなければならないとき コンテキスト、検索を実行します ハイブリッド 両方の結果を組み合わせたもの 検索の品質を最大化するシステム。
class HybridMemory:
"""Pattern Mem0: Vector Store + Knowledge Graph combinati."""
def __init__(self, vector_db, graph_db, embedding_model, llm):
self.vector_db = vector_db
self.graph_db = graph_db
self.embedding_model = embedding_model
self.llm = llm
def store(self, interaction: str, metadata: dict):
"""Salva una nuova memoria in entrambi i sistemi."""
# 1. Estrai entità e relazioni dal testo
entities, relations = self._extract_knowledge(interaction)
# 2. Vector Store: salva l'embedding del testo completo
vector = self.embedding_model.embed(interaction)
self.vector_db.upsert(
id=metadata.get("id", str(hash(interaction))),
vector=vector,
text=interaction,
metadata=metadata
)
# 3. Knowledge Graph: salva entità e relazioni
for entity in entities:
self.graph_db.merge_node(entity.label, entity.properties)
for relation in relations:
self.graph_db.merge_relation(
relation.source, relation.type, relation.target,
properties=relation.properties
)
def retrieve(self, query: str, top_k: int = 5) -> dict:
"""Recupera contesto da entrambi i sistemi."""
# 1. Vector similarity search
query_vector = self.embedding_model.embed(query)
vector_results = self.vector_db.search(query_vector, top_k=top_k)
# 2. Estrai entità dalla query per il graph traversal
query_entities = self._extract_entities(query)
# 3. Graph traversal: espandi il contesto relazionale
graph_context = []
for entity in query_entities:
neighbors = self.graph_db.get_neighbors(
entity, depth=2, limit=10
)
graph_context.extend(neighbors)
# 4. Combina e deduplica i risultati
return {
"vector_results": vector_results,
"graph_context": graph_context,
"combined_context": self._merge_results(
vector_results, graph_context
)
}
def _extract_knowledge(self, text: str):
"""Usa un LLM per estrarre entità e relazioni."""
prompt = f"""Estrai le entità e le relazioni dal seguente testo.
Formato output:
ENTITIES: [tipo:nome:proprietà, ...]
RELATIONS: [source-TIPO_RELAZIONE->target, ...]
Testo: {text}"""
response = self.llm.generate(prompt)
return self._parse_extraction(response)
ハイブリッド検索フロー
ハイブリッド取得は、両方のシステムの長所を活用する 2 段階のプロセスに従います。
- 絞り込みのためのベクトル類似度: ベクトル検索は、意味的に関連するドキュメントを迅速にフィルタリングし、検索スペースを数千件から数十件の結果に削減します。
- 強化のためのグラフトラバーサル: ベクトル結果で見つかったエンティティから開始して、グラフ トラバーサルによりナレッジ グラフ内の関係を追跡することでコンテキストを拡張し、意味的な類似性だけでは見つけられなかった関連情報を追加します。
- 再ランキングと合併: 結合された結果は、グラフ内の意味上の類似性と距離の両方を考慮して、全体的な関連性によって並べ替えられます。
- コンテキストアセンブリ: 最終的なコンテキストはトークン バジェット内で組み立てられ、最も関連性の高い結果が優先されます。
コンテキストウィンドウの最適化
コンテキスト ウィンドウは、AI エージェントの最も貴重な資産です。コンテキスト内ですべてのトークンが無駄になる 無関係で、有用な回答のトークンが 1 つ減ります。コンテキストウィンドウの最適化 利用可能な情報量のバランスをとる体系的なアプローチが必要です。 選択したコンテキストの品質と関連性。
トークンのカウントと予算の割り当て
最初のステップは、 トークンの予算 プロンプトの各コンポーネントごとに。 128K コンテキスト ウィンドウ トークンを持つエージェントの一般的な割り当ては次のようになります。
コンポーネントごとのトークン予算
| 成分 | 割り当てられたトークン | パーセンテージ | 注意事項 |
|---|---|---|---|
| システムプロンプト | 2,000 - 4,000 | 2~3% | 指示、性格、制約 |
| ツールの定義 | 3,000 - 8,000 | 3~6% | 利用可能なツールの説明と図 |
| 長期記憶 | 5,000 - 15,000 | 5~12% | RAG の結果、ナレッジ グラフからのコンテキスト |
| 会話履歴 | 20,000 - 50,000 | 15~40% | 最近のメッセージ、概要 |
| 応答用に予約済み | 8,000~16,000 | 6-12% | モデル応答用のスペース |
| セキュリティバッファ | 5,000 - 10,000 | 4~8% | ツールの予期しない結果に対するマージン |
セマンティック キャッシング
Il セマンティックキャッシング 再計算を避ける最適化手法です すでに処理されたものと同様の質問に対する埋め込みとクエリ。エージェントがメッセージを受け取ると、 クエリでは、まず意味的に類似したクエリが最近すでに処理されているかどうかを確認します。 類似性がしきい値 (通常は 0.95) を超える場合、結果がキャッシュから返されます。 ベクトル データベースで新たな検索を実行する必要はありません。
このアプローチにより、取得操作の待ち時間とコストが大幅に削減されます。 特に、ユーザーが同じ質問を別の方法で再定式化したり、 後続のクエリは同じテーマのバリエーションです。
階層的な検索
アプローチ 階層的な検索 知識ベースを複数のレベルで整理します 粒度のこと。最上位レベルには、文書全体の一般的な要約があります。レベルで 中間にはセクションの要約があります。最下位レベルには、次のような元のチャンクがあります。 すべての詳細。
検索は最高レベルから開始されます。つまり、一般的な概要が文書の内容を示している場合です。 これに関連して、セクション レベルに下がり、セクションのみのチャンク レベルに下がります。 より関連性の高いもの。このアプローチにより、埋め込み比較の数が大幅に削減されます。 必要なノイズを排除し、結果の品質を向上させます。
ベンチマークとトレードオフ
適切なメモリ システムの選択は、アプリケーションの特定のコンテキストによって異なります。 普遍的に最適なソリューションはありません。それぞれのアプローチには独自の長所があります。 最適な選択は遅延、コスト、精度の要件によって異なります。 そして実装の複雑さ。
メモリアプローチの包括的な比較
| アプローチ | レイテンシ | 正確さ | 料金 | 複雑 | 理想的な用途 |
|---|---|---|---|---|---|
| 引き違い窓 | ~0ms | 低い | ゼロ | 最小限 | 簡単なチャット、プロトタイプ |
| まとめ | 200~500ミリ秒 | 中~高 | 中くらい | 低い | 長時間のセッション、コーディング |
| ベクター DB (RAG) | 50~200ミリ秒 | 高い | 中くらい | 平均 | ナレッジベース、ドキュメント |
| ナレッジグラフ | 100~500ミリ秒 | 非常に高い | 高い | 高い | 関係推論 |
| ハイブリッド (Mem0) | 200~800ミリ秒 | 素晴らしい | 高い | 非常に高い | エンタープライズエージェント、プロダクション |
いつ何を使うか
- スライディングウィンドウのみ: シンプルなチャットボット、短い対話、永続性が必要ない迅速なプロトタイプ
- スライディング ウィンドウ + 要約: 長時間のコーディング セッション、会話のコンテキストだけで十分なパーソナル アシスタント
- ベクター DB (RAG): エージェントが外部ナレッジ ベース (ドキュメント、ソース コード、会社の FAQ) にアクセスする必要があり、クエリが独立している場合
- ナレッジグラフ: エンティティ間の関係が重要 (プロジェクト管理、CRM、診断システム) で、マルチホップ推論が必要な場合
- ハイブリッド (Mem0): セマンティック検索とリレーショナル推論の両方が必要で、予算が許す実稼働エンタープライズ エージェント
実際の実装: 本番環境に関する考慮事項
実稼働環境でメモリ システムを実装するには、次のようないくつかの側面に注意する必要があります。 単純なアルゴリズムの選択を超えています。同時実行管理、一貫性 データの管理、監視、プライバシーはすべて重要な側面です。
- プライバシーとGDPR: 思い出には個人データが含まれる場合があります。選択的削除と明示的な同意メカニズムを常に実装する
- 時間の減衰:古い記憶は関連性を失います。アクセスされていないメモリの重みを段階的に減らす減衰システムを実装しています。
- 競合と更新: 新しい情報が既存の記憶と矛盾する場合、エージェントはどのバージョンを保持するかを決定する必要があります。更新ログで常に最新の情報を優先する
- 監視: 取得ヒット率、平均レイテンシー、コンポーネントごとのトークン分布、知覚される応答品質などの指標を追跡します。
- グレースフルフォールバック: メモリ システムに障害が発生した場合 (ベクター DB のダウン、グラフの破損)、エージェントは引き続き機能し、現在の会話のみに機能が低下する必要があります。
結論
メモリはステートレス LLM を真のインテリジェント エージェントに変えるコンポーネントです そしてしつこい。シンプルな会話履歴からベクトルを使った高度なハイブリッドシステムまで データベースとナレッジ グラフ、それぞれのアプローチは複雑さの間の異なるバランスを提供します。 コンテキストのコストと品質。
ベクター ストアとナレッジ グラフを組み合わせた Mem0 パターンがベスト プラクティスとして浮上しています 重要なのは、単一のアプローチを選択することではなく、 トレードオフを理解し、ユースケースに適した組み合わせを選択してください。 最初は単純で、必要な場合にのみ複雑さを追加します。
次の記事では、 高度な通話ツール: エージェントのような REST API、Web サービス、カスタマイズされたツールを統合して、現実世界で動作します。見てみましょう ツール定義、入力検証、サニタイズ戦略のための JSON スキーマ そして再利用可能なツールのフレームワークを構築する方法。







