El problema fundamental que LatticeDB aborda es la fragmentación de datos y la complejidad operativa al intentar combinar diferentes paradigmas de búsqueda (relacional, semántico, lexical) sobre el mismo conjunto de datos en aplicaciones locales. Tradicionalmente, esto requeriría la integración de múltiples bases de datos o motores de búsqueda (ej., una base de datos de grafos, un índice vectorial, un motor de FTS), cada uno con su propio modelo de datos, capa de consulta y sobrecarga operativa.
LatticeDB emerge como una solución a esta complejidad, consolidando estas capacidades en un único motor embebido y un solo archivo. Esto simplifica drásticamente el desarrollo y despliegue para casos de uso que requieren una comprensión rica y conectada de los datos, como sistemas de memoria de agentes, herramientas de conocimiento local o pipelines de Retrieval Augmented Generation (RAG) que operan en un entorno de "local-first". La convergencia de grafos, vectores y texto en una única capa de consulta reduce la latencia de integración y la sobrecarga de gestión, haciendo que la manipulación de datos complejos sea más accesible para aplicaciones de una sola máquina.
Arquitectura del Sistema
LatticeDB se implementa como una base de datos embebida de un solo archivo, escrita en Zig, sin dependencias externas. Su arquitectura se basa en un modelo de escritor único con durabilidad garantizada por un Write-Ahead Log (WAL) para recuperación ante fallos. El almacenamiento subyacente para los nodos y propiedades del grafo utiliza una estructura B+Tree para búsquedas rápidas de nodos y propiedades, logrando latencias de lookup de 0.13 μs.
Para la búsqueda de similitud vectorial, LatticeDB integra el algoritmo Hierarchical Navigable Small World (HNSW), una estructura de índice de aproximación de vecinos más cercanos (ANN) que permite búsquedas eficientes en espacios de alta dimensión. El índice HNSW se configura con parámetros como M (número máximo de conexiones salientes por nodo) y ef_construction/ef_search (parámetros de calidad de búsqueda y construcción), optimizado para la distancia coseno. La búsqueda de texto completo se implementa con un índice invertido que utiliza el algoritmo BM25 para la clasificación de relevancia, incluyendo tokenización y stemming. La capa de consulta unificada soporta una variante del lenguaje Cypher, extendida con operadores para distancia vectorial (<=>) y búsqueda de texto completo (@@). Además, LatticeDB ofrece "durable named streams" y "graph changefeeds" que comparten la misma ruta de transacción/WAL que las escrituras del grafo, permitiendo el consumo de eventos y cambios del grafo desde el mismo archivo.
Flujo de Ingestión y Consulta de Datos
- 1 Crear Nodos/Edges Aplicación crea nodos y aristas con propiedades y etiquetas.
- 2 Generar Embeddings Texto de propiedades se convierte en vectores (hash_embed o modelo externo).
- 3 Indexar Vectores Vectores se insertan en el índice HNSW para búsqueda de similitud.
- 4 Indexar Texto Texto se indexa en el índice invertido para búsqueda FTS (BM25).
- 5 Escribir WAL Todas las operaciones se registran en el Write-Ahead Log para durabilidad.
- 6 Ejecutar Consulta Consulta Cypher combina traversal de grafo, búsqueda vectorial y FTS.
- 7 Devolver Resultados Resultados consolidados de los diferentes modos de búsqueda.
| Capa | Tecnología | Justificación |
|---|---|---|
| storage | B+Tree | Almacenamiento primario para nodos, aristas y propiedades, optimizado para búsquedas rápidas y acceso a disco. vs LSM-tree (para cargas de escritura muy intensivas) |
| data-processing | HNSW (Hierarchical Navigable Small World) | Índice para búsqueda de similitud de vectores (Approximate Nearest Neighbor), permitiendo búsquedas rápidas en espacios de alta dimensión. vs Annoy, FAISS (IVF-flat, PQ) M=16, ef_construction=200, ef_search=64, k=10 para recall@10 |
| data-processing | BM25 (Best Match 25) | Algoritmo de clasificación de relevancia para búsqueda de texto completo, utilizado sobre un índice invertido. vs TF-IDF, Okapi BM15 |
| storage | Write-Ahead Log (WAL) | Mecanismo de durabilidad y recuperación ante fallos, asegurando la integridad de las transacciones. vs Shadow Paging |
| messaging | Durable Named Streams / Graph Changefeeds | Proporciona un mecanismo para consumir eventos y cambios del grafo de forma duradera, compartiendo la ruta del WAL. vs Kafka (para sistemas distribuidos) |
Trade-offs
Ganancias
- ▲ Simplicidad Operacional
- ▲ Rendimiento en Búsquedas Combinadas
- ▲ Huella de Memoria para Vectores
- ▲▲ Latencia de Búsqueda de Nodos
- ▲▲ Latencia de Traversal de Grafos
Costes
- ▲ Escalabilidad Horizontal (Multi-nodo)
- ▲ Concurrencia de Escritura (Multi-proceso)
- △ Funcionalidad Completa de Cypher
- ▲ Ecosistema y Herramientas Maduras
from latticedb import Database
from latticedb.embedding import hash_embed
with Database("knowledge.db", create=True, enable_vectors=True, vector_dimensions=128) as db:
with db.write() as txn:
alice = txn.create_node(labels=["Person"], properties={"name": "Alice", "field": "ML"})
doc = txn.create_node(labels=["Document"], properties={"title": "Attention Is All You Need"})
chunk = txn.create_node(labels=["Chunk"], properties={"text": "The transformer architecture uses self-attention..."})
txn.set_vector(chunk.id, "embedding", hash_embed(chunk.properties["text"], dimensions=128))
txn.fts_index(chunk.id, chunk.properties["text"])
txn.create_edge(chunk.id, doc.id, "PART_OF")
txn.create_edge(doc.id, alice.id, "AUTHORED_BY")
txn.commit()MATCH (chunk:Chunk)-[:PART_OF]->(doc:Document)-[:AUTHORED_BY]->(author:Person)
WHERE chunk.embedding <=> $query < 0.5
AND doc.content @@ "neural networks"
RETURN doc.title, chunk.text, author.name
ORDER BY chunk.embedding <=> $query
LIMIT 5Fundamentos Teóricos
La integración de múltiples paradigmas de búsqueda en un solo sistema tiene raíces en la investigación de bases de datos federadas y sistemas de información heterogéneos, donde el desafío es unificar el acceso a datos almacenados en diferentes formatos y modelos. Sin embargo, la aproximación de LatticeDB es más cercana a la de un sistema de almacenamiento políglota dentro de un único motor, un concepto que ha ganado tracción con la evolución de las bases de datos NoSQL.
El uso de B+Trees como estructura de índice primaria para datos de grafos se remonta a los fundamentos de las bases de datos relacionales y de objetos, optimizando el acceso a disco y la gestión de la memoria. El algoritmo HNSW para la búsqueda vectorial fue introducido por Yury Malkov y Dmitry Yashunin en su paper "Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs" (2016), que revolucionó la eficiencia de la búsqueda ANN. El algoritmo BM25 para la búsqueda de texto completo es una función de clasificación clásica en recuperación de información, derivada del modelo de probabilidad binaria, y ha sido un estándar de facto desde su introducción en la década de 1990 por Stephen Robertson y Karen Spärck Jones. La combinación de estos algoritmos bien establecidos en un motor embebido demuestra una aplicación práctica de principios académicos para resolver problemas de ingeniería contemporáneos.