Cette page explique comment effectuer une recherche de similarité vectorielle dans Spanner à l'aide des fonctions vectorielles de distance cosinus, de distance euclidienne et de produit scalaire pour trouver les K voisins les plus proches. Ces informations s'appliquent aux bases de données utilisant le dialecte GoogleSQL et celles utilisant le dialecte PostgreSQL. Avant de lire cette page, il est important que vous compreniez les concepts suivants :
- Distance euclidienne : mesure la distance la plus courte entre deux vecteurs.
- Distance cosinus : mesure le cosinus de l'angle entre deux vecteurs.
- Produit scalaire : calcule le cosinus de l'angle multiplié par le produit des magnitudes de vecteurs correspondantes. Si vous savez que tous les embeddings vectoriels de votre ensemble de données sont normalisés, vous pouvez utiliser
DOT_PRODUCT()
comme fonction de distance. - K-plus proches voisins (KNN) : algorithme d'apprentissage automatique supervisé utilisé pour résoudre des problèmes de classification ou de régression.
Vous pouvez utiliser des fonctions de distance vectorielle pour effectuer une recherche vectorielle des k plus proches voisins (KNN) pour des cas d'utilisation tels que la recherche de similarités ou la génération augmentée par récupération. Spanner est compatible avec les fonctions COSINE_DISTANCE()
, EUCLIDEAN_DISTANCE()
et DOT_PRODUCT()
, qui fonctionnent sur les embeddings vectoriels et vous permettent de trouver le KNN de l'embedding d'entrée.
Par exemple, une fois que vous avez généré et enregistré vos données opérationnelles Spanner en tant qu'embeddings vectoriels, vous pouvez fournir ces embeddings vectoriels comme paramètre d'entrée dans votre requête pour trouver les vecteurs les plus proches dans l'espace N-dimensionnel afin de rechercher des éléments sémantiquement similaires ou associés.
Les trois fonctions de distance prennent les arguments vector1
et vector2
, qui sont de type array<>
, et doivent comporter les mêmes dimensions et avoir la même longueur. Pour en savoir plus sur ces fonctions, consultez les pages suivantes :
COSINE_DISTANCE()
dans GoogleSQLEUCLIDEAN_DISTANCE()
dans GoogleSQLDOT_PRODUCT()
dans GoogleSQL- Fonctions mathématiques dans PostgreSQL
(
spanner.cosine_distance()
,spanner.euclidean_distance()
etspanner.dot_product()
) - Choisissez parmi les fonctions de distance vectorielle pour mesurer la similarité des embeddings vectoriels.
Exemples
Les exemples suivants montrent la recherche KNN, la recherche KNN sur des données partitionnées et l'utilisation d'un index secondaire avec KNN.
Les exemples utilisent tous EUCLIDEAN_DISTANCE()
. Vous pouvez également utiliser COSINE_DISTANCE()
. De plus, si tous les embeddings vectoriels de votre ensemble de données sont normalisés, vous pouvez utiliser DOT_PRODUCT()
comme fonction de distance.
Exemple 1 : Recherche KNN
Prenons l'exemple d'une table Documents
qui comporte une colonne (DocEmbedding
) d'intégrations de texte précalculées à partir de la colonne DocContents
octets.
GoogleSQL
CREATE TABLE Documents (
UserId INT64 NOT NULL,
DocId INT64 NOT NULL,
Author STRING(1024),
DocContents BYTES(MAX),
DocEmbedding ARRAY<FLOAT32>
) PRIMARY KEY (UserId, DocId);
PostgreSQL
CREATE TABLE Documents (
UserId bigint NOT NULL,
DocId bigint NOT NULL,
Author varchar(1024),
DocContents bytea,
DocEmbedding float4[],
PRIMARY KEY (UserId, DocId)
);
En supposant qu'un embedding d'entrée pour "baseball, mais pas baseball professionnel" soit le tableau [0.3, 0.3, 0.7, 0.7]
, vous pouvez trouver les cinq documents les plus proches qui correspondent à la requête suivante :
GoogleSQL
SELECT DocId, DocEmbedding FROM Documents
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
ARRAY<FLOAT32>[0.3, 0.3, 0.7, 0.8])
LIMIT 5;
PostgreSQL
SELECT DocId, DocEmbedding FROM Documents
ORDER BY spanner.euclidean_distance(DocEmbedding,
'{0.3, 0.3, 0.7, 0.8}'::float4[])
LIMIT 5;
Résultats attendus de cet exemple :
Documents
+---------------------------+-----------------+
| DocId | DocEmbedding |
+---------------------------+-----------------+
| 24 | [8, ...] |
+---------------------------+-----------------+
| 25 | [6, ...] |
+---------------------------+-----------------+
| 26 | [3.2, ...] |
+---------------------------+-----------------+
| 27 | [38, ...] |
+---------------------------+-----------------+
| 14229 | [1.6, ...] |
+---------------------------+-----------------+
Exemple 2 : Recherche KNN sur des données partitionnées
La requête de l'exemple précédent peut être modifiée en ajoutant des conditions à la clause WHERE
pour limiter la recherche vectorielle à un sous-ensemble de vos données. Une application courante consiste à effectuer des recherches sur des données partitionnées, telles que des lignes appartenant à un UserId
spécifique.
GoogleSQL
SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
ARRAY<FLOAT32>[0.3, 0.3, 0.7, 0.8])
LIMIT 5;
PostgreSQL
SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY spanner.euclidean_distance(DocEmbedding,
'{0.3, 0.3, 0.7, 0.8}'::float4[])
LIMIT 5;
Résultats attendus de cet exemple :
Documents
+-----------+-----------------+-----------------+
| UserId | DocId | DocEmbedding |
+-----------+-----------------+-----------------+
| 18 | 234 | [12, ...] |
+-----------+-----------------+-----------------+
| 18 | 12 | [1.6, ...] |
+-----------+-----------------+-----------------+
| 18 | 321 | [22, ...] |
+-----------+-----------------+-----------------+
| 18 | 432 | [3, ...] |
+-----------+-----------------+-----------------+
Exemple 3 : Recherche KNN sur des plages d'index secondaires
Si le filtre de clause WHERE
que vous utilisez ne fait pas partie de la clé primaire de la table, vous pouvez créer un index secondaire pour accélérer l'opération avec une analyse d'index uniquement.
GoogleSQL
CREATE INDEX DocsByAuthor
ON Documents(Author)
STORING (DocEmbedding);
SELECT Author, DocId, DocEmbedding FROM Documents
WHERE Author="Mark Twain"
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
<embeddings for "book about the time traveling American">)
LIMIT 5;
PostgreSQL
CREATE INDEX DocsByAuthor
ON Documents(Author)
INCLUDE (DocEmbedding);
SELECT Author, DocId, DocEmbedding FROM Documents
WHERE Author="Mark Twain"
ORDER BY spanner.euclidean_distance(DocEmbedding,
<embeddings for "that book about the time traveling American">)
LIMIT 5;
Résultats attendus de cet exemple :
Documents
+------------+-----------------+-----------------+
| Author | DocId | DocEmbedding |
+------------+-----------------+-----------------+
| Mark Twain | 234 | [12, ...] |
+------------+-----------------+-----------------+
| Mark Twain | 12 | [1.6, ...] |
+------------+-----------------+-----------------+
| Mark Twain | 321 | [22, ...] |
+------------+-----------------+-----------------+
| Mark Twain | 432 | [3, ...] |
+------------+-----------------+-----------------+
| Mark Twain | 375 | [9, ...] |
+------------+-----------------+-----------------+
Étapes suivantes
En savoir plus sur les fonctions GoogleSQL
COSINE_DISTANCE()
,EUCLIDEAN_DISTANCE()
etDOT_PRODUCT()
En savoir plus sur les fonctions PostgreSQL
spanner.cosine_distance()
,spanner.euclidean_distance()
etspanner.dot_product()
Découvrez comment choisir parmi les fonctions de distance vectorielle pour mesurer la similarité des embeddings vectoriels.