How it works
- Write: Each turn is stored short-term (Redis, TTL-based) and embedded for semantic search; important turns are also persisted to the SQLite long-term store.
- Retrieve: At query time,
MemoryRetrievalPipeline.retrieve()(neuralcleave/memory/retrieval.py) pulls from all three tiers in one pass — short-term (priority), Qdrant ANN semantic search (falls back to in-memory cosine similarity if Qdrant is unreachable), and a SQLite long-term query — then deduplicates by content hash, ranks by score, and caps the result at atop_kthe caller passes in code (the cognitive pipeline uses 8). - Inject: The assembled results are serialized into prompt blocks and prepended to the LLM call.
Semantic embedding uses
sentence-transformers (all-MiniLM-L6-v2, downloaded automatically on first use). If it isn’t importable, neuralcleave/memory/embedder.py logs a warning and semantic search is silently skipped for that turn — short-term and long-term retrieval still work normally.Configuration
backend/embedding_model/chunk_size/top_k config — the embedding model and chunking strategy aren’t configurable today; top_k is a call-site parameter, not a config field.
API
The REST routes below only reach the SQLite long-term tier —
/memory/search is a plain content LIKE '%...%' query (neuralcleave/memory/long_term.py’s search()), not the semantic/Qdrant search. Semantic retrieval only happens internally, inside MemoryRetrievalPipeline.retrieve() as part of the chat pipeline — there’s no REST route that exposes it directly today.Search long-term memory (SQLite substring match)
session_id to scope the search to one session (omit for all sessions).
List recent entries
Edit an entry
Delete an entry
Prune
neuralcleave memory clear) for that.
Auto-compaction
Once a session’s estimated token usage crosses 50% of the context window, the pipeline automatically summarizes the conversation (viaConversationCompactor), replaces the in-memory history with that summary, and persists it to long-term SQLite — the same mechanism the manual /compact chat command uses, just triggered automatically instead of on request. Compaction runs fire-and-forget after a turn’s reply is already sent, so it never adds latency to the current response; a failure is logged and swallowed rather than surfaced.
A separate memory_archival job runs daily (03:00) via the heartbeat scheduler, condensing sessions inactive for 30+ days the same way neuralcleave memory archive does manually.
CLI
Privacy note
Withprivacy_mode = true, all LLM calls are forced to local Ollama — see Privacy Mode. The embedding model already runs locally regardless of that setting (no embeddings are ever sent to an external API); only the long-term SQLite store and Qdrant’s own storage location are affected by where you point sqlite_path/qdrant_url.