
Memo's Retrieval-Augmented Generation (RAG) system gives the model persistent, searchable memory across conversations. It is built on SQLite with vector extensions — no external vector database required.
┌──────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ Ingest Doc │────▶│ Chunk & Embed │────▶│ SQLite + vec0 │
│ (MD/TXT/PDF) │ │ (768-dim vectors) │ │ (ANN Index) │
└──────────────┘ └─────────────────────┘ └────────┬─────────┘
│
┌──────────────┐ ┌─────────────────────┐ │
│ User Query │────▶│ Embed Query │────▶────────┘
│ │ │ (same model) │ │ Cosine Search │
└──────────────┘ └─────────────────────┘ │ Top-K Results │
└────────┬────────┘
│
┌──────────────┐ ┌─────────────────────┐ │
│ LLM Response │◀────│ Inject Context │◀─────────────┘
│ (augmented) │ │ (prepend chunks) │
└──────────────┘ └─────────────────────┘
nomic-embed-text-v1.5The embedding server is managed as a subprocess with health checks and automatic restart on failure.
Vectors and metadata are stored in SQLite using the sqlite-vec extension with the vec0 virtual table for Approximate Nearest Neighbor (ANN) indexing:
CREATE VIRTUAL TABLE vec_memory USING vec0(
embedding float[768],
content text,
source text,
chunk_index integer,
created_at datetime
);
When a document or conversation chunk is ingested:
vec_memory table in a single transactionWhen a user query triggers memory recall:
min_similarity (default 0.7) are discarded[Relevant Memory]
- chunk_1 content (similarity: 0.92)
- chunk_2 content (similarity: 0.85)
[User Message]
...current query...
Memo supports cross-mode memory where external chat providers (OpenAI, Claude, etc.) can still write to and read from your local vector store:
This means your memory stays unified whether you're using a local GGUF model or an external API.
vec_memory table supports concurrent reads; writes are serialized via sync.RWMutexstoreMu to prevent races during model reload| Operation | Typical Latency |
|---|---|
| Chunk embedding (512 tokens) | ~50ms |
| Vector search (10K documents) | <5ms |
| Full ingestion (1MB text) | ~2s |
| Context injection | <1ms |
For best memory quality, use the same embedding model consistently. Switching embedding models requires re-indexing all stored documents.