Skip to content

Joshua9689/mnemosyne

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 Mnemosyne β€” Scientific Memory System for AI Agents

Named after the Greek goddess of memory, Mnemosyne gives your AI agents a real brain β€” not just a notepad.

Any Python project. Any AI agent framework. Zero external services.

✨ Features

  • πŸ—„οΈ Dual-Engine Storage β€” SQLite (structured) + Chroma (vector), no Redis/PostgreSQL needed
  • πŸ” Hybrid Retrieval β€” Semantic search + keyword matching, fused with Reciprocal Rank Fusion (RRF)
  • 🧬 Agent Isolation β€” Each agent gets independent DB + vector collection, memories never leak
  • ⏳ Ebbinghaus Forgetting β€” Scientifically decay stale memories, auto-cleanup
  • πŸ”— Relation Graph β€” Semantic, temporal, and entity-based links between memories
  • πŸ“ LLM Compression β€” Intelligent summarization (GLM-4-Flash / GPT-4o-mini / any OpenAI-compatible LLM)
  • 🧠 Self-Evolution β€” Learn from experience: auto-generate behavioral rules from memory patterns (v0.2.0)
  • 🈢 Chinese Optimized β€” jieba segmentation for FTS5, Zhipu embedding-3 support
  • πŸ”Œ Framework Adapters β€” Drop-in for Hermes, LangChain, AutoGen, or any custom agent

πŸš€ Quick Start

Install

# Basic (SQLite + FTS5 only, no vector search)
pip install mnemosyne-memory

# With vector search (recommended)
pip install mnemosyne-memory[chroma]

# With everything (chroma + jieba + LLM compression + evolution)
pip install mnemosyne-memory[all]

5-Minute Demo

from mnemosyne import Mnemosyne

# 1️⃣ Initialize β€” works with any Python project
memo = Mnemosyne(
    agent_id="my-agent",
    embedding_provider="zhipu",     # or "openai" / "local"
    zhipu_api_key="your-key",       # or set ZHIPU_API_KEY env var
)

# 2️⃣ Store a memory
memo.add("User prefers dark mode for all applications", importance=0.8)

# 3️⃣ Search memories
results = memo.search("user interface preferences")
print(results[0]["content"])
# β†’ "User prefers dark mode for all applications"

# 4️⃣ Auto-extract from conversation
memo.sync_turn(
    "Let's use PostgreSQL for the database",
    "Good choice, PostgreSQL is reliable for production",
)
# β†’ Automatically stores: "Let's use PostgreSQL for the database"

# 5️⃣ Check what the agent remembers
print(memo.stats())
# β†’ {total_memories: 2, by_type: {semantic: 2}, ...}

That's it. No external database server, no Redis, no Docker. Just Python.

πŸ—οΈ Architecture

User Query: "user preferences"
        β”‚
        β”œβ”€β”€β†’ SQLite FTS5 ──→ Keyword matches
        β”‚
        β”œβ”€β”€β†’ Chroma ANN ───→ Semantic matches
        β”‚
        └──→ RRF Fusion ───→ Merged & ranked results
                β”‚
                β”œβ”€β”€β†’ Relation Expansion (semantic/temporal/entity links)
                β”‚
                └──→ Final Scoring (importance Γ— confidence Γ— recency)

v0.2.0 Architecture β€” Self-Evolution Layer

Memories (SQLite + Chroma)
        β”‚
        β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚           EvolutionEngine                    β”‚
  β”‚                                              β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
  β”‚  β”‚ Error Pattern β”‚  β”‚ Success Pattern      β”‚ β”‚
  β”‚  β”‚ Analyzer      β”‚  β”‚ Analyzer             β”‚ β”‚
  β”‚  β”‚               β”‚  β”‚                      β”‚ β”‚
  β”‚  β”‚ confidence<0.6β”‚  β”‚ importanceβ‰₯0.7 &&    β”‚ β”‚
  β”‚  β”‚ + error words β”‚  β”‚ access_countβ‰₯2       β”‚ β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
  β”‚         β”‚                     β”‚              β”‚
  β”‚         β–Ό                     β–Ό              β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
  β”‚  β”‚     LLM Rule Generator               β”‚   β”‚
  β”‚  β”‚     (GLM-4-Flash / GPT-4o-mini)      β”‚   β”‚
  β”‚  β”‚                                      β”‚   β”‚
  β”‚  β”‚  Memories β†’ JSON Rule                β”‚   β”‚
  β”‚  β”‚  {rule_type, trigger_cond,           β”‚   β”‚
  β”‚  β”‚   action_guide}                      β”‚   β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
  β”‚                 β”‚                            β”‚
  β”‚                 β–Ό                            β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
  β”‚  β”‚  evolution_rules (SQLite)            β”‚   β”‚
  β”‚  β”‚                                      β”‚   β”‚
  β”‚  β”‚  Status: pending β†’ active/rejected   β”‚   β”‚
  β”‚  β”‚  Types:  avoid / prefer / pattern /  β”‚   β”‚
  β”‚  β”‚          workflow                    β”‚   β”‚
  β”‚  β”‚  Decay:  180d half-life, auto-expire β”‚   β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
  β”‚                 β”‚                            β”‚
  β”‚                 β–Ό                            β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
  β”‚  β”‚  Context Injection                   β”‚   β”‚
  β”‚  β”‚                                      β”‚   β”‚
  β”‚  β”‚  prefetch() β†’ match active rules     β”‚   β”‚
  β”‚  β”‚  β†’ inject into system_prompt         β”‚   β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🧠 Self-Evolution (v0.2.0)

The evolution layer enables agents to learn from their own experience β€” automatically generating behavioral rules from memory patterns, then injecting those rules into future conversations.

How It Works

  1. Pattern Detection β€” Scans memories for error patterns (low confidence, failure keywords) and success patterns (high importance, frequent access)
  2. LLM Rule Generation β€” Uses a lightweight LLM (GLM-4-Flash) to distill memories into concise behavioral rules
  3. Human-in-the-Loop β€” New rules start as pending and require human verification before becoming active
  4. Context Injection β€” Active rules are semantically matched to the current conversation and injected into the system prompt
  5. Natural Decay β€” Rules that aren't useful gradually expire (180-day half-life, auto-expire if hit_count < 3)

Rule Types

Type Description Example
avoid Pitfall avoidance "When QQ Bot Secret expires, check config consistency first"
prefer Preference adoption "When user asks for coding, prefer Kimi CLI with --quiet"
pattern Standard pattern "When handling government docs, use gov-doc template then validate"
workflow Multi-step workflow "For deployment: test β†’ backup β†’ deploy β†’ verify β†’ monitor"

Rule Lifecycle

                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚ pending β”‚ ← New rules (auto-generated or manual)
                 β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
                      β”‚ verify
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
              β–Ό               β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  active  β”‚   β”‚ rejected β”‚
        β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚
             β”‚ 180 days, hit_count < 3
             β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ expired  β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Usage

from mnemosyne import Mnemosyne

memo = Mnemosyne(
    agent_id="my-agent",
    embedding_provider="zhipu",
    zhipu_api_key="your-key",
)

# --- Manual Rule Creation ---

# Create a rule (status=pending by default)
rule_id = memo.evolve_add_rule(
    rule_type="avoid",
    trigger_cond="When handling API credentials that may expire",
    action_guide="Always check credential validity first before attempting operations",
)
print(f"Created rule: {rule_id}")

# Verify (accept or reject) a pending rule
memo.evolve_verify_rule(rule_id, accept=True)  # Now active

# --- Auto-Analysis ---

# Analyze memories and auto-generate rules
new_rules = memo.evolve_analyze()
for rule in new_rules:
    print(f"[{rule['rule_type']}] {rule['trigger_cond']} β†’ {rule['action_guide']}")

# --- Rule Management ---

# List rules
pending = memo.evolve_list_rules(status="pending")
active = memo.evolve_list_rules(status="active")

# Get evolution statistics
stats = memo.stats()
print(stats["evolution"])
# β†’ {"total_rules": 5, "by_status": {"active": 3, "pending": 2}, ...}

# --- Context Injection (automatic) ---

# prefetch() now automatically matches and injects active rules
context = memo.prefetch("My API key expired again")
# β†’ Includes relevant active rules like: "Always check credential validity first"

Safety Design

  • Human verification required β€” Rules default to pending; must be explicitly verified to become active
  • Active rule cap β€” Maximum 20 active rules injected at once (configurable via MAX_ACTIVE_RULES)
  • Low-cost LLM β€” Rule generation uses GLM-4-Flash (~Β₯0.001/analysis), not your main model
  • Natural decay β€” Inactive rules expire automatically, preventing stale rules from accumulating

πŸ“– Usage Guide

Embedding Providers

Provider Model Dimensions Requires
zhipu embedding-3 2048 ZHIPU_API_KEY
openai text-embedding-3-small 1536 OPENAI_API_KEY
local BAAI/bge-small-zh-v1.5 512 sentence-transformers
# Zhipu (Z.AI) β€” best for Chinese + cost-effective
memo = Mnemosyne(embedding_provider="zhipu", zhipu_api_key="your-key")

# OpenAI β€” best for English
memo = Mnemosyne(embedding_provider="openai", openai_api_key="your-key")

# Local β€” no API key needed, runs offline
memo = Mnemosyne(embedding_provider="local")

Multi-Agent Isolation

# Agent A β€” isolated memory
agent_a = Mnemosyne(agent_id="alice", db_dir="/data/agents/alice")

# Agent B β€” completely separate
agent_b = Mnemosyne(agent_id="bob", db_dir="/data/agents/bob")

# Alice's memories are invisible to Bob
agent_a.add("Secret project details", importance=0.9)
agent_b.search("secret project")  # β†’ [] empty

Ebbinghaus Forgetting

memo = Mnemosyne(
    agent_id="my-agent",
    decay_half_life=90,     # Memories halve in importance every 90 days
    decay_threshold=0.1,    # Below 0.1 β†’ auto-deleted
)

# Manual cleanup
deleted = memo.decay_cleanup()
print(f"Cleaned up {deleted} stale memories")

Memory Types

Type Description Example
episodic Specific events "Deployed v2.1 on May 15"
semantic General facts "User prefers dark mode"
procedural How-to knowledge "Always use GLM-5.1 for Chinese tasks"

Integration with Any Agent Framework

Mnemosyne is a plain Python library β€” use it with any agent framework:

# Works with any framework β€” just call the API
from mnemosyne import Mnemosyne

memo = Mnemosyne(agent_id="my-agent", embedding_provider="zhipu", zhipu_api_key="key")

# In your agent's message handler:
def on_user_message(user_msg, assistant_reply):
    # Auto-extract facts from conversation
    memo.sync_turn(user_msg, assistant_reply)

def before_response(user_msg):
    # Inject relevant memories + evolution rules into context
    context = memo.prefetch(user_msg)
    return context  # Add to your system prompt

def on_session_end():
    # Auto-analyze and generate evolution rules
    memo.evolve_analyze()

πŸ”Œ Framework Adapters

OpenClaw

Mnemosyne is a Python library, while OpenClaw is Node.js β€” so it can't be used as a direct plugin. However, there are two ways to leverage Mnemosyne with OpenClaw:

Option A: HTTP Service (recommended)

Wrap Mnemosyne as a lightweight REST API, and call it from OpenClaw skills via HTTP:

# server.py β€” run as a sidecar service
from mnemosyne import Mnemosyne
from flask import Flask, request, jsonify

app = Flask(__name__)
memo = Mnemosyne(agent_id="openclaw-agent", embedding_provider="zhipu", zhipu_api_key="key")

@app.route("/memory/add", methods=["POST"])
def add():
    memo.add(request.json["content"], importance=request.json.get("importance", 0.5))
    return jsonify({"status": "ok"})

@app.route("/memory/search", methods=["POST"])
def search():
    results = memo.search(request.json["query"], limit=request.json.get("limit", 5))
    return jsonify(results)

@app.route("/memory/evolve", methods=["POST"])
def evolve():
    rules = memo.evolve_analyze()
    return jsonify({"rules_generated": len(rules)})

app.run(port=8900)

Option B: Shared Database β€” Read the SQLite DB directly from Node.js using better-sqlite3. No Python runtime needed at search time, but you lose vector search (FTS5 only).

πŸ’‘ A native TypeScript port is on the roadmap. If you're interested, open an issue or contribute!

Hermes Agent

Drop-in MemoryProvider plugin for Hermes:

# config.yaml
memory:
  provider: mnemosyne

plugins:
  mnemosyne:
    embedding_provider: zhipu
    zhipu_api_key: ${ZHIPU_API_KEY}
    decay_half_life: 90
    decay_threshold: 0.1
pip install mnemosyne-memory[hermes]
# Place in: plugins/memory/mnemosyne/
# Restart Hermes β€” done!

The Hermes adapter registers 4 tools:

  • mnemosyne_search β€” Search/probe/related queries
  • mnemosyne_manage β€” Add/update/remove/merge/forget/list/stats
  • mnemosyne_feedback β€” Rate memories (helpful/unhelpful/outdated)
  • mnemosyne_evolve β€” Self-improvement: generate/analyze/verify/list/stats

LangChain

from mnemosyne import Mnemosyne
from langchain.memory import ConversationBufferMemory

memo = Mnemosyne(agent_id="langchain-agent", embedding_provider="openai", openai_api_key="key")

# Use as external long-term memory alongside LangChain's short-term memory
class MnemosyneLongTermMemory:
    def save(self, text: str):
        memo.add(text, importance=0.6)
    
    def recall(self, query: str) -> str:
        results = memo.search(query, limit=5)
        return "\n".join(r["content"] for r in results)
    
    def evolve(self):
        """Auto-generate experience rules."""
        return memo.evolve_analyze()

Custom Agent

from mnemosyne import Mnemosyne

class MyAgent:
    def __init__(self):
        self.memory = Mnemosyne(agent_id="custom-agent", embedding_provider="zhipu", zhipu_api_key="key")
    
    def chat(self, user_input: str) -> str:
        # 1. Recall relevant memories + evolution rules
        context = self.memory.prefetch(user_input)
        
        # 2. Generate response with memory context
        response = self.llm.generate(system=context, user=user_input)
        
        # 3. Store new facts
        self.memory.sync_turn(user_input, response)
        
        return response
    
    def end_session(self):
        # Auto-analyze and generate evolution rules
        self.memory.evolve_analyze()

πŸ“Š Performance

Tested on a 4-core / 8GB server with 100 memories:

Operation Latency
Write (SQLite + Chroma) ~900ms*
Search (hybrid) ~300ms
FTS5-only search ~5ms
Decay cleanup ~50ms
Evolution analysis ~2-3s**

*Write latency dominated by embedding API call (~600ms). Local embedding is faster. **Evolution analysis latency dominated by LLM API call.

πŸ› οΈ Requirements

  • Python 3.10+
  • SQLite (bundled with Python, zero setup)
  • Optional: chromadb (vector search), jieba (Chinese), openai (LLM compression + evolution)

Works on Linux, macOS, and Windows. No Docker, no Redis, no PostgreSQL.

πŸ“‹ Changelog

v0.2.0 (2026-05-16) β€” Self-Evolution

  • 🧠 EvolutionEngine β€” Auto-generate behavioral rules from memory patterns
  • πŸ“‹ Rule Types β€” avoid / prefer / pattern / workflow
  • βœ… Human-in-the-Loop β€” Rules require verification (pending β†’ active)
  • πŸ”„ Natural Decay β€” 180-day half-life, auto-expire inactive rules
  • πŸ’‰ Context Injection β€” Active rules auto-injected via prefetch()
  • πŸ”§ Hermes Tool β€” New mnemosyne_evolve tool with generate/analyze/verify/list/stats

v0.1.0 (2026-05-15) β€” Initial Release

  • πŸ—„οΈ Dual-engine storage (SQLite + Chroma)
  • πŸ” Hybrid retrieval (semantic + keyword, RRF fusion)
  • 🧬 Agent isolation
  • ⏳ Ebbinghaus forgetting
  • πŸ”— Relation graph
  • πŸ“ LLM compression
  • 🈢 Chinese optimization (jieba FTS5)
  • πŸ”Œ Framework adapters (Hermes, LangChain, OpenClaw)

🀝 Contributing

Contributions welcome! Areas of interest:

  • More embedding providers (Cohere, Voyage, etc.)
  • More framework adapters (CrewAI, AutoGen, Semantic Kernel)
  • Evolution dashboard / visualization
  • Memory export/import (JSONL, Markdown)
  • Web dashboard for memory + rules inspection
  • Benchmark suite
  • Multi-agent evolution (shared rule pools)

πŸ“„ License

MIT License β€” use freely, attribution appreciated.


If Mnemosyne helps your project, consider giving it a ⭐ on GitHub!

About

🧠 Scientific Memory System for AI Agents β€” SQLite + Chroma dual-engine, semantic retrieval, Ebbinghaus forgetting

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages