Megan Memory Prototype
Python/Flask prototype for a personal AI assistant with long-term graph-style memory, inspired by the architecture diagrams in the project brief.
What It Does
- Stores production memories in Neo4j as a knowledge graph.
- Keeps a SQLite local graph fallback so terminal tests run without external services.
- Extracts memory summaries, importance, nodes, and relationships with OpenAI when
OPENAI_API_KEYis set. - Falls back to deterministic local extraction when no API key is present.
- Answers questions by retrieving a graph neighborhood first: query terms -> seed entities -> related entities -> mentioned memories -> model answer.
- Runs Celery-powered sleep cycles that consolidate recent memories, strengthen useful graph links, rescore importance, and archive low-value noise.
- Maintains long-running teaching conversations with persisted messages and rolling summaries.
- Tracks token usage by conversation, day, week, and month.
- Exposes API endpoints for remembering, querying, graph inspection, and consolidation.
Setup
uv sync --extra test
copy .env.example .env
Add your key to .env when you want live OpenAI calls.
OPENAI_API_KEY=your_key_here
OPENAI_MODEL=gpt-4.1-mini
Production Graph DB
Use Neo4j for the real memory graph:
docker run --name megan-neo4j -p 7474:7474 -p 7687:7687 -e NEO4J_AUTH=neo4j/password neo4j:5
Then set:
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=password
NEO4J_DATABASE=neo4j
When NEO4J_URI is absent, the app uses instance/megan.sqlite3 as a local graph-compatible fallback for terminal-only development.
Live Data Stores
For a commercial/live deployment, Megan is configured for:
- Railway Postgres via
DATABASE_URLorAPP_DATABASE_URLas the main app data store. - Neo4j Aura via
NEO4J_URIfor long-term graph memory. - Railway Redis via
REDIS_URLfor Celery/background work. - Local SQLite as a development/offline cache with a sync outbox at
SYNC_DATABASE. - Tenant/user/device scope via
MEGAN_TENANT_ID,MEGAN_USER_ID, andSYNC_DEVICE_ID.
See docs/live-data-architecture.md for the production store map and sync rules. At runtime, GET /api/data/topology reports configured storage targets without exposing credentials.
Background Sleep Cycle
Celery runs the memory sleep cycle. Redis is the default broker/result backend:
docker run --name megan-redis -p 6379:6379 redis:7
Start the worker:
uv run celery -A megan.celery_app.celery_app worker --loglevel=info
Start the scheduler that triggers sleep every 4 hours:
uv run celery -A megan.celery_app.celery_app beat --loglevel=info
Trigger a background sleep cycle through Flask:
curl -X POST http://127.0.0.1:5000/api/sleep-cycle
For terminal-only testing without Redis/Celery worker:
uv run python -m megan.cli sleep-cycle
Native Desktop Direction
The commercial Windows desktop direction lives in desktop/.
It is a Windows App SDK / WinUI app backed by Megan.Desktop.Core, which writes local tenant-scoped data under %APPDATA%\Megan and syncs through the Megan API. This path is intended to replace the development-only Tauri/Flask desktop bridge so users do not need to run app.py or install Python.
The older Tauri shell remains available for experimentation. It no longer auto-starts the Flask backend unless MEGAN_TAURI_AUTOSTART_BACKEND=1 is set.
Native Android Direction
The Android companion app lives in android/.
It is a Kotlin / Jetpack Compose app focused on the two mobile surfaces Megan needs first:
- Conversation
- Settings
Android talks to the same Flask API as web and desktop. For emulator testing, set the mobile server URL to http://10.0.2.2:5000. For a real phone, bind Flask to 0.0.0.0 and use your PC's LAN address.
Local model support is routed through Megan's provider/model contract. The recommended first setup is to configure the Flask server with an OpenAI-compatible local endpoint, then select the local route from Android settings.
Run The App
uv run python app.py
Health check:
curl http://127.0.0.1:5000/api/health
Run The Vite React Client
The Flask app is the API server on port 5000. The React voice client runs through Vite on port 5173.
Terminal 1:
uv run python app.py
For local speaker recognition testing with SpeechBrain, run Flask without the debug reloader so Werkzeug does not scan SpeechBrain's lazy optional modules:
uv run flask --app app run --no-reload
Appearance recognition uses the optional InsightFace provider when installed. On Windows, prefer Python 3.10 or 3.11 for this stack, then install:
uv pip install insightface onnxruntime opencv-python
Terminal 2:
cd client
npm install
npm run dev
Open:
http://127.0.0.1:5173
The client supports browser speech input, optional spoken replies, direct memory capture, graph inspection, and per-request provider/model selection.
Model credentials stay server-side in .env. The default provider is OpenAI:
DEFAULT_AI_PROVIDER=openai
OPENAI_API_KEY=your_key_here
OPENAI_MODEL=gpt-4.1-mini
OPENAI_MODEL_OPTIONS=gpt-4.1-mini,gpt-4.1,gpt-4o,gpt-4o-mini
DeepSeek:
DEEPSEEK_API_KEY=your_key_here
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat
DEEPSEEK_MODEL_OPTIONS=deepseek-chat,deepseek-reasoner
Anthropic Claude:
ANTHROPIC_API_KEY=your_key_here
ANTHROPIC_MODEL=claude-sonnet-4-20250514
ANTHROPIC_MODEL_OPTIONS=claude-sonnet-4-20250514,claude-opus-4-20250514,claude-3-7-sonnet-20250219,claude-3-5-haiku-latest
When credentials are configured, Megan asks the provider API for its available models and caches the result for five minutes. The configured model lists are used as an offline fallback.
For an OpenAI-compatible endpoint, configure:
OPENAI_COMPATIBLE_API_KEY=your_key_here
OPENAI_COMPATIBLE_BASE_URL=http://127.0.0.1:11434/v1
OPENAI_COMPATIBLE_MODEL=local-model
OPENAI_COMPATIBLE_MODEL_OPTIONS=local-model,another-model
If the selected provider is not configured, Megan falls back to local deterministic behavior.
Test In The Terminal
uv run pytest
uv run python -m megan.cli smoke-test
uv run python -m megan.cli remember "Megan met John at Hospital Nairobi and discussed diabetes follow-up."
uv run python -m megan.cli ask "What does Megan remember about John?"
uv run python -m megan.cli chat "Teach me graph memory from where we left off."
uv run python -m megan.cli usage
uv run python -m megan.cli graph
uv run python -m megan.cli sleep-cycle
smoke-test deliberately disables OpenAI and Neo4j and runs the sleep cycle inline, so it proves the terminal path works anywhere.
Knowledge Graph Shape
Neo4j stores:
(:Memory)nodes for timestamped experiences.(:Entity {label, kind})nodes for people, places, concepts, events, emotions, states, and procedures.(:Memory)-[:MENTIONS]->(:Entity)links for provenance.(:Entity)-[:RELATED_TO {relation, confidence}]->(:Entity)links for semantic, episodic, and procedural relationships.
The answer path is:
question -> query terms -> seed Entity nodes -> related Entity nodes + Memory provenance -> graph context -> OpenAI answer
Sleep Cycle
The sleep cycle is the offline learning loop:
active memories -> graph neighborhoods -> cluster repeated themes -> rescore importance -> archive noise -> write consolidated memory -> strengthen useful edges
It is implemented in megan/sleep_cycle.py and can run either inline for testing or through Celery for background processing.
Long Conversations And Token Usage
Megan stores every conversation turn in CONVERSATION_DATABASE. For sessions that last more than an hour, it keeps continuity with:
- full persisted message history
- a rolling summary of older turns
- recent message window
- graph memory retrieval for the newest user message
The answer prompt is built from:
rolling summary + recent messages + graph context + latest user message
Token usage is recorded after every model operation. The client at http://127.0.0.1:5000/ shows daily, weekly, and monthly totals. The same data is available through:
curl http://127.0.0.1:5000/api/usage/summary
API
POST /api/memory/event
{
"event": "On June 1, 2026, Megan met John at Hospital Nairobi..."
}
POST /api/memory/query
{
"question": "What does Megan remember about John?"
}
GET /api/memory/graph
POST /api/memory/consolidate
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 megan-0.1.8.tar.gz.
File metadata
- Download URL: megan-0.1.8.tar.gz
- Upload date:
- Size: 443.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d1084fddde44d40dcbdc3ebaaa2dd0c30a092ff09c1c342c8568d17f7143283
|
|
| MD5 |
117f817530d0bdb4006c41d13f9a0c1e
|
|
| BLAKE2b-256 |
a36b1517f35d9c61b081790872a653fd894386a3c0377991266e6a092a3acb92
|
File details
Details for the file megan-0.1.8-py3-none-any.whl.
File metadata
- Download URL: megan-0.1.8-py3-none-any.whl
- Upload date:
- Size: 424.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b355323ee049098e15f079a98f9f37477cee015c1303772376d9d50039b6201c
|
|
| MD5 |
f20976de87cb510a7f24ee7c29493571
|
|
| BLAKE2b-256 |
e75d2d842269e582ffbfbf275c58c598ff942039498ffcb6174e763b3fb81546
|