Bases de datos vectoriales: el motor detrás de la búsqueda semántica y la IA

Una base de datos vectorial es una base de datos especializada diseñada para almacenar, indexar y consultar incrustaciones de vectores de alta dimensión. A diferencia de las bases de datos tradicionales que buscan por coincidencias exactas de palabras clave o consultas estructuradas, las bases de datos vectoriales buscan por similitud semántica: encuentran datos que están conceptualmente relacionados incluso si usan palabras diferentes.
Introducción
Una base de datos vectorial es una base de datos especializada diseñada para almacenar, indexar y consultar incrustaciones de vectores de alta dimensión. A diferencia de las bases de datos tradicionales que buscan por coincidencias exactas de palabras clave o consultas estructuradas, las bases de datos vectoriales buscan por similitud semántica: encuentran datos que están conceptualmente relacionados incluso si usan palabras diferentes.
Las bases de datos vectoriales se han convertido en una infraestructura esencial para las aplicaciones de IA: impulsan la generación de recuperación aumentada (RAG), la búsqueda semántica, los sistemas de recomendación, la detección de anomalías y la IA multimodal (texto, imagen, audio).
¿Qué son las incrustaciones de vectores?
De las palabras a los números
Las incrustaciones son representaciones numéricas de datos (texto, imágenes, audio o cualquier otra modalidad) producidas por modelos de aprendizaje automático. La magia es que elementos similares terminan muy juntos en el espacio vectorial:
"king" ──► [0.23, -0.45, 0.78, ..., 0.12] (768 dimensions)
"queen" ──► [0.25, -0.42, 0.76, ..., 0.15] (close to king)
"apple" ──► [-0.12, 0.65, 0.33, ..., -0.28] (far from king)
Cómo las incrustaciones capturan el significado
┌───────┐
│ man │
└───┬───┘
│
┌───────────────┼───────────────┐
│ │ │
┌───▼───┐ ┌───▼───┐ ┌───▼───┐
│ king │───────│ woman │───────│ queen │
└───┬───┘ └───┬───┘ └───┬───┘
│ │ │
└───────────────┼───────────────┘
│
┌───▼───┐
│ girl │
└───────┘
Vector arithmetic: king - man + woman = queen
Modelos de incrustación populares
| modelo | Dimensiones | Mejor para | Proveedor |
|---|---|---|---|
| incrustación-de-texto-3-pequeño | 512-1536 | Propósito general, rentable | Abierto AI |
| incrustación-de-texto-3-grande | 256-3072 | Búsqueda semántica de alta precisión | Abierto AI |
| Cohere Insertar v3 | 1024 | Clasificación multilingüe. | Coherir |
| BAAI/bge-large-es-v1.5 | 1024 | Código abierto, alta calidad | abrazando la cara |
| transformadores de oraciones/todos-MiniLM-L6-v2 | 384 | Ligero, rápido | abrazando la cara |
| enlace de imagen | 1024 | Multimodal (texto, imagen, audio) | meta |
Cómo funcionan las bases de datos vectoriales
Operaciones principales
- Indexación: cree una estructura de datos eficiente (índice ANN) sobre vectores.
- Ingestión: inserta vectores con metadatos en el índice.
- Consulta: dado un vector de consulta, encuentre los K vecinos más cercanos (KNN).
- Filtrado: combina similitud de vectores con filtros de metadatos (búsqueda híbrida).
El problema de la búsqueda
La búsqueda del vecino más cercano por fuerza bruta es O(N), demasiado lenta para millones de vectores:
# Brute force — O(N), not scalable
def brute_force_search(query_vector, all_vectors, k=10):
distances = []
for i, vec in enumerate(all_vectors):
dist = cosine_distance(query_vector, vec)
distances.append((dist, i))
return sorted(distances)[:k]
Índices aproximados del vecino más cercano (ANN)
Las bases de datos vectoriales utilizan algoritmos ANN para lograr un tiempo de búsqueda sublineal:
| Algoritmo | Velocidad | recordar | Memoria | Tiempo de construcción |
|---|---|---|---|---|
| HNSW (Mundo pequeño navegable jerárquico) | ⚡ Rápido | 95-99% | Alto | Lento |
| FIV (Índice de archivos invertido) | 🐢 Lento | 90-95% | Medio | Rápido |
| FIV + PQ (Cuantización del producto) | ⚡ Rápido | 85-95% | Bajo | Medio |
| DiskANN | ⚡ Rápido | 90-95% | Bajo (disco) | Medio |
| LSH (Hashing sensible a la localidad) | 🐢 Lento | 80-90% | Alto | Rápido |
HNSW: el algoritmo más popular
HNSW construye una estructura gráfica multicapa:
Layer 3: ────────●──────── (sparse, long-range connections)
│
Layer 2: ────●────────●─── (medium density)
│ │
Layer 1: ──●──●──●──●──●── (dense, short-range connections)
Search starts at top layer (coarse) and descends to bottom layer (fine).
Comparación de bases de datos vectoriales
| Característica | piña | Weaviate | Qdrant | milvus | croma | pgvector |
|---|---|---|---|---|---|---|
| Arquitectura | SaaS administrado | Híbrido | Independiente | Distribuido | Incrustado | Extensión PostgreSQL |
| Persistencia | nube | Nube/local | Nube/local | Nube/local | archivo local | PostgreSQL |
| Índice | HNSW | HNSW | HNSW | FIV/HNSW | HNSW | IVFFlato/HNSW |
| Búsqueda híbrida | si | si | si | si | Limitado | Sí (a través de SQL) |
| Multiinquilino | si | si | si | si | manuales | A través de esquemas |
| Filtrado | Prefiltro | Pre/post-filtro | Prefiltro | Post-filtro | Limitado | Filtro + índice |
| Metadatos | JSON | JSON | JSON | JSON | JSON | JSONB |
| Código abierto | No | Sí (BSL) | Sí (Apache 2.0) | Sí (Apache 2.0) | Sí (Apache 2.0) | Sí (PostgreSQL) |
| Autoanfitrión | No | si | si | si | si | si |
Casos de uso
1. Generación aumentada de recuperación (RAG)
El caso de uso de bases de datos vectoriales más popular: aumentar los LLM con datos privados:
User Query: "What is our company policy on remote work?"
┌─────────────────────────┐
│ Embedding Model │
│ text-embedding-3-small │
└────────────┬────────────┘
│ (query vector)
▼
┌─────────────────────────┐
│ Vector Database │
│ (company policies) │
└────────────┬────────────┘
│ (relevant chunks)
▼
┌─────────────────────────┐
│ LLM (GPT-4 / Claude) │
│ "Based on our policy │
│ document X, remote │
│ work is allowed 3 │
│ days per week..." │
└─────────────────────────┘
Implementación de Python:
import openai
from qdrant_client import QdrantClient
client = QdrantClient("localhost", port=6333)
def rag_query(question: str) -> str:
# 1. Embed the question
query_vector = openai.embeddings.create(
input=question, model="text-embedding-3-small"
).data[0].embedding
# 2. Search vector database
results = client.query_points(
collection_name="company_policies",
query=query_vector,
limit=5
)
# 3. Build context from retrieved chunks
context = "\n\n".join([r.payload["text"] for r in results.points])
# 4. Generate answer with context
response = openai.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Answer based on the provided context only."},
{"role": "user", "content": f"Context:\n{context}\n\nQuestion: {question}"}
]
)
return response.choices[0].message.content
2. Búsqueda Semántica
Busque por significado, no por palabras clave:
# Traditional keyword search — misses synonyms
SELECT * FROM products WHERE description LIKE '%cheap laptop%'
# May miss: "affordable notebook" or "budget computer"
# Vector semantic search — finds conceptually related items
results = vector_db.search(
query="budget-friendly portable computer",
collection="products",
limit=10
)
# Finds: "cheap laptop", "affordable notebook", "budget desktop", "entry-level PC"
Comparación de rendimiento:
| Tipo de búsqueda | recordar | Satisfacción del usuario | Complejidad de implementación |
|---|---|---|---|
| Palabra clave (BM25) | 40-60% | Bajo | Bajo |
| Semántico (Vector) | 70-90% | Alto | Medio |
| Híbrido (BM25 + Vector) | 85-95% | muy alto | Alto |
3. Búsqueda multimodal
Busque en diferentes tipos de datos:
# Text-to-image search
text_vector = embed_text("sunset over mountains")
image_results = vector_db.search(text_vector, collection="images")
# Image-to-text search
image_vector = embed_image(uploaded_photo)
text_results = vector_db.search(image_vector, collection="descriptions")
# Image-to-image search (visual similarity)
product_image_vector = embed_image(product_photo)
similar_products = vector_db.search(product_image_vector, collection="products")
4. Sistemas de recomendación
def recommend_items(user_id: str, n: int = 10):
# Get user's embedding (from past behavior)
user_vector = get_user_embedding(user_id)
# Find similar items in vector space
recs = vector_db.search(
query=user_vector,
collection="items",
limit=n,
with_payload=True
)
# Diversity re-ranking
return diversify(recs, diversity_factor=0.3)
Operaciones de bases de datos vectoriales
Crear una colección e insertar vectores
Ejemplo de Qdrant:
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance
client = QdrantClient("localhost", port=6333)
# Create collection with specific vector config
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(
size=1536, # Matches text-embedding-3-small
distance=Distance.COSINE # or DOT, EUCLIDEAN
),
)
# Insert vectors with payload (metadata)
client.upsert(
collection_name="documents",
points=[
{
"id": "doc_001",
"vector": [0.12, -0.45, ..., 0.78], # 1536-dimensional
"payload": {
"title": "Remote Work Policy",
"category": "HR",
"author": "HR Team",
"date": "2026-01-15",
"chunk_index": 0,
"text": "Employees may work remotely up to 3 days per week..."
}
},
# ... more points
]
)
Búsqueda híbrida con filtros
# Semantic search with metadata filters
results = client.query_points(
collection_name="documents",
query=query_vector,
query_filter=models.Filter(
must=[
models.FieldCondition(
key="category",
match=models.MatchValue(value="Engineering")
),
models.FieldCondition(
key="date",
range=models.Range(gte="2025-01-01")
),
],
should=[
models.FieldCondition(
key="author",
match=models.MatchValue(value="Alice")
),
]
),
limit=20,
score_threshold=0.75 # Minimum similarity score
)
Base de datos vectorial frente a base de datos tradicional
| Operación | PostgreSQL | pgvector | Base de datos vectorial dedicada |
|---|---|---|---|
| KNN exacto | ❌ (escaneo completo) | ❌ (lento) | ✅ (a través de la fuerza bruta) |
| búsqueda de RNA | ❌ | ✅ (IVFFlato, HNSW) | ✅ (optimizado) |
| Más de 10 millones de vectores | ✅ | ⚠️ El rendimiento se degrada | ✅ |
| Transmisión en tiempo real | ✅ | ⚠️ | ✅ |
| Búsqueda híbrida | ✅ (filtros SQL) | ✅ | ✅ |
| Multiinquilino | ✅ (esquemas) | ✅ | ✅ (nativo) |
| Transacciones ácidas | ✅ | ✅ | ⚠️ (limitado) |
| Consultas sobre viajes en el tiempo | ❌ | ❌ | ✅ (WAL) |
Desafíos y consideraciones
Maldición de dimensionalidad
- Las dimensiones más altas hacen que las métricas de distancia sean menos significativas.
- La mayoría de los modelos integrados utilizan dimensiones de 384 a 1536; esto es manejable.
- Más allá de 2000 dimensiones, considere la reducción de dimensionalidad (PCA, UMAP).
Mantenimiento del índice
- HNSW requiere una cantidad significativa de memoria (vectores + estructura gráfica).
- La FIV necesita un reentrenamiento periódico a medida que aumentan los datos.
- DiskANN cambia algo de velocidad por menos memoria.
Costo
vector_database_pricing:
pinecone:
starter: "$70/month for 100K vectors"
enterprise: "$2,000+/month for 10M+ vectors"
self_hosted_qdrant:
infrastructure: "$50-500/month (cloud VMs)"
maintenance: "Operational overhead"
Actualización de datos
- La ingesta en tiempo real entra en conflicto con la optimización del índice.
- Indexación por lotes para nuevos vectores, incremental para actualizaciones.
- Compensación entre frescura y calidad de búsqueda.
Conclusión
Las bases de datos vectoriales son un componente de infraestructura crítico para las aplicaciones de IA:
- Úsalos cuando necesites comprensión semántica, no concordancia de palabras clave.
- La mejor aplicación es RAG: aumenta los LLM con datos privados y actualizados.
- Elija según la escala: pgvector para proyectos pequeños, Pinecone/Qdrant para producción, Milvus para escala masiva.
- La búsqueda híbrida (vector + palabra clave + metadatos) proporciona los mejores resultados.
- La elección del modelo integrado es importante: pruebe diferentes modelos para su caso de uso específico.
El panorama de las bases de datos vectoriales está evolucionando rápidamente. Comience de manera simple (pgvector o Qdrant de código abierto), compare con sus datos y amplíe según sea necesario.
Artículos destacados

6 patrones de programación que aprendí de ingenieros senior

Crea un asistente privado de notas con IA
Convierte notas Markdown en un asistente consultable sin exponer borradores privados.

Automatiza la extracción de datos de facturas con OCR
Crea un flujo que lee facturas, extrae campos y marca valores dudosos para revisión.
Comentarios
0 comentariosTodavía no hay comentarios aprobados. Las respuestas nuevas pueden esperar moderación.