🧠 SoulMemory
A memory system for AI companions that mimics human memory: remembers, recalls, forgets, consolidates, feels, and connects.
🎯 Why SoulMemory?
Most AI chatbots have no memory. Every conversation starts from zero. SoulMemory gives your AI a persistent, human-like memory that:
- ✅ Remembers important events (and auto-detects what's important)
- 🔍 Recalls relevant memories using semantic search
- ⏳ Forgets trivial things naturally over time
- 🗜️ Consolidates old memories to save space
- 🔗 Links related memories automatically
- 😊 Feels emotions (auto-detected, in English and Spanish)
- 👥 Isolates memories per user (multi-user ready)
- 🛡️ Protects critical memories from ever being forgotten
✨ Features
| Feature | Description |
|---|---|
remember() |
Store memories with auto importance, emotion & associations |
recall() |
Semantic search (understands meaning, not just keywords) |
recall_by_emotion() |
Retrieve memories tagged with a specific emotion |
recall_by_tag() |
Retrieve memories with a custom tag |
about() |
Retrieve all memories mentioning a person or thing |
recall_between() |
Retrieve memories within a date range |
timeline() |
Chronological view of memories |
get_associated() |
Retrieve memories linked to a given memory |
associate() |
Manually link two memories together |
dream() |
Nightly maintenance: forget + consolidate |
emotional_timeline() |
Dominant emotion per week |
user() |
Isolated memory space per user |
decay() |
Natural forgetting based on time and usage |
consolidate() |
Compress similar old memories into summaries |
stats() |
Memory statistics and insights |
📦 Installation
pip install soulmemory
Or install from source:
git clone https://github.com/Romazea/soulmemory.git
cd soulmemory
pip install -e .
🚀 Quick Start
from soulmemory import SoulMemory
# Initialize
mem = SoulMemory("my_memory.db")
# Store memories (importance, emotion & associations auto-detected)
mem.remember("My girlfriend proposed to me today!")
mem.remember("Had a sandwich for lunch")
mem.remember("¡Estoy muy feliz y emocionado!") # Spanish works too!
# Search semantically
results = mem.recall("romantic news")
for r in results:
print(r['content']) # → "My girlfriend proposed to me today!"
# Clean up
mem.close()
🧩 Core Concepts
Memory Levels
| Level | Behavior | Example |
|---|---|---|
critical |
Never forgotten | "My mother passed away" |
important |
Fades slowly | "Got a promotion at work" |
normal |
Standard decay | "Meeting with the team" |
trivial |
Fades quickly | "It's cloudy today" |
Auto Importance Detection
SoulMemory automatically detects how important a memory is:
mem.remember("My girlfriend proposed to me!")
# → importance: 0.95, level: critical
mem.remember("It's raining outside")
# → importance: 0.35, level: trivial
Emotional Tagging (English + Spanish)
SoulMemory detects the emotion of each memory (six basic emotions + neutral):
mem.remember("We won the championship!")
# → emotion: "joy"
mem.remember("Mi perro murió ayer, estoy triste")
# → emotion: "sadness"
happy_memories = mem.recall_by_emotion("joy")
Memory Associations
Like the human brain, SoulMemory automatically links related memories:
mem.remember("Went to the gym in the morning")
mem.remember("Worked out at the gym today")
# → automatically linked (similar meaning)
results = mem.recall("gym")
linked = mem.get_associated(results[0]["id"])
# Or link memories manually
mem.associate(id_a, id_b)
Custom Tags
mem.remember("Luna is sick", tags=["mascotas", "ana"])
mem.recall_by_tag("mascotas")
mem.get_tags(memory_id) # → ["mascotas", "ana"]
People & Time
mem.about("Ana") # everything about Ana
mem.recall_between("2026-08-01", "2026-08-10") # date range (inclusive)
mem.timeline(limit=10) # most recent first
Multi-User Support
Each user gets a fully isolated memory space:
roman = mem.user("roman")
ana = mem.user("ana")
roman.remember("My girlfriend proposed to me!")
ana.recall("romantic news") # → only Ana's memories (no leaks)
mem.list_users() # → ['ana', 'roman']
mem.delete_user("ana") # GDPR-style full deletion
The Forgetting Curve
Memories fade over time, just like human memory:
forgotten = mem.decay(decay_rate=0.85, threshold=0.2)
print(f"Forgot {forgotten} memories")
The formula:
score = importance × (decay_rate ^ days_since_access) + (access_count × 0.05)
- More days without access → lower score
- More times accessed → stays "alive"
- Score below threshold → memory is forgotten
criticalmemories → never decay
Dreaming 😴
Run the nightly maintenance of the brain in one call:
result = mem.dream()
# → {'forgotten': 2, 'consolidated': 3}
Emotional Timeline
See the dominant emotion per week:
mem.emotional_timeline(weeks=4)
# → [{'week': 0, 'label': 'this week', 'dominant_emotion': 'joy', ...}]
📚 API Reference
remember(content, importance=None, level=None, emotion=None, tags=None, auto_detect=True, auto_associate=True, user_id="default")
Store a new memory.
mem.remember("First date with Ana at the coffee shop", tags=["ana"])
recall(query, limit=5, user_id="default")
Search for relevant memories.
results = mem.recall("what do I know about Ana?")
recall_by_emotion(emotion, limit=10, user_id="default")
Retrieve memories tagged with a specific emotion ('joy', 'sadness', 'anger', 'fear', 'surprise', 'disgust', 'neutral').
joy_memories = mem.recall_by_emotion("joy")
recall_by_tag(tag, limit=10, user_id="default")
Retrieve memories with a specific custom tag.
pet_memories = mem.recall_by_tag("mascotas")
about(name, limit=10, user_id="default")
Retrieve all memories that mention a person or thing.
ana_memories = mem.about("Ana")
recall_between(start, end, limit=50, user_id="default")
Retrieve memories created between two dates ('YYYY-MM-DD' or timestamps, inclusive).
week = mem.recall_between("2026-08-01", "2026-08-10")
timeline(limit=20, user_id="default")
Retrieve memories in chronological order (most recent first).
recent = mem.timeline(limit=10)
get_tags(memory_id)
Get the custom tags attached to a memory.
associate(memory_id_a, memory_id_b, strength=1.0)
Manually link two memories together.
get_associated(memory_id, limit=5)
Retrieve memories associated with a given memory.
linked = mem.get_associated(memory_id)
decay(decay_rate=0.85, threshold=0.2, user_id=None)
Run the forgetting process (all users by default).
consolidate(min_age_days=7, similarity_threshold=0.75, user_id=None)
Compress old, similar memories (all users by default).
dream(user_id=None)
Run decay + consolidation together (the brain's nightly maintenance).
forget(memory_id)
Delete a specific memory by ID.
stats(user_id=None)
Get memory statistics.
print(mem.stats())
# → {'total_memories': 42, 'by_level': {...}, 'by_emotion': {...}}
emotional_timeline(weeks=4, user_id=None)
Dominant emotion per week (week 0 = current week).
user(user_id)
Get an isolated memory space for a specific user. Returns a UserMemory with the same API.
list_users()
List all user IDs that have memories.
delete_user(user_id)
Delete a user and ALL their memories, links and tags.
🎬 Examples
The examples/ folder contains runnable demos:
python examples/quickstart.py # Basic usage (Spanish)
python examples/test_decay.py # The forgetting system
python examples/test_full.py # Full feature test
python examples/demo_emotions.py # Emotional tagging (EN + ES)
python examples/demo_associations.py # Memory associations
python examples/demo_multiuser.py # Multi-user isolation
python examples/demo_companion.py # Full AI companion simulation
🛠️ Use Cases
- 🤖 AI Companions that remember your life
- 💬 Chatbots with long-term memory
- Game NPCs that remember player interactions
- 📔 Personal AI journals that evolve over time
- 🏢 Multi-tenant services with isolated memory per user
🗺️ Roadmap
- Core memory storage
- Semantic search
- Importance auto-detection
- Decay (forgetting)
- Consolidation
- Emotional tagging (English + Spanish)
- Memory associations
- Multi-user support
- Custom tags
- Temporal recall & timelines
- Memory graph visualization
- Async API
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- sentence-transformers for embeddings
- sqlite-vec for vector search
Made with ❤️ for the AI community
If you find this useful, please ⭐ star the repository!
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file soulmemory-0.4.0.tar.gz.
File metadata
- Download URL: soulmemory-0.4.0.tar.gz
- Upload date:
- Size: 27.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62a0b68879301820a625610dcb37d0bc1691c188fc217ab9a15efa734be5c813
|
|
| MD5 |
c53af8bae795786221a2f1db876f020e
|
|
| BLAKE2b-256 |
a88e9ab1d5432b39e1bfccf5d17d9b441b1e93ced0db10818f03de29f481be77
|
File details
Details for the file soulmemory-0.4.0-py3-none-any.whl.
File metadata
- Download URL: soulmemory-0.4.0-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
416271ed58aa71eb13f29696e59e9c30359ff53ac2468c5167864dfac7743842
|
|
| MD5 |
89943606f6d4980b5765081d9dc5c341
|
|
| BLAKE2b-256 |
a7d9d44d1e66429b8d9baf29cc879b100084216c723ba74daa06ed2ef7f92bc0
|