Últimamente se habla mucho del uso de bases de datos vectoriales combinadas con grandes modelos de lenguaje. ¿Pero que relación tienen?. El punto en común entre ambos son los embeddings. ¿Qué es un embedding?. Un embedding es un vector que representa la descripción del significado de un texto (en este caso) en un espacio de múltiples dimensiones. Este espacio establece una relación entre los diversos significados de los textos, de tal forma que el angulo formado por dos vectores indica lo próximos que sus significados están.
Para calcular lo parecidos que son dos vectores usaremos la similitud coseno (cos_sim):
u ⋅ v /∣u∣∣v∣
Siendo u y v vectores. 1 significa que son idénticos, 0 que no tienen relación y -1 que son contrarios.
Los embeddings son usados en los modelos de lenguaje para representar el texto de forma interna y trabajar con él en forma de vectores (no confundir con los wordvectors, aunque la idea es la misma y están relacionados los wordvectors funcionan a nivel de token…si no sabes lo que es un token quédate con que funcionan a nivel de palabra).
Para estas pruebas usaremos el modelo de lenguaje BERT a través de la librería sentence-transformers.
Primero cargamos las librerías que necesitamos y el modelo
import numpy as np
from sentence_transformers import SentenceTransformer, util
#Cargamos el modelo
sbert_model = SentenceTransformer('all-mpnet-base-v2')
Estas son las sentencias con las que vamos a comparar nuestro texto de búsqueda. Las sentencias han sido obtenidas de la Wikipedia en inglés, en concreto la primera del articulo de mecánica cuántica y las siguientes de la definición de física clásica.
sentences = [
"a fundamental theory in physics that provides a description of the physical properties of nature at the scale of atoms and subatomic particles.",
"refers to theories of physics that do not use the quantisation paradigm, which includes classical mechanics and relativity.",
"physical objects ranging from those larger than atoms and molecules, to objects in the macroscopic and astronomical realm",
"in the context of general and special relativity, classical theories are those that obey Galilean relativity."
]
Buscamos *Quantum mechanics*, deberia de dar como mayor similitud el primer texto. Fijaros en la trampa de que el segundo incluye *quantisation paradigm* para «engañar» al modelo y ver si es capaz de buscar por «significado» y no solo por «similitud de las palabras»
El resultado:
similarity = tensor([[0.5077]])
similarity = tensor([[0.4847]])
similarity = tensor([[0.4180]])
similarity = tensor([[0.2300]])
Correcto el código más cercano a 1 es el primero.
Una pequeña optimización que se puede hacer si vas a almacenar estos vectores para compararlos varias veces. Podemos normalizar los vectores, esto significa que le damos longitud uno sin modificar la dirección del mismo, podemos usar el producto escalar (dot_score), mucho más rápido que la similitud coseno.
Si partimos de la similitud coseno u ⋅ v /∣u∣∣v∣ Al tener distancia 1 los módulos || son 1 por lo que el divisor desaparece y queda solo el producto escalar u ⋅ v
sentence_embeddings = sbert_model.encode(sentences)
query = "Quantum mechanics"
query_embedding = sbert_model.encode([query], normalize_embeddings = True)
for sentece in sentences:
sim = util.dot_score(query_embedding, sbert_model.encode([sentece], normalize_embeddings = True))
print("similarity = ", sim)
¿Pero que tiene esto que ver con las bases e datos vectorariales?. Una base de datos vectorial funciona básicamente como el ejemplo (en realidad usa diferentes operaciones especializadas para diversos casos). Asocia un vector con los datos originales a los que representa y permite buscar a partir de un texto, que es convertido en embedding.
Lo bueno de los embeddings es que no solo puede representar texto, usando modelos multimodales se pueden usar embeddings que provengan de imágenes, audios, vídeos, … Lo que permite cruzar datos heterogéneos.
Esta flexibilidad hace que muchas veces puedan cumplir funciones como búsqueda inteligente de textos, responder preguntas, buscar referencias o datos relacionados que a su vez se pueden combinar con los modelos de lenguaje aportando estos datos al contexto del mismo. Un ejemplo de este eso es su uso en técnicas como RAG descrito en esta entrada del blog
Puedes ver todo esto descrito en el siguiente vídeo de mi canal de Youtube:
