Metadata-Version: 2.4
Name: soulmemory
Version: 0.5.1
Summary: A memory system for AI companions that mimics human memory
License: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: sentence-transformers
Requires-Dist: sqlite-vec
Requires-Dist: numpy
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Dynamic: license-file

# 🧠 SoulMemory

<div align="center">

**A memory system for AI companions that mimics human memory: remembers, recalls, forgets, consolidates, feels, connects, and reflects.**

</div>

<div align="center">

[![PyPI version](https://img.shields.io/pypi/v/soulmemory.svg)](https://pypi.org/project/soulmemory/)
[![Python](https://img.shields.io/badge/Python-3.9%2B-blue.svg)](https://www.python.org/)
[![License](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

</div>

---

## 🎯 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)
- 🪞 **Reflects** the user's personality (key people, topics, mood)
- 💾 **Backs up** everything to JSON
- 🛡️ **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                         |
| `reflect()`           | Personality summary: dominant emotion, key people, topics   |
| `export_json()`       | Backup all memories, tags and links to JSON                 |
| `import_json()`       | Restore a JSON backup                                       |
| `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

```bash
pip install soulmemory
```

Or install from source:

```bash
git clone https://github.com/Romazea/soulmemory.git
cd soulmemory
pip install -e .
```

## 🚀 Quick Start

```python
from soulmemory import SoulMemory

# Initialize (multilingual=True for true Spanish understanding)
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:

```python
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):

```python
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:

```python
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

```python
mem.remember("Luna is sick", tags=["mascotas", "ana"])

mem.recall_by_tag("mascotas")
mem.get_tags(memory_id)  # → ["mascotas", "ana"]
```

### People & Time

```python
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:

```python
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
```

### Personality Reflection 🪞

A human-readable summary of who the user is:

```python
mem.reflect()
# → {'memory_count': 42, 'dominant_emotion': 'joy',
#    'key_people': ['Ana'], 'top_tags': ['mascotas'],
#    'critical_memories': 3, 'summary': 'A life in ...'}
```

### JSON Backups 💾

Your memories, safe forever:

```python
mem.export_json("backup.json")  # memories + tags + links
mem.import_json("backup.json")  # restores everything
```

### Multilingual Semantic Search 🌍

The default model (`all-MiniLM-L6-v2`) is English-optimized. For true Spanish understanding:

```python
mem = SoulMemory("my.db", multilingual=True)
# → uses paraphrase-multilingual-MiniLM-L12-v2

mem.recall("la chica del café")  # understands Spanish for real
```

*Warning: don't mix different embedding models in the same database.*

### The Forgetting Curve

Memories fade over time, just like human memory:

```python
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
- `critical` memories → never decay

### Dreaming 😴

Run the nightly maintenance of the brain in one call:

```python
result = mem.dream()
# → {'forgotten': 2, 'consolidated': 3}
```

### Emotional Timeline

See the dominant emotion per week:

```python
mem.emotional_timeline(weeks=4)
# → [{'week': 0, 'label': 'this week', 'dominant_emotion': 'joy', ...}]
```

## 📚 API Reference

### `SoulMemory(db_path="soulmemory.db", embedding_model=None, multilingual=False)`

Create a memory instance. `multilingual=True` switches to a multilingual embedding model.

### `remember(content, importance=None, level=None, emotion=None, tags=None, auto_detect=True, auto_associate=True, user_id="default")`

Store a new memory.

### `recall(query, limit=5, user_id="default")`

Search for relevant memories.

### `recall_by_emotion(emotion, limit=10, user_id="default")`

Retrieve memories tagged with a specific emotion.

### `recall_by_tag(tag, limit=10, user_id="default")`

Retrieve memories with a specific custom tag.

### `about(name, limit=10, user_id="default")`

Retrieve all memories that mention a person or thing.

### `recall_between(start, end, limit=50, user_id="default")`

Retrieve memories created between two dates (inclusive).

### `timeline(limit=20, user_id="default")`

Retrieve memories in chronological order (most recent first).

### `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.

### `reflect(user_id=None)`

Generate a personality summary of the user.

### `export_json(path="soulmemory_backup.json", user_id=None)`

Export all memories (with tags and links) to a JSON backup.

### `import_json(path)`

Restore memories from a JSON backup.

### `decay(decay_rate=0.85, threshold=0.2, user_id=None)`

Run the forgetting process.

### `consolidate(min_age_days=7, similarity_threshold=0.75, user_id=None)`

Compress old, similar memories.

### `dream(user_id=None)`

Run decay + consolidation together.

### `forget(memory_id)`

Delete a specific memory by ID.

### `stats(user_id=None)`

Get memory statistics.

### `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.

### `list_users()` / `delete_user(user_id)`

Manage users and GDPR-style deletion.

## 🎬 Examples

The `examples/` folder contains runnable demos:

```bash
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_multilingual.py  # Multilingual semantic search (ES)
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

- [x] Core memory storage
- [x] Semantic search
- [x] Importance auto-detection
- [x] Decay (forgetting)
- [x] Consolidation
- [x] Emotional tagging (English + Spanish)
- [x] Memory associations
- [x] Multi-user support
- [x] Custom tags
- [x] Temporal recall & timelines
- [x] Personality reflection (`reflect()`)
- [x] JSON backups
- [x] Multilingual embeddings
- [ ] v1.0.0 stability hardening

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgments

- [sentence-transformers](https://github.com/UKPLab/sentence-transformers) for embeddings
- [sqlite-vec](https://github.com/asg017/sqlite-vec) for vector search

---

<div align="center">

**Made with ❤️ for the AI community**

If you find this useful, please ⭐ star the repository!

</div>
