Une base de données vectorielle minimale à des fins éducatives.
Slogan: restez simple et ils apprendront ...
Vous voulez en savoir plus? Consultez la section «références» ci-dessous?

Dans cet exemple, nous utiliserons l'ensemble de données Math 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' ] qui contient "des problèmes de mots mathématiques à école primaire linguistique de haute qualité" sous forme de paires de question-answer comme celle ci-dessous
### 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
Notre objectif est de transformer ces paires question-answer en intégres, de les stocker dans Vektordb et d'effectuer certaines opérations.
Les intégres ne sont que des représentations numériques d'une information, généralement sous forme de vecteurs. Vous pouvez transformer n'importe quelle sorte de données en intégres (par exemple? ️??) Et ils préserveront la signification des données d'origine. Si vous voulez en savoir plus sur les intégres , consultez les intégres de cartographie: de la signification aux vecteurs et du dos.
Définissons une fonction d'assistance pour appeler les modèles de cohére dans le semis Amazon
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' )et l'utiliser pour générer des intégres pour un petit sous-ensemble de nos données (réponses uniquement, pour l'instant)
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 ])Nous sommes maintenant prêts à initialiser VekTordb et à commencer à charger des données
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 ]}))En tant que vérification de la santé mentale, nous pouvons imprimer un petit échantillon de notre base de données
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 '} |
+-----+-------------------------+------------------------------------+
Notre instance VEKTordb est soutenue par une implémentation de la recherche approximative des voisins les plus proches (ANN) qui utilise des arbres binaires pour représenter différentes partitions / divisions de l'hypero-espace.
Ces partitions sont générées en choisissant deux vecteurs au hasard, en trouvant l'hyperplan à équidistant entre les deux, puis en divisant les autres points en left et right en fonction de quel côté ils sont
Ce processus est répété jusqu'à ce que nous ayons au plus k éléments de chaque nœud (partition)
Nous pouvons obtenir de meilleurs résultats en générant une forêt d'arbres *? Et les rechercher tous, alors faisons-le:
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 " )Voici une représentation du premier arbre de notre forêt (les nœuds montrent le nombre d'instances dans chaque partition)
__________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
Enfin, nous pouvons exécuter une requête en recherchant simplement la base de données pour des réponses similaires à une question cible.
Nous utilisons des fonctions de distance comme celles illustrées ci-dessous pour quantifier à quel point deux vecteurs sont similaires les uns aux autres.
Par exemple, si nous posons la première question dans notre ensemble de données de formation
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 ) Nous nous attendons à ce que la réponse avec le même index ( 0 ) soit le résultat supérieur:
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): Mémoire à long terme dans la recherche et les bases de données vectorielles AI - VectorCMU 15-445/645 (Carnegie Mellon): systèmes de base de données