Una base de datos vectorial mínima para fines educativos.
Lema: Mantenlo simple y aprenderán ...
¿Quieres aprender más? ¿Vea la sección de 'referencias' a continuación?

En este ejemplo, utilizaremos el conjunto de datos de la escuela primaria Math 8k (GSM8K)
from datasets import load_dataset
# Number of samples we want to process
N_SAMPLES = 100
# Load dataset
# https://huggingface.co/datasets/openai/gsm8k
ds = load_dataset ( "openai/gsm8k" , "main" , split = "train" )[: N_SAMPLES ]
questions = ds [ 'question' ]
answers = ds [ 'answer' ] que contiene "problemas de palabras matemáticas de escuela primaria lingüísticamente de alta calidad" en forma de pares de question-answer como el que se muestra a continuación
### Question
Natalia sold clips to 48 of her friends in April, and then she sold half as many clips in May.
How many clips did Natalia sell altogether in April and May?
### Answer
Natalia sold 48/2 = <<48/2=24>>24 clips in May.
Natalia sold 48+24 = <<48+24=72>>72 clips altogether in April and May. #### 72
Nuestro objetivo es convertir estos pares question-answer en embedidas, almacenarlos en Vektordb y realizar algunas operaciones.
Los incrustaciones son solo representaciones numéricas de una información, generalmente en forma de vectores. Puede convertir cualquier tipo de datos en incrustaciones (¿por ejemplo? ️?) Y preservarán el significado de los datos originales. Si desea obtener más información sobre incrustaciones , consulte los incrustaciones de mapeo: de significado a vectores y viceversa.
Definamos una función auxiliar para llamar a los modelos de incrustación de coherencia a través de Amazon Bedrock
import json
import boto3
# Initialize Bedrock client
bedrock = boto3 . client ( "bedrock-runtime" )
def embed ( texts : list , model_id = "cohere.embed-english-v3" ):
"""Generates embeddings for an array of strings using Cohere Embed models."""
model_provider = model_id . split ( '.' )[ 0 ]
assert model_provider == "cohere" ,
f"Invalid model provider (Got: { model_provider } , Expected: cohere)"
# Prepare payload
accept = "*/*"
content_type = "application/json"
body = json . dumps ({
'texts' : texts ,
'input_type' : "search_document"
})
# Call model
response = bedrock . invoke_model (
body = body ,
modelId = model_id ,
accept = accept ,
contentType = content_type
)
# Process response
response_body = json . loads ( response . get ( 'body' ). read ())
return response_body . get ( 'embeddings' )y úselo para generar incrustaciones para un pequeño subconjunto de nuestros datos (solo respuestas, por ahora)
from tqdm import tqdm
# Text call limit for Cohere Embed models via Amazon Bedrock
# https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-embed.html
MAX_TEXTS_PER_CALL = 96
embeddings = []
for idx in tqdm ( range ( 0 , len ( answers ), MAX_TEXTS_PER_CALL ), "Generating embeddings" ):
embeddings += embed ( answers [ idx : idx + MAX_TEXTS_PER_CALL ])Ahora estamos listos para inicializar Vektordb y comenzar a cargar datos
from vektordb import ANNVectorDatabase
from vektordb . types import Vector
# Initialize database
vector_db = ANNVectorDatabase ()
# Load embeddings into the database
for idx in tqdm ( range ( len ( embeddings )), "Loading embeddings" ):
vector_db . insert ( idx , Vector ( embeddings [ idx ], { 'answer' : answers [ idx ][: 20 ]}))Como verificación de cordura, podemos imprimir una pequeña muestra de nuestra base de datos
vector_db . display (
np_format = {
'edgeitems' : 1 ,
'precision' : 5 ,
'threshold' : 3 ,
'suppress' : True
},
keys = range ( 10 )
) +-----+-------------------------+------------------------------------+
| Key | Data | Metadata |
+-----+-------------------------+------------------------------------+
| 0 | [-0.00618 ... -0.00047] | {'answer': 'Natalia sold 48/2 = '} |
| 1 | [-0.01997 ... -0.01791] | {'answer': 'Weng earns 12/60 = $'} |
| 2 | [-0.00623 ... -0.0061 ] | {'answer': 'In the beginning, Be'} |
| 3 | [-0.07849 ... 0.00721] | {'answer': 'Maila read 12 x 2 = '} |
| 4 | [-0.01669 ... 0.01263] | {'answer': 'He writes each frien'} |
| 5 | [0.02484 ... 0.05185] | {'answer': 'There are 80/100 * 1'} |
| 6 | [-0.01807 ... -0.01859] | {'answer': 'He eats 32 from the '} |
| 7 | [ 0.01265 ... -0.02016] | {'answer': 'To the initial 2 pou'} |
| 8 | [-0.00504 ... 0.0143 ] | {'answer': 'Let S be the amount '} |
| 9 | [-0.0239 ... -0.00905] | {'answer': 'She works 8 hours a '} |
+-----+-------------------------+------------------------------------+
Nuestra instancia de VektordB está respaldada por una implementación de la búsqueda aproximada de vecinos más cercanos (ANN) que utiliza árboles binarios para representar diferentes particiones/divisiones del hiperespacio.
Estas particiones se generan eligiendo dos vectores al azar, encontrando el hiperplano equidistante entre los dos y luego dividiendo los otros puntos a left y right dependiendo del lado.
Este proceso se repite hasta que tengamos en la mayoría de los elementos k en cada nodo (partición)
¿Podemos obtener mejores resultados generando un bosque de árboles *? Y buscarlos en todos, así que hagamos eso:
import random
# Set seed value for replication
random . seed ( 42 )
# Plant a bunch of trees ?️
vector_db . build ( n_trees = 3 , k = 3 )
print ( vector_db . trees [ 0 ], " n " )Aquí hay una representación del primer árbol en nuestro bosque (los nodos muestran el número de instancias en cada partición)
__________100______________
/
________________________________________________63______ __________37___________
/ /
_51__ _12_ 16____ ___21____
/ / / /
6 45____________________ _7 5 2 _14___ _10_ _11_____
/ / / / / / /
3 3 3 __________42_____________ 4 3 2 3 5 _9 _5 5 4 ___7
/ / / / / / / /
___18____ _____24____ 2 2 3 2 6 3 4 1 2 3 3 1 6_ 1
/ / / / /
_8_ _10_ ___11___ _13_ 3 3 1 3 2 4
/ / / / /
4 4 4 6_ 6_ _5 5 8_ 3 1
/ / / / / / / /
2 2 3 1 1 3 2 4 2 4 4 1 2 3 3 5
/ / / /
1 3 3 1 2 2 2 3
Finalmente, podemos ejecutar una consulta simplemente buscando en la base de datos respuestas similares a una pregunta objetivo.
Utilizamos funciones de distancia como las que se muestran a continuación para cuantificar cuán similares son dos vectores entre sí.
Por ejemplo, si hacemos la primera pregunta en nuestro conjunto de datos de capacitación
from vektordb . utils import print_similarity_scores
# Extract first question
query = questions [ 0 ]
print ( " n Query:" , query , " n " )
# Run search and display similarity scores
results = vector_db . search ( embed ([ query ])[ 0 ], 3 )
print_similarity_scores ( results ) Esperamos que la respuesta con el mismo índice ( 0 ) sea el resultado principal:
Query: Natalia sold clips to 48 of her friends in April, and then she sold half as many clips in May.
How many clips did Natalia sell altogether in April and May?
+-----+---------------------+
| Key | Score |
+-----+---------------------+
| 0 | 0.15148634752350043 |
| 15 | 0.6105711817572272 |
| 83 | 0.6823805943068366 |
+-----+---------------------+
COS 597A (Princeton): memoria a largo plazo en bases de datos y búsqueda de vectores AI - VectorCMU 15-445/645 (Carnegie Mellon): sistemas de bases de datos