Vector sets adalah struktur data Redis 8 yang menyimpan kumpulan elemen berlabel string dan setiap elemennya membawa satu vektor berdimensi tetap, sehingga pencarian dilakukan menurut kemiripan arah vektor alih-alih kecocokan teks. Topik ini membahas penambahan elemen dengan VADD dalam format VALUES dan FP32, pembacaan vektor tersimpan dengan VEMB, penghitungan elemen dan dimensi dengan VCARD serta VDIM, pencarian kemiripan dengan VSIM beserta opsi WITHSCORES dan COUNT, atribut JSON dengan VSETATTR dan VGETATTR, dan penghapusan elemen dengan VREM. Studi kasusnya berupa lima artikel panduan dengan vektor empat dimensi yang ditulis manual, sehingga setiap angka pada contoh dapat dihitung ulang.
Vektor dan kemiripan kosinus#
Vector set menyerupai sorted set dari sisi antarmukanya, tetapi yang menyertai setiap elemen bukan satu skor tunggal melainkan sebuah vektor, yaitu deretan bilangan pecahan yang mewakili makna objeknya. Vektor semacam ini lazim dihasilkan model embedding, yaitu model yang mengubah teks menjadi deretan bilangan, dan pembahasan pembuatannya berada di luar cakupan topik ini. Agar setiap angka dapat diperiksa ulang, seluruh contoh pada topik ini menggunakan vektor empat dimensi yang ditulis manual, misalnya vektor artikel-1 berisi 0.9 0.1 0.2 0.8.
Kemiripan dua vektor diukur dari arah keduanya melalui kemiripan kosinus (cosine similarity), bukan dari selisih angka per komponen. Dua vektor yang arahnya sama memperoleh skor tertinggi, sedangkan arah yang berlawanan memperoleh skor terendah. Skor yang dikembalikan VSIM berada pada rentang 1 ke 0, nilai 1 berarti vektor identik, dan dua vektor yang saling tegak lurus mendapat skor 0.5.
Karena penilaiannya menurut arah, dua artikel yang vektornya hampir searah dianggap berdekatan maknanya meskipun angka penyusunnya berbeda. Diagram berikut memperlihatkan dua pencarian yang berangkat dari artikel-1, yaitu artikel-2 yang vektornya hampir searah dan artikel-4 yang arahnya menyimpang lebih jauh.
Penyimpanan, kuantisasi, dan format VADD#
Redis menyiapkan pencarian kemiripan dengan menyusun elemen ke dalam graf HNSW (Hierarchical Navigable Small World), yaitu graf bertingkat yang memperkecil jumlah kandidat yang perlu dibandingkan pada setiap pencarian. VSIM menelusuri graf tersebut, sehingga pencarian tidak perlu membandingkan kueri dengan setiap elemen pada kumpulan yang besar. Perintah VLINKS dapat menampilkan tetangga setiap elemen pada graf HNSW, tetapi detail internalnya tidak perlu dipahami untuk menggunakan vector set.
Secara default Redis menyimpan vektor dalam bentuk kuantisasi int8, yaitu pemampatan setiap komponen menjadi bilangan bulat 8 bit untuk menghemat memori, dan jenis inilah yang disebut Q8. Akibat pemampatan tersebut, nilai yang dibaca VEMB merupakan pendekatan dari nilai aslinya. Opsi NOQUANT, yang diberikan pada VADD pertama untuk satu key, menyimpan vektor tanpa pemampatan, opsi Q8 menegaskan kuantisasi int8, sedangkan opsi BIN memilih kuantisasi biner yang lebih hemat dan lebih cepat dengan kualitas pencarian yang lebih rendah.
VADD menerima vektor dalam dua format. Format VALUES menyebut dimensinya terlebih dahulu, misalnya VALUES 4 diikuti empat angka desimal sebagai string, dan bentuk inilah yang paling praktis pada redis-cli. Format FP32 mengirim blob, yaitu deretan byte biner berisi bilangan pecahan 32 bit dengan urutan byte little-endian, sehingga blob biasanya disiapkan lewat kode program, terutama ketika vektor berasal dari keluaran model embedding. Seluruh elemen pada satu vector set wajib berdimensi sama, dan VADD terhadap elemen yang sudah ada berfungsi menimpa vektornya.
Menambah dan memeriksa elemen#
Perintah berikut membentuk vector set vs:artikel berisi lima elemen dengan dua format VADD. Blob untuk artikel-1 dibuat dengan Python karena format FP32 membutuhkan byte biner, dan fungsi struct.pack mengemas empat angka menjadi blob 16 byte mengikuti urutan byte little-endian. Opsi -X blob pada redis-cli membaca byte tersebut dari keluaran Python dan menempatkannya sebagai argumen vektor, sedangkan artikel-2 sampai artikel-5 ditambahkan melalui format VALUES. Setelah pembentukan, VCARD menghitung jumlah elemen, VDIM membaca dimensi vektor, dan VEMB menampilkan vektor yang tersimpan untuk artikel-1.
redis-cli del vs:artikel >/dev/null
# blob FP32 untuk vektor 0.9 0.1 0.2 0.8 dibuat dengan Python
python3 -c "import struct,sys; sys.stdout.buffer.write(struct.pack('<4f',0.9,0.1,0.2,0.8))" | redis-cli -X blob vadd vs:artikel FP32 blob artikel-1
# empat elemen berikutnya ditambahkan dengan format VALUES berdimensi 4
redis-cli vadd vs:artikel VALUES 4 0.8 0.2 0.3 0.7 artikel-2
redis-cli vadd vs:artikel VALUES 4 0.7 0.1 0.3 0.6 artikel-3
redis-cli vadd vs:artikel VALUES 4 0.1 0.9 0.8 0.2 artikel-4
redis-cli vadd vs:artikel VALUES 4 0.2 0.8 0.7 0.3 artikel-5
# jumlah elemen dan dimensi vektor
redis-cli vcard vs:artikel
redis-cli vdim vs:artikel
# membaca vektor tersimpan untuk artikel-1
redis-cli vemb vs:artikel artikel-11
1
1
1
1
5
4
0.8999999761581421
0.09921259433031082
0.19842518866062164
0.8007873892784119Balasan 1 dari setiap VADD menandakan elemen yang bersangkutan benar-benar baru. VEMB untuk artikel-1 mengembalikan 0.8999999761581421, 0.09921259433031082, 0.19842518866062164, dan 0.8007873892784119, nilai yang mendekati vektor aslinya tetapi tidak persis sama karena kuantisasi int8. Pergeseran kecil semacam ini wajar pada vector set yang menggunakan pengaturan default, sehingga pembacaan kembali vektor bukan cara yang tepat untuk memperoleh nilai aslinya.
Mencari elemen mirip dengan VSIM#
VSIM mengembalikan elemen yang paling mirip dengan sebuah vektor kueri dalam urutan skor menurun. Opsi ELE menjadikan vektor elemen yang sudah tersimpan sebagai kueri, sedangkan format VALUES memungkinkan pencarian langsung dari vektor yang tidak tersimpan sebagai elemen, misalnya vektor hasil model embedding atas pertanyaan pengguna. Opsi WITHSCORES menyisipkan skor pada setiap hasil, dan opsi COUNT membatasi jumlah hasilnya.
redis-cli del vs:artikel >/dev/null
# isi diisi ulang dengan vektor yang sama agar blok dapat dijalankan sendiri
redis-cli vadd vs:artikel VALUES 4 0.9 0.1 0.2 0.8 artikel-1
redis-cli vadd vs:artikel VALUES 4 0.8 0.2 0.3 0.7 artikel-2
redis-cli vadd vs:artikel VALUES 4 0.7 0.1 0.3 0.6 artikel-3
redis-cli vadd vs:artikel VALUES 4 0.1 0.9 0.8 0.2 artikel-4
redis-cli vadd vs:artikel VALUES 4 0.2 0.8 0.7 0.3 artikel-5
# kelima elemen paling mirip dengan artikel-1 beserta skornya
redis-cli vsim vs:artikel ele artikel-1 withscores count 5
# pencarian langsung dari vektor kueri tanpa menyimpan elemen baru
redis-cli vsim vs:artikel values 4 0.9 0.1 0.2 0.8 count 31
1
1
1
1
artikel-1
1
artikel-2
0.9945180714130402
artikel-3
0.9941712319850922
artikel-5
0.7333312332630157
artikel-4
0.6654322147369385
artikel-1
artikel-2
artikel-3Keluaran pertama memeringkat kelima elemen dari artikel-1, dengan artikel-2 memperoleh skor 0.9945180714130402 dan artikel-4 memperoleh skor terendah 0.6654322147369385. Elemen yang menjadi kueri muncul sebagai hasil pertama dengan skor 1 karena vektornya identik dengan dirinya, sehingga elemen kueri dapat disaring di sisi aplikasi apabila tidak diharapkan sebagai jawaban. Keluaran kedua melakukan pencarian dari vektor kueri yang sama tanpa menyimpannya sebagai elemen, dan COUNT 3 membatasi jawabannya menjadi artikel-1, artikel-2, dan artikel-3. Pencarian langsung seperti inilah dasar pencarian semantik, yaitu teks kueri diubah menjadi vektor oleh model embedding, kemudian vektornya dicocokkan dengan elemen yang sudah tersimpan.
Atribut JSON dan pencarian berfilter#
Setiap elemen dapat membawa atribut berupa satu objek JSON yang dilampirkan dengan VSETATTR, misalnya tema dan jumlah halaman artikel. VGETATTR membaca atribut tersebut kembali, sedangkan string kosong pada VSETATTR menghapusnya. Pada pencarian, opsi FILTER untuk VSIM menyaring kandidat menurut ekspresi yang ditulis terhadap atribut, sehingga kondisi atribut dan kemiripan vektor digabungkan dalam satu perintah. Ekspresi tersebut mendukung perbandingan teks dan angka beserta operator logika, misalnya .halaman > 10 untuk memilih artikel yang cukup panjang. VSIM juga menyediakan opsi WITHATTRIBS yang menyisipkan atribut setiap hasil pada keluarannya, dan VREM menghapus elemen beserta vektornya dari set.
redis-cli del vs:artikel >/dev/null
# isi diisi ulang dengan vektor yang sama agar blok dapat dijalankan sendiri
redis-cli vadd vs:artikel VALUES 4 0.9 0.1 0.2 0.8 artikel-1
redis-cli vadd vs:artikel VALUES 4 0.8 0.2 0.3 0.7 artikel-2
redis-cli vadd vs:artikel VALUES 4 0.7 0.1 0.3 0.6 artikel-3
redis-cli vadd vs:artikel VALUES 4 0.1 0.9 0.8 0.2 artikel-4
redis-cli vadd vs:artikel VALUES 4 0.2 0.8 0.7 0.3 artikel-5
# atribut JSON dilampirkan pada kelima elemen
redis-cli vsetattr vs:artikel artikel-1 '{"tema":"arsip cadangan","halaman":12}'
redis-cli vsetattr vs:artikel artikel-2 '{"tema":"arsip cadangan","halaman":9}'
redis-cli vsetattr vs:artikel artikel-3 '{"tema":"arsip cadangan","halaman":7}'
redis-cli vsetattr vs:artikel artikel-4 '{"tema":"jaringan","halaman":15}'
redis-cli vsetattr vs:artikel artikel-5 '{"tema":"jaringan","halaman":10}'
# membaca atribut artikel-1
redis-cli vgetattr vs:artikel artikel-1
# kemiripan yang dibatasi pada tema arsip cadangan
redis-cli vsim vs:artikel ele artikel-1 filter '.tema == "arsip cadangan"' count 3
# menghapus artikel-5 lalu menghitung ulang elemen
redis-cli vrem vs:artikel artikel-5
redis-cli vcard vs:artikel1
1
1
1
1
1
1
1
1
1
{"tema":"arsip cadangan","halaman":12}
artikel-1
artikel-2
artikel-3
1
4VGETATTR mengembalikan JSON artikel-1 persis sebagaimana disimpan. Pencarian berfilter menyingkirkan artikel-4 dan artikel-5 bertema jaringan dari kandidat, sehingga tiga jawaban teratasnya seluruhnya bertema arsip cadangan. Setelah artikel-5 dihapus dengan VREM, VCARD menghitung empat elemen tersisa.
Kesalahan umum#
Kesalahan pertama adalah menukar urutan vektor dan nama elemen pada VADD. Sintaksnya menempatkan format dan vektor lebih dahulu, sedangkan nama elemen menjadi argumen terakhir, dan urutan yang terbalik memunculkan pesan error ERR invalid vector specification. Seluruh blok contoh pada topik ini menaruh nama elemen di akhir perintah, sehingga pola penulisannya dapat disalin dengan aman.
Kesalahan kedua adalah membaca skor VSIM sebagai persentase kemiripan makna. Skor mengukur kedekatan arah vektor pada rentang 1 ke 0 dengan nilai 1 bagi vektor identik, sehingga artikel-4 yang temanya berbeda tetap memperoleh skor 0.6654322147369385. Penilaian kualitas pencarian dilakukan terhadap urutan hasilnya, bukan terhadap besaran angka skornya.
Kesalahan ketiga adalah mengganti vektor elemen tanpa disadari. VADD terhadap elemen yang sudah ada menimpa vektornya dan mengembalikan 0 tanpa pesan error, sehingga satu pemanggilan yang keliru dapat mengubah hasil pencarian seluruh kumpulan. Pembaruan vektor massal, misalnya ketika model embedding diganti versinya, sebaiknya dilakukan dengan menyusun ulang set pada key baru.
Ringkasan#
- Vector set menyimpan elemen berlabel string yang setiap anggotanya membawa vektor berdimensi tetap, dan pencariannya menurut kemiripan arah vektor.
- VADD menerima format VALUES dengan dimensi dan format FP32 berupa blob biner, sedangkan kuantisasi int8 default membuat nilai VEMB menjadi pendekatan dari nilai aslinya.
- VSIM dengan opsi ELE atau VALUES mengembalikan elemen termirip dalam urutan skor menurun, dan opsi WITHSCORES serta COUNT mengatur bentuk jawabannya.
- VSETATTR dan VGETATTR mengelola atribut JSON per elemen, FILTER menyaring hasil VSIM menurut atribut, dan VREM menghapus elemen.
Referensi#
- Vector sets — Redis — Dokumentasi tipe data vector sets beserta contoh dasar dan catatan urutan byte format FP32.
- VADD — Redis — Sintaks format FP32 dan VALUES beserta opsi kuantisasi Q8, NOQUANT, dan BIN.
- VSIM — Redis — Opsi ELE, WITHSCORES, COUNT, dan FILTER pada pencarian kemiripan.
- VEMB — Redis — Pembacaan vektor tersimpan beserta opsi RAW.
- VSETATTR — Redis — Atribut JSON per elemen beserta penghapusannya melalui string kosong.