Dodawanie filtru w zapytaniu wektorowym w usłudze Azure AI Search
Możesz zdefiniować wektorowe żądanie zapytania zawierające wyrażenie filtru, aby dodać kryteria dołączania lub wykluczania do zapytań. Z tego artykułu dowiesz się, jak wykonywać następujące działania:
W tym artykule użyto architektury REST na potrzeby ilustracji. Przykłady kodu w innych językach można znaleźć w repozytorium GitHub azure-search-vector-samples , które zawiera kompleksowe rozwiązania obejmujące zapytania wektorowe.
Eksplorator wyszukiwania można również użyć w witrynie Azure Portal do wykonywania zapytań dotyczących zawartości wektorowej. Jeśli używasz widoku JSON, możesz dodać filtry i określić tryb filtrowania.
Jak działa filtrowanie w zapytaniu wektorowym
Filtry mają zastosowanie do filterable
pól innych niż wektory, pola ciągu lub liczbowe, aby uwzględnić lub wykluczyć dokumenty wyszukiwania na podstawie kryteriów filtru. Chociaż pole wektorowe nie jest możliwe do filtrowania, filtry można stosować do innych pól w tym samym indeksie, w tym do dokumentów zawierających również pola wektorowe.
Filtry są stosowane przed wykonaniem zapytania lub po nim na podstawie parametru vectorFilterMode
.
Definiowanie filtru
Filtry określają zakres zapytania wektorowego. Filtry są ustawiane i iterowane przez ciąg niewektorowy i pola liczbowe przypisane jako filterable
w indeksie, ale cel filtru określa, co wykonuje zapytanie wektorowe: całe miejsce z możliwością wyszukiwania lub zawartość wyniku wyszukiwania.
Jeśli nie masz pól źródłowych z wartościami tekstowymi lub liczbowymi, sprawdź metadane dokumentu, takie jak Właściwości LastModified lub CreatedBy, które mogą być przydatne w filtrze metadanych.
2024-07-01 jest stabilną wersją tego interfejsu API. Ma:
vectorFilterMode
dla trybów filtrowania wstępnego (domyślne) lub postfiltrowania.filter
zawiera kryteria.
W poniższym przykładzie wektor jest reprezentacją tego ciągu zapytania: "to, co usługi platformy Azure obsługują wyszukiwanie pełnotekstowe". Zapytanie jest przeznaczone dla contentVector
pola . Rzeczywisty wektor ma 1536 osadzonych elementów, więc jest przycinany w tym przykładzie pod kątem czytelności.
Kryteria filtrowania są stosowane do pola tekstowego z możliwością filtrowania (category
w tym przykładzie) przed wykonaniem zapytania wektorowego przez aparat wyszukiwania.
POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
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,
. . .
-0.02178128,
-0.00086512347
],
"exhaustive": true,
"fields": "contentVector",
"k": 5
}
]
}
Ustawianie wektoraFilterMode
Parametr zapytania vectorFilterMode określa, czy filtr jest stosowany przed wykonaniem zapytania wektorowego, czy po nim.
Korzystanie z trybu filtrowania wstępnego
Filtrowanie wstępne stosuje filtry przed wykonaniem zapytania, zmniejszając obszar powierzchni wyszukiwania, na którym algorytm wyszukiwania wektorowego szuka podobnej zawartości.
W zapytaniu preFilter
wektorowym jest wartością domyślną.
Korzystanie z trybu postfiltrowania
Filtrowanie po filtrowaniu stosuje filtry po wykonaniu zapytania, zawężając wyniki wyszukiwania.
Testowanie porównawcze trybów filtrowania wektorów
Aby zrozumieć warunki, w których jeden tryb filtrowania działa lepiej niż drugi, przeprowadziliśmy serię testów w celu oceny wyników zapytań w przypadku małych, średnich i dużych indeksów.
- Mały (100 000 dokumentów, indeks 2,5 GB, 1536 wymiarów)
- Średni (1 milion dokumentów, indeks 25 GB, 1536 wymiarów)
- Duży (1 miliard dokumentów, indeks 1,9 TB, 96 wymiarów)
W przypadku małych i średnich obciążeń użyliśmy usługi Standardowa 2 (S2) z jedną partycją i jedną repliką. W przypadku dużego obciążenia użyliśmy usługi Standardowa 3 (S3) z 12 partycjami i jedną repliką.
Indeksy miały identyczną konstrukcję: jedno pole klucza, jedno pole wektorowe, jedno pole tekstowe i jedno pole filtrowalne liczbowo. Poniższy indeks jest zdefiniowany przy użyciu składni 2023-11-03.
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"
}
]
}
}
W zapytaniach użyliśmy identycznego filtru dla operacji filtrowania wstępnego i postfiltru. Użyliśmy prostego filtru, aby upewnić się, że zmiany wydajności były spowodowane trybem filtrowania, a nie złożonością filtrowania.
Wyniki zostały zmierzone w zapytaniach na sekundę (QPS).
Wnioski
Filtrowanie wstępne jest prawie zawsze wolniejsze niż pofiltrowaniu, z wyjątkiem małych indeksów, w których wydajność jest w przybliżeniu równa.
W przypadku większych zestawów danych filtrowanie wstępne jest o wielkości wolniejsze.
Dlaczego więc filtr wstępny jest domyślny, jeśli jest prawie zawsze wolniejszy? Wstępne filtrowanie gwarantuje, że
k
wyniki są zwracane, jeśli istnieją w indeksie, gdzie stronniczość sprzyja kompletności i precyzji z szybkością.Filtrowanie końcowe jest przeznaczone dla klientów, którzy:
- szybkość zaznaczenia (filtrowanie postfiltrujące może zwracać mniej niż
k
wyniki) - używanie filtrów, które nie są nadmiernie selektywne
- mają indeksy o wystarczających rozmiarach, tak aby wydajność filtrowania wstępnego jest niedopuszczalna
- szybkość zaznaczenia (filtrowanie postfiltrujące może zwracać mniej niż
Szczegóły
Biorąc pod uwagę zestaw danych z 100 000 wektorów o wymiarach 1536:
- Podczas filtrowania ponad 30% zestawu danych porównywano filtrowanie wstępne i filtrowanie postfiltrujące.
- Podczas filtrowania mniejszego niż 0,1% zestawu danych filtrowanie wstępne było o około 50% wolniejsze niż po filtrowaniu.
Biorąc pod uwagę zestaw danych z 1 milionami wektorów o wymiarach 1536:
- Podczas filtrowania ponad 30% zestawu danych wstępne filtrowanie było o około 30% wolniejsze.
- Podczas filtrowania mniejszego niż 2% zestawu danych wstępne filtrowanie było około siedmiu razy wolniejsze.
Biorąc pod uwagę zestaw danych z 1 miliardami wektorów o wymiarach 96:
- Podczas filtrowania ponad 5% zestawu danych wstępne filtrowanie było o około 50% wolniejsze.
- Podczas filtrowania mniejszego niż 10% zestawu danych wstępne filtrowanie było około siedmiu razy wolniejsze.
Na poniższym wykresie przedstawiono wstępne filtrowanie względne QPS obliczone jako wstępne filtrowanie QPS podzielone przez QPS postfilter.
Oś pionowa to QPS wstępnego filtrowania na QPS po filtrowaniu. Na przykład wartość 0,0 oznacza, że filtrowanie wstępne jest o 100% wolniejsze, 0,5 na osi pionowej oznacza, że filtrowanie wstępne jest o 50% wolniejsze, 1,0 oznacza, że filtrowanie wstępne i filtrowanie po są równoważne.
Oś pozioma reprezentuje współczynnik filtrowania lub procent dokumentów kandydatów po zastosowaniu filtru. Na przykład oznacza, 1.00%
że jeden procent korpusu wyszukiwania został wybrany przez kryteria filtru.