Bagikan melalui


Menambahkan filter ke kueri vektor di Azure AI Search

Nota

strictPostFilter saat ini dalam pratinjau publik. Pratinjau ini disediakan tanpa perjanjian tingkat layanan dan tidak direkomendasikan untuk beban kerja produksi. Fitur tertentu mungkin tidak didukung atau mungkin memiliki kemampuan terbatas. Untuk informasi lebih lanjut, lihat Supplemental Terms of Use for Microsoft Azure Previews.

prefilter dan postfilter umumnya tersedia dalam versi REST API stabil terbaru.

Di Azure AI Search, Anda bisa menggunakan ekspresi filter untuk menambahkan kriteria penyertaan atau pengecualian ke kueri vektor. Anda juga dapat menentukan mode pemfilteran yang menerapkan filter:

  • Sebelum eksekusi kueri, dikenal sebagai prafilter.
  • Setelah eksekusi kueri, dikenal sebagai postfiltering.
  • Setelah hasil teratask global diidentifikasi, dikenal sebagai postfiltering ketat (pratinjau).

Artikel ini menggunakan REST untuk ilustrasi. Untuk sampel kode dalam bahasa lain dan solusi end-to-end yang menyertakan kueri vektor, lihat repositori GitHub azure-search-vector-samples .

Anda juga bisa menggunakan Search Explorer di portal Azure untuk mengkueri konten vektor. Dalam tampilan JSON, Anda dapat menambahkan filter dan menentukan mode filter.

Cara kerja pemfilteran dalam kueri vektor

Pencarian Azure AI menggunakan algoritma Hierarkis Navigable Small World (HNSW) untuk pencarian Perkiraan Tetangga Terdekat (ANN), menyimpan grafik HNSW di beberapa pecahan. Setiap shard berisi sebagian dari seluruh indeks.

Filter berlaku untuk filterable bidang nonvektor, baik string atau numerik, untuk menyertakan atau mengecualikan dokumen pencarian berdasarkan kriteria filter. Bidang vektor itu sendiri tidak dapat difilter, tetapi Anda dapat menggunakan filter pada bidang lain dalam indeks yang sama untuk mempersempit dokumen yang dipertimbangkan untuk pencarian vektor. Jika indeks Anda tidak memiliki bidang teks atau numerik yang sesuai, periksa metadata dokumen yang mungkin membantu pemfilteran, seperti LastModified atau CreatedBy properti.

Parameter vectorFilterMode mengontrol tempat operasi filter diterapkan selama tahap pencarian, yang memengaruhi bagaimana hasil difilter ke subset item (seperti berdasarkan kategori, tag, atau atribut lainnya) dan memengaruhi latensi, pengenalan, dan throughput. Ada tiga mode:

  • preFilter menerapkan filter selama traversal HNSW pada setiap shard. Mode ini memaksimalkan pengenalan tetapi dapat melintasi lebih banyak grafik, meningkatkan CPU dan latensi untuk filter yang sangat selektif.

  • postFilter menjalankan traversal HNSW dan pemfilteran pada setiap shard secara independen, mempertemukan hasil di tingkat shard, dan kemudian mengagregasikan top k dari setiap shard ke dalam top k global. Mode ini dapat membuat negatif palsu untuk filter yang sangat selektif atau nilai kecil k.

  • strictPostFilter (pratinjau) menemukan posisi teratas k global yang belum difilter sebelum melakukan pemfilteran. Mode ini memiliki risiko tertinggi mengembalikan negatif palsu untuk filter yang sangat selektif dan nilai kecil k .

Untuk informasi selengkapnya tentang mode ini, lihat Mengatur mode filter.

Menentukan filter

Filter menentukan cakupan kueri vektor dan didefinisikan menggunakan Dokumen - Pos Pencarian (REST API). Kecuali Anda ingin menggunakan fitur pratinjau, gunakan versi stabil terbaru DARI REST API Layanan Pencarian untuk merumuskan permintaan.

REST API ini menyediakan:

  • filter untuk kriteria.
  • vectorFilterMode untuk menentukan kapan filter diterapkan selama kueri vektor. Untuk mode yang didukung, lihat Mengatur mode filter.
POST https://{search-endpoint}/indexes/{index-name}/docs/search?api-version={api-version}
Content-Type: application/json
api-key: {admin-api-key}
    
{
    "count": true,
    "select": "title, content, category",
    "filter": "category eq 'Databases'",
    "vectorFilterMode": "preFilter",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . // Trimmed for readability
                -0.02178128,
                -0.00086512347
            ],
            "fields": "contentVector",
            "k": 50
        }
    ]
}

Dalam contoh ini, penyematan vektor menargetkan contentVector bidang, dan kriteria filter berlaku untuk category, bidang teks yang dapat difilter. preFilter Karena mode digunakan, filter diterapkan sebelum mesin pencari menjalankan kueri, jadi hanya dokumen dalam kategori yang dipertimbangkan Databases selama pencarian vektor.

Mengatur mode filter

Parameter vectorFilterMode menentukan kapan dan bagaimana filter diterapkan relatif terhadap eksekusi kueri vektor. Anda dapat menggunakan mode berikut:

  • preFilter (disarankan)
  • postFilter
  • strictPostFilter (pratinjau)

Nota

preFilter adalah default untuk indeks yang dibuat setelah sekitar 15 Oktober 2023. Untuk indeks yang dibuat sebelum tanggal ini, postFilter adalah defaultnya. Untuk menggunakan preFilter dan fitur vektor tingkat lanjut lainnya, seperti kompresi vektor, Anda harus membuat ulang indeks Anda.

Anda dapat menguji kompatibilitas dengan mengirim kueri vektor dengan "vectorFilterMode": "preFilter" pada 2023-10-01-preview versi REST API atau yang lebih baru. Jika kueri gagal, indeks Anda tidak mendukung preFilter.

Prafilter menerapkan filter sebelum eksekusi kueri, yang mengurangi kandidat yang ditetapkan untuk algoritma pencarian vektor. Hasil teratask kemudian dipilih dari set yang difilter ini.

Dalam kueri vektor, preFilter adalah mode default karena mendukung pengenalan dan kualitas atas latensi.

Cara kerja mode ini

  1. Pada setiap shard, terapkan predikat filter selama traversal HNSW, perluas grafik hingga k kandidat ditemukan.

  2. Menghasilkan hasil teratask lokal yang telah difilter per pecahan.

  3. Agregasikan hasil yang telah difilter ke dalam kumpulan hasil teratas global.

Efek dari mode ini

Traversal memperluas permukaan pencarian untuk menemukan kandidat yang lebih terfilter, terutama jika filter selektif. Ini menghasilkan hasil teratask yang paling mirip di semua pecahan. Setiap shard mengidentifikasi hasil k yang memenuhi predikat filter.

Pra-pemfilteran menjamin bahwa hasil k akan dikembalikan jika tersedia dalam indeks. Untuk filter yang sangat selektif, ini dapat menyebabkan sebagian besar graf dilalui, sehingga meningkatkan biaya komputasi dan latensi, serta mengurangi throughput. Jika filter Anda sangat selektif (memiliki sangat sedikit kecocokan), pertimbangkan untuk menggunakan exhaustive: true untuk melakukan pencarian lengkap.

Diagram prafilter.

Tabel perbandingan

Pengaturan Penarikan (hasil terfilter) Biaya komputasi Risiko negatif palsu Kapan harus menggunakan
preFilter Sangat tinggi Lebih tinggi (meningkat dengan selektivitas dan kompleksitas filter) Tidak ada risiko Default yang disarankan untuk semua skenario, terutama ketika penarikan sangat penting (domain pencarian sensitif), saat menggunakan filter selektif, atau saat menggunakan k kecil.
postFilter Sedang hingga tinggi (berkurang dengan selektivitas filter) Mirip dengan unfiltered namun meningkat seiring dengan kompleksitas filter. Sedang (dapat mengabaikan kecocokan per pecahan) Opsi untuk filter yang tidak terlalu selektif dan juga untuk kueri tingkat lanjutk.
strictPostFilter Terendah (berkurang tercepat karena selektivitas filter) Mirip dengan tanpa penyaringan Tertinggi (dapat menghasilkan nol hasil untuk filter yang selektif atau kecil k) Opsi untuk aplikasi pencarian beraspek di mana menampilkan lebih banyak hasil setelah penerapan filter lebih memengaruhi pengalaman pengguna dibandingkan risiko hasil negatif palsu. Jangan gunakan dengan ukuran kecil k.

Pengujian tolok ukur prafilter dan pascafilter

Penting

Bagian ini berlaku untuk prafilter dan pascafilter, bukan postfiltering yang ketat.

Untuk memahami kondisi di mana satu mode filter berkinerja lebih baik daripada yang lain, kami menjalankan serangkaian pengujian untuk mengevaluasi hasil kueri melalui indeks kecil, sedang, dan besar.

  • Kecil (100.000 dokumen, indeks 2,5 GB, 1.536 dimensi)
  • Sedang (1 juta dokumen, indeks 25 GB, 1.536 dimensi)
  • Besar (1 miliar dokumen, indeks 1,9 TB, 96 dimensi)

Untuk beban kerja kecil dan menengah, kami menggunakan layanan Standar 2 (S2) dengan satu partisi dan satu replika. Untuk beban kerja besar, kami menggunakan layanan Standard 3 (S3) dengan 12 partisi dan satu replika.

Indeks memiliki konstruksi yang identik: satu bidang kunci, satu bidang vektor, satu bidang teks, dan satu bidang numerik yang dapat difilter. Indeks berikut didefinisikan menggunakan 2023-11-03 sintaks.

def get_index_schema(self, index_name, dimensions):
    return {
        "name": index_name,
        "fields": [
            {"name": "id", "type": "Edm.String", "key": True, "searchable": True},
            {"name": "content_vector", "type": "Collection(Edm.Single)", "dimensions": dimensions,
              "searchable": True, "retrievable": True, "filterable": False, "facetable": False, "sortable": False,
              "vectorSearchProfile": "defaulthnsw"},
            {"name": "text", "type": "Edm.String", "searchable": True, "filterable": False, "retrievable": True,
              "sortable": False, "facetable": False},
            {"name": "score", "type": "Edm.Double", "searchable": False, "filterable": True,
              "retrievable": True, "sortable": True, "facetable": True}
        ],
      "vectorSearch": {
        "algorithms": [
            {
              "name": "defaulthnsw",
              "kind": "hnsw",
              "hnswParameters": { "metric": "euclidean" }
            }
          ],
          "profiles": [
            {
              "name": "defaulthnsw",
              "algorithm": "defaulthnsw"
            }
        ]
      }
    }

Dalam kueri, kami menggunakan filter yang identik untuk operasi prafilter dan pascafilter. Kami menggunakan filter sederhana untuk memastikan bahwa variasi performa disebabkan oleh mode pemfilteran, bukan kompleksitas filter.

Hasil diukur dalam kueri per detik (QPS).

Poin-poin penting

  • Prafilter hampir selalu lebih lambat daripada postfiltering, kecuali pada indeks kecil di mana performanya kira-kira sama.

  • Pada himpunan data yang lebih besar, prafilter adalah urutan besarnya lebih lambat.

  • Mengapa prafilter default jika hampir selalu lebih lambat? Prafilter menjamin bahwa k hasil dikembalikan jika ada dalam indeks, di mana bias mendukung pengenalan dan presisi atas kecepatan.

  • Gunakan postfiltering jika Anda:

    • Kecepatan nilai atas pilihan (postfiltering dapat mengembalikan kurang dari k hasil).

    • Gunakan filter yang tidak terlalu selektif.

    • Memiliki indeks dengan ukuran yang memadai sehingga performa prafilter tidak dapat diterima.

Detail

  • Mengingat himpunan data dengan 100.000 vektor pada 1.536 dimensi:

    • Saat memfilter lebih dari 30% himpunan data, prafilter dan postfilter sebanding.

    • Saat memfilter kurang dari 0,1% himpunan data, prafilter sekitar 50% lebih lambat daripada postfilter.

  • Mengingat himpunan data dengan 1 juta vektor pada 1.536 dimensi:

    • Saat memfilter lebih dari 30% himpunan data, prafilter sekitar 30% lebih lambat.

    • Saat memfilter kurang dari 2% himpunan data, prafilter sekitar tujuh kali lebih lambat.

  • Mengingat himpunan data dengan 1 miliar vektor pada 96 dimensi:

    • Saat memfilter lebih dari 5% himpunan data, prafilter sekitar 50% lebih lambat.

    • Saat memfilter kurang dari 10% himpunan data, prafilter sekitar tujuh kali lebih lambat.

Grafik berikut menunjukkan QPS relatif prafilter, dihitung sebagai QPS prafilter dibagi dengan QPS postfilter.

Bagan memperlihatkan performa QPS untuk indeks kecil, sedang, dan besar untuk QPS relatif.

Sumbu vertikal mewakili performa relatif prafilter dibandingkan dengan postfiltering, yang dinyatakan sebagai rasio QPS (kueri per detik). Contohnya:

  • Nilai 0.0 berarti prafilter adalah 100% lebih lambat daripada postfiltering.
  • Nilai 0.5 berarti prafilter adalah 50% lebih lambat.
  • Nilai 1.0 berarti prafilter dan pemfilteran pasca setara.

Sumbu horizontal mewakili laju pemfilteran, atau persentase dokumen kandidat setelah menerapkan filter. Misalnya, tingkat 1.00% berarti kriteria filter memilih satu persen dari korpus pencarian.