Closed13

AIコンパニオン向けのオープンソースなメモリフレームワーク「MemU」を試す

kun432kun432

GitHubレポジトリ

https://github.com/NevaMind-AI/memU

GPT-5による翻訳

MemU: AIコンパニオンのための次世代メモリフレームワーク


referred from https://github.com/NevaMind-AI/memU

MemU は、AIコンパニオンのためのオープンソースメモリフレームワークです。高精度、迅速な検索、低コストを実現します。これは、さまざまなAIコンパニオンのシナリオに適応するインテリジェントな「メモリフォルダ」として機能します。

MemU を使えば、本当にあなたを覚えているAIコンパニオンを構築できます。彼らはあなたが誰であるか、何に関心を持っているかを学び、すべての対話を通じて共に成長していきます。

公式サイトはこちら: memu.pro

🥇 92% の精度 - 💰 90% のコスト削減 - 🤖 AIコンパニオン特化

  • AIコンパニオン特化 - AIコンパニオンアプリケーションに適応
  • 92% の精度 - Locomoベンチマークにおける最先端のスコア
  • 最大 90% のコスト削減 - 最適化されたオンラインプラットフォームによる実現
  • 高度な検索戦略 - セマンティック検索、ハイブリッド検索、コンテキスト検索など複数の手法
  • 24/7 サポート - 企業顧客向け

🚀 はじめに

MemUを始めるには3つの方法があります:

☁️ クラウド版 (オンラインプラットフォーム)

アプリケーションとMemUを統合する最速の方法です。セットアップの複雑さなしにすぐにアクセスしたいチームや個人に最適です。私たちがモデル、API、クラウドストレージをホストし、アプリケーションが最高品質のAIメモリを利用できるようにします。

  • 即時アクセス - 数分でAIメモリを統合開始
  • 管理されたインフラ - スケーリング、更新、メンテナンスを管理し、最適なメモリ品質を保証
  • プレミアムサポート - サブスクリプションでエンジニアチームから優先サポートを受けられる

🏢 エンタープライズ版

最大限のセキュリティ、カスタマイズ、制御、そして最高品質を必要とする組織向け:

  • 商用ライセンス - 完全な専有機能、商用利用権、ホワイトラベルオプション
  • カスタム開発 - SSO/RBAC統合、シナリオ特化のフレームワーク最適化を行う専任アルゴリズムチーム
  • インテリジェンス & 分析 - ユーザー行動分析、リアルタイム運用監視、自動エージェント最適化
  • プレミアムサポート - 24/7専任サポート、カスタムSLA、プロフェッショナルな実装サービス

🏠 セルフホスティング (コミュニティ版)

ローカルでの制御、データプライバシー、またはカスタマイズを重視するユーザー・開発者向け:

  • データプライバシー - 機密データを自社インフラ内に保持
  • カスタマイズ - ニーズに合わせてプラットフォームを修正・拡張
  • コスト管理 - 大規模展開でもクラウド利用料を回避

セルフホスティングREADME を参照


✨ 主な特徴

🎥 デモ動画

https://www.youtube.com/watch?v=qZIuCoLglHs


ファイルシステムとしてのメモリ

Organize - 自律的なメモリファイル管理

記憶はメモリエージェントによって管理されるインテリジェントなフォルダとして構造化されます。記憶に対する明示的なモデリングは行いません。メモリエージェントが記録・変更・アーカイブすべき内容を自動で判断します。まるで自分専用の司書が、あなたの思考を正確に整理してくれるようなものです。

記憶は孤立して存在するのではありません。本システムは関連する記憶間に有意味なリンクを自動的に作成し、検索からスムーズな想起へと記憶探索を変革します。

Evolve - 継続的な自己改善

オフライン時でもメモリエージェントは稼働し続けます。既存の記憶を分析して新たな洞察を生成し、パターンを特定し、自己反省によって要約ドキュメントを作成します。ナレッジベースは単に大きくなるだけでなく、時間と共に賢くなります。

Never Forget - 適応的な忘却メカニズム

メモリエージェントは利用パターンに基づいて情報を自動的に優先付けします。最近アクセスされた記憶は高いアクセス性を維持し、関連性の低いコンテンツは優先度を下げたり忘却されます。これにより、ニーズに応じて進化するパーソナライズされた情報階層が形成されます。


😺 利点

より高い記憶精度

MemUはLocomoデータセットにおけるすべての推論タスクで平均92.09%の精度を達成し、競合を大きく上回りました。技術レポートは近日公開予定です。


referred from https://github.com/NevaMind-AI/memU

(1) シングルホップ質問: 単一セッションに基づく回答が必要 (2) マルチホップ質問: 複数セッションから情報を統合する必要あり (3) 時系列推論: 会話内の時間的手掛かりを利用して回答可能 (4) オープンドメイン知識: 話者が提供した情報と常識や世界知識を統合して回答可能

高速検索

重要な情報をドキュメントに分類し、検索時には関連ドキュメントの内容のみを探索するため、断片化した文単位での埋め込み検索は不要です。

低コスト

数百ターンの会話を一度に処理できるため、開発者が繰り返しメモリ関数を呼ぶ必要がなく、複数のメモリ操作でトークンを無駄にすることを防ぎます。ベストプラクティス を参照。


🎓 ユースケース

  • AIコンパニオン
  • AIロールプレイ
  • AI IPキャラクター
  • AI教育
  • AIセラピー
  • AIロボット
  • AIクリエーション
  • 今後もさらに・・・

📄 ライセンス

MemUへの貢献は、Apache License 2.0 の下でライセンスされます。

公式サイト

https://memu.pro/

ネコがかわいい。

kun432kun432

公式ドキュメントを見ながら。まずざっとIntroductionのところを進めていく。

https://memu.pro/docs

Overview

MemUとは?

  • MemUはAIコンパニオン向けのオープンソースの次世代メモリーフレームワーク。
  • 高い精度・高速な検索・ローコストを実現する。
    • 92.9%の精度、50ミリ秒未満のメモリ検索、最大90%のコスト削減。
  • いろんなシナリオに適応でき、ユーザーのことをちゃんと覚えて成長していくAIが作れる。

MemUと他のメモリシステムの違い

機能 他のメモリシステム MemU
構造 断片的データ ドキュメント / 動画 / 画像(ファイルシステム)
メモリ形式 LLM推論 エージェント
検索方法 埋め込み検索 埋め込み検索+ドキュメント検索
知識ベース形式 ツリー/グラフネットワーク ドキュメント間ハイパーリンク
自己進化 なし あり
忘却メカニズム なし あり

ファイルシステムとしてのメモリ

  • 自律的メモリ管理
    • ユーザのメモリは専用のメモリエージェントによって、インテリジェントなフォルダとして構造化され管理される。
    • メモリエージェントは、関連性や使用パターンに基づいて、何を記録・修正・アーカイブするか自動で決定する。
  • 相互接続された知識グラフ
    • 記憶は単独で存在するわけではない。
    • MemUは関連する記憶同士を自動で意味のあるつながりとして、豊かなハイパーリンク付きドキュメントのネットワークを構築する。
  • 継続的自己改善
    • オフラインの場合でもメモリシステムは動き続ける。
    • 既存の記憶を分析して、新しい洞察を生み出す・パターンを特定・自己反省による要約ドキュメントの作成などを行う。
  • インテリジェントな永続システム
    • 動的な重要度アルゴリズムで記憶の永続性を革命的に進化。
    • 直近で参照された記憶は優先度が高くなり、重要な物事はアクセスがしやすくなる。
kun432kun432

Quickstart

Quickstartに従って進めてみる。QuickstartはMemUのクラウドサービスが前提となっているので、アカウントを作成し、APIキーを取得しておく。

https://app.memu.so/ にアクセスして、アカウント作成。全体的にデザインがかわいい。

ログインできたら左の鍵アイコンからAPIキーを作成

ローカルにuvでプロジェクトを作成。

uv init -p 3.12 memu-work && cd $_

MemUのPythonパッケージを追加

uv add memu-py
出力
(snip)
 + memu-py==0.1.8
(snip)

会話をMemUに保存するサンプル

memorize.py
import os
import time
from memu import MemuClient

# MemUクライアントを初期化
memu_client = MemuClient(
    base_url="https://api.memu.so", 
    api_key=os.getenv("MEMU_API_KEY")
)

# シングルターンの会話
question = "私の趣味は登山なんですよ。"
response = "えー、本当ですか?私も同じなんですよ!"

# MemUに保存
memo_response = memu_client.memorize_conversation(
    conversation=f"user: {question}\n\nassistant: {response}",
    user_id="user001", 
    user_name="Demo User", 
    agent_id="gpt001", 
    agent_name="GPT Assistant"
)
print(f"💾 保存しました!タスクID: {memo_response.task_id}")

# タスク完了を待つ
while True:
    status = memu_client.get_task_status(memo_response.task_id)
    print(f"タスクの状態: {status.status}")
    if status.status in ['SUCCESS', 'FAILURE', 'REVOKED']:
        break
    time.sleep(2)

MemUのAPIキーを環境変数にセットして、実行。

export MEMU_API_KEY=XXXXXXXXXX
uv run memorize.py
出力
2025-08-28 20:23:22 | memu.sdk.python.client:95 | INFO | MemU SDK client initialized with base_url: https://api.memu.so/
2025-08-28 20:23:22 | memu.sdk.python.client:248 | INFO | Starting memorization for user user001 and agent gpt001
2025-08-28 20:23:22 | memu.sdk.python.client:261 | INFO | Memorization task started: 31ui90QN5opRaB43TeRPhqvzlIE
💾 保存しました!タスクID: 31ui90QN5opRaB43TeRPhqvzlIE
2025-08-28 20:23:22 | memu.sdk.python.client:284 | INFO | Getting status for task: 31ui90QN5opRaB43TeRPhqvzlIE
タスクの状態: PROCESSING
2025-08-28 20:23:24 | memu.sdk.python.client:284 | INFO | Getting status for task: 31ui90QN5opRaB43TeRPhqvzlIE
タスクの状態: PROCESSING
(snip)
2025-08-28 20:24:05 | memu.sdk.python.client:284 | INFO | Getting status for task: 31ui90QN5opRaB43TeRPhqvzlIE
タスクの状態: PROCESSING
2025-08-28 20:24:07 | memu.sdk.python.client:284 | INFO | Getting status for task: 31ui90QN5opRaB43TeRPhqvzlIE
タスクの状態: SUCCESS

45秒ぐらいかかって完了したみたい。結構処理が重たいのかな?

管理画面で見てみる。左メニューの「Task」には、実行したメモリ保存タスクがリストアップされるみたい。一番右の"diff"アイコンをクリック。

タスクの実行前後でどのような変化(diff)があったかを確認できるみたい。メモリの内容に応じてカテゴリも自動で生成されている。各カテゴリで更新された内容は以下となっている。

diffの内容を日本語訳してみた(DeepL)

カテゴリ diff 内容
activity + ユーザーが趣味は登山だと共有すると、アシスタントは自分も登山を楽しんでいることを明かし、本心からの驚きと興奮を示した。これにより、アウトドア活動という共通の趣味に対する共感と熱意が生まれ、二人の間に絆が生まれた瞬間となった。
profile + ユーザーは登山を趣味としており、これはユーザーが山登りや自然景観の探索といったアウトドアの身体活動に関心を持っていることを示している。
+ 登山という趣味から推測されるように、ユーザーは身体的な健康を重視し、自然豊かな屋外環境で過ごす時間を楽しんでいる可能性が高い。
+ ユーザーはおそらく登山活動に関連する実践的な経験や知識を有しており、安全な登山や山岳地帯の移動に必要な技術を含んでいる。
+ ユーザーは、登山などの個人的な趣味を共有することを楽しんでいるかもしれない。それは、共通の趣味を通じて他者と社会的につながり、関係を築く方法としてである。
+ ユーザーはアウトドア趣味や自然に関する活発な会話を求めているか、あるいはそれを好んでいる可能性があり、登山や関連トピックについて議論することに関心があることを示唆している。
+ 登山への関心は、ユーザーを社会的・文化的環境における他者と区別し、登山を特徴的な個人の特性とする可能性がある。
event + ある最近の会話で、ユーザーは趣味が登山であると明かしました。アシスタントは自分も登山を楽しんでいることを打ち明け、本心からの驚きと興奮を示しました。これにより、ユーザーとアシスタントの間にはアウトドア活動への共通の興味を通じた、つながりと相互の熱意が生まれた瞬間が生まれました。
mountain climbing + ユーザーは登山を趣味としており、これはユーザーが山登りや自然景観の探索といったアウトドアの身体活動に関心を持っていることを示している。
+ 登山という趣味から推測されるように、ユーザーは身体的な健康を重視し、自然豊かな屋外環境で過ごす時間を楽しんでいる可能性が高い。
+ ユーザーはおそらく登山活動に関連する実践的な経験や知識を有しており、安全な登山や山岳地帯の移動に必要な技術を含んでいる。
+ ユーザーは、登山などの個人的な趣味を共有することを楽しんでいるかもしれない。それは、共通の趣味を通じて他者と社会的につながり、関係を築く方法としてである。
+ ユーザーはアウトドア趣味や自然に関する活発な会話を求めているか、あるいはそれを好んでいる可能性があり、登山や関連トピックについて議論することに関心があることを示唆している。
+ 登山への関心は、ユーザーをその社会的・文化的環境における他の人々から際立たせ、登山を特徴的な個人の特性とするかもしれない。
+ ある最近の会話で、ユーザーは自身の趣味が登山であることを明かした。アシスタントは、自分も登山を楽しんでいることを打ち明けることで、純粋な驚きと興奮を示した。これにより、ユーザーとアシスタントの間には、アウトドア活動への共通の興味を通じて、つながりと相互の熱意が生まれる瞬間が生まれた。

あの2行からこれだけメモリ作るのか・・・ある程度推測な部分も仮定して進めるのかな?diffというぐらいなので今後の情報次第で修正するだろうし。ただいずれにせよ、処理量が結構多いような気はするな。

「Conversation」メニューでは、会話履歴を参照することができる。

「Memory」メニューでは、ユーザ単位でどういうメモリが保存されているかを見ることができる。タスクで抽出した内容から生成されているのだろうと思うけど、ちょっと見え方が違うね。

kun432kun432

登録したメモリの参照は公式ブログの方にあるみたい。

https://memu.pro/blog/memu-best-practice

が、メモリの参照に関するサンプルコードは見当たらない。ただ、これベストプラクティスだけでなくて、MemUのメモリの概念や仕組みみたいなことも書いてあるように思える。結構重要なことが色々書いてあるように思えるので、ここは後で見るとして、リンクを辿っていくと、参照時のサンプルコードというかSDKの説明は以下にあった。

https://memu.pro/blog/memu-sdk-guide

一番シンプルに書くとこんな感じで参照できる。

import os
from memu import MemuClient

# MemUクライアントを初期化
memu_client = MemuClient(
    base_url="https://api.memu.so", 
    api_key=os.getenv("MEMU_API_KEY")
)

result = memu_client.retrieve_default_categories(
    user_id="user001",  # 保存時と同じユーザID
    agent_id="gpt001",  # 保存時と同じエージェントID
)

print(result.model_dump_json(indent=2))
出力
{
  "categories": [
    {
      "name": "profile",
      "type": "auto",
      "user_id": "user001",
      "agent_id": "gpt001",
      "description": "Default profile category",
      "is_active": true,
      "memories": null,
      "memory_count": null,
      "summary": "## Interests & Activities  \n- Hobby: mountain climbing  \n- Interested in outdoor physical activities involving climbing mountains and exploring natural landscapes  \n- Likely has practical experience and knowledge related to safe climbing and navigating mountainous terrain  \n- Enjoys spending time in natural outdoor environments  \n\n## Personality & Characteristics  \n- Values physical fitness  \n- Possibly enjoys sharing personal interests like mountain climbing to connect socially  \n- Possibly seeks or appreciates engaging conversations about outdoor hobbies and nature  \n- Mountain climbing interest might be a distinctive personal trait within User's social or cultural environment"
    },
    {
      "name": "event",
      "type": "manual",
      "user_id": "user001",
      "agent_id": "gpt001",
      "description": "Default event category",
      "is_active": true,
      "memories": null,
      "memory_count": null,
      "summary": "- **2025-08-28**  \n  The User shared that their hobby is mountain climbing. The assistant responded with surprise and excitement, revealing that it also enjoys mountain climbing. This exchange created a moment of connection and mutual enthusiasm about their shared interest in outdoor activities."
    }
  ],
  "total_categories": 2
}

他にも参照の仕方は複数ある(クエリに関連したものを検索、カテゴリに関連したものを検索、とか)みたい。

kun432kun432

公式ドキュメントの内容は充実しているとはいえず、上でも少し触れたように現時点では公式ブログも参照したほうが良さそう。

ということで、MemUのブログ記事を見ていく。

kun432kun432

Understanding MemU: Core Concepts and Terms

https://memu.pro/blog/understanding-memu


MemUとは?

  • MemUは、AIコンパニオン向けのオープンソース記憶フレームワーク。
    • 高精度・高速検索・低コストで使えるのがウリ。
    • 様々なシナリオに合わせて、賢い「記憶フォルダ」として動作する。
  • MemUを使えば、ユーザのことを本当に覚えてくれるAIコンパニオンが作れる。
    • ユーザが、誰で・何に興味があって、を学び、全てのインタラクションを通じてユーザと一緒に進化していく。

ファイルシステムとしてのメモリ

  • MemUは、メモリを「自律的なファイルシステム」として扱い、ユーザのインタラクションに対して自律的に処理を行う
    • ユーザがデータを入力すると、メモリシステムは、自動で、以下を行う
      • 関連情報を抽出
      • 既存のドキュメントを修正
      • 新しいファイルを作成
      • 全体の構造を整理、など
    • 手動で介入する必要はない
  • このファイルシステムでは、人間と同じように、重要なメモリは目立つ場所に配置しすぐ取り出せるようにする。
    • アクセス頻度や最近使ったか、文脈が関連しているか、などから、どのメモリが重要かを動的に調整
    • ユーザにとって最も重要なものが常に見つけやすくする

メモリーアーキテクチャの概要


referred from https://memu.pro/blog/understanding-memu

Input Layer(入力層) 

  • Conversation(会話): ユーザーとエージェントのリアルタイムな対話をキャッチして処理する
  • User Activity Tracking(ユーザー活動の追跡): ユーザーの行動を監視・分析して、行動パターンを見つける
  • Multimodal Processing(マルチモーダル処理・開発中): ユーザーがアップロードした音声や動画コンテンツを処理する

Memory Organization(メモリの整理) 

  • Key Information Extraction(重要情報の抽出): 高度な要約アルゴリズムで、入ってきたデータから大事なメモリをドキュメントに抽出する
  • Automatic Classification(自動分類): 抽出したメモリを、あらかじめ決められた分類法に従ってカテゴリ分けする

Memory Graph Connection(メモリグラフの接続) 

  • Dynamic Linking(動的リンク): 複数のカテゴリにまたがる関連メモリ同士をつなげる
  • Knowledge Graph Construction(知識グラフの構築): Wikipediaみたいなハイパーリンク構造を作って、文脈をたどりながら知識を発見できるようにする

Continuous Learning & Self-evolving(継続的学習と自己進化) 

  • Background Processing(バックグラウンド処理): システムがアイドル状態の時に、自律エージェントがメモリパターンを分析する
  • Dynamic Category Generation(動的カテゴリ生成): 既存のメモリ内容から新しいカテゴリを自動で作って、ユーザーのニーズに合わせてメモリ構造を進化させる
  • Theory-of-mind(心の理論): ユーザーの深い意図を理解して、より細かいメモリアイテムを生成できる
  • Adaptive Evolution(適応的進化): システムの関連性を保つために、常に自己最適化し続ける

コアコンセプト

メモリのカテゴリ

  • MemUのメモリカテゴリは、ドキュメントにおけるファイル名のように、関連するメモリをグループ化して、メモリの検索をしやすくするための「整理箱」のような役割。
  • MemUは、主に3つのカテゴリタイプをサポートする:
    • ** System categories(システムカテゴリ)**
      • プロフィール(個人情報)やイベント(ユーザーの重要な出来事)
      • よく使う用途向けにあらかじめ用意されたカテゴリ
    • Custom Categories(カスタムカテゴリ)
      • ユーザーごとのニーズに合わせて作成するカテゴリ。
      • たとえば、ショッピングガイド用の「購入」カテゴリ、など。
    • Cluster Categories(クラスタカテゴリ)
      • 自動クラスタリング・自己反省・自己進化によって作られる自律的なカテゴリ。
      • 人間による介入は一切不要

メモリアイテム

  • MemUのメモリ管理で最も小さい単位で、メモリ検索の基本ユニット
  • 各メモリアイテムは、自己完結した情報を持ち、通常1~2文くらい程度から成る。

すでにGitHub READMEや公式ドキュメントと重複した情報が含まれているが、特に重要なのは「カテゴリ」の概念ではないかな。

kun432kun432

MemU SDK Guide - Cloud Version Documentation

https://memu.pro/blog/memu-sdk-guide

一応、クラウドバージョンと明記されている。セルフホストの場合にも適用できるかどうかはわからないが、一通り見ていく。


インストール・設定

Quickstartで既に実施しているので詳細は割愛。MemUのクラウドサービスを利用する場合は

  • MemUのPythonパッケージをインストール
  • MemUのクラウドからAPIキーを取得

を行った上で利用する。

あと、オプションで、メモリのカテゴリをクラウド上で作成することもできる。このカテゴリの追加は「Settings」メニューから「プロジェクト」単位で設定できる様子。


メモリカテゴリとは?

一つ前のブログ記事と重複するが、一応見ておく。

  • MemUのメモリカテゴリは、関連する記憶をまとめて整理する「コンテナ」みたいな役割
  • 論理的な区切りにもなり、検索の効率もアップする。

カテゴリの種類

  1. System Categories(システムカテゴリ) 
    • よく使う用途向けにあらかじめ用意されてるカテゴリ。たとえば:
      • profile:年齢・職業・学歴・家族構成などの基本的な個人情報
      • event:予定・会議・デート・節目など、ユーザの人生における重要な出来事
  2. Custom Categories(カスタムカテゴリ) 
    • ユーザごとのニーズに合わせて作るカテゴリ。たとえば、
      • ショッピングガイド用のエージェントの場合ならば、「purchase」(購入情報)など
    • MemUはシナリオに合わせて自動でいろんなカテゴリを作ってくれる
      • が、手動で「purchase」カテゴリを追加しておくと、購入履歴に関するメモリを強制的に作らせることも可能
  3. Cluster Categories(クラスタカテゴリ) 
    • 自動クラスタリング・自己反省により、完全自動で生成されるカテゴリ。
    • 人間による介入は一切不要。

カテゴリのベストプラクティス

  • カテゴリ名の命名規則: 説明的で一貫性のある名前をつけること
    • プロンプトがない場合、カテゴリ名がメモリアイテムを分類する最大のヒントになるため、良い名前をつけることが重要。
      • (訳注: カテゴリにはプロンプトを付与することも可能。どのカテゴリにどう含めるか、をLLMが判断しやすくするため、と思われる)
    • アルファベット・スペース・ハイフンのみ使用可能。
    • 良い例: ‎purchase, ‎travel plan
    • 避けるべき例: ‎@user_stuff
  • カテゴリ数の目安: カテゴリを絞り込むこと(推奨: 5~15個のカスタムカテゴリ)

使い方

本題である、SDKの使い方。

ユーザの入力のメモリへの保存

入力できるフォーマットのデータを用意する。フォーマットはいくつかある。

会話のリスト

各要素がrolecontentの2つのキーを持つリスト。

[
  {
    "role": "user", 
    "content": "登山が大好きなのですが、安全上のアドバイスはありますか?"
  },
  {
    "role": "assistant", 
    "content": "登山における安全上の基本ポイントをご紹介します…"
  }
]

会話の文字列

\nで各メッセージをつなぐ

出力
user: 登山が大好きなのですが、安全上のアドバイスはありますか?\nassistant: 登山における安全上の基本ポイントをご紹介します…

ユーザのアクティビティ

上の会話リストと同じように思えるが、ユーザメッセージだけのリスト、ってところがユーザのアクティビティを表している、ということなのかな?

[
  {
    "role": "user",
    "content": "外出するので、天気予報を確認してください..."
  },
  {
    "role": "user",
    "content": "ナビゲーションツールを用意してください: 地図、コンパス..."
  }
]

次に SDK で メモリ保存を呼び出す。

from memu import MemuClient

memu_client = MemuClient(
    base_url="https://api.memu.so",
    api_key="<MemUのAPIキー>"
)

receipt = memu_client.memorize_conversation(
    conversation=conversation_messages,
    user_id="user001",
    user_name="John Doe",
    agent_id="agent001",
    agent_name="Assistant",
    session_date="2025-08-08T08:30:00.000+09:00",
)

会話メッセージ以外には以下のような「メタデータ」を設定できる。

パラメータ名 説明
user_id ユーザーの一意なID
user_name ユーザー名(メッセージのロール名と同じ)
agent_id エージェントの一意なID
agent_name エージェント名(メッセージのロール名と同じ)
session_date 会話が行われた日時(ISO 8601形式、任意)

ただ、これuser_id とか agent_id とかは管理画面で見る限りは会話履歴の管理上のキーみたいに思えるので、「メタデータ」という表現にはやや違和感がある。おそらく conversation で渡す実際の会話データに対して、付帯するデータ、という意味でのメタデータということなのだろうとは思うのだけど。

タスクステータスの確認

メモリ保存を呼び出すとタスクIDが返ってくる。

task_id = receipt.task_id
status = memu_client.get_task_status(task_id)

Quickstart でもやったけど、タスクは非同期に行われるようなので、タスクの完了はこのタスクIDを定期的にチェックすることで確認ができる。

タスクステータスには以下のような情報が含まれる。

  • ステータスコード: status.status で確認
    • ステータスは以下のどれか
      • PENDING: タスク受信・キュー投入済み
      • PROCESSING: メモリ化タスク処理中
      • FINISH: タスク正常完了
      • FAILURE: エラー発生
  • 詳細情報: status.detail_info で確認
    • ステータスに関する詳細情報(エラー理由や進捗メッセージなど)

ユーザメモリの取得

保存したメモリの取得には3つの方法がある。

1. デフォルトカテゴリから取得

デフォルトカテゴリには、システムカテゴリとカスタムカテゴリが含まれる。ここに含まれるメモリを全て取得するには retrieve_default_categories() メソッドを使用する。

result = memu_client.retrieve_default_categories(
    user_id="user001",
    agent_id="agent001",
)

以下が返される

  • result.total_categories: カテゴリの総数
  • result.categories: メモリカテゴリのリスト。その中にメモリも含まれる。

Quickstartでやっているので詳細はそちらを参照。

2. 関連するクラスタカテゴリから取得

おそらくだけど、category_query で渡したキーワードを、カテゴリ「名」などに対して検索を行って、関連するカテゴリ内のメモリを取得する、ということなのだと思う。

result = memu_client.retrieve_related_clustered_categories(
    user_id="user001",
    agent_id="agent001",
    category_query="outdoor activities",
    top_k=5,
    min_similarity=0.3
)

3. 関連メモリアイテムを取得

こちらはより直接的に query で渡したキーワードを、個々のメモリアイテムに対して検索を行って、関連するメモリを取得する、ということだと思う。

result = memu_client.retrieve_related_memory_items(
    user_id="user001",
    agent_id="agent001",
    query="hiking safety",
    top_k=10,
    min_similarity=0.3
)

フルコードのサンプル

GitHubレポジトリにもあるが、会話データはJSONファイルになっていたので、コード内に埋め込む形にした。

https://github.com/NevaMind-AI/memU/tree/main/example/client

full_sample.py
import os
import json
import time
from typing import List, Dict
from memu import MemuClient

def wait_for_task_completion(memu_client: MemuClient, task_id: str) -> None:
    """メモリ化タスクの完了を待つ"""
    while True:
        status = memu_client.get_task_status(task_id)
        print(f"タスクの状態: {status.status}")
        
        if status.status in ['SUCCESS', 'FAILURE', 'REVOKED']:
            break
        time.sleep(2)

def main():
    # MemUクライアントを初期化
    memu_client = MemuClient(
        base_url="https://api.memu.so",
        api_key=os.getenv("MEMU_API_KEY")
    )
    
    conversation_messages = [
        {"role": "user", "content": "山登りが大好きです。安全のためのアドバイスはありますか?"},
        {"role": "assistant", "content": "山登りの必須安全対策はこちらです:必ず誰かにルートと帰宅予定時刻を伝えてください。出発前に天候を確認し、悪化した場合は引き返す準備を。必携の10の必需品を持ちましょう:ナビゲーションツール、ヘッドランプ、救急キット、火を起こす道具、修理用具、日よけ、緊急用シェルター、予備の食料、水、予備の衣類。標識のある道を歩き、一人登山は避けましょう。自分の限界を知り、初心者なら簡単なルートから始めてください。"},
        {"role": "user", "content": "本格的なイタリアのパスタを一から作りたいです。手順を教えてもらえますか?"},
        {"role": "assistant", "content": "新鮮なパスタ作りをお手伝いします!まず、00番粉または薄力粉・中力粉を400g用意し、中央にくぼみを作って卵を4個割り入れます。フォークで少しずつ粉を卵に混ぜ込みます。まとまったら10〜15分ほどこねて、なめらかで弾力のある生地にします。ラップで包んで30分休ませましょう。その後、パスタマシンまたは麺棒で薄く伸ばします。フェットチーネならシートを折り畳み、細長く切ります。生パスタは沸騰した塩水で2〜3分で茹で上がります。"},
        {"role": "user", "content": "今の仕事で行き詰まっています。会社を変えずにキャリアを進めるにはどうしたらいいですか?"},
        {"role": "assistant", "content": "会社内で成長するための戦略はいくつかあります。まず、上司にキャリアの目標を率直に伝え、伸ばすべきスキルについて具体的なフィードバックをもらいましょう。追加の責任を引き受けたり、能力を示せるチャレンジングなプロジェクトに自ら参加するのも効果的です。上級社員からメンターを得たり、別部署の業務を学ぶのも良い方法です。研修、資格取得、カンファレンス参加などで自己研鑽も。社内の人間関係を築き、成果をリーダー陣に見える形で示すことも大切です。"},
        {"role": "user", "content": "2週間の日本旅行を計画しています。必見の場所と文化的マナーを教えてください。"},
        {"role": "assistant", "content": "2週間の日本旅行なら、まず東京(4〜5日)で渋谷・新宿や浅草などを観光。次に京都(3〜4日)で伏見稲荷や清水寺など寺社巡りや伝統文化を体験。大阪(2日)で食文化を堪能し、奈良(1日)で鹿公園や東大寺を訪れるのがおすすめです。マナーとしては、挨拶の際に軽くお辞儀、室内で靴を脱ぐ、歩きながら食べない、電車では静かにする、チップは不要、などに注意。都市間移動にはJRパスが便利です。"},
        {"role": "user", "content": "25歳で初めての仕事に就きました。財務管理と資産形成を始めるにはどうしたらいいですか?"},
        {"role": "assistant", "content": "初めてのお仕事おめでとうございます!まずは50/30/20ルールで予算を作りましょう:50%を生活必需品、30%を娯楽や欲しいもの、20%を貯蓄や借金返済に。まずは生活費の3〜6か月分の緊急資金を確保します。会社が401k(企業年金)マッチングを提供しているなら、全額もらえるだけ拠出を。それは実質的に「無料のお金」です。高金利の借金は優先的に返済を。安定したらRoth IRA(個人年金口座)を開き、非課税で老後資金を育てましょう。長期的には低コストのインデックスファンドに投資するのが有効です。貯蓄は自動化して習慣にしてください。"},
        {"role": "user", "content": "運動を始めたいのですが、まったくの初心者です。初心者向けのルーティンを教えてください。"},
        {"role": "assistant", "content": "週3回、休養日を挟んで全身運動を取り入れるのがおすすめです。各セッションは軽い有酸素運動5〜10分でウォームアップを。基本の動きに集中しましょう:スクワット、腕立て(膝つきからでもOK)、プランク、ランジ、ヒップリフト。各8〜12回を2〜3セット。加えて15〜20分のウォーキングや軽い有酸素運動を。大事なのは強度よりフォームです。回数や保持時間を少しずつ増やし、体の声を聞いて無理しないこと。継続が何より大切です。"},                                                                          
        {"role": "user", "content": "スペイン語を学びたいのですが、どこから始めればいいかわかりません。初心者に効果的な学習法は?"},
        {"role": "assistant", "content": "まずは基本から始めましょう。スペイン語は表記通りに発音する言語なので、発音ルールを覚えることが重要です。挨拶や自己紹介、よく使う質問などの基本フレーズを学びましょう。DuolingoやBabbelのようなアプリで日々の練習を組み立てると効果的です。まず最もよく使われる1000語を覚えましょう。会話の80%をカバーできます。規則動詞の現在形の活用も練習してください。初心者向けのポッドキャスト、YouTube、Netflixのスペイン語番組を字幕付きで視聴し、言語に触れる機会を増やすことも大切です。会話パートナーや言語交換グループに参加すると実践力がつきます。毎日15〜30分の継続練習が鍵です。"},
        {"role": "user", "content": "裏庭に家庭菜園を作りたいのですが、初心者です。どんな野菜が育てやすいですか?"},
        {"role": "assistant", "content": "初心者におすすめの野菜は、レタス、大根、インゲン、トマト、バジルやパセリなどのハーブです。日当たりの良い場所(直射日光6〜8時間)を選びましょう。土をテストして堆肥を混ぜ、栄養を補給。最初は種よりも苗を買った方が成功率が高いです。地域の最終霜日を過ぎてから植えてください。水は一定に与えつつ過剰にはならないように。多くの野菜は週1インチ程度の水を必要とします。株元にマルチングすると水分保持や雑草防止に効果的。まずは1.2m×1.2m程度の区画から始め、無理なく育てましょう。"}
    ]

    
    # 会話をMemUに保存
    print("マルチターン会話を処理中...")
    memo_response = memu_client.memorize_conversation(
        conversation=conversation_messages,
        user_id="user001",
        user_name="User",
        agent_id="assistant001",
        agent_name="Assistant"
    )
    
    # タスク完了を待つ
    wait_for_task_completion(memu_client, memo_response.task_id)
    print("タスクが完了しました!")
    
    # 関連するメモリを取得
    memories = memu_client.retrieve_related_memory_items(
        user_id="user001",
        query="ハイキング 安全対策",
        top_k=3
    )
    
    for memory_item in memories.related_memories:
        print(f"関連するメモリ:\n{memory_item.memory.content[:100]}...")
    
    memu_client.close()

if __name__ == "__main__":
    main()

実行

uv run full_sample.py
出力
2025-08-28 23:24:51 | memu.sdk.python.client:95 | INFO | MemU SDK client initialized with base_url: https://api.memu.so/
マルチターン会話を処理中...
2025-08-28 23:24:51 | memu.sdk.python.client:248 | INFO | Starting memorization for user user001 and agent assistant001
2025-08-28 23:24:51 | memu.sdk.python.client:261 | INFO | Memorization task started: 31v4DMwJf6zp3YkTHZVHzhry9CF
2025-08-28 23:24:51 | memu.sdk.python.client:284 | INFO | Getting status for task: 31v4DMwJf6zp3YkTHZVHzhry9CF
タスクの状態: PROCESSING
2025-08-28 23:24:53 | memu.sdk.python.client:284 | INFO | Getting status for task: 31v4DMwJf6zp3YkTHZVHzhry9CF
タスクの状態: PROCESSING
(snip)
2025-08-28 23:29:19 | memu.sdk.python.client:284 | INFO | Getting status for task: 31v4DMwJf6zp3YkTHZVHzhry9CF
タスクの状態: PROCESSING
2025-08-28 23:29:21 | memu.sdk.python.client:284 | INFO | Getting status for task: 31v4DMwJf6zp3YkTHZVHzhry9CF
タスクの状態: PROCESSING
2025-08-28 23:29:23 | memu.sdk.python.client:284 | INFO | Getting status for task: 31v4DMwJf6zp3YkTHZVHzhry9CF
タスクの状態: SUCCESS
タスクが完了しました!
2025-08-28 23:29:23 | memu.sdk.python.client:387 | INFO | Retrieving related memories for user user001, query: 'ハイキング 安全対策'
2025-08-28 23:29:24 | memu.sdk.python.client:400 | INFO | Retrieved 3 related memories
関連するメモリ:
User expressed a strong interest in mountain climbing and requested comprehensive safety advice to e...
関連するメモリ:
User is likely planning to undertake actual mountain climbing activities soon and is seeking to ensu...
関連するメモリ:
User is likely planning to undertake actual mountain climbing activities in the near future and is s...

これぐらいのボリュームだと4分程度かかっている。

クラウド側のGUIでも見てみる。

結構な情報量になっている。

kun432kun432

そうそう、一応クラウド版の料金を見ておこう。

https://memu.pro/pricing

が、現状はまだ料金プランがFIXされていない様子に見える。

ただし、管理画面からも料金プランの変更などはできるようで、ここには料金プランが表示されている。

なるほど、有料版は$29/mで始まる漢字なのだね。ただ現在はおそらく準備中、ということで無料のStarterプランのみとなっている。

上に実際の使用量がでている。一応ここまででメモリ保存は2回やってて、これを見る限りはメモリの量とかじゃなくて、保存で実行したAPIコールの単位での課金に見える。メモリの抽出などはおそらくクラウド側でLLMを使ってやってると思うのだが、結構重たい処理やってるようなイメージがあるけど、そのあたりについては特に明記されていない。この設定だとなるべくまとめて一気に保存するほうがお得になるような気がするのだが。まあ有料サービス開始時にどうなっているかはわからない。

あとおまけで、GitHubのREADMEの一番下に

アンケート

改善にご協力ください!3分間のアンケートに回答して30クォータを無料で獲得: https://...

とあるので、追加クレジットがもらえるらしい。README参照。

kun432kun432

MemU Best Practice Guide

https://memu.pro/blog/memu-best-practice

MemUにおけるメモリ管理のベストプラクティス、実装パターン、最適化戦略などがまとまっているみたい。


短期メモリと長期メモリ

(続く)

短期メモリ


referred from https://memu.pro/blog/memu-best-practice and translated into Japanese by kun432

入出力の構造

短期メモリは一般的な会話履歴の構造になっている

  • 入力: システムプロンプト + 会話履歴(コンテキスト)+ ユーザクエリ
  • 出力: LLM・エージェントからのレスポンス
[
    {"role": "system", "content": "..."}, # システムプロンプト
    {"role": "user", "content": "..."}, # チャットメッセージの履歴
    {"role": "assistant", "content": "..."},
    ...
    {"role": "assistant", "content": "..."}, # チャットメッセージの履歴
    {"role": "user", "content": "..."}, # 現在のユーザのクエリ
]

いつ短期メモリを使うか?

  • 単一のセッション内
  • ユーザがLLMエージェントとアクティブにやり取りしている時

短期メモリの機能

  • 圧縮なしのフォーマット: 全ての会話の詳細を維持
  • 時系列順: 自然な会話の流れを保持

コンテキスト長とパフォーマンス

現在のLLMは200万以上の入力トークンをサポートしている。実際には、推論中に入力キーバリューキャッシュが保持されるため、約8,000トークンまでのコンテキストはレイテンシーに顕著な影響を与えない。

キャッシュ価格比較

キャッシュヒットとキャッシュミスにおけるコスト差を理解することは、最適化において極めて重要。

入力タイプ 1,000トークンあたりのコスト 相対コスト
標準入力 $0.25 10倍
キャッシュ済み入力 $0.025 1倍

長期メモリ


referred from https://memu.pro/blog/memu-best-practice and translated into Japanese by kun432

入出力の構造

長期メモリは、静的・動的の両方のメモリを組み合わせた、より複雑な構造になる

  • 入力: [システムプロンプト + 静的メモリ] + 会話履歴(短期メモリ)+ [ユーザクエリ + 検索した関連メモリ]
  • 出力: LLM・エージェントからのレスポンス
[
    {
        "role": "system",
        "content": "... \nユーザのプロファイル: xxx"
    }, # システムプロンプト + 静的メモリ(プロフィールなど)
    {
        "role": "user",
        "content": "..."
    }, # 会話のメッセージ
    {
        "role": "assistant",
        "content": "..."
    },
    ...
    {
        "role": "assistant",
        "content": "..."
    }, # 会話のメッセージ
    {
        "role": "user",
        "content": "... \n [関連メモリ1]xxx \n [関連メモリ2]xxx \n [関連メモリ3]xxx"
    } # ユーザクエリ+コンテキストに関連したメモリ
]

いつ長期メモリを使うか?

  • 複数のセッションにまたがる場合
  • ユーザが数時間・数日・数週間後に戻ってきた場合
  • ユーザ設定や過去のインタラクションの永続化のため
  • コンテキストが実用的なトークン制限を超える場合(10万トークン以上、推論速度に影響する場合)

長期メモリの機能

  • 効率的な検索のための圧縮・要約されたメモリ
  • インテリジェントな検索のためのセマンティックなインデックス

ベストプラクティス

メモリのための会話の長さ

  • MemUはメモリタスクで使用されるAPI呼び出しごとに課金する。
  • 最適なユーザ体験とコスト削減のためには、API呼び出しを行う前に複数のチャットメッセージ(短期記憶)を完全な会話にまとめることがベスト

メモリのカテゴリ

プロフィール / システム カテゴリ

  • ユーザの基本情報を保持
  • 一般的に静的で簡潔
  • エージェントが各ユーザを完全に理解できるよう、システムプロンプトにプロフィールカテゴリの記憶を含めることを推奨

カスタム/クラスタ カテゴリ

  • 比較的分散している
  • 関連カテゴリはユーザの現在のメッセージに依存する
  • 通常より多くのトークンを必要とする
  • ユーザのメッセージに応答するための動的でカスタマイズされたコンテキストを提供する。よって、カスタムカテゴリとクラスタカテゴリのメモリをユーザのクエリに追加することを推奨

LLMメッセージの作成方法

システムプロンプトの構造

'''
[オリジナルのエージェントのシステムプロンプト]

ユーザーのプロファイル:
[プロファイルカテゴリから取得したメモリ]
'''

ユーザクエリの構造

'''
[オリジナルのユーザクエリまたはメッセージ]

関連メモリ:
[カスタム/クラスタカテゴリから取得したメモリ]
'''

メモリ検索ガイド: いつどのメソッドを使うのか?

利用可能なメソッドは3つ

  1. retrieve_default_categories()
  2. retrieve_related_clustered_categories(category_query)
  3. retrieve_related_memory_items(query, [include_categories])

利用可能なメソッド

  1. retrieve_default_categories() ⭐⭐⭐ 最も基本的で強く推奨

説明:

  1. retrieve_related_clustered_categories(category_query) ⭐⭐ 高度なクラスタリング

  2. retrieve_related_memory_items(query, [include_categories]) ⭐⭐ コンテキスト特化型取得

利用例:
• 「先月プロジェクトXについて何を話したか?」
• 文脈に応じた関連メモリの取得
• 特定イベントのタイムライン構築

1. retrieve_default_categories()

⭐⭐⭐最も基本・強く推奨

  • 説明:
    • システムレベル(例: プロフィール、イベント)およびユーザ定義カテゴリの両方からデフォルトカテゴリを取得
    • 事前設定されたメモリカテゴリの内容全体を返す
    • システムプロンプトの初期化時に配置する
  • 使用タイミング: システム初期化またはセッション開始時(1回のみ)
  • レイテンシ: 約50ms

⭐⭐高度なクラスタリング

  • 説明:
    • セマンティック類似性に基づいて自動的にクラスタリングされたカテゴリを取得する
    • 自動生成されたメモリカテゴリの内容全体を返す
    • システムプロンプトの初期化時、または動的にユーザクエリに配置する
  • 使用タイミング:
    • 特定のトピックにセマンティック的に関連するカテゴリを探す場合(システムプロンプト内)
    • ユーザークエリに対して高度なセマンティック検索を行う場合(ユーザークエリに追加)
  • レイテンシ: 約200ms

⭐⭐特定のコンテキストの検索

  • 説明:
    • 現在のコンテキストやクエリに関連する特定のメモリ項目を取得する
    • カテゴリだけでなく、実際のメモリ内容を返す
  • 使用タイミング: 過去のイベントや情報について具体的なクエリに回答する場合
  • レイテンシ: 約200ms

実装例

実際のコードとは異なる、まあイメージのような書き方になっている。

# 初期化
system_prompt ← original_system_prompt + memu_client.retrieve_default_categories()
chat_history ← []

# チャットループ
while True:
    user_query ← get_input()
    [オプション] memories ← memu_client.retrieve_related_memory_items(user_query)
    response ← llm(system_prompt + chat_history + user_query + memories)
    chat_history.append({"user": user_query, "assistant": response})
    memu_client.memorize(chat_history)

一般論として、メモリをどこにどう突っ込むか?というところはなかなか難しいところだと感じる。MemUではキャッシュを重要視している雰囲気があって、キャッシュのことを考えるとシステムプロンプトなどはあとから更新しない方が良いとは思うのだけど、ユーザプロンプトにメモリを追加するというのは、会話履歴としてみると汚れる・全体コンテキストの中で追加した情報が強くなりすぎる、というようなことも起きうる、と思うので、目的に沿うのかどうかは正直ケースバイケースかなと思ったり。

でもまあキャッシュは意識したほうがいいのはそれはそう。

kun432kun432

ここまでの所感

あくまでも個人的な印象

  • 少しのデータからかなりのボリュームの情報が生成されるのは果たしてどうなんだろう?
    • 少ないデータから仮定の情報を生成しているように思える
      • 「事前予測」だと考えれば、先回りしてそれっぽいレスポンスを生成できる、ということなのかな?
      • diff的に更新されるように見える(実際には試していない)ので、もし違ったら訂正すればいい、ということなのかも?
    • メモリが生成されるまでに時間が結構掛かる
      • ちょっとしたデータでも数十秒、多少増やしたら数分、というレベルだと、メモリが利用できるまでには一定のタイムラグがあり、かつ、処理リソースはそれなりに占有されるかな
    • 生成されるボリュームや処理リソースを踏まえて、コスト的にどうなんだろう?
      • MemU自体はメモリタスクごとのAPIコール単位の課金らしい
      • LLMを駆使しているように思えるのでそこそこコストがかかるのでは?と思ったり。
      • セルフホストした場合にどうなるかは気になるところ
  • 現時点ではドキュメントが足りない
    • 公式ドキュメントの内容が薄い
      • 現時点ではブログなども参照する必要がある
    • 仕組みがイマイチ見えない
      • 色々説明はあるが、実際にどのようなコンポーネントを使っているか?などが想像できない
      • GitHubでコード読むしかない
  • 長期メモリ専門のソリューションに思える
    • 短期メモリのメソッドがなく、短期/長期メモリを包括したソリューションというわけではなく、長期メモリ部分のみを提供するもの
    • 実行時間なども含めて、都度都度投げ込むのではなく定期バッチ的に使う感じ
  • ネコかわいい

とりあえず、現状一番ネックなのは、中味を理解するにはコードを読むしかない、というところ・・・

DeepWikiで少し見てみるかな
https://deepwiki.com/NevaMind-AI/memU

一応セルフホストも試しておこうと思う。

kun432kun432

ちなみにGitHubの初回コミットは3週間前なので出来立てホヤホヤ。まあドキュメントが不足がちなのもしょうがないかという気もする。

kun432kun432

セルフホスト

セルフホストも試してみる。セルフホストは以下にドキュメントがある。

https://github.com/NevaMind-AI/memU/tree/main/README.self_host.md

基本的にはdocker composeで上げるだけのようだけど、LLMプロバイダのAPIキーが必要とある、まあコンテキストの抽出とかで必要になるので当然といえば当然かな。

で、Dockerコンテナにはいくつかのバリエーションがある様子。

モード(タグ) イメージサイズ 用途 GPU対応 ローカルモデル対応 docker composeファイル
minimal 約200MB APIサーバーのみ compose/docker-compose.minimal.yml
server 約500MB 標準デプロイ オプション オプション compose/docker-compose.yml
server-cpu 約500MB CPU専用サーバー compose/docker-compose.server-cpu.yml
local-cpu 約2GB ローカルモデル(CPU) compose/docker-compose.local-cpu.yml
gpu 約3GB以上 GPUアクセラレート&ローカルモデル compose/docker-compose.gpu.yml

GPUとか何に使うのかな?と思ったけど、以下あたりからコードを追いかけていくと、どうやらEmbeddingモデルのためにTransformers / sentence-transformers などがインストールされる、ということみたい。ただし、それらはEmbeddingモデルのために使われるみたいで、LLMの方は特にローカルモデルの記載も見当たらないように思える。おそらくその場合はOpenAI互換APIを別途用意することになりそう。

https://github.com/NevaMind-AI/memU/tree/main/compose/README.md

とりあえず普通にAPIプロバイダのLLM/Embeddingを使うならば serverで良さそう。APIプロバイダの場合にどれぐらいのコストがかかるのかも見ておきたいし。逆に minimal とかどういう位置づけなのかよくわからない。

手元のUbuntu-22.04(RTX4090、ただし今回はGPUは関係ない)で試してみる。

レポジトリクローン

git clone https://github.com/NevaMind-AI/memU && cd memU

.envを雛形から作成

cp env.example .env

いろいろ項目はあるけども、今回はデフォルトになっているOpenAIでやる。関係しそうなのはこのあたり。

https://github.com/NevaMind-AI/memU/blob/a3a93bb45d41bbf2f10f07777b83c5c15c3e2e34/env.example#L35-L40

https://github.com/NevaMind-AI/memU/blob/a3a93bb45d41bbf2f10f07777b83c5c15c3e2e34/env.example#L57-L62

APIキーだけセットすればそれで良さそうなので、そこだけ修正。

では起動。serverの場合はレポジトリ直下のdocker-compose.yamlで良さそうなので、そのままdocker composeで起動。

docker compose up 

初回はビルドが走るのでちょっと時間がかかるけども、以下のようになればOK。

出力
(snip)
 ✔ memu-server                Built                                                                                0.0s
 ✔ Network memu_memu-network  Created                                                                              0.1s
 ✔ Volume "memu_memu-logs"    Created                                                                              0.0s
 ✔ Volume "memu_memu-memory"  Created                                                                              0.0s
 ✔ Container memu-server      Created                                                                              0.1s
Attaching to memu-server
memu-server  | 🚀 Starting MemU Server in Docker...
memu-server  | ======================================
memu-server  | 📊 Server Configuration:
memu-server  |    Host: 0.0.0.0
memu-server  |    Port: 8000
memu-server  |    Debug: false
memu-server  |    Memory Dir: /app/memory/server
memu-server  |    LLM Provider: openai
memu-server  |    Embeddings: true
memu-server  |
memu-server  | ✅ Configuration validated
memu-server  |
memu-server  | 🌐 Server will be available at:
memu-server  |    API: http://localhost:8000
memu-server  |    Docs: http://localhost:8000/docs
memu-server  |    Health: http://localhost:8000/health
memu-server  |
memu-server  | 📝 Press Ctrl+C to stop the server
memu-server  |
memu-server  | 🚀 Starting MemU Server...
memu-server  |    Host: 0.0.0.0
memu-server  |    Port: 8000
memu-server  |    Debug: False
memu-server  |    Memory Dir: /app/memory/server
memu-server  |    LLM Provider: openai
memu-server  |    Embeddings: True
memu-server  |
memu-server  | INFO:     Started server process [1]
memu-server  | INFO:     Waiting for application startup.
memu-server  | INFO:     Application startup complete.
memu-server  | INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

これで以下のエンドポイントが用意される

  • APIのベースURL: http://localhost:8000
  • APIドキュメント: http://localhost:8000/docs
  • ヘルスチェック用: http://localhost:8000/health

実際にドキュメントにアクセスしてみるとこんな感じ。

なるほどね、GUIはクラウドサービスのみ、ってことね。

ではコードからメモリを作成してみる。Quickstartのコードを使う。

uv init -p 3.12 memu-selfhost-work && cd $_
uv add memu-py
出力
(snip)
 + memu-py==0.1.11
(snip)

サンプル。接続先のURLをローカルのものに変更、APIキーはないと怒られるのでダミーで。実際には .env で設定できる。

add_memory.py
import os
import time
from memu import MemuClient

memu_client = MemuClient(
    base_url="http://<サーバのIPアドレス>:8000",
    api_key="dummy"
)

question = "私の趣味は登山なんですよ。"
response = "えー、本当ですか?私も同じなんですよ!"

memo_response = memu_client.memorize_conversation(
    conversation=f"user: {question}\n\nassistant: {response}",
    user_id="user001",
    user_name="Demo User",
    agent_id="gpt001",
    agent_name="GPT Assistant"
)
print(f"💾 保存しました!タスクID: {memo_response.task_id}")

while True:
    status = memu_client.get_task_status(memo_response.task_id)
    print(f"タスクの状態: {status.status}")
    if status.status in ['SUCCESS', 'FAILURE', 'REVOKED']:
        break
    time.sleep(2)

実行

uv run add_memory.py
出力
2025-09-22 13:03:28 | memu.sdk.python.client:98 | INFO | MemU SDK client initialized with base_url: http://XXX.XXX.XXX.XXX:8000/
2025-09-22 13:03:28 | memu.sdk.python.client:258 | INFO | Starting memorization for user user001 and agent gpt001
2025-09-22 13:03:28 | memu.sdk.python.client:271 | INFO | Memorization task started: 8ae4e406-cbe4-40f2-b85d-379e6689ad17
💾 保存しました!タスクID: 8ae4e406-cbe4-40f2-b85d-379e6689ad17
2025-09-22 13:03:28 | memu.sdk.python.client:294 | INFO | Getting status for task: 8ae4e406-cbe4-40f2-b85d-379e6689ad17
タスクの状態: PROCESSING
(snip)
2025-09-22 13:04:31 | memu.sdk.python.client:294 | INFO | Getting status for task: 8ae4e406-cbe4-40f2-b85d-379e6689ad17
タスクの状態: PROCESSING
2025-09-22 13:04:33 | memu.sdk.python.client:294 | INFO | Getting status for task: 8ae4e406-cbe4-40f2-b85d-379e6689ad17
タスクの状態: SUCCESS

次に参照。

read_memory.py
import os
from memu import MemuClient

memu_client = MemuClient(
    base_url="http://<サーバのIPアドレス>:8000",
    api_key="dummy"
)

result = memu_client.retrieve_default_categories(
    user_id="user001", 
    agent_id="gpt001",
)

print(result.model_dump_json(indent=2))
uv run read_memory.py
出力
2025-09-22 13:07:25 | memu.sdk.python.client:98 | INFO | MemU SDK client initialized with base_url: http://XXX.XXX.XXX.XXX:8000/
2025-09-22 13:07:25 | memu.sdk.python.client:368 | INFO | Retrieved 2 categories
{
  "categories": [
    {
      "name": "profile",
      "type": "default",
      "user_id": null,
      "agent_id": null,
      "description": "Default profile memories",
      "memory_items": null,
      "summary": null
    },
    {
      "name": "event",
      "type": "default",
      "user_id": null,
      "agent_id": null,
      "description": "Default event memories",
      "memory_items": null,
      "summary": null
    }
  ],
  "total_categories": 2
}

んー、クラウド版のときはこれで何かしらサマリーが取得できたのだけど・・・よく見るとuser_idなんかもnullになってる・・・

サーバの中身を見てみる。

docker exec -ti memu-server bash
出力
memu@cf26ab41cf9b:/app$

以降はコンテナ内での作業。

メモリは /app/memory に保存されているらしい。で、データは/app/memory/server/gpt001/user001 にあった。

cd /app/memory/server/gpt001/user001
ls -lt 
出力
ls -lt
total 16
-rw-r--r-- 1 memu memu 1157 Sep 22 04:04 mountain_climbing.md
-rw-r--r-- 1 memu memu  642 Sep 22 04:04 event.md
-rw-r--r-- 1 memu memu  682 Sep 22 04:04 profile.md
-rw-r--r-- 1 memu memu  338 Sep 22 04:03 activity.md

中身はこんな感じ。

profile.md
[f30a7b][mentioned at 2025-09-22] Demo User's hobby is mountain climbing, which is an important and enjoyable part of Demo User's personal life. [9c645a,ce7bec,f679d9,2b916f,09fc5c]
[f679d9][mentioned at 2025-09-22] Demo User likely maintains a good level of physical fitness to pursue mountain climbing as a hobby. [f30a7b,2b916f,4428f1,09fc5c,9c645a]
[09fc5c][mentioned at 2025-09-22] Demo User probably has experience with outdoor activities beyond casual interest. [2b916f,f679d9,f30a7b,4428f1,9c645a]
[2b916f][mentioned at 2025-09-22] Demo User may be interested in building social connections through shared hobbies like mountain climbing. [f30a7b,09fc5c,f679d9,4428f1,9c645a]
event.md
[ce7bec][mentioned at 2025-09-22] On 2025-09-22, Demo User shared with the assistant that Demo User's hobby is mountain climbing. The assistant responded with surprise and enthusiasm, revealing that the assistant also enjoys mountain climbing. This exchange created a moment of connection and shared interest between Demo User and the assistant. [9c645a,f30a7b,2b916f,4428f1,f679d9]
[4428f1][mentioned at 2025-09-22] Demo User might be currently or recently active in mountain climbing around the date 2025-09-22, indicating a recent or ongoing engagement in mountain climbing activities around that time. [2b916f,f679d9,f30a7b,09fc5c,ce7bec]
activity.md
[9c645a][mentioned at 2025-09-22] Demo User shared with the assistant on 2025-09-22 that Demo User's hobby is mountain climbing, and the assistant responded with surprise and enthusiasm, revealing that the assistant also enjoys mountain climbing, creating a moment of connection and shared interest between Demo User and the assistant. []
mountain_climbing.md
[f30a7b][mentioned at 2025-09-22] Demo User's hobby is mountain climbing, which is an important and enjoyable part of Demo User's personal life. [f30a7b]
[f679d9][mentioned at 2025-09-22] Demo User likely maintains a good level of physical fitness to pursue mountain climbing as a hobby. [f679d9]
[09fc5c][mentioned at 2025-09-22] Demo User probably has experience with outdoor activities beyond casual interest. [09fc5c]
[2b916f][mentioned at 2025-09-22] Demo User may be interested in building social connections through shared hobbies like mountain climbing. [2b916f]
[ce7bec][mentioned at 2025-09-22] On 2025-09-22, Demo User shared with the assistant that Demo User's hobby is mountain climbing. The assistant responded with surprise and enthusiasm, revealing that the assistant also enjoys mountain climbing. This exchange created a moment of connection and shared interest between Demo User and the assistant. [ce7bec]
[4428f1][mentioned at 2025-09-22] Demo User might be currently or recently active in mountain climbing around the date 2025-09-22, indicating a recent or ongoing engagement in mountain climbing activities around that time. [4428f1]

一応抽出はできているのかな?参照が上手くいかないような。他の参照方法だといけるのかな?

Issue見るとこれかも。

https://github.com/NevaMind-AI/memU/issues/24

うーん、クラウド側はすでに対応されているみたいで、セルフホスト版は次のバージョンアップ待ちか。なお、別の検索方法も試してみたけど、そちらも上手くいかず・・・・

import os
from memu import MemuClient

memu_client = MemuClient(
    base_url="http://<サーバのIPアドレス>:8000",
    api_key="dummy"
)

memories = memu_client.retrieve_related_memory_items(
    user_id="user001",
    query="趣味",
    top_k=3
)

for memory_item in memories.related_memories:
    print(f"関連するメモリ:\n{memory_item.memory.content[:100]}...")
出力
2025-09-22 13:31:57 | memu.sdk.python.client:98 | INFO | MemU SDK client initialized with base_url: http://rtx4090.local:8000/
2025-09-22 13:31:57 | memu.sdk.python.client:415 | INFO | Retrieving related memories for user user001, query: '趣味'
2025-09-22 13:31:58 | memu.sdk.python.client:428 | INFO | Retrieved 0 related memories

とりあえずセルフホストは時期尚早かな

このスクラップは3ヶ月前にクローズされました