Recuperación por asociación: un modelo mental basado en la memoria para la búsqueda vectorial
Aprenda cómo funcionan juntos los embeddings, la similitud semántica, la búsqueda de vecino más cercano aproximada y los filtros de metadatos, utilizando la memoria humana como guía.
Pueden pasar años sin pensar siquiera en un maestro de la infancia. Luego, un olor a tiza, el aroma de la cafetería escolar o una canción que solía sonar durante el viaje en autobús de regreso traen a esa persona de vuelta de inmediato y con total claridad. Nunca se buscó su nombre; apareció algo similar y el recuerdo surgió por sí solo.
Ese es el comportamiento que los sistemas de búsqueda semántica, la generación mejorada por recuperación de información (RAG) y los sistemas de recomendación basados en IA intentan reproducir, aunque de forma imperfecta pero seria. El componente que lo hace posible es la base de datos vectorial. Este artículo utiliza el modelo mental de la recuperación por asociación para explicar qué son los vectores, cómo se mide la similitud, cómo escala la búsqueda del vecino más cercano y cómo todas estas partes forman un pipeline de recuperación. También señala dónde deja de ser válida esta analogía, ya que esos son precisamente los puntos en los que suelen fallar los sistemas en producción.
Almacenamiento por significado en lugar de por nombre
La memoria humana no cuenta con un índice alfabético. No existe una carpeta mental llamada “Comida” que contenga una subcarpeta “Italiana” con un archivo llamado “Pizza”. Esa estricta jerarquía es la forma en que una base de datos convencional organiza los datos: cada registro se encuentra en una dirección conocida y se accede a él mediante una clave exacta.
En cambio, la memoria se organiza por significado y asociación: según el contexto, las sensaciones y la forma en que una cosa se relaciona con otras. La idea de pizza está vinculada a las noches de viernes, a un viaje a Nápoles, a la comida reconfortante, a las tiras de queso estiradas, al aroma del orégano y quizás a un compañero de cuarto en la universidad que arruinó todas las tandas de masa casera. Pensar en pizza no abre un único archivo; activa todo un conjunto de recuerdos relacionados, comenzando por los más fuertemente vinculados.
Una base de datos vectorial utiliza exactamente este principio. Los elementos se almacenan según su significado y se recuperan en función de cuán similares son a la solicitud, no porque una clave coincida al cien por ciento.
Qué codifica un vector
Para comprender la base de datos primero hay que entender qué contiene. Un vector, en este contexto, es simplemente una lista ordenada de números que representa un significado.
Una máquina no tiene una comprensión real de qué es la pizza. Lo que un modelo de embedding puede aprender, al procesar enormes cantidades de texto, es la asociación que tiene una palabra. “Pizza” aparece cerca de “queso”, “italiano”, “masa”, “horno” y “rebanada”. Esos términos son diferentes de los que rodean a “sushi”, pero tienen muchas similitudes con los que rodean a “pan plano” o “calzone”.
El modelo condensa esos patrones en una lista de números de longitud fija, que suele contener de unos cientos a un par de miles de valores; 384 y 1,536 son tamaños típicos. Ningún número en particular lleva una etiqueta legible, pero juntos permiten posicionar el elemento con precisión en un espacio de alta dimensión. La propiedad importante es la siguiente: las entradas con significados similares terminan teniendo vectores que se encuentran cerca unos de otros. “Pizza” queda cerca de “pan plano” y muy lejos del “informe de ganancias trimestrales”.
Similitud como un espectro, no como una coincidencia
Una consulta tradicional es binaria: una fila satisface la condición o no la satisface. Al filtrar por “perro”, se obtienen filas que contienen exactamente “perro”, sin nada relacionado con “cachorro”, “golden retriever” o “compañero de cuatro patas leal”.
La similitud semántica reemplaza esa respuesta de sí o no por una puntuación que indica cuán similares son dos significados. En una escala ilustrativa, “cachorro” podría obtener una puntuación de 0.94 frente a “perro”, “lobo” algo como 0.71, y “factura” alrededor de 0.08. La métrica suele ser la similitud coseno o una distancia relacionada como el producto escalar o la distancia euclidiana, y la elección adecuada depende de cómo se entrenó el modelo de embedding.
Esto refleja el efecto del polvo de tiza: no se trata de una coincidencia exacta, sino de un indicio que activa recuerdos cercanos, los cuales a su vez activan a sus vecinos. En una base de datos vectorial, la mecánica es numérica. La consulta se convierte en un vector, y la base de datos devuelve los elementos almacenados cuyos vectores están más cerca de él. “Cerca” significa similar en significado.
Por eso, una búsqueda de “¿cómo soluciono una consulta lenta en la base de datos?” puede mostrar un documento titulado “Optimización del rendimiento de las consultas a gran escala”, aunque ambas frases apenas compartan una palabra. Sus vectores están cerca porque expresan la misma intención.
Una advertencia sobre los números
Las puntuaciones de similitud son relativas, no absolutas. Un valor de 0.8 obtenido con un modelo de embedding no es comparable con uno de 0.8 de otro modelo, y incluso dentro del mismo modelo el rango típico depende del dominio. Considere las puntuaciones como una forma de clasificar candidatos, y si aplica un umbral, cámbielo según sus propios datos en lugar de elegir un número redondo.
Una corrección relacionada: el SQL basado únicamente en palabras clave no puede expresar similitud semántica, pero eso no significa que las bases de datos SQL estén excluidas. Extensiones como pgvector, mencionadas a continuación, añaden columnas vectoriales y operadores de similitud a Postgres, por lo que esta capacidad puede existir dentro de una base de datos relacional.
Búsqueda de vecino más cercano a gran escala
¿Cómo localiza realmente la base de datos los vectores más cercanos? La operación principal se denomina búsqueda de vecino más cercano, y hacerla rápida es la razón principal por la que existen las bases de datos vectoriales.
Imagínese cada elemento almacenado como una estrella en una galaxia, dispuesta según su significado, con elementos relacionados agrupándose en la misma región. Una consulta introduce una nueva estrella en esa galaxia y pregunta cuáles son las cinco estrellas existentes más cercanas.
El enfoque ingenuo mide la distancia desde la consulta hasta cada vector almacenado, ordena los resultados y devuelve los mejores. Para miles de vectores, esto es rápido y perfectamente adecuado. Pero para millones o billones, comparar con todo se vuelve extremadamente costoso muy rápidamente.
Por lo tanto, los sistemas de producción dependen de algoritmos de vecino más cercano aproximado (ANN). En lugar de visitar cada estrella, utilizan un índice que reduce la búsqueda a regiones prometedoras, aceptando una pequeña pérdida en precisión a cambio de un gran aumento en velocidad. El algoritmo más utilizado hoy en día es HNSW, abreviatura de Hierarchical Navigable Small World. No es necesario conocer su funcionamiento interno para usar una base de datos vectorial, pero debe saberse que es la razón por la cual una búsqueda entre cien millones de embeddings puede completarse en milisegundos.
La expresión “aproximado” merece atención. Un índice de redes neuronales artificiales puede omitir ocasionalmente al verdadero vecino más cercano, y la tasa con la que encuentra los resultados reales de mayor calidad, denominada precisión de recuperación, depende de los parámetros del índice que equilibran la memoria y la latencia con la precisión. Si la calidad de la recuperación parece inexplicablemente irregular a gran escala, vale la pena revisar la configuración del índice; nuestra guía sobre ajustar índices HNSW para RAG en producción aborda en profundidad esos parámetros.
Dentro del almacén de embeddings
En esencia, una base de datos vectorial es un almacenamiento optimizado para una única tarea: conservar vectores y realizar búsquedas de vecino más cercano sobre ellos de manera muy rápida.
Imagínese una biblioteca que ignora el Sistema Decimal de Dewey y organiza los libros según su “sentimiento”. Los libros sobre duelo están junto a los sobre pérdida, estos a su vez al lado de los sobre soledad, luego aislamiento, y finalmente memorias de expediciones en solitario. Nadie asignó manualmente esas categorías; el orden surgió porque los lectores atraídos por uno suelen querer también los demás.
Pinecone, Weaviate, Chroma y Qdrant son ejemplos de esa biblioteca. Se les carga con incrustaciones de documentos, descripciones de productos, imágenes convertidas en vectores o patrones de comportamiento de usuarios, y ellos mantienen el índice para que las búsquedas sigan siendo rápidas a medida que la colección crece.
Cada registro almacenado generalmente tiene tres partes:
- Un ID que identifica de forma única el elemento.
- El vector que representa su significado.
- Metadatos opcionales como título, fecha, categoría o URL de origen, que pueden utilizarse para filtrar resultados.
Los metadatos son más valiosos de lo que parecen a primera vista. Una solicitud realista sería la siguiente: encontrar los cinco documentos más similares a la consulta, pero solo aquellos de los últimos 30 días y únicamente de la base de conocimientos del equipo de ingeniería. Eso es una búsqueda vectorial combinada con un filtro de metadatos, y la mayoría de los sistemas en producción dependen de esta combinación. También es importante cómo se aplica el filtro: filtrar después de la búsqueda de similitud puede dejarle con menos resultados de los que solicitó, por lo que verifique si su base de datos aplica filtros durante la búsqueda en sí.
El proceso completo de recuperación
Ya sea que se encuentre dentro de un sistema RAG, una función de búsqueda semántica o cualquier aplicación que utilice conocimientos almacenados, la recuperación sigue los mismos cuatro pasos.
- Incluir el contenido. Cada documento, artículo, descripción de producto o registro que se desee hacer buscable pasa por un modelo de incrustación, y el vector resultante se almacena junto con el contenido original. Los documentos largos suelen dividirse primero en fragmentos, ya que un único vector para todo un manual mezcla demasiadas ideas entre sí.
- Incluir la consulta con el mismo modelo. Esto no es opcional. Diferentes modelos de incrustación generan vectores en espacios no relacionados, por lo que comparar una consulta de un modelo con documentos de otro da como resultado distancias sin sentido. Cambiar de modelo implica volver a incrustar toda la colección.
- Buscar. El vector de la consulta se envía a la base de datos, la búsqueda de vecinos más cercanos encuentra los vectores almacenados más próximos, y se devuelven los resultados principales, generalmente junto con puntuaciones de similitud.
Desde el punto de vista del usuario, una respuesta relevante aparece en cuestión de momentos. Bajo este proceso, el significado se convierte en números, esos números se comparan con millones de elementos almacenados, se devuelven las coincidencias más cercanas y se genera una respuesta a partir de contenido real.
Por qué la búsqueda vectorial está en todas partes ahora
Hace poco tiempo, las bases de datos vectoriales eran una herramienta de nicho que solo se utilizaba al desarrollar búsquedas semánticas o sistemas de recomendación especializados. Ahora forman parte estándar de muchas aplicaciones de IA. RAG necesita un lugar donde almacenar y consultar las incrustaciones de documentos. Los agentes consultan bases de conocimiento por su significado. Las recomendaciones a gran escala se basan en la similitud vectorial. La búsqueda multimodal, como encontrar imágenes a partir de una descripción de texto o productos a partir de una foto subida, también funciona mediante vectores.
Si está desarrollando aplicaciones basadas en modelos de lenguaje grande en entornos de producción, es muy probable que ya dependa de la búsqueda vectorial o que lo haga pronto. Lo alentador es que la idea central ya nos resulta familiar: desde que existimos, la memoria ha estado recuperando las asociaciones más cercanas a todo aquello que llega a nuestros sentidos. Una base de datos vectorial hace lo mismo con números, en milisegundos, y con millones de elementos.
Dónde falla la analogía con la memoria
La comparación con el cerebro es útil para la intuición, pero existen algunas diferencias importantes en la práctica:
- La memoria se adapta continuamente; un modelo de embedding está congelado. Si el vocabulario de su dominio cambia, los vectores no se actualizan por sí solos.
- La memoria combina el contexto sin esfuerzo; un vector solo captura lo que se le ha proporcionado. Un texto de origen mal dividido o con ruido genera vecinos de mala calidad.
- La similitud no equivale a relevancia. Dos pasajes pueden ser similares en significado, pero solo uno responde realmente a la pregunta; por eso muchos sistemas añaden búsquedas por palabras clave o un paso de reclasificación adicional.
Poniéndose manos a la obra
Puede experimentar sin necesidad de crear ninguna infraestructura:
- ChromaDB se ejecuta localmente dentro de Python sin necesidad de cuenta, clave API ni despliegue, y solo requiere unas pocas líneas de código para instalarse e inicializarse. Es adecuado para el aprendizaje y proyectos pequeños.
- Qdrant ofrece un nivel gratuito en la nube y un cliente en Python bien estructurado, ideal cuando se desea algo similar a entornos de producción sin tener que administrar servidores uno mismo. Verifique los límites actuales del plan antes de confiar en ellos.
- pgvector es una extensión para Postgres. Si ya utiliza Postgres, esta extensión agrega la búsqueda vectorial sin necesidad de crear una base de datos separada, lo que mantiene la arquitectura simple.
Cualquiera que sea su elección, el flujo de trabajo es idéntico: elegir un modelo de embedding, incrustar el contenido, almacenar los vectores, incrustar las consultas recibidas y realizar búsquedas. Los conceptos permanecen los mismos; solo cambia la biblioteca cliente.
El mismo modelo a ambos lados de la puntuación
La similitud del coseno solo significa algo si la consulta y el pasaje salen del mismo modelo.
def cosine(a: list[float], b: list[float]) -> float:
dot = sum(x * y for x, y in zip(a, b))
na = sum(x * x for x in a) ** 0.5
nb = sum(y * y for y in b) ** 0.5
if na == 0 or nb == 0:
return 0.0
return dot / (na * nb)
# query and passage must come from the same embedding model
score = cosine(embed(query), embed(passage))
El filtro de metadatos va antes de la búsqueda de vecinos y decide quién entra en el conjunto de candidatos.
hits = collection.query(
query_embeddings=[embed(query)],
n_results=8,
where={"tenant_id": tenant_id},
)
Puntos clave
- Un embedding convierte el significado en una posición, de modo que los elementos similares terminan cerca uno del otro.
- Las puntuaciones de similitud clasifican a los candidatos; calibre cualquier umbral con sus propios datos.
- Los índices ANN como HNSW sacrifican un poco de precisión en la recuperación a cambio de grandes ganancias de velocidad a gran escala.
- Los filtros de metadatos convierten la similitud bruta en respuestas que respetan las reglas de tiempo, origen y acceso.
- Las consultas y los documentos deben compartir un mismo modelo de embedding, y la calidad de la recuperación depende tanto del particionamiento y de la calidad de los datos como de la base de datos.
Lecturas relacionadas
- Cómo realmente funcionan las bases de datos vectoriales: desde los embeddings hasta la búsqueda híbrida — Explica cómo los embeddings codifican el significado, cómo escalan la búsqueda y el indexado por similitud, y cuándo la búsqueda híbrida y las bases de datos vectoriales son adecuadas para los sistemas de IA empresariales.