R-Mem

April 13, 2026 · View on GitHub

R-Mem

AI Agent のための長期メモリ — Rust で実装

mem0 のメモリアーキテクチャを Rust で研究する軽量実装。
シングルバイナリ。SQLite バックエンド。Python 不要。

License: MIT Rust Built with Claude Code Crates.io Awesome SQLite

クイックスタート · 統合ガイド · 仕組み · 使い方 · MCP · アーキテクチャ · ロードマップ

🌐 English · 繁體中文 · 简体中文 · 한국어

Note

本プロジェクトは学習目的で、mem0 の優れたメモリアーキテクチャを Rust で再実装したものです。オリジナルの設計は mem0 チームの功績です。これは代替品ではなく、異なる言語によるアーキテクチャの研究です。ディスカッション、アイデア、コントリビューションを歓迎します!


なぜ R-Mem か?

mem0 は優れた設計のメモリシステムであり、豊富な plugin エコシステムを持っています。R-Mem はより狭い問いを立てています:コアのメモリロジックだけを Rust で書き直し、完全に SQLite をバックエンドにしたらどうなるか?

結果は同じ三層アーキテクチャ — vector memorygraph memoryhistory — と 階層アーカイブ システムを 2,826 行の Rust で実現。外部サービス不要。バイナリ一つ。トレードオフは明確:統合の数は mem0 よりはるかに少ないが、運用オーバーヘッドはほぼゼロ。

R-Mem は RustClaw から生まれました — 私たちのミニマリスト Rust AI agent フレームワークです。RustClaw にはその哲学に合ったメモリレイヤーが必要でした:シングルバイナリ、外部サービスゼロ。そこで mem0 のアーキテクチャを研究し、Rust で再構築しました。

R-Memmem0
📦 バイナリ3.6 MB 静的リンクPython + pip(豊富なエコシステム)
💾 アイドル RSS< 10 MB200 MB+(より多くの機能をロード)
📝 コード2,826 行~91,500 行(26+ 種の store driver)
🔍 VectorSQLite + FTS5Qdrant、Chroma、Pinecone…
🕸️ GraphSQLite のみNeo4j / Memgraph
🤖 LLMOpenAI、Anthropic、OllamaOpenAI、Anthropic など
🗄️ Archive階層メモリ + fallback 検索

mem0 の数字は豊かなエコシステムを反映しています — より多くの store、より多くの統合、より多くの柔軟性。R-Mem は最小限のフットプリントのためにそれらを意図的にトレードオフしています。

R-Mem が mem0 に追加する機能

機能R-Memmem0
階層アーカイブ削除/更新されたメモリを保存 + fallback 検索削除されたら消失
FTS5 プリフィルタ2 段階検索:キーワード → vector(19 倍高速)vector のみ
MCP Server内蔵 rustmem mcp、Claude Code / Cursor 対応提供なし
依存ゼロのデプロイシングルバイナリ、SQLite、Docker 不要Python + pip + vector DB + graph DB
Anthropic ネイティブ対応Claude API を直接サポートOpenAI 互換プロキシ経由
設定可能なパイプライン[memory] セクション:閾値や上限などすべて調整可能ハードコードされたデフォルト
メモリカテゴリ自動分類:preference, personal, plan, professional, health非構造化

🔍 仕組み

Input text

├─ 📦 Vector Memory ──────────────────────────────────
│    │
│    ├─ LLM が事実を抽出
│    │    → ["Name is Alice", "Works at Google"]
│    │
│    ├─ Embedding → cosine similarity 検索
│    │    (FTS5 プリフィルタ + vector ランキング)
│    │
│    ├─ Integer ID mapping
│    │    (LLM の UUID ハルシネーション防止)
│    │
│    ├─ LLM が各事実について判定:
│    │    ├─ ADD       新しい情報
│    │    ├─ UPDATE    より具体的 → 旧バージョンをアーカイブ
│    │    ├─ DELETE    矛盾 → 旧バージョンをアーカイブ
│    │    └─ NONE      重複 — スキップ
│    │
│    └─ アクション実行 + 履歴に書き込み

├─ 🕸️ Graph Memory ──────────────────────────────────
│    │
│    ├─ LLM がエンティティ + 関係を抽出
│    ├─ 競合検出(古いデータを soft-delete、新しいデータを追加)
│    └─ 多値 vs 単値の関係処理

└─ 🗄️ Archive ───────────────────────────────────────

     ├─ 削除/更新されたメモリを embedding 付きで保存
     ├─ アクティブな結果が弱い場合の fallback 検索
     └─ アーカイブが閾値を超えると自動圧縮

🚀 クイックスタート

前提条件

要件インストール
Rust 1.75+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
LLM バックエンドOllama(ローカル)、OpenAI、または Anthropic

ビルド & 実行

git clone https://github.com/Adaimade/R-Mem.git && cd R-Mem
cargo build --release
# → target/release/rustmem(3.6 MB)

設定

プロジェクトルートに rustmem.toml を作成:

Ollama(ローカル) OpenAI Anthropic
[llm]
provider = "openai"
base_url = "http://127.0.0.1:11434"
model = "qwen2.5:32b"

[embedding]
provider = "openai"
base_url = "http://127.0.0.1:11434"
model = "nomic-embed-text"
[llm]
provider = "openai"
api_key = "sk-..."
model = "gpt-4o"

[embedding]
provider = "openai"
api_key = "sk-..."
model = "text-embedding-3-small"
[llm]
provider = "anthropic"
api_key = "sk-ant-..."
model = "claude-sonnet-4-6"

[embedding]
provider = "openai"
api_key = "sk-..."
model = "text-embedding-3-small"

注意: Anthropic は embedding モデルを提供していないため、[llm] で Anthropic を使用する場合でも [embedding] は OpenAI または Ollama を使用します。


🔗 統合ガイド

⚠️ MemoryManager を構築するだけでは不十分

最も一般的な統合ミス:MemoryManager を初期化したものの、会話ループで add()search() を一度も呼び出さないこと。メモリシステムは存在するが使われていない — ユーザーが言ったことは何も記憶されません。

正しい会話ループ

毎ターン、2 つのメモリ操作を含める必要があります:

  1. LLM 呼び出し前 — 想起(関連するメモリを検索)
  2. LLM 呼び出し後 — 学習(新しい事実を抽出して保存)
loop {
    user_message = receive()

    // 1. 想起 — LLM を呼び出す前に
    memories = rmem.search(user_id, user_message, limit=10)
    context = format_as_context(memories)

    // 2. メモリコンテキスト付きで LLM を呼び出す
    response = llm.chat(system_prompt + context + user_message)

    // 3. 学習 — 応答後に
    rmem.add(user_id, user_message)

    send(response)
}

メモリコンテキストの形式

search() の結果を LLM が理解できるコンテキストにフォーマットします:

[Memory]
このユーザーについての既知の事実:
- ユーザーの名前は Alice
- ユーザーはダークモードを好む
- ユーザーは Rust プロジェクトに取り組んでいる

これを system prompt 内またはユーザーメッセージの前に配置して、LLM が参照できるようにします。

マルチスコープパターン

アプリが複数のチャネル(例:Telegram + Discord)にサービスを提供する場合、3 つのスコープレイヤーを使用します:

スコープ用途ID の例
local単一の会話 / グループtelegram:group_123
userチャネル横断の個人メモリuser:456
global全ユーザー共有global:system

想起時に結果をマージします:

local_results  = search("telegram:group_123", query)
user_results   = search("user:456", query)
global_results = search("global:system", query)
all = deduplicate(local + user + global)

よくある間違い

  • ❌ MemoryManager を初期化するがループで search() / add() を呼ばない
  • ❌ 学習のみで想起しない(メモリは保存されるが取得されない)
  • ❌ 想起のみで学習しない(古いメモリを読むが新しいものを学習しない)
  • ❌ LLM 呼び出し前に add() を実行する(現在のメッセージが既知の事実として扱われる)

📖 使い方

CLI

# メモリを追加
rustmem add -u alice "My name is Alice and I work at Google. I love sushi."

# セマンティック検索
rustmem search -u alice "What does Alice eat?"

# ユーザーの全メモリを一覧
rustmem list -u alice

# グラフ関係を表示
rustmem graph -u alice

# REST API サーバーを起動
rustmem server

REST API

rustmem server で起動後:

# ➕ メモリを追加
curl -X POST http://localhost:8019/memories/add \
  -H 'Content-Type: application/json' \
  -d '{"user_id": "alice", "text": "I moved to Tokyo last month"}'

# 🔍 検索
curl -X POST http://localhost:8019/memories/search \
  -H 'Content-Type: application/json' \
  -d '{"user_id": "alice", "query": "where does she live", "limit": 5}'

# 📋 全件取得
curl http://localhost:8019/memories?user_id=alice

# 🏷️ カテゴリでフィルタ(preference, personal, plan, professional, health, misc)
curl http://localhost:8019/memories?user_id=alice&category=preference

# 🗑️ 削除
curl -X DELETE http://localhost:8019/memories/{id}

# 📜 履歴
curl http://localhost:8019/memories/{id}/history

# 🗄️ アーカイブされたメモリを表示
curl http://localhost:8019/archive?user_id=alice

# 🕸️ グラフ関係を表示
curl http://localhost:8019/graph?user_id=alice

AI Agent へのドロップイン

# mem0(以前)
from mem0 import Memory
m = Memory()
m.add("Alice loves sushi", user_id="alice")

# R-Mem(以後 — HTTP に切り替えるだけ)
import httpx
httpx.post("http://localhost:8019/memories/add",
    json={"user_id": "alice", "text": "Alice loves sushi"})

🔌 MCP Server

R-Mem は MCP server として動作します — 1 コマンドで Claude Code や Cursor に長期メモリを付与:

# Claude Code
claude mcp add rustmem -- /path/to/rustmem mcp

# Cursor (.cursor/mcp.json)
{
  "mcpServers": {
    "rustmem": {
      "command": "/path/to/rustmem",
      "args": ["mcp"]
    }
  }
}

7 つの tools: add_memorysearch_memorylist_memoriesget_memorydelete_memoryget_graphreset_memories


🏗️ アーキテクチャ

src/
├── main.rs          CLI エントリポイント(clap)
├── config.rs        TOML + 環境変数設定
├── server.rs        REST API(axum)
├── mcp.rs           MCP server(rmcp)— stdio 経由の 7 tools
├── memory.rs        コアオーケストレータ — 階層メモリパイプライン
├── extract.rs       LLM 呼び出し:OpenAI + Anthropic native
├── embedding.rs     OpenAI 互換 embedding クライアント
├── store.rs         SQLite vector store(WAL + FTS5 + archive)
└── graph.rs         SQLite graph store(soft-delete、多値関係)

9 ファイル。2,826 行。3.6 MB バイナリ。外部サービスゼロ。


🗺️ ロードマップ

ステータス機能説明
crates.io に公開cargo install rustmem — ワンライナーインストール
MCP Serverrustmem mcp — stdio 経由の 7 tools、Claude Code / Cursor 対応
階層アーカイブ削除/更新されたメモリを保存 + fallback 検索
FTS5 2 段階検索キーワードプリフィルタ + vector 再ランキング — 19 倍高速
メモリカテゴリ自動分類:preference, personal, plan, professional, health
Anthropic NativeClaude API の直接サポート(プロキシ不要)
Agent SDK(lib crate)Rust コードから rustmem::{memory, store, graph} を直接使用
LongMemEval Benchmarkgpt-4o-mini で 48.2%、mem0(約 49%)にほぼ匹敵
Production Audit11 項目のセキュリティ/安定性修正、25 個のユニットテスト、cargo bench
🔲Episodic Memoryタスク実行履歴(tool 呼び出し、パラメータ、結果)
🔲User Preference Modelセッション横断のユーザースタイルと行動モデリング
🔲Skill Abstraction繰り返される成功パターンを skill として自動抽出
🔲バッチインポート既存の mem0 エクスポートデータを読み込み
🔲マルチモーダル画像/音声メモリサポート
🔲Dashboardメモリ検査用の軽量 web UI

R-Mem v0.3.0 は学習プロジェクトとして機能完備です。コアアーキテクチャは安定しており、本番レベルの堅牢化済みです。コミュニティからの貢献、fork、探索を歓迎します — issue または PR をお気軽にどうぞ。


MIT License · v0.3.0

Ad HuangClaude Code で構築