Compare commits

..

No commits in common. "971548321f2be910e484e77e35e547f01a8e1c91" and "28a8953ac581679dc606f3c3de605eb4d2917109" have entirely different histories.

9 changed files with 134 additions and 98 deletions

View file

@ -5,9 +5,11 @@ OPENAI_BASE_URL=https://your-openai-compatible-endpoint.com/v1
EMBEDDER_API_KEY=AIzaSy-your-google-gemini-api-key-here EMBEDDER_API_KEY=AIzaSy-your-google-gemini-api-key-here
# Database Configuration # Database Configuration
QDRANT_HOST=qdrant POSTGRES_DB=mem0_db
QDRANT_PORT=6333 POSTGRES_USER=mem0_user
QDRANT_COLLECTION_NAME=mem0 POSTGRES_PASSWORD=mem0_password
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
# Neo4j Configuration # Neo4j Configuration
NEO4J_AUTH=neo4j/mem0_neo4j_password NEO4J_AUTH=neo4j/mem0_neo4j_password
@ -34,5 +36,4 @@ EXPERT_MODEL=o3 # Expert-level comprehensive analysis
# - Ensure all models are available on your OpenAI-compatible endpoint # - Ensure all models are available on your OpenAI-compatible endpoint
# - Verify model availability: curl -H "Authorization: Bearer $API_KEY" $BASE_URL/v1/models # - Verify model availability: curl -H "Authorization: Bearer $API_KEY" $BASE_URL/v1/models
# - Neo4j must be version 5.18+ for vector.similarity.cosine() function # - Neo4j must be version 5.18+ for vector.similarity.cosine() function
# - Qdrant vector database for embeddings storage (replaces PostgreSQL+pgvector) # - Ollama must be running locally with nomic-embed-text:latest model
# - Ollama must be running locally with nomic-embed-text:latest model

View file

@ -1,12 +1,12 @@
# Mem0 Interface - Production Ready # Mem0 Interface - Production Ready
A fully operational Mem0 interface with Qdrant and Neo4j integration, featuring intelligent model routing, comprehensive memory management, and production-grade monitoring. A fully operational Mem0 interface with PostgreSQL and Neo4j integration, featuring intelligent model routing, comprehensive memory management, and production-grade monitoring.
## Features ## Features
### Core Memory System ### Core Memory System
- ✅ **Mem0 OSS Integration**: Complete hybrid datastore (Vector + Graph + KV storage) - ✅ **Mem0 OSS Integration**: Complete hybrid datastore (Vector + Graph + KV storage)
- ✅ **Qdrant**: Purpose-built vector database for high-performance embeddings storage - ✅ **PostgreSQL + pgvector**: High-performance vector embeddings storage
- ✅ **Neo4j 5.18**: Graph relationships with native vector similarity functions - ✅ **Neo4j 5.18**: Graph relationships with native vector similarity functions
- ✅ **Google Gemini Embeddings**: Enterprise-grade embedding generation - ✅ **Google Gemini Embeddings**: Enterprise-grade embedding generation
- ✅ **Memory Operations**: Store, search, update, delete memories with semantic search - ✅ **Memory Operations**: Store, search, update, delete memories with semantic search
@ -62,7 +62,7 @@ curl http://localhost:8000/health
### Core Components ### Core Components
- **FastAPI Backend**: Production-ready API with comprehensive monitoring - **FastAPI Backend**: Production-ready API with comprehensive monitoring
- **Mem0 OSS**: Hybrid memory management (vector + graph + key-value) - **Mem0 OSS**: Hybrid memory management (vector + graph + key-value)
- **Qdrant**: Purpose-built vector database for embeddings storage and similarity search - **PostgreSQL + pgvector**: Vector embeddings storage and similarity search
- **Neo4j 5.18**: Graph relationships with native vector functions - **Neo4j 5.18**: Graph relationships with native vector functions
- **Google Gemini**: Enterprise-grade embedding generation - **Google Gemini**: Enterprise-grade embedding generation
@ -203,13 +203,13 @@ curl http://localhost:8000/graph/relationships/alice
### Service Dependencies ### Service Dependencies
- **Neo4j**: Must start before backend for vector functions - **Neo4j**: Must start before backend for vector functions
- **Qdrant**: Required for vector storage initialization - **PostgreSQL**: Required for vector storage initialization
- **Ollama**: Must be running locally on port 11434 - **Ollama**: Must be running locally on port 11434
- **API Endpoint**: Must have valid models available - **API Endpoint**: Must have valid models available
## Production Notes ## Production Notes
- **Memory Usage**: Neo4j and Qdrant require adequate RAM for vector operations - **Memory Usage**: Neo4j and PostgreSQL require adequate RAM for vector operations
- **API Rate Limits**: Monitor usage on custom endpoint - **API Rate Limits**: Monitor usage on custom endpoint
- **Data Persistence**: All data stored in Docker volumes - **Data Persistence**: All data stored in Docker volumes
- **Scaling**: Individual services can be scaled independently - **Scaling**: Individual services can be scaled independently
@ -217,4 +217,4 @@ curl http://localhost:8000/graph/relationships/alice
## Development ## Development
See individual README files in `backend/` and `frontend/` directories for development setup. See individual README files in `backend/` and `frontend/` directories for development setup.

View file

@ -9,7 +9,7 @@ A production-ready FastAPI backend that provides intelligent memory integration
1. **Mem0Manager** (`mem0_manager.py`) 1. **Mem0Manager** (`mem0_manager.py`)
- Central orchestration of memory operations - Central orchestration of memory operations
- Integration with custom OpenAI-compatible endpoint - Integration with custom OpenAI-compatible endpoint
- Memory persistence across Qdrant and Neo4j - Memory persistence across PostgreSQL and Neo4j
- Performance timing and operation tracking - Performance timing and operation tracking
2. **Configuration System** (`config.py`) 2. **Configuration System** (`config.py`)
@ -39,8 +39,8 @@ A production-ready FastAPI backend that provides intelligent memory integration
``` ```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
Qdrant │ │ Neo4j │ │ Custom LLM │ PostgreSQL │ │ Neo4j │ │ Custom LLM │
(Vector DB) │ │ (APOC) │ │ Endpoint │ (pgvector) │ │ (APOC) │ │ Endpoint │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ • Vector Store │ │ • Graph Store │ │ • claude-sonnet-4│ │ • Vector Store │ │ • Graph Store │ │ • claude-sonnet-4│
│ • Embeddings │ │ • Relationships │ │ • Gemini Embed │ │ • Embeddings │ │ • Relationships │ │ • Gemini Embed │
@ -134,9 +134,11 @@ backend/
| `OPENAI_COMPAT_API_KEY` | Your custom endpoint API key | - | ✅ | | `OPENAI_COMPAT_API_KEY` | Your custom endpoint API key | - | ✅ |
| `OPENAI_BASE_URL` | Custom endpoint URL | - | ✅ | | `OPENAI_BASE_URL` | Custom endpoint URL | - | ✅ |
| `EMBEDDER_API_KEY` | Google Gemini API key for embeddings | - | ✅ | | `EMBEDDER_API_KEY` | Google Gemini API key for embeddings | - | ✅ |
| `QDRANT_HOST` | Qdrant vector database host | qdrant | ✅ | | `POSTGRES_HOST` | PostgreSQL host | postgres | ✅ |
| `QDRANT_PORT` | Qdrant vector database port | 6333 | ✅ | | `POSTGRES_PORT` | PostgreSQL port | 5432 | ✅ |
| `QDRANT_COLLECTION_NAME` | Qdrant collection name | mem0 | ✅ | | `POSTGRES_DB` | Database name | mem0_db | ✅ |
| `POSTGRES_USER` | Database user | mem0_user | ✅ |
| `POSTGRES_PASSWORD` | Database password | - | ✅ |
| `NEO4J_URI` | Neo4j connection URI | bolt://neo4j:7687 | ✅ | | `NEO4J_URI` | Neo4j connection URI | bolt://neo4j:7687 | ✅ |
| `NEO4J_USERNAME` | Neo4j username | neo4j | ✅ | | `NEO4J_USERNAME` | Neo4j username | neo4j | ✅ |
| `NEO4J_PASSWORD` | Neo4j password | - | ✅ | | `NEO4J_PASSWORD` | Neo4j password | - | ✅ |
@ -281,7 +283,7 @@ docker exec mem0-neo4j cypher-shell -u neo4j -p mem0_neo4j_password \
### Key Integration Points Verified ### Key Integration Points Verified
- ✅ **Ollama Embeddings**: nomic-embed-text:latest working for vector generation - ✅ **Ollama Embeddings**: nomic-embed-text:latest working for vector generation
- ✅ **Qdrant**: Vector storage and similarity search operational - ✅ **PostgreSQL + pgvector**: Vector storage and similarity search operational
- ✅ **Neo4j 5.18**: Graph relationships and native vector functions working - ✅ **Neo4j 5.18**: Graph relationships and native vector functions working
- ✅ **Custom LLM Endpoint**: All 4 models accessible and routing correctly - ✅ **Custom LLM Endpoint**: All 4 models accessible and routing correctly
- ✅ **Memory Persistence**: Data survives container restarts via Docker volumes - ✅ **Memory Persistence**: Data survives container restarts via Docker volumes
@ -388,7 +390,7 @@ backend:
#### Dependency Requirements #### Dependency Requirements
- Neo4j 5.18+ (for vector.similarity.cosine function) - Neo4j 5.18+ (for vector.similarity.cosine function)
- Ollama running locally with nomic-embed-text:latest - Ollama running locally with nomic-embed-text:latest
- Qdrant vector database - PostgreSQL with pgvector extension
- Valid API keys for custom LLM endpoint - Valid API keys for custom LLM endpoint
### Debugging Commands ### Debugging Commands
@ -445,4 +447,4 @@ docker logs mem0-backend --tail 20 -f
## 📄 License ## 📄 License
This POC is designed for demonstration and evaluation purposes. This POC is designed for demonstration and evaluation purposes.

View file

@ -10,16 +10,18 @@ class Settings(BaseSettings):
"""Application settings loaded from environment variables.""" """Application settings loaded from environment variables."""
# API Configuration # API Configuration
openai_api_key: str = Field(..., env="OPENAI_COMPAT_API_KEY") openai_api_key: str = Field(..., env="OPENAI_API_KEY")
openai_base_url: str = Field(..., env="OPENAI_COMPAT_BASE_URL") openai_base_url: str = Field(..., env="OPENAI_BASE_URL")
embedder_api_key: str = Field(..., env="EMBEDDER_API_KEY") embedder_api_key: str = Field(..., env="EMBEDDER_API_KEY")
# ollama_base_url: str = Field(..., env="OLLAMA_BASE_URL") # ollama_base_url: str = Field(..., env="OLLAMA_BASE_URL")
# Database Configuration # Database Configuration
qdrant_host: str = Field("localhost", env="QDRANT_HOST") postgres_host: str = Field("localhost", env="POSTGRES_HOST")
qdrant_port: int = Field(6333, env="QDRANT_PORT") postgres_port: int = Field(5432, env="POSTGRES_PORT")
qdrant_collection_name: str = Field("mem0", env="QDRANT_COLLECTION_NAME") postgres_db: str = Field("mem0_db", env="POSTGRES_DB")
postgres_user: str = Field("mem0_user", env="POSTGRES_USER")
postgres_password: str = Field("mem0_password", env="POSTGRES_PASSWORD")
# Neo4j Configuration # Neo4j Configuration
neo4j_uri: str = Field("bolt://localhost:7687", env="NEO4J_URI") neo4j_uri: str = Field("bolt://localhost:7687", env="NEO4J_URI")
@ -33,6 +35,10 @@ class Settings(BaseSettings):
# Model Configuration - Ultra-minimal (single model) # Model Configuration - Ultra-minimal (single model)
default_model: str = Field("claude-sonnet-4", env="DEFAULT_MODEL") default_model: str = Field("claude-sonnet-4", env="DEFAULT_MODEL")
@property
def postgres_url(self) -> str:
"""Build PostgreSQL connection URL."""
return f"postgresql://{self.postgres_user}:{self.postgres_password}@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}"
@property @property
def cors_origins_list(self) -> List[str]: def cors_origins_list(self) -> List[str]:
@ -45,4 +51,4 @@ class Settings(BaseSettings):
# Global settings instance # Global settings instance
settings = Settings() settings = Settings()

View file

@ -39,13 +39,14 @@ class Mem0Manager:
} }
}, },
"vector_store": { "vector_store": {
"provider": "qdrant", "provider": "pgvector",
"config": { "config": {
"collection_name": settings.qdrant_collection_name, "dbname": settings.postgres_db,
"host": settings.qdrant_host, "user": settings.postgres_user,
"port": settings.qdrant_port, "password": settings.postgres_password,
"embedding_model_dims": 2560, "host": settings.postgres_host,
"on_disk": True "port": settings.postgres_port,
"embedding_model_dims": 2560
} }
}, },
"graph_store": { "graph_store": {

View file

@ -9,7 +9,8 @@ openai
google-genai google-genai
# Database # Database
qdrant-client psycopg2-binary
pgvector
neo4j neo4j
langchain-neo4j langchain-neo4j
rank-bm25 rank-bm25
@ -29,4 +30,4 @@ python-json-logger
# CORS and Security # CORS and Security
python-jose[cryptography] python-jose[cryptography]
passlib[bcrypt] passlib[bcrypt]

66
config/postgres-init.sql Normal file
View file

@ -0,0 +1,66 @@
-- Initialize PostgreSQL database for Mem0 with pgvector extension
-- Create the pgvector extension for vector operations
CREATE EXTENSION IF NOT EXISTS vector;
-- Create user if not exists (in case it's needed)
DO
$do$
BEGIN
IF NOT EXISTS (
SELECT FROM pg_catalog.pg_roles
WHERE rolname = 'mem0_user') THEN
CREATE ROLE mem0_user LOGIN PASSWORD 'mem0_password';
END IF;
END
$do$;
-- Grant necessary permissions
GRANT ALL PRIVILEGES ON DATABASE mem0_db TO mem0_user;
GRANT ALL ON SCHEMA public TO mem0_user;
-- Create table for vector embeddings (if needed by Mem0's pgvector implementation)
CREATE TABLE IF NOT EXISTS embeddings (
id SERIAL PRIMARY KEY,
user_id VARCHAR(255),
content TEXT,
embedding VECTOR(2560), -- OpenAI embedding dimension
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
-- Create index for efficient vector similarity search
CREATE INDEX IF NOT EXISTS embeddings_embedding_idx ON embeddings
USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
-- Create index for user_id lookups
CREATE INDEX IF NOT EXISTS embeddings_user_id_idx ON embeddings (user_id);
-- Create index for metadata queries
CREATE INDEX IF NOT EXISTS embeddings_metadata_idx ON embeddings USING GIN (metadata);
-- Grant permissions on the table
GRANT ALL PRIVILEGES ON TABLE embeddings TO mem0_user;
GRANT USAGE, SELECT ON SEQUENCE embeddings_id_seq TO mem0_user;
-- Create table for memory history tracking
CREATE TABLE IF NOT EXISTS memory_history (
id SERIAL PRIMARY KEY,
memory_id VARCHAR(255),
user_id VARCHAR(255),
action VARCHAR(50),
previous_value TEXT,
new_value TEXT,
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
-- Create indexes for memory history
CREATE INDEX IF NOT EXISTS memory_history_memory_id_idx ON memory_history (memory_id);
CREATE INDEX IF NOT EXISTS memory_history_user_id_idx ON memory_history (user_id);
CREATE INDEX IF NOT EXISTS memory_history_created_at_idx ON memory_history (created_at);
-- Grant permissions
GRANT ALL PRIVILEGES ON TABLE memory_history TO mem0_user;
GRANT USAGE, SELECT ON SEQUENCE memory_history_id_seq TO mem0_user;

View file

@ -1,17 +1,20 @@
services: services:
# Qdrant vector database for vector storage # PostgreSQL with pgvector extension for vector storage
qdrant: postgres:
image: qdrant/qdrant:latest image: pgvector/pgvector:pg17-trixie
container_name: mem0-qdrant container_name: mem0-postgres
environment:
POSTGRES_DB: ${POSTGRES_DB:-mem0_db}
POSTGRES_USER: ${POSTGRES_USER:-mem0_user}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mem0_password}
expose: expose:
- "6333" - "5432"
volumes: volumes:
- qdrant_data:/qdrant/storage - postgres_data:/var/lib/postgresql/data
command: > - ./config/postgres-init.sql:/docker-entrypoint-initdb.d/init.sql
sh -c "apt-get update && apt-get install -y curl && ./entrypoint.sh"
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:6333/"] test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mem0_user} -d ${POSTGRES_DB:-mem0_db}"]
interval: 10s interval: 5s
timeout: 5s timeout: 5s
retries: 5 retries: 5
restart: unless-stopped restart: unless-stopped
@ -54,9 +57,11 @@ services:
OPENAI_API_KEY: ${OPENAI_COMPAT_API_KEY} OPENAI_API_KEY: ${OPENAI_COMPAT_API_KEY}
OPENAI_BASE_URL: ${OPENAI_COMPAT_BASE_URL} OPENAI_BASE_URL: ${OPENAI_COMPAT_BASE_URL}
EMBEDDER_API_KEY: ${EMBEDDER_API_KEY:-AIzaSyA_} EMBEDDER_API_KEY: ${EMBEDDER_API_KEY:-AIzaSyA_}
QDRANT_HOST: qdrant POSTGRES_HOST: postgres
QDRANT_PORT: 6333 POSTGRES_PORT: 5432
QDRANT_COLLECTION_NAME: ${QDRANT_COLLECTION_NAME:-mem0} POSTGRES_DB: ${POSTGRES_DB:-mem0_db}
POSTGRES_USER: ${POSTGRES_USER:-mem0_user}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mem0_password}
NEO4J_URI: bolt://neo4j:7687 NEO4J_URI: bolt://neo4j:7687
NEO4J_USERNAME: ${NEO4J_USERNAME:-neo4j} NEO4J_USERNAME: ${NEO4J_USERNAME:-neo4j}
NEO4J_PASSWORD: ${NEO4J_PASSWORD:-mem0_neo4j_password} NEO4J_PASSWORD: ${NEO4J_PASSWORD:-mem0_neo4j_password}
@ -66,7 +71,7 @@ services:
ports: ports:
- "${BACKEND_PORT:-8000}:8000" - "${BACKEND_PORT:-8000}:8000"
depends_on: depends_on:
qdrant: postgres:
condition: service_healthy condition: service_healthy
neo4j: neo4j:
condition: service_healthy condition: service_healthy
@ -76,7 +81,7 @@ services:
command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
volumes: volumes:
qdrant_data: postgres_data:
neo4j_data: neo4j_data:
neo4j_logs: neo4j_logs:
neo4j_import: neo4j_import:
@ -84,4 +89,4 @@ volumes:
networks: networks:
default: default:
name: mem0-network name: mem0-network

View file

@ -37,14 +37,7 @@
padding: 20px; padding: 20px;
background: #fafafa; background: #fafafa;
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;
display: flex;
justify-content: space-between;
align-items: center;
}
.chat-header-content {
text-align: center; text-align: center;
flex: 1;
} }
.chat-header h1 { .chat-header h1 {
@ -58,31 +51,6 @@
font-size: 14px; font-size: 14px;
} }
.clear-chat-btn {
background: #f8f9fa;
color: #666;
border: 1px solid #e0e0e0;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
font-size: 12px;
font-weight: 500;
display: flex;
align-items: center;
gap: 5px;
transition: all 0.2s ease;
}
.clear-chat-btn:hover {
background: #e9ecef;
border-color: #ced4da;
color: #495057;
}
.clear-chat-btn:active {
background: #dee2e6;
}
.chat-messages { .chat-messages {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
@ -274,13 +242,8 @@
<!-- Chat Section --> <!-- Chat Section -->
<div class="chat-section"> <div class="chat-section">
<div class="chat-header"> <div class="chat-header">
<div class="chat-header-content"> <h1>What can I help you with?</h1>
<h1>What can I help you with?</h1> <p>Chat with your memories - User: pratik</p>
<p>Chat with your memories - User: pratik</p>
</div>
<button class="clear-chat-btn" id="clearChatBtn" title="Clear chat history">
🗑️ Clear Chat
</button>
</div> </div>
<div class="chat-messages" id="chatMessages"> <div class="chat-messages" id="chatMessages">
@ -318,7 +281,6 @@
const memoriesList = document.getElementById('memoriesList'); const memoriesList = document.getElementById('memoriesList');
const memoryCount = document.getElementById('memoryCount'); const memoryCount = document.getElementById('memoryCount');
const refreshButton = document.getElementById('refreshMemories'); const refreshButton = document.getElementById('refreshMemories');
const clearChatBtn = document.getElementById('clearChatBtn');
// Chat history in localStorage // Chat history in localStorage
let chatHistory = JSON.parse(localStorage.getItem('chatHistory') || '[]'); let chatHistory = JSON.parse(localStorage.getItem('chatHistory') || '[]');
@ -334,7 +296,6 @@
if (e.key === 'Enter') sendMessage(); if (e.key === 'Enter') sendMessage();
}); });
refreshButton.addEventListener('click', loadMemories); refreshButton.addEventListener('click', loadMemories);
clearChatBtn.addEventListener('click', clearChatWithConfirmation);
}); });
// Load chat history from localStorage // Load chat history from localStorage
@ -532,13 +493,6 @@
}, 5000); }, 5000);
} }
// Clear chat history with confirmation
function clearChatWithConfirmation() {
if (confirm('Are you sure you want to clear the chat history? This action cannot be undone.')) {
clearChatHistory();
}
}
// Clear chat history (for debugging) // Clear chat history (for debugging)
function clearChatHistory() { function clearChatHistory() {
chatHistory = []; chatHistory = [];