Pengambilan tahap pertama pada basis data vektor memprioritaskan kecepatan, sehingga peringkat yang dihasilkannya masih kasar. Topik ini menjelaskan reranking sebagai tahap kedua yang menata ulang kandidat hasil tahap pertama dengan cross-encoder, membandingkan biaya dan presisi cross-encoder dengan bi-encoder, lalu menunjukkan perubahan peringkatnya melalui simulasi kecil yang dijalankan sungguhan.
Pipeline pencarian dua tahap#
Reranking menambahkan satu tahap di belakang pencarian vektor, dan tahap itulah yang menentukan kualitas akhirnya. Tahap pertama menggunakan bi-encoder, yaitu model embedding yang mengkodekan query dan dokumen secara terpisah, dijalankan di dalam basis data vektor bersama filter yang diperlukan. Tahap ini cepat karena vektor dokumen sudah diindeks, tetapi peringkatnya aproksimatif dan kasar. Konsekuensinya, tahap pertama sengaja mengambil kandidat yang lebih banyak daripada yang dibutuhkan, misalnya 100 kandidat padahal aplikasi hanya menampilkan 10.
Tahap kedua menyaring kumpulan kandidat tersebut dengan model yang lebih teliti, lalu mengembalikan 10 teratas sebagai hasil akhir. Diagram berikut merangkum alur dua tahap ini dari query menuju hasil akhirnya.
Pembagian kerja ini menempatkan biaya di tempat yang tepat. Pemindaian indeks ANN yang murah menangani seluruh collection, sedangkan model yang mahal hanya menghadapi 100 kandidat. Kualitas akhirnya mendekati kualitas model yang teliti, dengan kecepatan yang mendekati kecepatan indeks ANN.
Reranking tidak mengubah isi basis data sama sekali, karena tahapnya berjalan setelah hasil pencarian keluar. Tidak ada indeks yang dibangun ulang dan tidak ada data yang ditulis ulang, sehingga penerapannya hanya menambah satu langkah komputasi di antara pencarian dan tampilan hasilnya.
Kekasaran peringkat tahap pertama berakar pada strukturnya. Seluruh dokumen dipadatkan menjadi satu vektor tunggal, sehingga interaksi antar kata di dalam dokumen maupun di antara query dan dokumen tidak dapat ditangkap. Kedekatan vektor menandakan dokumen yang membahas topik serupa, tetapi tidak menjamin dokumen tersebut paling menjawab permintaan secara tepat.
Bi-encoder dan cross-encoder#
Perbedaan keduanya terletak pada cara membaca teks. Bi-encoder mengkodekan query dan dokumen masing-masing menjadi satu vektor, kemudian relevansinya dihitung sebagai jarak atau kesamaan arah antar keduanya. Karena dokumen dikodekan terpisah dari query, vektor dokumen dapat dihitung lebih dahulu, disimpan, dan diindeks, sehingga biaya per dokumen saat pencarian hanya satu operasi jarak.
Cross-encoder membaca pasangan query dan dokumen bersama-sama dalam satu model, sehingga setiap token dokumen dapat berinteraksi langsung dengan setiap token query. Interaksi ini menghasilkan skor relevansi yang jauh lebih presisi, misalnya mampu membedakan dokumen yang menyebut istilah yang diminta hanya sebagai glosarium dari dokumen yang benar-benar membahasnya. Biayanya membesar, karena tidak ada skor yang dapat dihitung lebih dahulu dan setiap pasangan membutuhkan satu perhitungan model penuh saat query datang.
Perbedaan itu terlihat pada dokumen yang menyebut istilah query hanya sekali di tengah daftar panjang. Bi-encoder memasukkan istilah itu ke dalam satu vektor bersama seluruh isi dokumen, sehingga pengaruhnya terencerkan, sedangkan cross-encoder membaca pasangan itu utuh dan dapat menilai seberapa langsung dokumen menjawab pertanyaannya.
Tabel berikut merangkum perbandingan keduanya beserta perannya di dalam pipeline.
| Aspek | Bi-encoder | Cross-encoder |
|---|---|---|
| Cara membaca | query dan dokumen dikodekan terpisah | pasangan query dan dokumen dibaca bersama |
| Kapan dihitung | vektor dokumen dapat dihitung lebih dahulu | skor dihitung saat query datang |
| Biaya per dokumen | satu operasi jarak | satu perhitungan model penuh |
| Presisi peringkat | kasar | lebih presisi |
| Peran | tahap pengambilan | tahap rerank |
Biaya cross-encoder yang jauh lebih mahal per pasangan membuatnya hanya digunakan pada kumpulan kandidat kecil, misalnya 10 kandidat akhir dari 100 kandidat tahap pertama. Membalik pembagian jumlah keduanya tidak masuk akal, karena menilai seluruh collection dengan cross-encoder sama saja dengan membuang seluruh manfaat indeks.
Simulasi perubahan peringkat#
Simulasi berikut menampilkan sepuluh kandidat dari tahap pengambilan pertama beserta dua kolom skor, yaitu skor tahap pertama dan skor rerank. Kedua kolom itu berupa konstanta ilustrasi untuk menunjukkan mekanismenya, bukan keluaran model sungguhan, karena model tidak tersedia di sandbox.
"""Ilustrasi perubahan peringkat setelah tahap rerank."""
import numpy as np
# Sepuluh kandidat dari tahap pengambilan pertama. Kedua kolom skor adalah
# konstanta ilustrasi untuk menunjukkan mekanisme, bukan keluaran model
# bi-encoder maupun cross-encoder sungguhan.
kandidat = ["d01", "d02", "d03", "d04", "d05", "d06", "d07", "d08", "d09", "d10"]
skor_tahap1 = np.array([0.92, 0.90, 0.88, 0.85, 0.83, 0.81, 0.79, 0.76, 0.74, 0.71])
skor_rerank = np.array([0.61, 0.58, 0.66, 0.55, 0.70, 0.52, 0.63, 0.93, 0.48, 0.45])
urut_tahap1 = np.argsort(-skor_tahap1)
urut_rerank = np.argsort(-skor_rerank)
print("posisi akhir dokumen skor tahap 1 skor rerank pergeseran")
for pos, i in enumerate(urut_rerank, start=1):
awal = int(np.flatnonzero(urut_tahap1 == i)[0]) + 1
print(f"{pos:>2} {kandidat[i]} {skor_tahap1[i]:.2f} "
f"{skor_rerank[i]:.2f} {awal} -> {pos}")posisi akhir dokumen skor tahap 1 skor rerank pergeseran
1 d08 0.76 0.93 8 -> 1
2 d05 0.83 0.70 5 -> 2
3 d03 0.88 0.66 3 -> 3
4 d07 0.79 0.63 7 -> 4
5 d01 0.92 0.61 1 -> 5
6 d02 0.90 0.58 2 -> 6
7 d04 0.85 0.55 4 -> 7
8 d06 0.81 0.52 6 -> 8
9 d09 0.74 0.48 9 -> 9
10 d10 0.71 0.45 10 -> 10Keluaran memperlihatkan pergeseran yang tipikal. Dokumen d08 yang tadinya menempati peringkat tujuh naik ke peringkat pertama karena skor reranknya paling tinggi, sedangkan d01 dan d02 yang menempati dua peringkat teratas pada tahap pertama jatuh ke peringkat lima dan enam. Tiga hasil akhirnya menjadi d08, d05, dan d03, bukan tiga teratas tahap pertama.
Pergeseran seperti inilah nilai yang ditambahkan reranking. Kandidat yang kedekatan vektornya tinggi tetapi isinya kurang membahas permintaan diturunkan, sedangkan kandidat yang isinya paling menjawab permintaan naik. Perubahan hanya terjadi di dalam kumpulan kandidat tahap pertama, sehingga kecepatan pengambilan tetap terjaga dan presisi peringkat akhirnya naik.
Ringkasan#
- Pipeline dua tahap mengambil kandidat besar dengan bi-encoder dan filter, misalnya 100, lalu menata ulang hasil akhirnya, misalnya top-10, dengan cross-encoder.
- Bi-encoder dapat menghitung vektor dokumen lebih dahulu sehingga murah, sedangkan cross-encoder membaca setiap pasangan bersama sehingga presisi tetapi mahal.
- Reranking hanya menyusun ulang kandidat tahap pertama, sehingga kecepatan pengambilan tetap terjaga dengan peringkat akhir yang lebih teliti.
Referensi#
- Dokumentasi Qdrant — Qdrant — Dokumentasi resmi Qdrant yang memuat pencarian dan penyusunan hasil pada mesin vektor.
- Konsep pencarian — Qdrant — Halaman konsep pencarian Qdrant yang menjelaskan bentuk query pada tahap pengambilan pertama.