Metadata-Version: 2.4
Name: fennec_memory
Version: 0.1.0
Summary: Production-grade memory, intelligent caching, and persistence layer for LLM and RAG applications.
Author-email: Yousef Khalil <yousefkhalil435@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Fennec Community
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://fennec-community.vercel.app/
Keywords: llm,rag,memory,cache,semantic-cache,conversation-memory,long-term-memory,persistence,ai-memory,vector-cache
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.0
Requires-Dist: numpy>=1.24
Provides-Extra: redis
Requires-Dist: redis>=4.0; extra == "redis"
Provides-Extra: sqlite
Provides-Extra: faiss
Requires-Dist: faiss-cpu>=1.7; extra == "faiss"
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == "openai"
Provides-Extra: huggingface
Requires-Dist: sentence-transformers>=2.2; extra == "huggingface"
Requires-Dist: torch>=2.0; extra == "huggingface"
Provides-Extra: ollama
Requires-Dist: ollama>=0.1; extra == "ollama"
Provides-Extra: crypto
Requires-Dist: cryptography>=41.0; extra == "crypto"
Provides-Extra: all
Requires-Dist: redis>=4.0; extra == "all"
Requires-Dist: faiss-cpu>=1.7; extra == "all"
Requires-Dist: openai>=1.0; extra == "all"
Requires-Dist: sentence-transformers>=2.2; extra == "all"
Requires-Dist: torch>=2.0; extra == "all"
Requires-Dist: ollama>=0.1; extra == "all"
Requires-Dist: cryptography>=41.0; extra == "all"
Dynamic: license-file

# fennec-memory

**Production-grade memory, intelligent caching, and persistence for LLM and RAG applications**

`fennec-memory` gives your AI application a complete memory stack — from short-term conversation buffers and semantic long-term memory, to a multi-level intelligent cache with semantic deduplication, to a durable persistence layer with encryption, versioning, and multi-tenant support.

---

## What's Inside

The library is organized into three independent but composable subsystems:

| Subsystem | Module | Purpose |
|---|---|---|
| **Memory** | `fennec_memory.memory` | Conversation and agent memory types |
| **Cache** | `fennec_memory.cache` | Multi-level semantic + key-value cache |
| **Persistence** | `fennec_memory.persistence` | Durable storage with security and versioning |

---

## Installation

```bash
pip install fennec-memory
```

Install optional extras based on your stack:

```bash
pip install fennec-memory[redis]        # Redis storage backend
pip install fennec-memory[faiss]        # FAISS vector index for semantic cache
pip install fennec-memory[openai]       # OpenAI embeddings
pip install fennec-memory[huggingface]  # HuggingFace / sentence-transformers
pip install fennec-memory[ollama]       # Ollama local embeddings
pip install fennec-memory[crypto]       # Encryption for persistence layer
pip install fennec-memory[all]          # Everything
```

---

## Memory System

### Conversation Memory Types

```python
from fennec_memory.memory import (
    ConversationBufferMemory,
    ConversationBufferWindowMemory,
    ConversationSummaryMemory,
    ConversationEntityMemory,
)

# Simple buffer — keeps full history
mem = ConversationBufferMemory()
mem.add("user", "What is RAG?")
mem.add("assistant", "RAG stands for Retrieval-Augmented Generation.")
print(mem.get_history())

# Sliding window — keeps last N turns
window_mem = ConversationBufferWindowMemory(window_size=5)

# Summary memory — compresses old turns into a summary
summary_mem = ConversationSummaryMemory()

# Entity memory — tracks named entities across the conversation
entity_mem = ConversationEntityMemory()
```

### Long-Term Memory

```python
from fennec_memory.memory import LongTermMemory, MemoryConfig

config = MemoryConfig(
    max_long_term=10_000,
    importance_threshold=0.6,
    enable_decay=True,
    decay_rate=0.01,
    enable_persistence=True,
    persistence_path="./memory_store",
)

ltm = LongTermMemory(config=config)
ltm.store("The user prefers concise answers.", importance=0.85)
results = ltm.retrieve("user preferences", top_k=5)
```

### Semantic Memory

```python
from fennec_memory.memory import SemanticMemory

sem = SemanticMemory()
sem.add("Paris is the capital of France.")
sem.add("The Eiffel Tower is in Paris.")

results = sem.search("French landmarks", top_k=3)
for r in results:
    print(r.text, r.score)
```

### Intelligent Memory Manager

```python
from fennec_memory.memory import AIMemoryManager, MemoryConfig

manager = AIMemoryManager(config=MemoryConfig())

# Automatically routes to short-term, working, or long-term
manager.remember("User said they are a software engineer.", importance=0.7)

# Retrieve relevant memories for a query
context = manager.recall("What do I know about this user?", top_k=5)
```

### User Profile Manager

```python
from fennec_memory.memory import UserProfileManager

profiles = UserProfileManager()
profiles.update("user_123", preferences={"language": "Arabic", "tone": "formal"})
profile = profiles.get("user_123")
print(profile.preferences)
```

### Privacy & Security

```python
from fennec_memory.memory import SensitiveDataMasker, MemoryEncryptor, AccessController, Permission

masker = SensitiveDataMasker()
safe_text = masker.mask("My SSN is 123-45-6789")
# "My SSN is ***-**-****"

encryptor = MemoryEncryptor(key="your-secret-key")
encrypted = encryptor.encrypt("sensitive memory content")
decrypted = encryptor.decrypt(encrypted)
```

### RAG Context Builder

```python
from fennec_memory.memory import ContextBuilder, Document

builder = ContextBuilder()
docs = [Document(content="...", metadata={"source": "wiki"})]
context = builder.build(query="What is RAG?", memories=mem.get_history(), documents=docs)
print(context.formatted_prompt)
```

---

## Cache System

### Multi-Level Semantic Cache

```python
from fennec_memory.cache import MultiLevelCache, CacheConfig, StorageBackend

config = CacheConfig(
    storage_backend=StorageBackend.SQLITE,   # or REDIS, MEMORY
    semantic_threshold=0.92,                  # cosine similarity for cache hit
    ttl_seconds=3600,
)

cache = MultiLevelCache(config=config)

# Store a response
cache.set(query="What is the capital of France?", response="Paris.")

# Retrieve — returns on exact or semantic match
result = cache.get("Capital city of France?")
if result:
    print(result.response)   # "Paris."  — semantic hit
    print(result.similarity) # 0.96
```

### Cache Manager with Embeddings

```python
from fennec_memory.cache import CacheManager, CacheConfig
from fennec_memory.cache import OpenAIEmbeddingProvider, EmbeddingConfig

embedder = OpenAIEmbeddingProvider(
    config=EmbeddingConfig(api_key="sk-..."),
)

cache_manager = CacheManager(config=CacheConfig(), embedder=embedder)
```

### Redis Backend

```python
from fennec_memory.cache import CacheConfig, StorageBackend, RedisConfig

config = CacheConfig(
    storage_backend=StorageBackend.REDIS,
    redis=RedisConfig(host="localhost", port=6379, db=0),
)
```

### Multi-Tenant Cache

```python
from fennec_memory.cache import TenantManager, TenantConfig

tenants = TenantManager()
tenants.register("tenant_a", TenantConfig(max_entries=5000, ttl_seconds=1800))
tenants.register("tenant_b", TenantConfig(max_entries=1000, ttl_seconds=600))
```

### Embedding Providers

```python
from fennec_memory.cache import (
    OpenAIEmbeddingProvider,
    HuggingFaceEmbeddingProvider,
    OllamaEmbeddingProvider,
)

# OpenAI
provider = OpenAIEmbeddingProvider(api_key="sk-...")

# HuggingFace (local)
provider = HuggingFaceEmbeddingProvider(model="sentence-transformers/all-MiniLM-L6-v2")

# Ollama (local)
provider = OllamaEmbeddingProvider(model="nomic-embed-text")
```

---

## Persistence System

### Persistence Manager

```python
from fennec_memory.persistence import PersistenceManager, PersistenceManagerConfig, StorageType

config = PersistenceManagerConfig(
    default_storage=StorageType.KEY_VALUE,
    enable_versioning=True,
    enable_encryption=True,
)

pm = PersistenceManager(config=config)

# Store data
await pm.save(key="session:abc123", data={"messages": [...]})

# Retrieve
result = await pm.load(key="session:abc123")
print(result.data)
```

### Storage Backends

```python
from fennec_memory.persistence import KeyValueStorage, VectorStorage, DatabaseStorage, ObjectStorage

# Key-value store
kv = KeyValueStorage()
await kv.set("key", {"value": 42})
data = await kv.get("key")

# Vector store
vs = VectorStorage()
await vs.upsert(id="doc1", vector=[0.1, 0.2, ...], metadata={"source": "wiki"})
results = await vs.search(query_vector=[0.1, 0.2, ...], top_k=5)
```

### Versioning & Snapshots

```python
from fennec_memory.persistence import VersionManager, BackupManager

version_mgr = VersionManager()
version_mgr.save_version(key="config:v1", data={...})
history = version_mgr.get_history("config:v1")

backup_mgr = BackupManager()
snapshot = backup_mgr.create_snapshot("session:abc123")
backup_mgr.restore(snapshot)
```

### Security & Encryption

```python
from fennec_memory.persistence import EncryptionEngine, AccessControlManager, DataSanitizer, Permission

enc = EncryptionEngine(secret_key="your-32-byte-key")
encrypted = enc.encrypt(b"sensitive payload")
plain = enc.decrypt(encrypted)

acl = AccessControlManager()
acl.grant(user="alice", resource="session:*", permission=Permission.READ)
acl.check(user="bob", resource="session:xyz", permission=Permission.WRITE)
```

### Storage Routing

```python
from fennec_memory.persistence import StorageRouter, RoutingRule, DataTier

router = StorageRouter()
router.add_rule(RoutingRule(tier=DataTier.HOT, storage_type=StorageType.KEY_VALUE))
router.add_rule(RoutingRule(tier=DataTier.COLD, storage_type=StorageType.OBJECT))
```

---

## Integration with fennec-community

`fennec-memory` is designed to work seamlessly alongside [`fennec-community`](https://pypi.org/project/fennec-community/) and [`fennec-guard`](https://pypi.org/project/fennec-guard/):

```python
from fennec_memory.memory import AIMemoryManager, ContextBuilder
from fennec_memory.cache import MultiLevelCache
from fennec_community.rag.core import RAGSystem

memory = AIMemoryManager()
cache = MultiLevelCache()
rag = RAGSystem(...)

def chat(user_id: str, query: str) -> str:
    # Check semantic cache first
    cached = cache.get(query)
    if cached:
        return cached.response

    # Retrieve relevant memories
    past_context = memory.recall(query, top_k=5)

    # Run RAG
    answer = rag.query(query, extra_context=past_context)

    # Store in memory and cache
    memory.remember(f"Q: {query} A: {answer}", importance=0.6)
    cache.set(query=query, response=answer)
    return answer
```

---

## Requirements

- Python >= 3.9
- pydantic >= 2.0
- numpy >= 1.24

All other dependencies are optional — install only what you need.

---

## License

MIT License — see [LICENSE](LICENSE) for details.

---

## Contributing

Contributions are welcome! Please open an issue or pull request on [GitHub](https://github.com/fennec-community/fennec-memory).
