FAISS: búsqueda vectorial de Meta para investigación
Qué cubre este artículo
- Qué es FAISS y por qué es una librería y no una base de datos.
- Qué tipos de índices ofrece FAISS y cómo elegir el correcto.
- Cómo instalar y usar FAISS con Python.
- Cómo el soporte GPU acelera la búsqueda vectorial.
- Dónde se sitúa FAISS comparado con Chroma y Qdrant.
Introducción
FAISS significa Facebook AI Similarity Search y es una librería de Meta para búsqueda vectorial eficiente. A diferencia de Chroma o Qdrant, FAISS no es una base de datos, sino una librería C++ con bindings para Python. No almacena metadatos, no proporciona API REST y no gestiona persistencia de forma automática. A cambio, FAISS es extremadamente rápida y escala a miles de millones de vectores. Este artículo te muestra cómo instalar FAISS, elegir tipos de índices y utilizarla para RAG.
¿Por qué necesito FAISS?
Si tienes que buscar en muchos vectores y necesitas el máximo rendimiento, FAISS es una de las soluciones más rápidas disponibles. Meta desarrolla FAISS para sus propios productos y la optimiza continuamente. En cuanto a soporte GPU, FAISS lidera: puede indexar y buscar vectores en la GPU, lo que reduce drásticamente los tiempos de búsqueda.
FAISS es ideal para investigación, prototipos y aplicaciones donde quieras gestionar la infraestructura por ti mismo. Si buscas una base de datos lista para usar con persistencia, filtrado y API, Chroma o Qdrant te servirán mejor. Pero si necesitas control máximo y velocidad, FAISS es la opción correcta.
FAISS en pocas palabras
FAISS trabaja con índices que almacenan y buscan en vectores. Un índice es un objeto que rellenas con vectores y luego consultas. FAISS ofrece diferentes tipos de índices que realizan distintos compromisos entre velocidad, precisión y memoria. Los más importantes son:
- IndexFlatL2: búsqueda por fuerza bruta con distancia L2. Exacta, pero lenta con grandes volúmenes de datos.
- IndexFlatIP: búsqueda por fuerza bruta con producto interno. Exacta, también lenta con grandes volúmenes.
- IndexIVFFlat: búsqueda basada en clusters. Más rápida que Flat, con ligera pérdida de precisión.
- IndexIVFPQ: basada en clusters con cuantización de producto. Muy eficiente en memoria, mayor pérdida de precisión.
- IndexHNSWFlat: búsqueda basada en grafos. Muy rápida y precisa, mayor uso de memoria.
También puedes combinar índices, por ejemplo IVF con PQ para búsqueda aproximada eficiente en memoria.
Para quién está pensado este artículo
Este artículo va dirigido a desarrolladores e investigadores que necesitan máximo rendimiento en búsqueda vectorial y están dispuestos a asumir más trabajo manual. Deberías tener conocimientos de Python y entender qué son los embeddings. Si eres nuevo en bases de datos vectoriales, empieza por el artículo de descripción general sobre bases de datos vectoriales y el artículo sobre modelos de embedding.
Términos clave
| Término | Significado |
|---|---|
| Index | objeto FAISS que almacena y busca en vectores |
| Flat | búsqueda por fuerza bruta sin aproximación |
| IVF | Inverted File, búsqueda aproximada basada en clusters |
| PQ | Product Quantization, compresión de vectores para ahorrar memoria |
| HNSW | Hierarchical Navigable Small World, búsqueda aproximada basada en grafos |
| GPU Index | índice que se ejecuta en la tarjeta gráfica |
| Recall | proporción de vecinos encontrados correctamente sobre todos los vecinos reales |
| nlist | número de clusters en IVF |
| nprobe | número de clusters a buscar durante una consulta |
Instalación
FAISS para CPU
pip install faiss-cpu
FAISS para GPU
Para soporte GPU necesitas una tarjeta NVIDIA con CUDA:
pip install faiss-gpu
Si quieres compilar FAISS desde el código fuente, encontrarás las instrucciones en el repositorio FAISS de GitHub. Para la mayoría de aplicaciones, la instalación con pip es suficiente.
Primeros pasos
Crear un índice simple
import faiss
import numpy as np
dimension = 768
# Vectores aleatorios para el ejemplo
vectors = np.random.rand(1000, dimension).astype('float32')
# Índice Flat con distancia L2
index = faiss.IndexFlatL2(dimension)
index.add(vectors)
print(f"Vectores en el índice: {index.ntotal}")
# Consulta de búsqueda
query = np.random.rand(1, dimension).astype('float32')
distanzen, indizes = index.search(query, k=5)
print("Índices encontrados:", indizes)
print("Distancias:", distanzen)
FAISS espera vectores como arrays numpy de tipo float32. Asegúrate de que tus embeddings tengan este formato.
Índice IVF con entrenamiento
Los índices IVF deben entrenarse antes de agregar vectores. El entrenamiento determina los centros de los clusters.
import faiss
import numpy as np
dimension = 768
nlist = 100 # Número de clusters
vectors = np.random.rand(10000, dimension).astype('float32')
# Cuantificador como base para IVF
quantizer = faiss.IndexFlatL2(dimension)
# Crear índice IVF
index = faiss.IndexIVFFlat(quantizer, dimension, nlist)
# Entrenar con los vectores
index.train(vectors)
# Agregar vectores
index.add(vectors)
# Establecer parámetros de búsqueda
index.nprobe = 10 # Número de clusters a buscar
# Consulta de búsqueda
query = np.random.rand(1, dimension).astype('float32')
distanzen, indizes = index.search(query, k=5)
print("Índices encontrados:", indizes)
El parámetro nprobe controla el compromiso entre velocidad y precisión. Más nprobe significa resultados más precisos, pero búsqueda más lenta.
Índice HNSW
import faiss
import numpy as np
dimension = 768
vectors = np.random.rand(10000, dimension).astype('float32')
# Índice HNSW
index = faiss.IndexHNSWFlat(dimension, 32)
index.hnsw.efConstruction = 40
index.hnsw.efSearch = 16
index.add(vectors)
query = np.random.rand(1, dimension).astype('float32')
distanzen, indizes = index.search(query, k=5)
print("Índices encontrados:", indizes)
HNSW no requiere entrenamiento. El parámetro M (aquí 32) controla las conexiones del grafo, efConstruction la calidad de construcción y efSearch la precisión de búsqueda.
Usar GPU
import faiss
import numpy as np
dimension = 768
vectors = np.random.rand(100000, dimension).astype('float32')
# Obtener recurso GPU
res = faiss.StandardGpuResources()
# Crear índice CPU y trasladarlo a GPU
cpu_index = faiss.IndexFlatL2(dimension)
gpu_index = faiss.index_cpu_to_gpu(res, 0, cpu_index)
gpu_index.add(vectors)
query = np.random.rand(1, dimension).astype('float32')
distanzen, indizes = gpu_index.search(query, k=5)
print("Índices encontrados:", indizes)
El número 0 en index_cpu_to_gpu es el ID de la GPU. Con múltiples tarjetas gráficas, puedes elegir cuál usar.
Guardar y cargar índices
# Guardar
faiss.write_index(index, "mein_index.faiss")
# Cargar
index = faiss.read_index("mein_index.faiss")
FAISS solo almacena los vectores y la estructura del índice. Los metadatos como textos o fuentes debes gestionarlos por separado, por ejemplo en un archivo JSON o una base de datos SQLite.
Comparativa de tipos de índices
| Tipo de índice | Entrenamiento | Precisión | Velocidad | Memoria | GPU |
|---|---|---|---|---|---|
| IndexFlatL2 | No | Exacta | Lenta | Alta | Sí |
| IndexFlatIP | No | Exacta | Lenta | Alta | Sí |
| IndexIVFFlat | Sí | Alta | Media | Media | Sí |
| IndexIVFPQ | Sí | Media | Rápida | Baja | Sí |
| IndexHNSWFlat | No | Alta | Rápida | Alta | No |
Con conjuntos pequeños de hasta aproximadamente 10.000 vectores, IndexFlatL2 es suficiente. Para volúmenes medios, IVFFlat ofrece un buen equilibrio. Cuando tienes grandes cantidades de datos con restricciones de memoria, IVFPQ es tu mejor opción. HNSW es ideal si necesitas búsquedas rápidas y precisas y dispones de memoria suficiente.
Comparativa con Chroma y Qdrant
| Característica | FAISS | Chroma | Qdrant |
|---|---|---|---|
| Tipo | Biblioteca | Base de datos vectorial | Base de datos vectorial |
| Persistencia | Manual (write_index) | Automática | Automática |
| Metadatos | No | Sí | Sí |
| API | Python/C++ | Python | REST, gRPC, Python |
| Filtrado | No | Simple | Avanzado |
| Soporte GPU | Sí | No | No |
| Escalabilidad | Muy alta | Pequeña a media | Alta |
| Curva de aprendizaje | Alta | Baja | Media |
FAISS es la solución más rápida para búsqueda pura de vectores, especialmente con GPU. Sin embargo, carece de características que ofrecen las bases de datos dedicadas: persistencia, metadatos, filtrado y API. En la práctica, frecuentemente usarás FAISS como motor bajo una capa propia que proporciona estas funcionalidades. Si no quieres construir esa capa, Chroma y Qdrant son mejores alternativas. Para más detalles sobre combinar diferentes métodos de búsqueda, consulta el artículo sobre Hybrid Search.
Errores comunes
- Tipo de dato incorrecto: FAISS espera arrays de
float32. Si pasasfloat64oint, obtendrás errores o problemas silenciosos. Convierte usando.astype('float32'). - Sin entrenamiento en IVF: Los índices IVF deben entrenarse antes de agregar vectores. Si lo olvidas,
add()fallará. - Datos de entrenamiento insuficientes: IVF necesita suficientes vectores para entrenar. Una regla práctica es contar con al menos 39 veces tantos vectores como
nlist. - nprobe demasiado bajo: Un valor bajo de
nprobeacelera la búsqueda pero reduce la precisión. Prueba diferentes valores y mide el recall. - Sin persistencia: FAISS no almacena índices automáticamente. Si tu proceso termina, los datos desaparecen a menos que llames a
write_index. - Metadatos gestionados por separado: FAISS solo devuelve posiciones de índice. Debes mantener tu propia tabla de mapeo que conecte posiciones con textos o fuentes.
- Memoria de GPU superada: Con índices muy grandes, la memoria de GPU puede ser insuficiente. Divide el índice o usa IVFPQ para compresión.
- Índice no actualizado tras cambios en datos: Cuando añades nuevos vectores, HNSW los integra automáticamente. Con IVF, la calidad puede degradarse si añades muchos vectores nuevos sin reentrena.
- Dimensiones inconsistentes: El índice se crea con una dimensión fija. Vectores con otra dimensión generarán errores.
Hardware, costos y seguridad
FAISS se ejecuta en cualquier máquina con CPU. Para volúmenes pequeños y medianos, un escritorio estándar es suficiente. Para grandes volúmenes y soporte GPU, necesitas una tarjeta gráfica NVIDIA con VRAM adecuada, mínimo 8 GB, preferiblemente 24 GB o más. La aceleración GPU puede ser de 10 a 100 veces, dependiendo del tipo de índice y el volumen de datos.
Costos: FAISS es código abierto bajo licencia MIT y completamente gratuito. Los costos principales provienen del hardware, especialmente de las GPUs.
Seguridad: FAISS no tiene interfaz de red ni autenticación. Se ejecuta como una biblioteca en tu proceso. La seguridad depende de cómo asegures el entorno donde corre FAISS. Como todos los datos permanecen localmente, no existe riesgo de filtración de información a servicios externos. Si integras FAISS en un servicio, asegura ese servicio como lo harías con cualquier otra aplicación.
Enlaces de referencia
- FAISS GitHub Repository
- FAISS Documentación
- FAISS Tutorial
- Resumen de bases de datos vectoriales
- Fundamentos de RAG
- RAG local
- Modelos de embedding
- Configurar Chroma
- Configurar Qdrant
- Hybrid Search
- Fundamentos de Docker
Preguntas frecuentes
¿Es FAISS una base de datos?
No. FAISS es una biblioteca para búsqueda de vectores. No ofrece persistencia, metadatos ni API. Debes agregar estas características por tu cuenta.
¿Necesito una GPU para FAISS?
No. FAISS funciona también en CPU. Una GPU acelera significativamente la búsqueda con grandes volúmenes de datos, pero no es obligatoria.
¿Qué tarjetas gráficas se soportan?
FAISS soporta tarjetas gráficas NVIDIA con CUDA. Las tarjetas AMD no tienen soporte oficial.
¿Cómo guardo un índice FAISS de forma permanente?
Con faiss.write_index(index, ruta_archivo) guardas el índice en un archivo. Con faiss.read_index(ruta_archivo) lo cargas de nuevo.
¿Puedo almacenar metadatos en FAISS?
No. FAISS solo almacena vectores. Debes gestionar los metadatos en una base de datos separada o archivo, vinculándolos mediante posiciones de índice.
¿Cuál es el mejor tipo de índice?
Depende de tus requisitos. Para volúmenes pequeños, IndexFlatL2 es suficiente. Para volúmenes grandes con requisitos de velocidad, HNSW o IVFFlat son recomendables. Si tienes limitaciones de memoria, IVFPQ es la solución.
¿Cómo elijo nlist y nprobe en IVF?
Una buena regla es establecer nlist como la raíz cuadrada del número de vectores. nprobe controla el equilibrio entre velocidad y precisión. Comienza con nprobe igual a nlist dividido entre 10 y experimenta.
¿Puedo combinar FAISS con Ollama?
Sí. Ollama proporciona el modelo de lenguaje, FAISS la búsqueda de vectores. Tu script de Python conecta ambos y gestiona los metadatos por ti.
¿Es FAISS gratuito?
Sí, FAISS es código abierto bajo licencia MIT y completamente gratuito. Solo pagas por el hardware.
¿Cómo mido la precisión de un índice?
Compara los resultados del índice aproximado con los de un índice exacto como IndexFlatL2. La proporción de resultados coincidentes es el recall.
¿Puedo usar FAISS en Docker?
Sí. Hay imágenes oficiales de Docker con soporte GPU. Necesitas configurar Docker con NVIDIA Container Toolkit. Consulta el artículo sobre fundamentos de Docker para más detalles.
¿Cuál es la diferencia entre FAISS y Chroma?
Chroma es una base de datos vectorial completa con persistencia y metadatos. FAISS es una biblioteca de búsqueda pura que es más rápida pero requiere más trabajo manual.
Fuentes
- FAISS GitHub Repository
- FAISS Documentación
- FAISS Wiki con Tutoriales
- HNSW Paper de Malkov y Yashunin
- Product Quantization Paper de Jegou et al.


