Skip to content

Apache-2.0 · v0.6.1 · runs on your machine

Search and memory that run entirely on your machine.

HMS is a local-first document search engine and a vector-symbolic associative memory in one store. Hybrid BM25 and exact-cosine retrieval, byte-offset hits, crash-safe persistence, and superposed memory you can bind, bundle and query. No service calls and no telemetry.

  • Rust
  • Python
  • Node

Install, ingest, search

The code below is read from the quickstart examples that CI runs on every pull request.

cargo add holographic-memory --features security
// 1. Ingest. A store is a directory (`None` would use the current directory); it persists
// there and reopens with the same arguments.
let store_dir = tempfile::tempdir()?;
let hms = HmsCore::new(
    DIMENSIONS,
    Some(store_dir.path().display().to_string()),
    None,
)?;
let start = Instant::now();
let inputs: Vec<DocumentInput> = corpus.iter().map(to_input).collect();
hms.memorize_documents(inputs)?;
println!(
    "ingested {} documents in {:.1?}",
    corpus.len(),
    start.elapsed()
);

// Hits carry the passage and its byte range in the source text.
let hit = &hms.search_documents("asylum from persecution", &SearchOptions::default())?[0];
println!(
    "\n{} bytes {}..{} score {:.3}: {}",
    hit.document_id,
    hit.start_byte,
    hit.end_byte,
    hit.score,
    hit.text.as_deref().unwrap_or("")
);

The engine itself. Every other runtime is a surface over it.

pip install holographic-sdk
# 1. Ingest. The server keeps one store per tenant; you send the text and a vector per document.
docs = [
    {"id": d["id"], "vector": toy_embed(d["text"]), "text": d["text"], "metadata": {"title": d["title"]}}
    for d in corpus
]
client = HolographicClient(url=URL, api_key=API_KEY, tenant_id=tenant)
started = time.perf_counter()
client.add_documents(docs)
print(f"ingested {len(docs)} documents in {(time.perf_counter() - started) * 1000:.1f} ms")

# Hits carry the stored text, metadata and the exact cosine score.
top = client.query(toy_embed("asylum from persecution"), top_k=1)["matches"][0]
print(f"\n{top['id']} score {top['score']:.3f}: {top['text']}")

An HTTP client for hms-server. The holographic-vsa wheel is the quantized-phase substrate, a different package.

git clone https://github.com/writerslogic/holographic-memory
cd holographic-memory && npm ci --omit=optional && npm run build
// 1. Ingest. A store is a directory; it persists there and reopens with the same arguments.
const memory = new DocumentMemory(new HolographicMemorySystem(4096, mkdtempSync(join(tmpdir(), 'hms-quickstart-'))))
const started = performance.now()
await memory.ingest(corpus.map(toInput))
console.log(`ingested ${corpus.length} documents in ${(performance.now() - started).toFixed(1)} ms`)

// Hits carry the passage and its byte range in the source text.
const [hit] = await memory.search('asylum from persecution')
console.log(`\n${hit.documentId} bytes ${hit.startByte}..${hit.endByte} score ${hit.score.toFixed(3)}: ${hit.text}`)

Built from source with a Rust toolchain. The npm package is deprecated until the next release.

Full quickstart with the SQLite comparison and encryption →

Measured, and traceable

Both results are read from committed files under benchmarks/results/ each time the site is built.

Hybrid retrieval on SciFact 0.729 nDCG@10, HMS hybrid search
nDCG@10 by method00.250.50.751HMS hybrid (BM25 + exact cosine)0.729HMS lexical (stemmed BM25)0.688BM25 as published in BEIR0.665HMS dense (exact cosine)0.645

BEIR SciFact test split, 300 queries over 5,183 documents, MiniLM-L6-v2 embeddings (384 dimensions). The published BM25 figure (0.665, Thakur et al. 2021) is quoted from the BEIR paper, not re-run here.

Source: benchmarks/results/public_scifact.json · Apple M4 · benchmark page

Vector search on nytimes-256-angular Queries per second at fixed recall, one thread
Queries per second at fixed recall@10, by systemrecall@10 ≥ 0.90recall@10 ≥ 0.95HMS VGraph (4-bit codes, rerank) †13,133not reachedSymphonyQG (qb=0)5,913not reachedHMS VGraph (8-bit codes, rerank)4,409not reachedRaBitQ HNSW 1+42,066not reachedFAISS HNSW M=162,038379FAISS HNSW M=322,011509hnswlib M=161,352348Lucene HNSW M=161,108278RaBitQ IVF 1+8969803RaBitQ IVF 1+4940not reachedLucene HNSW M=32358129SymphonyQG (qb=4)not reachednot reached
  • At recall@10 of 0.90: the fastest HMS configuration (HMS VGraph (8-bit codes, rerank)) ran at 4,409 QPS, slower than the fastest other system (SymphonyQG (qb=0), 5,913 QPS).
  • Not reached at 0.90 by: SymphonyQG (qb=4).
  • At recall@10 of 0.95: no HMS configuration reached it. Reached by: FAISS HNSW M=16, FAISS HNSW M=32, Lucene HNSW M=16, Lucene HNSW M=32, RaBitQ IVF 1+8, hnswlib M=16.
  • † HMS VGraph (4-bit codes, rerank): opt-in encoding that ran at lower machine load than the other rows; the benchmark page treats it as unconfirmed.

Source: benchmarks/results/public_qgraph_nytimes-256-angular.json · Apple M4 · load gate met by 0 of 107 configurations (limit 3.0), so throughput is indicative · benchmark page

One engine, two layers

Document search is a conventional hybrid retriever. The vector-symbolic layer is the associative memory. Both sit on one crash-safe store. Module map →

HMS architecture Applications reach one Rust engine through its language surfaces. The engine has two layers, document search and vector-symbolic memory, over one persistent store. Your application HMS engine (Rust, in your process) What comes back Text and metadata plus embeddings you supply (optional) Rust Python Node hms-server (HTTP) Document search Chunk256 words Stemmed BM25 Exact cosine Blendmin-max Ranked hitspassage, byte range Vector-symbolic memory Atomshash-seeded Bind, bundlepermute Triplesmulti-hop CleanupHopfield Persistent store Memory-mapped segmented log, atomic batches, replay AES-256-GCM store (feature: security) Signed audit log, provenance (features) Passageswith source offsets Facts and answersrecalled by resonance

Why holographic

A hologram stores the whole picture in every fragment. A hypervector memory does the same: many facts are superposed into one long vector, no single bit holds any one fact, and damage is spread thinly over all of them.

  1. Bind a key to a value with XOR. The result looks like neither, and binding again with the key gives the value back.
  2. Bundle many bound pairs by majority vote into one vector that stays a little similar to each of them.
  3. Resonate: unbind with a key and compare against known values. The right one stands out from the noise, even after you corrupt the memory.

The demo uses dense binary vectors so the algebra is easy to see. The engine uses sparse binary vectors, and its document search does not rank with hypervectors; the concepts page says exactly which parts do.

A memory in one vector

4,096 bits hold every key-value pair at once. Pick how many pairs, damage the memory, and ask for one value back.

bit set flipped by damage

Similarity of the unbound memory to each known value

    What is being computed

    Each key and each value is a random 4,096-bit vector. A pair is key XOR value. The memory is the bitwise majority of all pairs, then damage flips the chosen share of its bits. To ask, XOR the memory with a key and measure the fraction of matching bits against every value. Unrelated vectors match about half their bits, with a spread near 0.8 percentage points, so a match well above 0.5 is the stored value. More pairs shrink the signal; more damage shrinks it too. Past some point the answer is wrong, and the demo says so.

    Retrieval quality on SciFact

    SystemnDCG@10Recall@100
    HMS hybrid (BM25 + exact cosine)0.7290.953
    HMS lexical (stemmed BM25)0.6880.925
    HMS dense (exact cosine)0.6450.925
    NumPy exact cosine, same embeddings0.6450.925
    HMS sparse vector path0.4700.779

    Same embeddings for every dense row. The benchmark pages carry the full comparison, including where HMS loses. Source: benchmarks/results/public_scifact.json.

    What is in the box

    How to read this site

    The document pipeline is conventional retrieval: stemmed BM25 fused with exact cosine over embeddings you supply. The vector-symbolic layer powers the meaning memory, composition and the experimental vector index. Where HMS loses to another system on a measured benchmark, the benchmark pages say so, and every number on this site traces to a committed file under benchmarks/results/.

    New here? Start with the quickstart, then read what "holographic" means in this code. Looking something up? Use the search box, the glossary or the FAQ. The version selector in the header switches between latest (the newest tagged release that carries these docs), dev (the main branch) and each tagged release. How the site is built and checked is on its own page.