【ガンダムコントで解説】AIエージェントに「長期記憶」を持たせる!GibsonAI/Memori 導入と活用法
Memoriは、LLM(大規模言語モデル)やAIエージェントに、人間のように「記憶」を持たせ、文脈(コンテキスト)を理解させるためのオープンソースのメモリーエンジンです。
これはまるで、ホワイトベース隊が「ザビ家の陰謀」や「アムロのわがまま」といった過去の経験や人間関係を、戦闘のたびにいちいち思い出さなくても、自然に判断を下せるようになるのと同じです!
役立ちポイント
長期記憶(LTM)の実現
LLMは通常、セッション(会話)が終わるとすべて忘れてしまいます。Memoriは、過去の会話や重要な情報(エンティティ、事実、好み、ルール)を永続的にデータベースに保存します。
文脈の自動注入
次の会話やタスクの際に、関連する記憶(長期記憶や短期記憶)を自動的かつインテリジェントにLLMのプロンプトに含めます。これにより、エージェントは過去の経緯を踏まえた、より賢く、一貫性のある応答や行動ができます。
コント
アムロとブライト艦長
ブライト
「アムロ、なぜ連邦軍がジオンに勝ったのか、君はもう3回も説明しただろう!毎回『えーっと、何だっけ?』はやめろ!」
アムロ(Memori搭載)
「ブライトさん、分かっています。ミノフスキー粒子の特性と、サイド7での戦闘データですよね。短期記憶に昇格済みです。今回は『ザクにはヒートホークが効かない』という長期記憶を基に、ビームサーベルで挑みます!」
ブライト
「……フン、少しは成長したようだな!」
役立ちポイント
Pydanticによる構造化
MemoriはPythonのPydanticを活用し、記憶を抽出・分類する際に、構造化された型安全なデータとして扱います。
信頼性の向上
エンジニアは、単なるテキストの羅列ではなく、「ユーザー名」「プロジェクト名」「技術スタック」といった検証済みの情報として記憶を扱えるため、エージェントの処理の信頼性が大幅に向上します。
コント
マチルダさんと整備班
マチルダさん
「ホワイトベースの修理データ、今回もメモ書きで提出したのかい?」
整備班(Memori使用)
「いえ、今回の修理はPydanticで型検証されたデータです!『修理箇所
ガンダムの左肩』『交換部品
ビームサーベル』『緊急度
A』と、構造化されています!メモの紛失や誤字によるデータ欠損はありません!」
マチルダさん
「素晴らしい!これなら本国のデータとすぐに同期できるね!」
役立ちポイント
共通の記憶領域
複数のAIエージェント(例
計画立案エージェント、実行エージェント、ユーザー対応エージェント)が、Memoriデータベースを介して共通の知識ベースを共有できます。
シームレスな連携
エージェント間でいちいち文脈を引き継ぐ必要がなくなり、より複雑なタスクを分担し、効率的かつ一貫性のあるチームワークを実現できます。
コント
カイさんとハヤト
カイ(情報収集エージェント)
「敵はシャアのザク。過去の戦闘で長期記憶に登録された『シャアは赤が好き』という情報と、『新しいモビルスーツの弱点』を短期記憶に格納したぞ!」
ハヤト(戦闘エージェント)
「了解!共通のMemoriデータベースでその情報を見た!俺は『シャアの予想進路』を自動でプロンプトに含めて、最適な迎撃ルートを計算する!」
ブライト艦長
「(…みんな、私が怒鳴らなくても連携できるようになったのか…)」
MemoriはPythonで提供されています。
まずは、戦いに必要な装備(ライブラリ)を整えます。
pip install Memori
デフォルトではSQLiteを使用できますが、より本格的な運用ではPostgreSQLなども使えます。特に準備は不要で、実行時に自動でデータベースファイルが作成されます。
LLMを扱うライブラリ(LangChainやLlamaIndexなど)と組み合わせて使用しますが、ここではMemori単体での基本的な使い方を紹介します。
この例では、エージェント(アムロ)が「連邦軍のパイロットである」という基本情報と、「過去の戦闘経験」を記憶し、次の会話でそれを活用します。
from Memori import Memori
# 1. パイロット(エージェント)を初期化
# 'pilot_amuro'というIDで記憶エンジンを起動
amuro = Memori(agent_id='pilot_amuro')
print("--- 起動(Memori初期化) ---")
# 2. 初期設定の注入(長期記憶に登録)
# 'conscious_ingest=True'で、重要な情報(基本設定、ルール)を意識的に短期記憶にも注入
initial_facts = [
"私は連邦軍のパイロットである。",
"私のモビルスーツはRX-78 ガンダムである。",
"シャア・アズナブルは宿敵である。",
]
for fact in initial_facts:
# Memoriに情報をインジェスト(取り込み)
amuro.ingest_memory(
memory_type="FACT",
memory_value=fact,
conscious_ingest=True
)
print("\n--- 記憶の確認(検索) ---")
# 'pilot_amuro'に関連する記憶を検索
relevant_mems = amuro.retrieve_memory(query="私の立場と宿敵について教えて")
for mem in relevant_mems:
# 検索結果(関連度の高い記憶)を表示
print(f"**関連記憶:** {mem.memory_value}")
# 3. 会話の記録と処理(戦闘経験の記録)
print("\n--- 会話の記録と処理 ---")
# 新しい会話を記録(ユニバーサル記録)
amuro.universal_record(
speaker="ブライト艦長",
message="アムロ、ザクにはビームライフルが最も有効だ。ヒートホークは避けろ!"
)
# 記録された会話からエンティティや事実を自動抽出・分類し、長期記憶に保存される
amuro.process_last_record()
# 4. 次の戦闘(LLMへのプロンプト)に記憶を自動注入
print("\n--- 次のプロンプトへの自動注入 ---")
# 'get_context()'で、Memoriが最も関連性の高い記憶を自動で選び、
# LLMに渡すべきプロンプト文脈を生成
context_for_llm = amuro.get_context(query="次のザクとの戦闘で取るべき行動は?")
print("LLMへ渡すコンテキスト(アムロの記憶):")
print(context_for_llm)
LLMへ渡すコンテキスト(アムロの記憶):
**短期記憶:**
- 私は連邦軍のパイロットである。
- 私のモビルスーツはRX-78 ガンダムである。
- シャア・アズナブルは宿敵である。
**長期記憶:**
- ブライト艦長: アムロ、ザクにはビームライフルが最も有効だ。ヒートホークは避けろ!
---
次のザクとの戦闘で取るべき行動は?
解説
amuro.get_context()で、Memoriは「私は誰か」「宿敵は誰か」といった短期記憶と、「直近のブライト艦長の忠告」という長期記憶の中から関連度の高いものを選び出し、LLMが即座に使える一つの文脈(プロンプト)としてまとめてくれます。
これで、アムロ(エージェント)は毎回同じ質問をすることなく、賢く次の行動を判断できるようになるわけです!