Bases de Datos Vectoriales
Qué Hacen las Bases de Datos Vectoriales
Una base de datos vectorial es un almacén de datos especializado optimizado para almacenar, indexar y consultar vectores de alta dimensionalidad. En un sistema RAG, contiene los embeddings de tus fragmentos de documentos y te permite encontrar rápidamente los fragmentos más similares a un embedding de consulta.
Las bases de datos regulares están diseñadas para coincidencias exactas: dame la fila donde id = 42 o donde nombre = 'Alice'. Las bases de datos vectoriales resuelven un problema fundamentalmente diferente: dame los 10 vectores más cercanos a este vector de consulta en un espacio con cientos o miles de dimensiones. Esto se llama búsqueda de Vecino Más Cercano Aproximado (ANN), y requiere algoritmos de indexación especializados para realizarla rápidamente.
Una base de datos vectorial típica almacena tres cosas por entrada:
- El vector -- el embedding en sí (e.g., 1536 flotantes)
- Los metadatos -- campos estructurados como fuente, fecha, autor o categoría
- El texto del documento -- el fragmento original de texto que fue embebido
Cuando consultas, envías un vector y recibes las top-K entradas más similares, cada una con sus metadatos y texto.
El Panorama: Eligiendo la Base de Datos Correcta
FAISS (Facebook AI Similarity Search)
FAISS es una biblioteca, no una base de datos. Desarrollada por Meta, proporciona algoritmos de búsqueda de similitud altamente optimizados que se ejecutan en memoria. Es extremadamente rápido -- a menudo la opción más rápida para conjuntos de datos de menos de 10 millones de vectores.
Mejor para: Desarrollo local, prototipado, aplicaciones donde todos los datos caben en memoria, pipelines de procesamiento por lotes.
Limitaciones: Sin persistencia incorporada (guardas/cargas archivos de índice manualmente), sin filtrado de metadatos, sin servidor API incorporado, sin autenticación. Tienes que construir todo alrededor.
import faiss
import numpy as np
# Crear un indice para vectores de 1536 dimensiones
dimension = 1536
index = faiss.IndexFlatL2(dimension) # Busqueda exacta con distancia L2
# Agregar vectores
vectors = np.random.rand(1000, dimension).astype('float32')
index.add(vectors)
# Buscar 5 vecinos mas cercanos
query = np.random.rand(1, dimension).astype('float32')
distances, indices = index.search(query, k=5)
print(f"Indices mas cercanos: {indices[0]}")
print(f"Distancias: {distances[0]}")
# Guardar y cargar el indice
faiss.write_index(index, "my_index.faiss")
loaded_index = faiss.read_index("my_index.faiss")
ChromaDB
ChromaDB es una base de datos de embeddings de código abierto diseñada específicamente para aplicaciones de IA. Tiene una API limpia en Python, maneja la persistencia automáticamente, soporta filtrado de metadatos e incluye una función de embedding incorporada para que puedas pasar texto sin procesar en lugar de vectores pre-calculados.
Mejor para: Prototipado, conjuntos de datos pequeños a medianos (hasta unos pocos millones de documentos), proyectos donde la experiencia del desarrollador importa, aprendizaje de conceptos RAG.
Limitaciones: No diseñado para escala masiva (miles de millones de vectores), lenguaje de consulta limitado comparado con bases de datos completas.
import chromadb
# Crear un cliente persistente
client = chromadb.PersistentClient(path="./chroma_db")
# Crear una coleccion (como una tabla)
collection = client.get_or_create_collection(
name="documents",
metadata={"hnsw:space": "cosine"} # Usar similitud coseno
)
# Agregar documentos con metadatos
collection.add(
documents=[
"La fotosintesis convierte la energia luminosa en energia quimica.",
"La mitocondria es la central energetica de la celula.",
"Las redes neuronales estan inspiradas en neuronas biologicas.",
],
metadatas=[
{"source": "libro_biologia", "chapter": 5},
{"source": "libro_biologia", "chapter": 3},
{"source": "libro_informatica", "chapter": 12},
],
ids=["doc1", "doc2", "doc3"]
)
# Consultar con lenguaje natural
results = collection.query(
query_texts=["Como crean energia las plantas?"],
n_results=2,
where={"source": "libro_biologia"} # Filtro de metadatos
)
print(results["documents"])
print(results["distances"])
Pinecone
Pinecone es un servicio de base de datos vectorial completamente gestionado. No ejecutas ninguna infraestructura -- creas un índice a través de su API y Pinecone maneja almacenamiento, indexación, escalado y disponibilidad.
Mejor para: Despliegues en producción, equipos que no quieren gestionar infraestructura, aplicaciones que requieren alta disponibilidad y escalado.
Limitaciones: Dependencia de proveedor, costos recurrentes, los datos salen de tu infraestructura, la latencia depende de la red (aunque ofrecen despliegues regionales).
pgvector
pgvector es una extensión de PostgreSQL que agrega búsqueda de similitud vectorial a tu base de datos PostgreSQL existente. Si ya usas PostgreSQL, esta es una opción convincente porque mantienes tus vectores junto a tus datos relacionales.
Mejor para: Equipos que ya usan PostgreSQL, aplicaciones que necesitan JOINs SQL entre resultados vectoriales y datos relacionales, requisitos de infraestructura más simples.
Limitaciones: El rendimiento está por debajo de las bases de datos vectoriales dedicadas a muy alta escala. Las opciones de indexación son más limitadas.
Weaviate
Weaviate es una base de datos vectorial de código abierto con una API GraphQL, módulos incorporados para generación de embeddings y búsqueda híbrida (combinando búsqueda vectorial y por palabras clave en una sola consulta).
Mejor para: Equipos que quieren búsqueda híbrida lista para usar, arquitecturas orientadas a GraphQL, aplicaciones que necesitan soporte multimodal incorporado.
Qdrant
Qdrant es una base de datos vectorial de código abierto escrita en Rust, con énfasis en rendimiento y APIs con tipado seguro. Tiene excelentes capacidades de filtrado y soporta almacenamiento tanto en memoria como en disco.
Mejor para: Aplicaciones críticas en rendimiento, equipos que necesitan filtrado avanzado, ecosistemas Rust o gRPC.
Resumen Comparativo
| Característica | FAISS | ChromaDB | Pinecone | pgvector | Qdrant | |----------------|-------|----------|----------|----------|--------| | Tipo | Biblioteca | Base de datos | Gestionado | Extensión | Base de datos | | Persistencia | Manual | Incorporada | Gestionada | PostgreSQL | Incorporada | | Filtrado de metadatos | No | Sí | Sí | SQL | Sí | | Hosting gestionado | No | No | Sí | Vía proveedores | Opción cloud | | Búsqueda híbrida | No | No | Sí | Con tsvector | Sí | | Mejor escala | Millones | Millones | Miles de millones | Millones | Miles de millones | | Curva de aprendizaje | Media | Baja | Baja | Baja (si sabes SQL) | Media |
Estrategias de Indexación
Cuando tu conjunto de datos crece más allá de decenas de miles de vectores, la búsqueda exacta de vecinos más cercanos (comparar la consulta con cada vector almacenado) se vuelve demasiado lenta. Las bases de datos vectoriales usan algoritmos aproximados para intercambiar una pequeña cantidad de precisión por mejoras masivas de velocidad.
HNSW (Hierarchical Navigable Small World)
HNSW es el algoritmo de indexación más popular y el predeterminado en ChromaDB, Qdrant y pgvector. Construye un grafo multicapa donde cada nodo es un vector. La búsqueda comienza en la capa superior (gruesa) y navega hacia capas más finas.
- Velocidad de búsqueda: Excelente (sub-milisegundo para millones de vectores)
- Tiempo de construcción del índice: Moderado
- Memoria: Alta (la estructura del grafo vive en memoria)
- Precisión: Muy alta (típicamente 95-99% de recall)
Parámetros clave:
M-- número de conexiones por nodo (mayor = mejor recall, más memoria)ef_construction-- amplitud del haz durante la construcción del índice (mayor = mejor recall, construcción más lenta)ef_search-- amplitud del haz durante la búsqueda (mayor = mejor recall, búsqueda más lenta)
IVF (Inverted File Index)
IVF particiona el espacio vectorial en clusters usando k-means. En tiempo de consulta, solo busca los clusters más cercanos al vector de consulta. Este es el enfoque predeterminado de FAISS para búsqueda a gran escala.
- Velocidad de búsqueda: Buena (depende del parámetro nprobe)
- Tiempo de construcción del índice: Rápido
- Memoria: Menor que HNSW
- Precisión: Buena (depende del número de clusters y nprobe)
import faiss
import numpy as np
dimension = 1536
n_vectors = 100000
# Crear indice IVF con 100 clusters
quantizer = faiss.IndexFlatL2(dimension)
index = faiss.IndexIVFFlat(quantizer, dimension, 100)
# Entrenar el indice (IVF requiere entrenamiento con datos de muestra)
training_data = np.random.rand(n_vectors, dimension).astype('float32')
index.train(training_data)
index.add(training_data)
# Buscar -- nprobe controla el tradeoff entre precision y velocidad
index.nprobe = 10 # Buscar en los 10 clusters mas cercanos
query = np.random.rand(1, dimension).astype('float32')
distances, indices = index.search(query, k=5)
Cuándo Usar Cuál Base de Datos
Recién comenzando o aprendiendo: ChromaDB. La API es intuitiva, la persistencia es automática y puedes pasar de cero a buscar en cinco minutos.
Necesitas máximo rendimiento local: FAISS. Nada lo supera en velocidad pura en una sola máquina. Combínalo con un almacén de metadatos simple si necesitas filtrado.
Yendo a producción con un equipo: Pinecone si quieres cero gestión de infraestructura. Qdrant si quieres autoalojar con excelente rendimiento. Weaviate si necesitas búsqueda híbrida y GraphQL.
Ya usas PostgreSQL: pgvector. Mantener todo en una sola base de datos simplifica tu arquitectura enormemente, y el rendimiento es suficiente para la mayoría de las cargas de trabajo hasta unos pocos millones de vectores.
Consejo: Comienza con ChromaDB para desarrollo, luego migra a tu base de datos de producción una vez que tus requisitos estén claros. Los cambios en el código de recuperación son mínimos -- generalmente solo cambiar la inicialización del cliente y ajustar la sintaxis de consulta.
En la siguiente lección, aprenderás cómo meter tus documentos en estas bases de datos procesándolos y preparándolos para embedding.