memvid-core is a crash-safe, deterministic, single-file (.mv2) AI memory format.
This crate exposes that format to Rig through two composable primitives:
MemvidStore— aVectorStoreIndexyou register with an agent for RAG.MemvidPersistHook— aPromptHookthat appends every prompt and response to the memvid file as the agent runs.
Persist with the hook, recall with the store. They share an Arc<Mutex<Memvid>>,
so writes are searchable on the next turn.
| Feature | Default | Description |
|---|---|---|
lex |
✅ | BM25 / Tantivy lexical search. |
vec |
— | HNSW vector search via memvid-core/vec (ONNX Runtime + BGE / Nomic / GTE). |
api_embed |
— | Remote embedding providers (OpenAI, etc.). |
temporal |
— | Temporal track / point-in-time queries. |
encryption |
— | At-rest encryption of the .mv2 file. |
Add the crate:
[dependencies]
rig-memvid = "0.1"Wire a store and a persistence hook into your Rig agent:
use rig::providers::openai;
use rig_memvid::{MemvidStore, MemvidPersistHook, MemoryConfig, WritePolicy};
# async fn run() -> anyhow::Result<()> {
let store = MemvidStore::builder()
.path("./agent_memory.mv2")
.open_or_create()?;
let openai = openai::Client::from_env()?;
let hook = MemvidPersistHook::new(
store.clone(),
MemoryConfig {
policy: WritePolicy::Raw,
commit_each_turn: true,
default_tags: vec!["chat".into()],
},
);
let agent = openai
.agent(openai::GPT_4O)
.preamble("You are a helpful assistant with persistent memory.")
.dynamic_context(4, store)
.build();
let response = agent
.prompt("What did we discuss yesterday?")
.with_hook(hook)
.await?;
println!("{response}");
# Ok(()) }See also:
examples/chatbot_with_memory.rs(OpenAI) andexamples/chatbot_with_memory_ollama.rs(local Ollama).
By default, MemvidStore uses BM25 lexical search. Enable the vec feature
to switch reads and writes through memvid's HNSW vector index:
[dependencies]
rig-memvid = { version = "0.1", features = ["lex", "vec"] }let store = MemvidStore::builder()
.path("./agent_memory.mv2")
.with_default_embedder()? // BGE-small, 384-dim
.open_or_create()?;When an embedder is attached:
put_textembeds the payload and stores it viaput_with_embedding_and_options.top_n/top_n_idsembed the query and runvec_search_with_embedding.- Only
MemvidFilter::scopeis honoured on the vec path.uri,as_of_frame, andas_of_tsreturnMemvidError::UnsupportedFilter— drop down toMemvidStore::search(SearchRequest)for full filter control.
⚠️ Dependency conflict:vecpinsort = =2.0.0-rc.10, which collides withrig-fastembed's=2.0.0-rc.9. If you depend onrig-fastembed, stay lex-only until the pins converge upstream.
Bootstrapping the local embedder model
ONNX models and tokenizers load from $XDG_CACHE_HOME/memvid/text-models/
(or the platform equivalent). Memvid does not auto-download — fetch them
manually:
mkdir -p ~/Library/Caches/memvid/text-models # macOS
curl -L https://huggingface.co/BAAI/bge-small-en-v1.5/resolve/main/onnx/model.onnx \
-o ~/Library/Caches/memvid/text-models/bge-small-en-v1.5.onnx
curl -L https://huggingface.co/BAAI/bge-small-en-v1.5/resolve/main/tokenizer.json \
-o ~/Library/Caches/memvid/text-models/bge-small-en-v1.5_tokenizer.jsonNote the underscore in
bge-small-en-v1.5_tokenizer.json— memvid expects that exact filename.
MemvidFilter implements SearchFilter and accepts the following keys via
eq(...):
| Key | Type | Meaning |
|---|---|---|
uri |
String |
Restrict to frames whose URI matches a prefix |
scope |
String |
Restrict to a logical scope |
as_of_frame |
u64 |
Point-in-time view by frame id |
as_of_ts |
i64 |
Point-in-time view by unix-millis timestamp |
gt / lt / or are not supported by memvid's query model and produce
MemvidError::UnsupportedFilter at query time.
rig-memvid |
rig-core |
memvid-core |
|---|---|---|
0.1 |
0.36 |
2.0 |
This crate is community-maintained and not affiliated with the rig project.
- No WASM.
memvid-coredepends ontantivy,mmap, and optionallyonnxruntime; this crate will not build forwasm32-*targets. - BM25 tokenization is strict. Lexical queries with stopwords or
full-sentence phrasing may return zero hits — prefer keyword-style
queries on the lex path, or enable
vecfor semantic retrieval.