Toda la base de conocimiento en un archivo

Urna guarda texto, imágenes y referencias, ya convertidos en vectores, dentro de un único .urna. Tu app copia ese archivo y responde preguntas citando la fuente, sin servidor, sin internet y sin clave de API.
v0.5.1 · código abierto bajo MIT · Rust + Python
.csv
.jsonl
.sqlite
.jpg
Island
Basic Land · Island
corpus/
01001001 01110011 01101100 01100001 01101110 01100100IslandBasic Land · Island256 números por chunk, de potion
corpus.toml
[source] kind = "sqlite"
[[models]] preset = "potion"
[[models]] preset = "clip-vit-b32"
Island
JPEGAV1
Basic Land · Island
JPEGAV1
103 kB → 13 kBpromedio por cartaJPEG, fuente · AV1, en el archivo
drift p50 0,961
escaneos de cartas4 GB
.urna533 MB
más chico
100 % del exact61 % del exact34 % del exact26 % del exact21 % del exact
model_hashclip-vit-b32
HNSW + BM25 → cosine
Island
Forest
Mountain
p50, texto a imagen
Island
Basic Land · Island
urna validateheaderseccionesarchivocontenido
El runtime nunca abre un socket

Una carpeta y unas pocas líneas de TOML se vuelven un solo .urna: chunks, vectores, índice, medios y manifest, cada sección firmada.

Los escaneos de las cartas entran al archivo en AV1 y los vectores pasan a un preset más chico. El archivo se achica, la cita sigue igual.

El gate de model_hash revisa el modelo, HNSW recorre el grafo, BM25 encuentra la palabra y el coseno exacto define el orden.

La respuesta trae la cita de vuelta hasta la fuente, y urna validate revisa cada capa antes de la primera consulta, sin red.

cómo funciona

De una carpeta de documentos
a un archivo que responde

1
Reúne las fuentes
Texto, PDFs, hojas de cálculo, imágenes. Describes de dónde viene cada cosa y qué modelo la va a leer, en un TOML de pocas líneas.
2
Genera el .urna
Una llamada hace el resto: urna.build en Python, o urna build --spec desde un checkout del repo. Divide en fragmentos, calcula los vectores, construye los índices y firma cada sección con SHA-256. El resultado es un único archivo, idéntico byte a byte en cualquier máquina.
3
Pregunta desde dentro de la app
El runtime de Rust abre el archivo con mmap y devuelve los fragmentos más cercanos, cada uno con una cita urna:// que lleva de vuelta al texto original.
Abierto a auditoría, como debería serlo toda base de datos
Autocontenido, verificable, reproducible, offline.
El archivo es toda la base de datos
Fragmentos, vectores, índices, medios y manifiesto en el mismo .urna. Cópialo como copiarías un archivo SQLite, versiónalo en git, inclúyelo en el instalador. No hay ningún servicio que levantar ni ningún índice que mantener sincronizado.
Cada respuesta apunta a un fragmento que puedes verificar
Cada sección tiene su SHA-256, y también el archivo entero y el contenido decodificado. La cita urna://content_hash/chunk_id sigue siendo la misma después de comprimir el texto, y urna cite la resuelve al fragmento guardado.
Offline, sin excepciones
El runtime nunca abre un socket. El modelo de texto por defecto viene en el paquete de Python, o urna setup lo descarga una vez al instalar. Si el modelo de la consulta no coincide con el del archivo, la búsqueda se detiene en el acto en lugar de devolver basura disfrazada de respuesta.
en la práctica

Benchmark público, la misma vara

urna frente a usearch, hnswlib, sqlite-vec y lancedb, en la misma máquina, con los datos y el comando para reproducirlo
0,72 ms
p50
1,02 ms
p99
recall 1,0
0,72 ms por consulta, recall 1,0
100.000 vectores de 384 dimensiones, 200 consultas, un hilo. El preset hybrid respondió con un p50 de 0,72 ms y un p99 de 1,02 ms. Es el único de la tabla que verifica sus propios bytes antes de la primera consulta; eso cuesta unos 360 ms al abrir.
Ver en la documentación: 0,72 ms por consulta, recall 1,0
38.000 cartas de Magic en 533 MB
4 GB de escaneos JPEG se convirtieron en un archivo 7,46 veces más pequeño, con texto, vectores, índice y las imágenes AV1 dentro, y la búsqueda encuentra la carta tantas veces como en el archivo lossless.
Ver en la documentación: 38.000 cartas de Magic en 533 MB
30.725
fragmentos
7
datasets
FakeRecogna11,9 mil
Fake.br7,2 mil
FakeTrue.Br3,6 mil
factck-br1,3 mil
30.000 fragmentos de verificación de datos
truw puntúa afirmaciones en portugués contra siete datasets públicos de fake news. El corpus es un .urna de 30.725 fragmentos: 120 MB con el preset exact, 31 MB con tiny.
Ver en la documentación: 30.000 fragmentos de verificación de datos

Benchmark del 2026-09-10 en arm64, un solo hilo. Lo que Urna no hace: update y delete in situ, filtros por metadatos, escrituras concurrentes. Ver la tabla completa.

benchmarks

Los benchmarks de urna

Mide compresión, búsqueda y latencia sobre las 38.627 cartas de Magic (3,98 GB de JPEG) guardadas en un archivo .urna, y compara urna con usearch, hnswlib, sqlite-vec y lancedb sobre los mismos vectores y en la misma máquina

Compresión frente a búsqueda por nombre

7 archivos · 1000 consultas cada uno
índice de compresión sin pérdida de búsqueda7,46x

veces más pequeño que los 3,98 GB de JPEG de origen. El archivo en crf50 pesa 533 MB y encuentra la carta por nombre tantas veces como el lossless de 3,61 GB: txt@1 a +0,001, dentro del error estándar.

lossless · 3,61 GB
neardup · 1,37 GB
crf50 · 533 MB

Qué mide esta métrica

txt@1 es la fracción de las 1000 consultas en las que la carta correcta salió en primer lugar. La consulta es el nombre de la carta como texto ("artwork of the card {name}"), buscado en el espacio de imagen de clip: el modelo solo ve el arte, por eso el nivel es bajo en todos los archivos; lo que importa es dónde cae.

drift es el coseno entre el vector de la imagen comprimida y el de la original: 1,00 es idéntico, y cuanto más bajo, más cambió el codec lo que ve el modelo. El peor decil (p10) es la carta en el borde del 10 % que más cambió; la mediana (p50) es la carta del medio.

Cómo leer este gráfico

Cada columna es un archivo con las mismas 38.627 cartas, del lossless (3,61 GB) al AV1 en crf60 (230 MB), en orden de compresión.

Arriba, las dos líneas de drift bajan todo el tiempo y cruzan el floor del gate ya en el segundo archivo. Abajo, la búsqueda se mantiene plana hasta crf50: las barras verdes están dentro de un error estándar del lossless; la línea discontinua marca dónde cae la búsqueda, y las barras rojas son los archivos que quedan más allá.

archivotamañodrift p10txt@1±1 error estándarz vs lossless
lossless3,61 GB0,99680,0920,00910,00
neardup1,37 GB0,96660,0960,00930,31
avif q481,2 GB0,96800,0960,00930,31
crf40981 MB0,95940,0890,0090-0,23
crf50533 MB0,93890,0930,00920,08
crf55370 MB0,92110,0740,0083-1,46
crf60230 MB0,88660,0690,0080-1,89

1000 consultas por archivo, las mismas cartas en todos; error estándar binomial; z es la distancia del txt@1 de cada archivo al del lossless en errores estándar combinados: hasta crf50, ninguno pasa de 1.

medido el 2026-09-12 · benchmark/experiments/14-utility-ladder/results.json

presets
Elige el tamaño. El contenido es el mismo
Cinco presets combinan compresión del texto, precisión de los vectores e índices, más micro, que recorta dimensiones. Tres aquí, todos en la documentación
Para preguntas con siglas, nombres propios, términos raros:
Texto comprimido con zstd
Vectores en float32
HNSW + BM25 como candidatos
Rerank por coseno exacto
Ver el preset
Medido en 30.725 fragmentos. Aquí el recall mide cuán estable se mantiene el ranking bajo cuantización, no el acierto en preguntas reales. Ver los cinco presets y micro.
integración
Se instala con un comando. Se integra en cinco líneas
Un binario de Rust con tres grupos de verbos (engine, agent, setup) y una API de Python. Tras la instalación, todo lo de abajo funciona sin red
$
Instala
instalador
$
Construye
urna build
$
Pregunta
urna ask
El instalador verifica el SHA-256 antes de escribir. urna setup descarga una vez el embedder offline y termina en urna doctor, que te dice qué capa falló, si es que falló alguna.
curl -sSf https://raw.githubusercontent.com/hoffresearch/urna/main/scripts/install.sh | sh urna setup
Fuentes, medios y modelo en un TOML, desde un checkout del repo. La misma especificación genera la misma base en cualquier máquina.
urna build --spec corpus.toml
Fragmentos citados, directo en la terminal.
urna ask corpus.urna "¿funciona sin conexión?" -k 3
JSONL con fragmento, fuente, puntuación y cita, listo para tu app o tu agente.
urna retrieve corpus.urna "¿funciona sin conexión?" -k 5 --format jsonl
Abre con mmap y devuelve resultados citados. El model_hash esperado frena un modelo equivocado antes de la búsqueda.
import urna from urna.embed_potion import potion_embedder emb, db = potion_embedder(), urna.open("corpus.urna") qvec = emb.embed_texts(["¿funciona sin conexión?"])[0] hits = db.retrieve(qvec, 5, expected_model_hash=emb.model_hash())
Todos los checksums antes de distribuir: cabecera, secciones, archivo, contenido.
urna validate corpus.urna
De la cita de vuelta al texto guardado, con los hashes que lo prueban.
urna cite corpus.urna "urna://content_hash/chunk_id"
Latencia y recall en tu máquina, con tu corpus.
urna benchmark corpus.urna -q 100 -k 10 --ann 100
canales

Una release, todos los gestores de paquetes

El mismo urna 0.5.1 en crates.io, PyPI, npm y Homebrew, con un checksum y una attestation junto a cada archivo
El mismo binario en todas partes
cargo, pip, npm, bun, pnpm, yarn, brew, el one-liner de curl y PowerShell instalan el mismo build: macOS y Linux en arm64 y x86_64, Windows en x86_64. npx y uvx lo ejecutan sin instalar nada.
Ver en la documentación: El mismo binario en todas partes
tar.xz
zip
sha256
sigstore
SBOM
ssh tag
Una release que se puede verificar
Cada archivo trae su propio .sha256 y una attestation de sigstore que gh attestation verify comprueba, además de un SBOM CycloneDX y binarios compilados con cargo-auditable. Las tags de release van firmadas con ssh.
Ver en la documentación: Una release que se puede verificar
Dentro de tu app, sin la CLI
urna-format y urna-runtime están en crates.io para Rust, y el paquete de Python abre el mismo archivo. El repo tiene ejemplos de fastapi, flask y jupyter y un Dockerfile, y cargo install urna --no-default-features deja una CLI solo de engine de 2,1 MB.
Ver en la documentación: Dentro de tu app, sin la CLI
Sin instalarnpx @urna/cli validate corpus.urnauvx --from urna urna validate corpus.urnacargo binstall urna
en la terminal

Tres grupos de verbos y una pantalla para usarlos

urna tui abre un .urna, le hace preguntas y revisa la instalación sin salir de la terminal. urna setup muestra el plan antes de escribir nada y termina en los checks de doctor
urna tui en la pestaña ask: diez resultados citados para una pregunta, el texto guardado del seleccionado y su cita
urna tui
urna setup en el paso verify, con todos los checks en verde
urna setup
engine

Entra un archivo y un vector, salen resultados. Sin Python.

  • inspect
  • validate
  • stats
  • media
  • search
  • search-ann
  • search-graph
  • search-space
  • search-text
  • benchmark
  • cite
  • doctor
agent

Entra texto o un spec, salen respuestas citadas, con el embedder offline de Python.

  • ask
  • retrieve
  • build
setup

El instalador en el que termina todo canal, y el explorador de la terminal.

  • setup
  • tui
Antes de empezar
Las dudas más comunes en una primera lectura. El resto está en la documentación, con comando y salida
Leer la documentación

Tu base de conocimiento, lista para viajar

Instala, construye el corpus, copia el archivo en la app. El resto es mmap
Instalar
v0.5.1 · MIT · macOS, Linux y Windows