Melakukan penelusuran kemiripan vektor di Spanner dengan menemukan K-nearest neighbors

Halaman ini menjelaskan cara melakukan penelusuran kesamaan vektor di Spanner dengan menggunakan fungsi vektor jarak kosinus, jarak Euclidean, dan perkalian titik untuk menemukan K-nearest neighbors. Informasi ini berlaku untuk database dialek GoogleSQL dan database dialek PostgreSQL. Sebelum membaca halaman ini, Anda harus memahami konsep berikut:

  • Jarak Euclidean: mengukur jarak terpendek antara dua vektor.
  • Jarak kosinus: mengukur kosinus sudut antara dua vektor.
  • Perkalian titik: menghitung kosinus sudut yang dikalikan dengan hasil perkalian besaran vektor yang sesuai. Jika Anda tahu bahwa semua embedding vektor dalam set data Anda telah dinormalisasi, maka Anda dapat menggunakan DOT_PRODUCT() sebagai fungsi jarak.
  • K-nearest neighbors (KNN): algoritma machine learning terawasi yang digunakan untuk memecahkan masalah klasifikasi atau regresi.

Anda dapat menggunakan fungsi jarak vektor untuk melakukan penelusuran vektor tetangga K-terdekat (KNN) untuk kasus penggunaan seperti penelusuran kesamaan atau retrieval-augmented generation. Spanner mendukung fungsi COSINE_DISTANCE(), EUCLIDEAN_DISTANCE(), dan DOT_PRODUCT(), yang beroperasi pada embedding vektor, sehingga Anda dapat menemukan KNN dari embedding input.

Misalnya, setelah membuat dan menyimpan data Spanner operasional sebagai embedding vektor, Anda dapat memberikan embedding vektor ini sebagai parameter input dalam kueri untuk menemukan vektor terdekat dalam ruang N-dimensi untuk menelusuri item yang secara semantik mirip atau terkait.

Ketiga fungsi jarak mengambil argumen vector1 dan vector2, yang berjenis array<>, dan harus terdiri dari dimensi yang sama dan memiliki panjang yang sama. Untuk mengetahui detail selengkapnya tentang fungsi ini, lihat:

Contoh

Contoh berikut menunjukkan penelusuran KNN, penelusuran KNN atas data berpartisi, dan penggunaan indeks sekunder dengan KNN.

Semua contoh menggunakan EUCLIDEAN_DISTANCE(). Anda juga dapat menggunakan COSINE_DISTANCE(). Selain itu, jika semua embedding vektor dalam set data Anda dinormalisasi, Anda dapat menggunakan DOT_PRODUCT() sebagai fungsi jarak.

Pertimbangkan tabel Documents yang memiliki kolom (DocEmbedding) embedding teks yang telah dikomputasi sebelumnya dari kolom DocContents byte.

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)
);

Dengan asumsi bahwa embedding input untuk "bisbol, tetapi bukan bisbol profesional" adalah array [0.3, 0.3, 0.7, 0.7], Anda dapat menemukan lima dokumen terdekat teratas yang cocok, dengan kueri berikut:

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;

Hasil yang diharapkan dari contoh ini:

Documents
+---------------------------+-----------------+
| DocId                     | DocEmbedding    |
+---------------------------+-----------------+
| 24                        | [8, ...]        |
+---------------------------+-----------------+
| 25                        | [6, ...]        |
+---------------------------+-----------------+
| 26                        | [3.2, ...]      |
+---------------------------+-----------------+
| 27                        | [38, ...]       |
+---------------------------+-----------------+
| 14229                     | [1.6, ...]      |
+---------------------------+-----------------+

Contoh 2: Penelusuran KNN pada data yang dipartisi

Kueri dalam contoh sebelumnya dapat diubah dengan menambahkan kondisi ke klausa WHERE untuk membatasi penelusuran vektor ke subset data Anda. Salah satu penerapan umum hal ini adalah untuk menelusuri data yang dipartisi, seperti baris yang termasuk dalam UserId tertentu.

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;

Hasil yang diharapkan dari contoh ini:

Documents
+-----------+-----------------+-----------------+
| UserId    | DocId           | DocEmbedding    |
+-----------+-----------------+-----------------+
| 18        | 234             | [12, ...]       |
+-----------+-----------------+-----------------+
| 18        | 12              | [1.6, ...]      |
+-----------+-----------------+-----------------+
| 18        | 321             | [22, ...]       |
+-----------+-----------------+-----------------+
| 18        | 432             | [3, ...]        |
+-----------+-----------------+-----------------+

Contoh 3: Penelusuran KNN melalui rentang indeks sekunder

Jika filter klausa WHERE yang Anda gunakan bukan bagian dari kunci utama tabel, Anda dapat membuat indeks sekunder untuk mempercepat operasi dengan pemindaian khusus indeks.

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;

Hasil yang diharapkan dari contoh ini:

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, ...]        |
+------------+-----------------+-----------------+

Langkah berikutnya