El problema fundamental que TurboQuant aborda es la indexación eficiente y de baja latencia de vectores de alta dimensionalidad para la búsqueda de vecinos más cercanos aproximados (ANN), un componente crítico en sistemas de Recuperación Aumentada por Generación (RAG) y otras aplicaciones de IA. La explosión de modelos de embeddings ha generado la necesidad de almacenar y buscar eficientemente millones o miles de millones de vectores, que tradicionalmente consumen grandes cantidades de memoria y requieren fases de entrenamiento complejas y costosas computacionalmente. TurboQuant resuelve esto mediante una cuantificación vectorial 'data-oblivious' que no requiere entrenamiento, reduciendo drásticamente el consumo de memoria y mejorando la velocidad de búsqueda e ingestión.

La relevancia actual radica en la creciente demanda de sistemas RAG que operen con restricciones estrictas de privacidad, memoria o latencia. Las soluciones existentes como FAISS, aunque potentes, a menudo implican compromisos en estos frentes, especialmente en entornos de edge computing o en arquitecturas donde la transferencia de datos es costosa. TurboQuant ofrece una alternativa que permite un stack RAG completamente 'air-gapped' y local, sin sacrificar rendimiento.

Arquitectura del Sistema

TurboQuant se basa en una arquitectura que comprime vectores de alta dimensionalidad mediante una serie de transformaciones y cuantificación escalar. Primero, los vectores se normalizan para convertirlos en direcciones unitarias en una hiperesfera, almacenando su norma por separado. Luego, se aplica una rotación ortogonal aleatoria a todos los vectores, lo que transforma la distribución de cada coordenada a una Beta conocida, independientemente de los datos de entrada. Esta propiedad es clave para la naturaleza 'data-oblivious' del algoritmo.

Posteriormente, se realiza una cuantificación escalar Lloyd-Max sobre cada coordenada. Dado que la distribución de las coordenadas es conocida (Beta), los límites de los buckets y los centroides óptimos se precalculan matemáticamente, no a partir de los datos. Esto permite empaquetar cada coordenada en un entero pequeño (2 o 4 bits), logrando una compresión significativa (ej., 16x para vectores de 1536 dimensiones a 2 bits). Para mitigar el subestimado sistemático de los productos internos debido a la cuantificación, se aplica una renormalización de longitud por vector, almacenando un escalar que corrige el sesgo del estimador del producto interno durante la búsqueda. La búsqueda se realiza rotando la consulta una vez y puntuando directamente contra los valores del codebook utilizando intrínsecos SIMD (NEON en ARM, AVX-512 VNNI en x86) para maximizar el throughput. La ingestión es online e incremental, con persistencia crash-safe mediante fsync y atomic rename para cambios incrementales.

Flujo de Ingestión y Cuantificación de Vectores

  1. 1 Vector Original Vector de entrada float32 de alta dimensionalidad (ej. 1536 dim)
  2. 2 Normalización El vector se convierte en unitario; su norma se almacena por separado.
  3. 3 Rotación Aleatoria Multiplicación por una matriz ortogonal aleatoria predefinida.
  4. 4 Calibración (Opcional) Ajuste de shift/scale por coordenada para mapear cuantiles empíricos a centro...
  5. 5 Cuantificación Lloyd-Max Cada coordenada se mapea a un entero pequeño (2 o 4 bits) usando límites prec...
  6. 6 Cálculo de Factor de Renormalización Se calcula ||v|| / ⟨u, x̂⟩ para corregir el sesgo del producto interno.
  7. 7 Bit-Packing Los enteros pequeños se empaquetan eficientemente en bytes.
  8. 8 Almacenamiento Vector comprimido, norma y factor de renormalización se persisten.

Flujo de Búsqueda de Vecinos Más Cercanos

  1. 1 Vector de Consulta Vector de consulta float32 de alta dimensionalidad.
  2. 2 Rotación de Consulta La consulta se rota con la misma matriz ortogonal usada en la ingestión.
  3. 3 Filtrado (Opcional) Aplicación de allowlist de IDs o bitmask en el kernel SIMD.
  4. 4 Puntuación SIMD El kernel SIMD puntúa directamente contra los valores del codebook y los vect...
  5. 5 Renormalización de Puntuación La puntuación se multiplica por el factor de renormalización almacenado.
  6. 6 Inserción en Heap Los resultados se insertan en un min-heap para mantener los k mejores.
  7. 7 Resultados Se devuelven los k vectores más cercanos (puntuaciones e IDs).
CapaTecnologíaJustificación
compute Rust Lenguaje de programación principal para el núcleo de alto rendimiento, aprovechando su seguridad de memoria y control de bajo nivel. vs C++
compute Python Bindings (Maturin) Interfaz para facilitar la integración con el ecosistema de ML/IA de Python, permitiendo su uso en frameworks como LangChain y LlamaIndex. vs PyO3 directamente
compute SIMD Intrinsics (NEON, AVX-512, AVX2) Optimización de kernels de búsqueda para aprovechar el paralelismo a nivel de datos en CPUs modernas, logrando un throughput significativamente mayor. vs OpenMP para paralelismo a nivel de hilo, CUDA para GPUs Compilación para x86-64-v2 como baseline, con selección en tiempo de ejecución de AVX-512/AVX2.
storage Filesystem (fsync, atomic rename) Mecanismo de persistencia incremental y crash-safe para el índice, asegurando durabilidad con baja latencia para pequeñas actualizaciones. vs Base de datos embebida, Almacenamiento en la nube con versionado
data-processing TurboQuant Algorithm Algoritmo de cuantificación vectorial 'data-oblivious' que permite alta compresión y búsqueda eficiente sin fase de entrenamiento. vs Product Quantization (PQ), Locality Sensitive Hashing (LSH), IVF-Flat Bit-width configurable (2-bit, 4-bit) para balancear compresión y recall.

Trade-offs

Ganancias
  • ▲▲ Consumo de memoria
  • Velocidad de búsqueda
  • ▲▲ Velocidad de ingestión (add/remove)
  • Simplicidad operativa (sin entrenamiento)
  • Privacidad y soberanía de datos
Costes
  • Recall (a bajas dimensiones y bit-widths)
  • Complejidad de implementación (SIMD, Rust)
from turbovec import TurboQuantIndex
index = TurboQuantIndex(dim=1536, bit_width=4)
index.add(vectors)
scores, indices = index.search(query, k=10)
Muestra cómo instanciar TurboQuantIndex, añadir vectores y realizar una búsqueda.
from turbovec import IdMapIndex
import numpy as np
index = IdMapIndex(dim=1536, bit_width=4)
index.add_with_ids(vectors, np.array([1001, 1002, 1003], dtype=np.uint64))
scores, ids = index.search(query, k=10)
index.remove(1002)
Demuestra cómo usar IDs externos, añadir vectores con IDs, buscar y eliminar por ID.
from turbovec import IdMapIndex
import numpy as np
idx = IdMapIndex(dim=1536, bit_width=4)
idx.add_with_ids(vectors, ids)
allowed = np.array([1001, 1003], dtype=np.uint64)
scores, ids = idx.search(query, k=10, allowlist=allowed)
Ilustra cómo pasar una lista de IDs permitidos para filtrar resultados directamente en el kernel de búsqueda.

Fundamentos Teóricos

El algoritmo TurboQuant se basa en principios de la teoría de la información y la cuantificación vectorial, específicamente en la minimización de la distorsión. La idea de que, tras una rotación aleatoria, las coordenadas de vectores de alta dimensión siguen una distribución predecible (Beta, convergiendo a Gaussiana) es un resultado fundamental en la teoría de la probabilidad en espacios de alta dimensión. Esto permite el uso de cuantificadores escalares óptimos como el Lloyd-Max, que minimizan el error cuadrático medio para una distribución de probabilidad conocida, un concepto desarrollado por S. P. Lloyd en 1957 y J. Max en 1960.

La técnica de renormalización de longitud por vector para corregir el sesgo del producto interno se inspira en trabajos como 'RaBitQ: Quantizing High-Dimensional Vectors with a Theoretical Error Bound for Approximate Nearest Neighbor Search' (SIGMOD 2024), que aborda la precisión de la estimación del producto interno en espacios cuantificados. La eficiencia de búsqueda SIMD, por su parte, se nutre de técnicas avanzadas de procesamiento vectorial, como las utilizadas en FAISS FastScan, que optimizan las operaciones de búsqueda de tablas de consulta (LUT) y acumuladores para arquitecturas de CPU modernas.