Menemukan perkiraan tetangga terdekat (ANN) dan menyertakan embedding vektor kueri

Halaman ini menjelaskan cara menemukan tetangga terdekat (ANN) dan membuat kueri embedding vektor menggunakan fungsi jarak ANN.

Jika set data kecil, Anda dapat menggunakan K-nearest neighbors (KNN) untuk menemukan vektor k-terdekat yang tepat. Namun, seiring bertambahnya ukuran set data, latensi dan biaya penelusuran KNN juga meningkat. Anda dapat menggunakan ANN untuk menemukan k-tetangga terdekat yang diperkirakan dengan latensi dan biaya yang berkurang secara signifikan.

Dalam penelusuran ANN, vektor k yang ditampilkan bukanlah k tetangga terdekat yang sebenarnya karena penelusuran ANN menghitung perkiraan jarak dan mungkin tidak melihat semua vektor dalam set data. Terkadang, beberapa vektor yang bukan termasuk k-tetangga terdekat teratas akan ditampilkan. Hal ini dikenal sebagai kehilangan ingatan. Seberapa besar kehilangan perolehan yang dapat Anda terima bergantung pada kasus penggunaan, tetapi dalam sebagian besar kasus, kehilangan sedikit perolehan sebagai imbalan atas peningkatan performa database adalah pertukaran yang dapat diterima.

Untuk mengetahui detail selengkapnya tentang fungsi jarak perkiraan yang didukung di Spanner, lihat halaman referensi berikut untuk dialek database Anda:

Mengueri embedding vektor

Spanner mempercepat penelusuran vektor approximate nearest neighbor (ANN) dengan menggunakan indeks vektor. Anda dapat menggunakan indeks vektor untuk mengkueri embedding vektor. Untuk mengkueri embedding vektor, Anda harus membuat indeks vektor terlebih dahulu. Anda kemudian dapat menggunakan salah satu dari tiga fungsi jarak perkiraan untuk menemukan ANN.

Batasan saat menggunakan fungsi jarak jauh perkiraan mencakup hal berikut:

  • Fungsi jarak perkiraan harus menghitung jarak antara kolom penyematan dan ekspresi konstanta (misalnya, parameter atau literal).
  • Output fungsi jarak perkiraan harus digunakan dalam klausa ORDER BY sebagai satu-satunya kunci pengurutan, dan LIMIT harus ditentukan setelah ORDER BY.
  • Kueri harus secara eksplisit mengecualikan baris yang tidak diindeks. Dalam sebagian besar kasus, ini berarti kueri harus menyertakan klausa WHERE <column_name> IS NOT NULL yang cocok dengan definisi indeks vektor, kecuali jika kolom sudah ditandai sebagai NOT NULL dalam definisi tabel.

Untuk mengetahui daftar batasan mendetail, lihat halaman referensi fungsi jarak perkiraan.

Contoh

Pertimbangkan tabel Documents yang memiliki kolom DocEmbedding dari sematan teks yang telah dihitung sebelumnya dari kolom byte DocContents, dan kolom NullableDocEmbedding yang diisi dari sumber lain yang mungkin bernilai null.

GoogleSQL

CREATE TABLE Documents (
  UserId       INT64 NOT NULL,
  DocId        INT64 NOT NULL,
  Author       STRING(1024),
  DocContents  BYTES(MAX),
  DocEmbedding ARRAY<FLOAT32> NOT NULL,
  NullableDocEmbedding ARRAY<FLOAT32>,
  WordCount    INT64
) PRIMARY KEY (UserId, DocId);

PostgreSQL

CREATE TABLE documents (
  user_id      bigint not null,
  doc_id       bigint not null,
  author       varchar(1024),
  doc_contents bytea,
  doc_embedding float4[] not null,
  nullable_doc_embedding float4[],
  word_count   bigint,
  PRIMARY KEY (user_id, doc_id)
);

Untuk menelusuri 100 vektor terdekat ke [1.0, 2.0, 3.0]:

GoogleSQL

SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

PostgreSQL

SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
  options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;

Jika kolom penyematan dapat bernilai null:

GoogleSQL

SELECT DocId
FROM Documents
WHERE NullableDocEmbedding IS NOT NULL AND WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

PostgreSQL

SELECT doc_id
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
  options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;

Langkah berikutnya