A personalized AI assistant with long-term memory that learns from your notes, conversations, and experiences. Built with retrieval-augmented generation (RAG) to provide personalized responses grounded in your own knowledge base.
This system ingests your personal notes and documents, converts them into semantic embeddings stored in a vector database, and uses GPT-4.1 to answer questions with full context of your life, preferences, and experiences. Think of it as "ChatGPT with perfect memory of who you are."
Key Features:
- ๐ง Long-term Memory: Remembers everything you tell it across sessions
 - ๐ฏ Intelligent Retrieval: Advanced multi-query retrieval that understands context and implied questions
 - ๐ค Preference Learning: Automatically extracts and applies your preferences from conversations
 - ๐ Note Ingestion: Import Markdown files, journals, and personal documents
 - ๐ Semantic Search: Find relevant memories using meaning, not just keywords
 - โฐ Time-Aware: Weights recent information higher while preserving old memories
 - ๐ฌ Contextual Responses: Tailored advice based on your preferences, habits, and history
 - ๐ Continuous Learning: Learns new facts and preferences from every conversation
 
๐ Personal Notes/Documents
    โ (Markdown Loader & Chunker)
๐ข Vector Embeddings (OpenAI)
    โ (Store in Vector DB)
๐๏ธ Pinecone Vector Store
    โ (Intelligent Multi-Query Retrieval)
๐ Intelligent Retriever + Preference Tracker
    โ (Context-Aware RAG)
๐ค GPT-4.1 + Personal Context + User Preferences
    โ (Auto-Extract New Preferences)
๐ฌ Personalized Response + Learning
- Python 3.11+
 - OpenAI API key
 - Pinecone API key (for vector storage)
 
# Clone the repository
git clone https://github.com/yourusername/self-fed-memory.git
cd self-fed-memory
# Option A: Local venv (recommended for most users)
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[ui]"
# Option B: Conda (optional, if you prefer)
conda create -n self-mem python=3.11 -y
conda activate self-mem
pip install -e ".[ui]"
# Option C: Docker (no local Python needed)
docker build -t self-fed-memory:latest .
- Use the lockfile for fast, deterministic installs:
 
# with your venv/conda env activated
make dev           # installs from requirements-dev.txt and sets up git hooks
# or
pip install -r requirements-dev.txtTo update dependencies (and refresh the lock):
make lock-upgrade  # regenerates requirements-dev.txt from pyproject extrasCreate a .env file in the root directory:
cp .env.example .envEdit .env with your API keys:
# Mandatory
OPENAI_API_KEY=sk-your-openai-key-here
PINECONE_API_KEY=pcn-your-pinecone-key-here
# Optional tracing and monitoring
LANGSMITH_TRACING=true
LANGSMITH_API_KEY=lsv2-your-langsmith-key-here
LANGSMITH_PROJECT=self_memory
# Optional (with defaults)
PINECONE_ENV=us-east-1
PINECONE_INDEX=self-memory
EMBEDDING_MODEL=text-embedding-3-large
# Testing (recommended for development)
TEST_PINECONE_INDEX=self-memory-test
TEST_EMBEDDING_MODEL=text-embedding-3-large
# Optional: Supabase (for chat history, users, permanent memories)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-secret-or-service-role-keyNo manual step is required. The Pinecone index and namespace are created on first use if missing. Proceed directly to ingestion.
# Ingest a folder of Markdown files
python scripts/ingest_folder.py /path/to/your/notespython -c "
from app.core.embeddings import get_embeddings
from app.core.memory import MemoryManager
from app.core.chains.qa_chain import IntegratedQAChain
mem = MemoryManager(get_embeddings())
chain = IntegratedQAChain(mem, k=5, name='Your Name')
while True:
    q = input('You: ')
    if q.lower() in ['quit', 'exit']: break
    res = chain.invoke({'question': q})
    print('AI:', res['answer'])
"
# Or use the intelligent QA chain
python -c "
from app.core.embeddings import get_embeddings
from app.core.memory import MemoryManager
from app.core.chains.intelligent_qa_chain import IntelligentQAChain
mem = MemoryManager(get_embeddings())
chain = IntelligentQAChain(mem, name='Your Name', k=8)
while True:
    q = input('You: ')
    if q.lower() in ['quit', 'exit']: break
    res = chain.invoke({'question': q, 'conversation_history': ''})
    print('AI:', res['answer'])
"# First ensure dependencies are installed in your active env
# (either of the following):
#   make dev                  # installs from the lockfile (recommended)
#   pip install -r requirements-dev.txt
#   # or if you prefer extras (slower resolver): pip install -e ".[ui]"
# Then start API and UI (requires venv/conda activated)
make run
# Or run via Docker Compose (no local Python needed)
docker compose up --buildOnce the UI is running (Streamlit at http://localhost:8501), you can:
- Open the Settings (โ) to configure Intelligent mode, API base URL, and persistence. "Store chat history (Supabase)" is enabled by default; the backend will simply ignore it if Supabase is not configured.
 - Use the Memory Manager (๐ง ) โ "Upload Markdown Files" to ingest 
.mdfiles. The loader honors frontโmatter and filename dates and chunks documents for retrieval. Uploaded items are indexed for vector search (Pinecone) and, for core types (preference/fact/profile), also persisted to Supabase when configured. - In Memory Manager โ "Delete Memories", you can delete by IDs or use "Delete ALL (with confirm)" which opens a confirmation dialog and lets you select target: both, Pinecone only, or Supabase only. The action respects the conversation's DEV/PROD mode toggle.
 
If you want to persist chat history and permanent memories, set SUPABASE_URL and SUPABASE_KEY in your .env. Use the Project API โSecretโ key (new) or the legacy service_role key. Do not use the JWT signing secret. A suggested schema is provided in app/core/knowledge_store.py docstring. When enabled:
- Single-user by default: chats are stored under a single default session. You donโt need to manage session IDs.
 - You can override the default with 
SUPABASE_DEFAULT_SESSION_IDif desired. /chatacceptsstore_chatand will persist messages automatically. It also returns the session id used (for debugging/ops), but the UI no longer requires it.POST /permanent_memories/upsertstores permanent memories (single-user)GET /chat/history?session_id=...reads a session's message history; the UI auto-loads this history on start when asidis present in the URL or aSession IDis set in Settings.- Test vs Production tables: set 
TEST_SUPABASE_TABLE_PREFIX(defaults totest_). Toggle per-request withuse_test_supabase(see below). The UI now provides a single Developer mode toggle that switches both Pinecone and Supabase to test resources for the current conversation. 
Vector retrieval remains in Pinecone; store any retrievable content via /memories/upsert as before.
- The system uses a rules-based router to send core items (types: 
preference,fact,profile,user_core) to Supabase permanent memories, and all items to Pinecone for semantic retrieval (unlessroute_to_vector=false). - From conversations, the Preference Extractor labels items with 
type, and the router persists them accordingly whenstore_chat=true. - API supports:
POST /memories/upsertwith fieldstype,category,route_to_vector.POST /memories/deletewithtarget=pinecone|supabase|both.POST /memories/delete_allto wipe all memories in selected backend(s); respectsuse_test_indexanduse_test_supabasefor DEV vs PROD separation.GET /memories/searchmerging Pinecone + Supabase (substring) results.
 
- Pinecone: 
use_test_index(andTEST_PINECONE_INDEXenv) switch to test index/namespace. - Supabase: 
use_test_supabaseswitches to test table prefix (TEST_SUPABASE_TABLE_PREFIX, defaulttest_).- Frontend now uses a single Developer mode toggle that sets both flags for all requests issued by that conversation. The sidebar shows "๐งช DEV" next to chats in developer mode, and the chat header shows a "Mode: ๐งช DEV MODE" badge.
 - Note: the default session id is the same across prefixes unless you override with 
SUPABASE_DEFAULT_SESSION_ID. 
 
- Use the Supabase SERVICE-ROLE key only on the server (never expose to the browser). Keep it in environment secrets.
 - If you must use the anon/publishable key in the browser, enforce Row Level Security (RLS) policies that strictly scope access by user/session and restrict all writes.
 - Protect write/read endpoints with an API key: set 
API_AUTH_KEYin backend env and include headerx-api-key: <API_AUTH_KEY>when calling:POST /chat(only enforced whenstore_chat=true)POST /permanent_memories/upsertGET /chat/history
 - Always use HTTPS and rotate keys regularly.
 
self-fed-memory/
โโโ app/                          # Main Python package
โ   โโโ api/
โ   โ   โโโ main.py               # FastAPI app factory and CORS
โ   โ   โโโ routes_chat.py        # /chat, /memories/*, OpenAI-compatible endpoints
โ   โโโ core/                     # Core business logic
โ   โ   โโโ chains/
โ   โ   โ   โโโ intelligent_qa_chain.py # Preference-aware, contextual QA
โ   โ   โ   โโโ memory_chain.py         # (present, reserved)
โ   โ   โ   โโโ qa_chain.py             # Basic integrated QA
โ   โ   โโโ embeddings.py         # Embedding engine (OpenAI with offline fallback)
โ   โ   โโโ knowledge_store.py    # Supabase-backed persistence (sessions, memories)
โ   โ   โโโ memory.py             # MemoryManager (Pinecone/Mock + retriever)
โ   โ   โโโ memory_router.py      # Routes items to Pinecone and Supabase
โ   โ   โโโ preference_tracker.py # Extracts and queries user preferences/facts
โ   โ   โโโ retriever.py          # Time-weighted + intelligent multi-query retrieval
โ   โ   โโโ types.py              # Helpers (dict โ Document)
โ   โ   โโโ vector_store/
โ   โ       โโโ mock.py           # In-memory VectorStore for tests/offline
โ   โ       โโโ pinecone.py       # Pinecone VectorStore adapter
โ   โโโ ingestion/
โ   โ   โโโ markdown_loader.py    # Markdown parsing + timestamping + chunking
โ   โโโ utils/
โ       โโโ text_splitter.py      # Shared chunking strategy
โโโ frontend/
โ   โโโ app.py                    # Streamlit UI (chat + memory manager + settings)
โโโ scripts/
โ   โโโ ingest_folder.py          # CLI: bulk-ingest a directory of .md files
โโโ tests/                        # Unit, integration, and manual tests
โโโ Dockerfile
โโโ docker-compose.yml
โโโ pyproject.toml
โโโ README.md
โโโ tests/README.md
โโโ design_doc.md
from app.core.embeddings import get_embeddings
from app.core.memory import MemoryManager
from app.core.chains.intelligent_qa_chain import IntelligentQAChain
memory = MemoryManager(get_embeddings(), use_time_weighting=True)
chain = IntelligentQAChain(memory, name="Alex", k=8)
result = chain.invoke({
    "question": "Based on what you know about me, which restaurant would I enjoy more: a fancy French bistro or a simple sushi place?"
})
print(result["answer"])
print(f"Applied {result['user_preferences_found']} preferences and {result['user_facts_found']} facts")from app.core.embeddings import get_embeddings
from app.core.memory import MemoryManager
from app.core.chains.qa_chain import IntegratedQAChain
mm = MemoryManager(get_embeddings())
chain = IntegratedQAChain(mm, k=5, name="User")
response = chain.invoke({"question": "What are my core values?"})
print(response["answer"])from app.core.embeddings import get_embeddings
from app.core.memory import MemoryManager
memory = MemoryManager(get_embeddings())
memory.add_chunks([
    {
        "id": "mem_2024_01_15_spanish",
        "content": "I started learning Spanish today using Duolingo.",
        "source": "conversation",
        "created_at": "2024-01-15T12:00:00",
        "type": "fact",
        "category": "learning"
    }
])from app.core.embeddings import get_embeddings
from app.core.memory import MemoryManager
from app.core.preference_tracker import PreferenceTracker
memory_manager = MemoryManager(get_embeddings())
tracker = PreferenceTracker(memory_manager)
# Extract preferences from a conversation
conversation = """
User: I really enjoyed that small tapas place, but the loud music was annoying.
I prefer quieter atmospheres where I can actually have a conversation.
Assistant: That's great feedback! For quieter dining, you might enjoy...
"""
result = tracker.extract_and_store_preferences(conversation)
print(f"Extracted {result['preferences']} preferences and {result['facts']} facts")
# Get all stored preferences
preferences = tracker.get_user_preferences()
print(f"Total stored preferences: {len(preferences)}")# The system automatically weights recent memories higher
response = chain.invoke({"query": "What have I been working on lately?"})# Install test dependencies
pip install -e ".[test]"
# Run automated unit tests (fast, no API keys required)
make test
# Run with coverage
make test-cov
# Run manual verification tests (requires API keys + human evaluation)
make test-manual
# List available manual tests
make test-manual-listTesting Philosophy: Fast, reliable automation for logic verification + comprehensive manual testing for quality assurance.
We use pre-commit to automatically run checks locally.
Setup (once):
# If you used `make dev`, hooks are already installed.
# Otherwise, install dev/test deps and hooks:
pip install -e ".[dev,test]"
pre-commit install
# Optional: run on all files once
pre-commit run --all-filesWhat runs when:
- Commit:
- ruff auto-fix and format
 - mypy (uses config in 
pyproject.toml) - unit + integration tests: 
pytest -q -m "unit or integration" --maxfail=1(with coverage; same thresholds as CI) 
 - Push:
- no additional local checks (to avoid duplication); CI repeats the same suite
 
 
Notes:
- Manual tests are not run by hooks (they require real API keys and human review).
 - The commit hook selects tests by marker; any "deselected" count you see in output just reflects excluded markers (e.g., 
manual). - Use any environment you prefer (venv, Conda, Docker). Hooks run in your active shell environment.
 
# Format code
ruff format .
# Lint code
ruff check .
# Type checking
mypy app/To add support for a new vector database:
- Create a new file in 
app/core/vector_store/ - Extend the LangChain 
VectorStorebase class - Implement required methods like 
similarity_search,add_documents, etc. - Update the factory logic in 
MemoryManagerto use your new store 
Example:
# app/core/vector_store/chroma.py
from langchain_core.vectorstores import VectorStore
from langchain_core.documents import Document
class ChromaVectorStore(VectorStore):
    def similarity_search(self, query: str, k: int = 5) -> List[Document]:
        # Implementation here
        pass
    def add_documents(self, documents: List[Document]) -> List[str]:
        # Implementation here
        passAll configuration is handled through environment variables and the Settings class in app/core/config.py.
| Variable | Default | Description | 
|---|---|---|
OPENAI_API_KEY | 
- | Required OpenAI API key | 
PINECONE_API_KEY | 
- | Required Pinecone API key | 
PINECONE_INDEX | 
self-memory | 
Pinecone index name | 
PINECONE_NAMESPACE | 
self-memory-namespace | 
Pinecone namespace | 
EMBEDDING_MODEL | 
text-embedding-3-large | 
OpenAI embedding model | 
LANGSMITH_TRACING | 
false | 
Enable LangSmith tracing | 
LANGSMITH_API_KEY | 
- | LangSmith API key (optional) | 
LANGSMITH_PROJECT | 
self_memory | 
LangSmith project name | 
TEST_PINECONE_INDEX | 
self-memory-test | 
Separate index for testing | 
TEST_EMBEDDING_MODEL | 
text-embedding-3-large | 
Embedding model for tests | 
API_AUTH_KEY | 
- | Optional API auth for protected endpoints | 
- Markdown ingestion and chunking
 - Vector embeddings with OpenAI
 - Pinecone vector storage
 - Time-weighted retrieval
 - Basic Q&A chain with LangChain
 - Configuration management
 - Intelligent retrieval system with multi-query support
 - Automatic preference extraction and learning
 - Context-aware response generation
 - Conversation memory with preference application
 
-  FastAPI backend with 
/chat, OpenAI-compatible endpoints, and memory upsert - Streamlit web interface (chat UI)
 - Enhanced preference management and editing
 - Improved chunking strategies
 
- Knowledge graph layer (Neo4j)
 - Multiple data source connectors
 - Advanced UI with React/Next.js
 - Mobile app
 - Voice interface
 
- Email/calendar integration
 - Social media ingestion
 - Goal tracking and reminders
 - Memory visualization
 - Local LLM support for privacy
 
- Fork the repository
 - Create a feature branch: 
git checkout -b feature-name - Make your changes and add tests (unit tests for logic, manual tests for user experience)
 - Run the automated test suite: 
make test - For changes affecting user experience, run manual verification: 
make test-manual - Submit a pull request
 
- Local Control: Your data stays in your chosen vector database
 - API Usage: OpenAI processes queries but doesn't store them (with proper settings)
 - Encryption: Consider encrypting sensitive data at rest
 
MIT License - see LICENSE file for details.
- Built with LangChain for LLM orchestration
 - Uses Pinecone for vector storage
 - Inspired by the "Second Brain" methodology
 - OpenAI GPT-4.1 for language understanding
 
"Your AI assistant that truly knows you."