Skip to main content

urna: offline-first vector database, rust and python

Urna

A vector database in one file, with citations that stay valid.

A .urna file holds the chunks, the embeddings, the source spans, the indices and the search contract. The rust runtime maps it into memory, checks its hashes, and answers with exact cosine scores and a urna://content_hash/chunk_id citation for every hit. It works offline and rebuilds byte for byte. Python builds the file, rust serves it.

Renamed from nest after 0.4.0. A .nest file written by 0.4.0 still opens.

Install

brew install hoffresearch/urna/urna
npm install -g @urna/cli
cargo install urna-cli
curl -sSf https://raw.githubusercontent.com/hoffresearch/urna/main/scripts/install.sh | sh

Then run setup once. It downloads the offline embedder, prepares a python env and checks the install:

urna setup

Python only, no setup step needed:

pip install "urna[embed]"

Windows, docker, cargo binstall and how to verify a download are in the install reference.

In the terminal

urna setup shows the plan before it writes anything and ends on the doctor checks.

urna setup: the verify step with every doctor check passing

urna tui opens a corpus, validates it, and lets you ask it questions. Each hit shows its score, the stored text and its citation.

urna tui my_corpus.urna
urna tui: the ask tab with scored hits and the cited text of the selected one

Quickstart

examples/quickstart/ has twelve short paragraphs and the spec that builds them. From a checkout:

urna build --spec examples/quickstart/corpus.toml
urna ask examples/quickstart/out/quickstart.urna "can I use this offline" -k 1
urna retrieve examples/quickstart/out/quickstart.urna "how do citations work" -k 2 --format jsonl
urna cite examples/quickstart/out/quickstart.urna 'urna://sha256:1147b256.../sha256:b5dfeb09...'
urna validate examples/quickstart/out/quickstart.urna

ask prints the answer with its citation, retrieve prints json for another program, cite turns a citation back into the stored text, and validate checks every hash. To build from your own rows, see usage section 13.

What the file guarantees

Property How
Self-contained The file is the whole database. Copy it like a sqlite file.
Verifiable Sha-256 per section, per file and over the decoded content. urna cite resolves any citation.
Reproducible Same chunks and same model give a byte-identical file on any machine.
Offline The runtime never opens a socket. A query from the wrong model fails at the model_hash check.

Python

import urna
from urna.embed_potion import potion_embedder

emb = potion_embedder()
db = urna.open("my_corpus.urna")
qvec = emb.embed_texts(["can I use this offline"])[0]

hits = db.retrieve(qvec, 5, expected_model_hash=emb.model_hash())
print(hits[0].citation_id, hits[0].score, hits[0].text)
Search variants, validate, build
db.search(qvec, 5)                                     # exact
db.search_ann(qvec, 5, 100)                            # hnsw, then exact rerank
db.search_hybrid(qvec, "vacina contra covid", 5, 100)  # bm25 + vectors, exact rerank
db.search_graph(qvec, 5, hops=2, ef=100)               # chunk graph from the seeds
db.search_space("clip-vit-b32", ivec, 5)               # one named multimodal space

assert db.validate() is True
info = db.inspect()

Each chunk is a dict with canonical_text, source_uri, byte_start, byte_end and embedding:

urna.build(
    output_path="my_corpus.urna",
    embedding_model="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
    embedding_dim=384,
    chunker_version="fixed-512/1",
    model_hash=model_hash,
    chunks=chunks,
    reproducible=True,
    preset="hybrid",
)

python examples/quickstart/quickstart.py runs the whole loop, build to cited hits, with no network.

CLI

The engine verbs take a file and a vector and never run python. The agent verbs (ask, retrieve, build) take text and use the offline embedder. setup and tui are the terminal ui. urna --help lists all three groups.

Agent verbs
urna ask my_corpus.urna "can I use this offline" -k 3
urna retrieve my_corpus.urna "can I use this offline" -k 5 --format jsonl
urna build --spec corpus.toml --dry-run

build reads one toml: the source (sqlite, csv, jsonl, an image dir), the media settings, and one or more embedding models from the registry (potion, clip-vit-b32, siglip2, wemm-2b, ...). Each model becomes a named vector space in the same file. The full spec is in usage section 13.

Search
urna search my_corpus.urna "[0.1, 0.2, ...]" -k 10
urna search-ann my_corpus.urna "[0.1, 0.2, ...]" -k 10 --ef 200
urna search-graph my_corpus.urna "[0.1, 0.2, ...]" -k 10 --hops 2 --ef 100
urna search-space my_corpus.urna "[0.1, ...]" --space "wemm-2b@256" -k 5
urna search-text my_corpus.urna "vacina contra covid funciona" -k 5
Inspect, validate, stats, cite, media, benchmark, doctor
urna inspect my_corpus.urna --json
urna validate my_corpus.urna
urna stats my_corpus.urna
urna cite my_corpus.urna 'urna://sha256:1aa9.../sha256:8f314...'
urna media my_corpus.urna --export DIR
urna benchmark my_corpus.urna -q 100 -k 10 --ann 100 --madvise-cold
urna doctor

Benchmarks

100,000 x 384 rows, k=10, one thread, same machine for every store.

Store p50 (ms) p99 (ms) Cold open (ms)
hnswlib 0.32 0.53 182
usearch 0.67 61.4 58
urna hybrid 0.72 1.02 356
urna exact 7.80 8.32 292
lancedb 16.7 19.4 612
sqlite-vec 19.8 24.8 50

Both urna rows return recall@10 = 1.000. Urna's cold open includes checking every section hash before the first answer. Urna does not do updates, filters or concurrent writers. Method and the full table: docs/benchmarks.md.

Presets: size vs recall
Preset Embeddings Index Size Recall@10
exact float32 1.000 1.000
compressed float16 0.339 1.000
tiny int8 hnsw 0.256 0.992
micro mrl256-int8 hnsw 0.223 0.810
nano int4 hnsw 0.209 0.913
hybrid float32 hnsw + bm25 0.609 1.000

Measured on a 30,725-chunk pt-br corpus. Recall here is rank stability under quantization, not real-query quality. Details in usage section 6.

Images: 38,627 magic cards in one file
Profile Media File Vs the jpeg source
archive JPEG XL, byte-reversible 3.61 GB 1.10x
stills AV1 all-intra crf35 1.37 GB 2.89x
retrieval AV1 all-intra crf50 533 MB 7.46x

Text-to-image hit@1 over every card: siglip2 0.750, wemm-2b 0.744, jina 0.336, clip 0.098. Code and data: mtg-urna-benchmark.

Reference

The crates are urna-format (the container), urna-runtime (search), urna-cli (the binary) and urna-python (the bridge).

License

MIT, see docs/LICENSE. Hoff Research

Made it simple, but significant (∂μfμν = jν)

Author: brenner cruvinel

Release files for urna 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for urna 0.5.0
File
urna-0.5.0-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
urna-0.5.0-cp312-abi3-manylinux_2_34_x86_64.whl CPython 3.12 abi3 Linux glibc 2.34+ x86-64 Details
urna-0.5.0-cp312-abi3-manylinux_2_34_aarch64.whl CPython 3.12 abi3 Linux glibc 2.34+ ARM64 Details
urna-0.5.0-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.12 abi3 macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 Details

Total release size: 117.8 MB

Release files / urna-0.5.0-cp312-abi3-win_amd64.whl

Download URL urna-0.5.0-cp312-abi3-win_amd64.whl
Size 29.1 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
0574f0b64edd4b847579e2342cbdea813fb6386863fc623367dcce51377d8c35
BLAKE2b-256 checksum
How to use checksums
919f83d261a33438513c6a06904c6bc43ea5182d848e0cb36491f212daeca586
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / urna-0.5.0-cp312-abi3-manylinux_2_34_x86_64.whl

Download URL urna-0.5.0-cp312-abi3-manylinux_2_34_x86_64.whl
Size 29.4 MB
Tags CPython 3.12 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
42d19f5e82d4caacf1f0c4615cda1141f0653bea1a6b179b3ab9599723f81390
BLAKE2b-256 checksum
How to use checksums
bc0d8cc38b4ece6a410b1916762d8f2d328762e25831cc1b57975d7581ec136f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / urna-0.5.0-cp312-abi3-manylinux_2_34_aarch64.whl

Download URL urna-0.5.0-cp312-abi3-manylinux_2_34_aarch64.whl
Size 29.3 MB
Tags CPython 3.12 Linux glibc 2.34+ ARM64 abi3
SHA-256 checksum
How to use checksums
cf2cb2312ec0e75a2b51384e4a6f0983082348b997de92941c0878b1bb059155
BLAKE2b-256 checksum
How to use checksums
4c9837c2be999e82730ce24205e4222d2759bd31db50687b044b49355be3857c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / urna-0.5.0-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL urna-0.5.0-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 30.0 MB
Tags CPython 3.12 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
229ce9c9458397ed055fe2884fc6aa0436b2ce2a524dffc279922b2f474a0b38
BLAKE2b-256 checksum
How to use checksums
f8c236730b121f32869dedcd7f8e1607932f42a6dd3fba6aff20899594f99f3d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

0.5.0 This release

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page