Simple Memory API
Free Self-Hosted Version
A lightweight, self-hosted memory API with semantic search capabilities. No cloud dependencies, no API keys required (except optional Llama).
Open Source • MIT Licensed
View on GitHubFeatures
Simple Text Memories
Store and retrieve text-based memories with ease.
Semantic Search
Vector embeddings plus keyword search for accurate retrieval.
Graph Memory
Link memories together to form a knowledge graph.
Content Encryption
AES-128 encryption for memory content at rest.
API Key Authentication
Simple, secure API key system.
Optional AI Enhancement
Use local Llama 8B for summaries and keyword extraction.
SQLite Storage
Lightweight, file-based database.
No External Dependencies
Runs completely offline (except Ollama if used).
Docker Support
One-command deployment.
Architecture
┌─────────────────┐
│ Your App │
│ (Web/Mobile) │
└────────┬────────┘
│
HTTP (Port 8000)
│
┌────────┴────────┐
│ Memory API │
│ (FastAPI) │
│ (Port 8000) │
└────────┬────────┘
│
├──► SQLite DB (memories, embeddings)
│
└──► Ollama (optional, for AI features)
(Port 11434)
Quick Start
Option 1: Docker (Recommended)
# Clone the repository
git clone https://github.com/ranjalii/zymemoryfree.git
mkdir zymemoryfree
# Start everything (API + Ollama)
docker-compose up -d
# Pull Llama model (optional, for AI features)
docker exec -it zymemoryfree-ollama-1 ollama pull llama3.1:8b-instruct-fp16
# Create API key
curl -X POST http://localhost:8000/api-keys \
-H "Content-Type: application/json" \
-d '{"user_id": "user@example.com"}'
# Save the returned API key!
Option 2: Local Python Setup
# Clone the repository
git clone https://github.com/ranjalii/zymemoryfree.git
mkdir zymemoryfree
# Run setup script
./setup_local.sh
# Activate virtual environment
source venv/bin/activate
# Start server
python3 app_local.py
API Usage
1. Create API Key
curl -X POST http://localhost:8000/api-keys \
-H "Content-Type: application/json" \
-d '{"user_id": "user@example.com"}'
Response:
{
"api_key": "mem_xxxxxxxxxxxxxxxxxxxx",
"user_id": "user@example.com",
"message": "Save this API key securely..."
}
2. Create a Memory
curl -X POST http://localhost:8000/memories \
-H "Content-Type: application/json" \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx" \
-d '{
"content": "I prefer Python for data science projects",
"metadata": {"category": "preferences"},
"enhance": true
}'
Response:
{
"id": 1,
"content": "I prefer Python for data science projects",
"metadata": {
"category": "preferences",
"keywords": ["Python", "data science", "projects"]
},
"created_at": 1234567890,
"updated_at": 1234567890
}
3. Search Memories
curl -X POST http://localhost:8000/memories/search \
-H "Content-Type: application/json" \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx" \
-d '{
"query": "What programming language do I like?",
"top_k": 5
}'
Response:
[
{
"id": 1,
"content": "I prefer Python for data science projects",
"metadata": {
"category": "preferences",
"keywords": ["Python", "data science"]
},
"created_at": 1234567890,
"updated_at": 1234567890,
"score": 0.87
}
]
4. List All Memories
curl http://localhost:8000/memories?limit=20&offset=0 \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx"
5. Get Specific Memory
curl http://localhost:8000/memories/1 \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx"
6. Delete Memory
curl -X DELETE http://localhost:8000/memories/1 \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx"
7. Create Memory Link (Graph)
curl -X POST http://localhost:8000/graph/links \
-H "Content-Type: application/json" \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx" \
-d '{
"from_memory_id": 1,
"to_memory_id": 2,
"link_type": "related"
}'
8. Get Linked Memories
curl http://localhost:8000/graph/links/1?direction=both \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx"
Response:
{
"memory_id": 1,
"outgoing": [
{
"id": 2,
"content": "Related memory content",
"link_type": "related",
"link_created_at": 1234567890
}
],
"incoming": []
}
9. Get Memory Graph
curl http://localhost:8000/graph/1?depth=2 \
-H "X-API-Key: mem_xxxxxxxxxxxxxxxxxxxx"
Response:
{
"center": {"id": 1, "content": "..."},
"nodes": [
{"id": 1},
{"id": 2},
{"id": 3}
],
"edges": [
{"from": 1, "to": 2, "type": "related"},
{"from": 2, "to": 3, "type": "caused_by"}
],
"depth": 2
}
API Endpoints
Core Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/ |
API info | No |
GET |
/health |
Health check | No |
GET |
/docs |
Interactive API docs | No |
POST |
/api-keys |
Create API key | No |
POST |
/memories |
Create memory | Yes |
GET |
/memories |
List memories | Yes |
GET |
/memories/{id} |
Get memory | Yes |
DELETE |
/memories/{id} |
Delete memory | Yes |
POST |
/memories/search |
Search memories | Yes |
GET |
/stats |
User statistics | Yes |
Graph Endpoints
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/graph/links |
Create link between memories | Yes |
GET |
/graph/links/{id} |
Get linked memories | Yes |
DELETE |
/graph/links |
Delete link | Yes |
GET |
/graph/{id} |
Get memory graph (N hops) | Yes |
Graph Memory
The graph memory feature allows you to create semantic links between memories, building a knowledge graph over time.
Use Cases
1. Causal Chains
Link cause-and-effect memories:
"Car won't start" --causes--> "Called mechanic" --leads-to--> "Battery replaced"
2. Related Concepts
Group related information:
"Python basics" --related--> "List comprehensions" --related--> "Generator expressions"
3. Timeline/Story
Build narrative connections:
"Met Sarah at conference" --then--> "Coffee meeting" --then--> "Collaboration proposal"
4. Dependencies
Track prerequisite knowledge:
"Linear algebra" --required-for--> "Machine learning" --required-for--> "Neural networks"
Link Types
Suggested link types (you can use any string):
related- General relationshipcaused_by- Causal relationshipleads_to- Temporal sequencepart_of- Hierarchical relationshipcontradicts- Conflicting informationsupports- Supporting evidencerequired_for- Dependency
Graph Visualisation
The /graph/{id}?depth=N endpoint returns a graph structure that can be visualised using libraries like:
- D3.js (JavaScript) - Force-directed graphs
- Cytoscape.js (JavaScript) - Network visualisations
- NetworkX (Python) - Graph analysis and visualisation
- vis.js (JavaScript) - Interactive network graphs
Optional: Llama AI Features
The API can optionally use local Llama 8B Instruct for:
- Summarising long text
- Extracting keywords
- Generating tags
Setup Ollama (Optional)
# Install Ollama
# Visit: https://ollama.com/download
# Pull Llama model
ollama pull llama3.1:8b-instruct-fp16
# Start Ollama (if not already running)
ollama serve
Using AI Enhancement
When creating a memory, set "enhance": true:
{
"content": "Long text about machine learning and neural networks...",
"enhance": true
}
The API will automatically add summary and keywords to the metadata.
Configuration
Environment Variables
Create a .env file (auto-generated by setup_local.sh):
# Database path
DB_PATH=db/memories.db
# Encryption key (CRITICAL - KEEP SECRET!)
ENCRYPTION_KEY=<auto-generated-key>
# Ollama settings (optional)
OLLAMA_API_URL=http://localhost:11434/api/generate
OLLAMA_MODEL=llama3.1:8b-instruct-fp16
Encryption
Content encryption is enabled by default to protect your memories at rest.
How It Works
- Algorithm: Fernet (AES-128-CBC + HMAC-SHA256)
- What's encrypted: Memory content and metadata
- What's NOT encrypted: Embeddings (needed for fast search), user IDs, timestamps
- Performance: Minimal overhead (~1ms per memory)
Generating a New Key
# Generate and print a new encryption key
python3 encryption.py
# Output:
# ENCRYPTION_KEY=<base64-key>
Key Management
Store securely: Use a password manager, encrypted backup, or secrets manager.
Rotation: Not supported yet - all data must be re-encrypted if key changes.
Disabling Encryption
If you don't need encryption (not recommended):
# In .env file
ENCRYPTION_KEY=
Migrating Existing Data
If you have unencrypted data and want to enable encryption:
- Backup your database:
cp db/memories.db db/memories.db.backup - Generate new key:
python3 encryption.py - Add key to
.env - Restart server
New memories will be encrypted. Old memories remain in plaintext (the system handles both).
Python SDK Example
import requests
class MemoryClient:
def __init__(self, api_key, base_url="http://localhost:8000"):
self.api_key = api_key
self.base_url = base_url
self.headers = {"X-API-Key": api_key}
def create(self, content, metadata=None, enhance=False):
return requests.post(
f"{self.base_url}/memories",
json={"content": content, "metadata": metadata, "enhance": enhance},
headers=self.headers
).json()
def search(self, query, top_k=5):
return requests.post(
f"{self.base_url}/memories/search",
json={"query": query, "top_k": top_k},
headers=self.headers
).json()
def list(self, limit=20, offset=0):
return requests.get(
f"{self.base_url}/memories?limit={limit}&offset={offset}",
headers=self.headers
).json()
def delete(self, memory_id):
return requests.delete(
f"{self.base_url}/memories/{memory_id}",
headers=self.headers
).json()
# Usage
client = MemoryClient("mem_xxxxxxxxxxxxxxxxxxxx")
# Create memory
client.create("I love Python programming", {"category": "preferences"})
# Search
results = client.search("What do I love?")
print(results)
Performance
- Storage: ~1KB per memory (text + embedding)
- Search Speed: <100ms for 10,000 memories on consumer hardware
- Embedding: ~50ms per memory (BGE-small-en-v1.5)
- AI Enhancement: ~2-5s with Llama 8B (optional)
Security
Implemented
- Content encryption at rest (Fernet/AES-128)
- API key authentication for all protected endpoints
- User isolation (users can only access their own memories)
- SQLite with file permissions (database file protection)
Recommended for Production
- HTTPS: Run behind reverse proxy (nginx/Caddy)
- Restrict CORS: Limit allowed origins in production
- Rate limiting: Add rate limiting middleware
- API key rotation: Implement key expiration and rotation
- Secrets management: Use vault or secrets manager for keys
- Regular backups: Automated database and key backups
What's NOT Protected
- Embeddings are stored in plaintext (needed for fast search)
- API keys stored as plaintext in DB (hash them for production)
- No protection against SQL injection (using parameterised queries is sufficient)
Deployment
Production Recommendations
- Reverse Proxy: Use nginx or Caddy for HTTPS
- API Key Protection: Restrict
/api-keysendpoint - Rate Limiting: Add rate limiting middleware
- Backups: Regularly backup
db/memories.db - Monitoring: Set up health check pings in production
Example nginx Config
server {
listen 443 ssl;
server_name memory.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Troubleshooting
"Llama not available"
- Install Ollama: https://ollama.com/download
- Pull model:
ollama pull llama3.1:8b-instruct-fp16 - Check Ollama is running:
curl http://localhost:11434/api/tags
"Invalid API key"
- Create a new API key:
POST /api-keys - Use it in
X-API-Keyheader (notAuthorization)
Docker issues
# Check logs
docker-compose logs -f
# Restart services
docker-compose restart
# Rebuild
docker-compose down && docker-compose up --build -d
Comparison with Full Version
| Feature | Free Version | Full Version |
|---|---|---|
| Authentication | API Keys | Google OAuth + Multi-tenant |
| Storage | SQLite | PostgreSQL + Vector Extension |
| AI Model | Local Llama (optional) | Gemini API |
| Memory Structure | Simple text | Hey Maple system |
| Encryption | Fernet (AES-128) | Multi-layer encryption |
| Versioning | No | Full version history |
| Graph | Basic directed graph | Advanced linking and Graph RAG |
| Access Control | User-level | Role-based (read/write/owner) |
| Scaling | Single instance | Horizontal scaling |
Support
- GitHub Repository: github.com/ranjalii/zymemoryfree
- Documentation:
/docsendpoint (interactive API docs) - Issues: Open an issue on GitHub
- Email: contact@heymaple.app
What's Next?
- Add batch import/export
- Web UI for memory management
- Support for images and files
- Integration examples (Python, JavaScript, etc.)
- Multi-language support
Made for the open-source community