Embeddings & Vector databases

Embeddings

Un ordenador no puede entender texto ni relación semántica o significado entre palabras. Solo puede entender números. Esto lo resolvemos mediante el uso de embeddings.

Un embedding es la representación de texto (en forma de números) en un espacio vectorial. Esto permite a los modelos de IA comparar y operar sobre el significado de las palabras.

flowchart TD
    A["perro"] --> B
    B --> C["[-0.003, 0.043, ..., -0.01]"]
    
    N1["(texto que queremos convertir)"]:::note --> A
    N2["(vectores con contenido semántico)"]:::note --> C
    
    classDef note fill:none,stroke:none,color:#777;    

Los vectores de cada palabra o documento capturan el significado semántico del texto.

  • perro estará cerca de mascota
  • contrato estará lejos de playa

Vector vs SQL databases

El problema con las BBDD típicas es que solo buscan matches exactos. Si yo busco por coche solo me sacará las entradas que contengan coche.

En cambio, como las BBDD vectoriales pueden interpretar la semántica de las palabras mediante los vectores, si busco por coche puede sacarme valores como sedán, SUV, Land Rover, etc.

Las BBDD vectoriales son muy buenas cuando necesitamos buscar items similares por proximidad uno respecto al otro. Un ejemplo de uso es buscar películas parecidas (Netflix). Otro ejemplo son los recomendadores de items parecidos en tiendas online (Amazon).

Como ejecutar una búsqueda (query) mediante vectores

(You can see the code here)

Necesitamos:

  • Una BBDD Vectorial (CosmosDB)
  • Un modelo para transformar los embeddings (text-embedding-3-large)

El flujo completo es el siguiente:

  1. Usar un embedding model para crear embeddings del contenido que queremos indexar
  2. Insertar el texto original y los vectores del contenido en una BBDD vectorial
  3. Cuando queramos ejecutar una query usar el mismo embedding model de antes con la query a buscar. Con el embedding resultante buscamos vectores similares en la BBDD y sacamos el texto original de original_text

    Introducir vectores en CosmosDB

    Para poder buscar necesitamos rellenar antes la BBDD con contenido. Lo mantenemos simple. Metemos

    • un ID a mano
    • el texto original
    • los vectores resultado de hacer el embedding sobre el texto original

El pseudocódigo se ve así y se ejecuta de uno en uno

def main():
	text = "A shiba walks alone in the park"
	# this sends the text to the model text-embedding-3-large 
	vectors = createEmbeddingsForText(text)
	item = {
		"id": "1",
		"original_text": text,
		"vectors": vectors
	}
	uploadToCosmosDB(item)

ejemplos de los datos que guardo

{
	"id": "1",
	"original_text": "A shiba walks alone in the park",
	"vectors": [-0.003, 0.043, ..., -0.001]
}
{
	"id": "2",
	"original_text": "A dog sleeps on the bed",
	"vectors": [0.021, ..., 0.071]
}
{
	"id": "3",
	"original_text": "A wild bear hunts in the mountain",
	"vectors": // some vectors
}
{
	"id": "4",
	"original_text": "Two boats colide in the ocean",
	"vectors": // some vectors
}
{
	"id": "5",
	"original_text": "A car travels during the night",
	"vectors": // some vectors
}

Ejecutar una búsqueda

Ahora si realizo una búsqueda, puedo buscar por proximidad semántica y no solo por matches exactos como en una BBDD tradicional.

pseudocódigo

def main():
	text_to_search = "inu"
	# it needs to be the same model as before
	vectors = createEmbeddingsForText(text)
	# we search for the top 3 results
	results = queryCosmosDB(vectors)

Aunque inu no se encuentra en la BBDD como tal, vemos que el hit más fuerte es el que contiene shiba. El segundo más fuerte (aunque bastante distanciado) es el que contiene dog.

text: 'A shiba walks alone in the park', cosine_distance: 0.57116
text: 'A dog sleeps on the bed', cosine_distance: 0.28378
text: 'A wild bear hunts in the mountain', cosine_distance: 0.21090

Si por el contrario busco vehicle ahora los hits más fuertes son los que contienen medios de transporte

text: 'A car travels during the night', cosine_distance: 0.37720
text: 'Two boats colide in the ocean', cosine_distance: 0.23041
text: 'A shiba walks alone in the park', cosine_distance: 0.15880

Reference(s)

Using Embeddings to Find Similar Texts with Azure OpenAI and Cosmos DB | by Shubham Agarwal | Medium