Gunakan fitur kueri vektor k-nearest neighbor (KNN) dari Tablestore untuk mengidentifikasi item data yang paling mirip dengan vektor target dalam dataset berskala besar. Jika hasil pencarian semantik tidak sesuai harapan, ikuti panduan pemecahan masalah ini untuk meningkatkan kinerja fitur tersebut.
Rumus penilaian untuk kueri vektor KNN
Fitur kueri vektor KNN dari Tablestore mendukung pencarian tetangga terdekat berdasarkan vektor dan cocok untuk skenario seperti generasi data terkaya (RAG), sistem rekomendasi, deteksi kesamaan, pemrosesan bahasa alami (NLP), serta pencarian semantik. Untuk informasi lebih lanjut, lihat Menggunakan Kueri Vektor KNN.
Fitur kueri vektor KNN mendukung algoritma pengukuran jarak berikut: euclidean, dot_product, dan cosine. Rumus penilaian bervariasi berdasarkan algoritma yang digunakan. Tablestore menggunakan rumus penilaian ini untuk mengukur kemiripan antar vektor. Tabel berikut menjelaskan rumus penilaian yang digunakan.
Jenis metrik | Rumus penilaian |
euclidean |
|
dot_product |
|
cosine |
|
Pemecahan masalah dan analisis
1. Periksa metode pengurutan
Pastikan metode pengurutan diatur ke ScoreSort saat menggunakan fitur kueri vektor KNN untuk mengurutkan hasil berdasarkan skor. Secara default, hasil diurutkan berdasarkan kunci utama.
2. Sesuaikan kombinasi KnnVectorQuery dan BoolQuery
Saat menggunakan kombinasi KnnVectorQuery dan BoolQuery, disarankan menetapkan tipe kueri indeks pencarian ke KnnVectorQuery. Jika kondisi kueri BoolQuery disertakan dalam filter kueri vektor KNN (Filter), penilaian tidak akan terpengaruh.
Jika tipe kueri diatur ke BoolQuery dan KnnVectorQuery ditentukan sebagai subkueri dari BoolQuery, kondisi kueri lainnya dari BoolQuery dapat memengaruhi penilaian. Untuk informasi lebih lanjut, lihat Lampiran 1: Kombinasi Kueri Vektor KNN dan Kueri Boolean.
Contoh kode Java berikut menunjukkan cara menggunakan fitur kueri vektor KNN:
private static void knnVectorQuery(SyncClient client) {
SearchQuery searchQuery = new SearchQuery();
KnnVectorQuery query = new KnnVectorQuery();
query.setFieldName("Col_Vector");
query.setTopK(10); // Mengembalikan 10 vektor teratas dalam tabel yang memiliki kemiripan tertinggi dengan vektor yang ditentukan.
query.setFloat32QueryVector(new float[]{0.1f, 0.2f, 0.3f, 0.4f});
// Tentukan kondisi kueri untuk 10 vektor teratas: nilai kolom Col_Keyword adalah hangzhou dan nilai kolom Col_Long kurang dari 4.
query.setFilter(QueryBuilders.bool()
.must(QueryBuilders.term("Col_Keyword", "hangzhou"))
.must(QueryBuilders.range("Col_Long").lessThan(4))
);
searchQuery.setQuery(query);
searchQuery.setLimit(10);
// Urutkan hasil kueri berdasarkan skor.
searchQuery.setSort(new Sort(Collections.singletonList(new ScoreSort())));
SearchRequest searchRequest = new SearchRequest("<TABLE_NAME>", "<SEARCH_INDEX_NAME>", searchQuery);
SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
columnsToGet.setColumns(Arrays.asList("Col_Keyword", "Col_Long"));
searchRequest.setColumnsToGet(columnsToGet);
// Panggil operasi Pencarian.
SearchResponse resp = client.search(searchRequest);
for (SearchHit hit : resp.getSearchHits()) {
// Tampilkan skor.
System.out.println(hit.getScore());
// Tampilkan data.
System.out.println(hit.getRow());
}
}3. Periksa kinerja pembuatan vektor
Tablestore menghitung kemiripan antar vektor tanpa mempertimbangkan apakah pembuatan vektor optimal. Vektor dalam database dan vektor yang ingin Anda kueri dihasilkan oleh model Embedding eksternal. Dalam beberapa kasus, vektor yang dihasilkan mungkin tidak akurat. Untuk memperbaiki kinerja pembuatan vektor yang buruk, lakukan langkah-langkah berikut:
Gunakan Metode atau Alat Lain Selain Tablestore untuk Penilaian.
Berikan nama vektor yang ingin Anda kueri sebagai
Vektor adan vektor yang ingin Anda kembalikan dari tabel Tablestore sebagaiVektor b.CatatanAnda dapat menggunakan indeks pencarian, indeks sekunder, atau operasi lain untuk membaca data dari tabel data dalam model Kolom Lebar guna mendapatkan data
Vektor b.Hitung
Skor a, yang mewakili kemiripan antara Vektor a dan Vektor b, menggunakan metodeMetricFunction.COSINE.compare(a, b)yang dijelaskan dalam Lampiran: Contoh Kode untuk Rumus Penilaian Kueri Vektor KNN.
Gunakan Tablestore untuk Penilaian.
Gunakan fitur kueri vektor KNN dari Tablestore untuk menanyakan
Vektor adan periksaSkor bdari setiap baris dalam respons.Bandingkan dan Analisis Skor.
Jika tidak ada baris yang berisi
Vektor bditemukan dalam kueri vektor KNN Tablestore, secara teoriSkor bdari setiap baris dalam respons lebih tinggi daripadaSkor a.Hal ini menunjukkan bahwa kinerja buruk kueri vektor KNN disebabkan oleh pembuatan vektor yang tidak optimal dari model Embedding. Respons kueri mencakup data vektor dengan skor lebih tinggi daripada yang diharapkan, sementara data vektor dengan skor lebih rendah tidak dikembalikan.
Pilih Solusi.
Masalah ini sering terjadi di bidang spesialisasi. Misalnya, pembuatan vektor mungkin tidak bekerja dengan baik untuk istilah dalam industri bioteknologi dan medis jika menggunakan model Embedding umum. Istilah tertentu mungkin memiliki semantik serupa dalam bidang spesialisasi tetapi sangat berbeda dalam model Embedding umum. Dalam hal ini, pertimbangkan solusi berikut:
Gunakan model Embedding yang didedikasikan untuk bidang spesialisasi.
ModelScope menyediakan berbagai model Embedding. Pilih model yang sesuai untuk bidang spesialisasi seperti layanan publik, e-commerce, perawatan kesehatan, hukum, atau keuangan berdasarkan kebutuhan bisnis Anda. Untuk informasi lebih lanjut, lihat Daftar Model Embedding.
Kumpulkan korpus spesialisasi dalam jumlah besar secara legal untuk melatih model Embedding yang sesuai.
Lampiran: Contoh kode untuk rumus penilaian kueri vektor KNN
Contoh kode Java berikut menunjukkan cara menggunakan rumus penilaian algoritma pengukuran jarak:
import java.util.concurrent.ThreadLocalRandom;
public class CompareVector {
public static void main(String[] args) {
// Tentukan a sebagai vektor yang ingin Anda kueri.
float[] a = randomVector(512);
// Tentukan b sebagai vektor yang Anda harapkan baris yang dikembalikan termasuk.
float[] b = randomVector(512);
// Tentukan algoritma pengukuran kemiripan yang Anda konfigurasikan dalam indeks pencarian untuk menghasilkan skor.
System.out.println(MetricFunction.COSINE.compare(a, b));
}
public static float[] randomVector(int dim) {
float[] vec = new float[dim];
for (int i = 0; i < dim; i++) {
vec[i] = ThreadLocalRandom.current().nextFloat();
if (ThreadLocalRandom.current().nextBoolean()) {
vec[i] = -vec[i];
}
}
return l2normalize(vec, true);
}
public static float[] l2normalize(float[] v, boolean throwOnZero) {
double squareSum = 0.0f;
int dim = v.length;
for (float x : v) {
squareSum += x * x;
}
if (squareSum == 0) {
if (throwOnZero) {
throw new IllegalArgumentException("normalize a zero-length vector");
} else {
return v;
}
}
double length = Math.sqrt(squareSum);
for (int i = 0; i < dim; i++) {
v[i] /= length;
}
return v;
}
public enum MetricFunction {
/**
* Jarak Euclidean.
*/
EUCLIDEAN {
@Override
public float compare(float[] v1, float[] v2) {
return 1 / (1 + VectorUtil.squareDistance(v1, v2));
}
},
/**
* Dot product.
*/
DOT_PRODUCT {
@Override
public float compare(float[] v1, float[] v2) {
return (1 + VectorUtil.dotProduct(v1, v2)) / 2;
}
},
/**
* Cosine.
*/
COSINE {
@Override
public float compare(float[] v1, float[] v2) {
return (1 + VectorUtil.cosine(v1, v2)) / 2;
}
};
public abstract float compare(float[] v1, float[] v2);
}
static final class VectorUtil {
private static void checkParam(float[] a, float[] b) {
if (a.length != b.length) {
throw new IllegalArgumentException("vector dimensions differ: " + a.length + "!=" + b.length);
}
}
public static float dotProduct(float[] a, float[] b) {
checkParam(a, b);
float res = 0f;
for (int i = 0; i < a.length; i++) {
res += b[i] * a[i];
}
return res;
}
public static float cosine(float[] a, float[] b) {
checkParam(a, b);
float sum = 0.0f;
float norm1 = 0.0f;
float norm2 = 0.0f;
for (int i = 0; i < a.length; i++) {
float elem1 = a[i];
float elem2 = b[i];
sum += elem1 * elem2;
norm1 += elem1 * elem1;
norm2 += elem2 * elem2;
}
return (float) (sum / Math.sqrt((double) norm1 * (double) norm2));
}
public static float squareDistance(float[] a, float[] b) {
checkParam(a, b);
float sum = 0.0f;
for (int i = 0; i < a.length; i++) {
float difference = a[i] - b[i];
sum += difference * difference;
}
return sum;
}
}
}

