Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание
strictPostFilter в настоящее время находится в общедоступной предварительной версии. Предварительный просмотр предоставляется без соглашения об уровне обслуживания и не рекомендуется для эксплуатационных рабочих нагрузок. Некоторые функции могут не поддерживаться или могут иметь ограниченные возможности. Дополнительные сведения см. в разделе Supplemental Terms of Use for Microsoft Azure Previews.
prefilter и postfilter общедоступны в последней стабильной версии REST API.
В Поиск с использованием ИИ Azure можно использовать выражение filter для добавления условий включения или исключения в запрос vector. Можно также указать режим фильтрации, который применяет фильтр:
- Перед выполнением запроса, известное как префильтровка.
- После выполнения запроса, известного как postfiltering.
- После определения глобальных топ-результатов
k, известных как строгая послефильтрация (предварительная версия).
В этой статье используется REST для иллюстрации. Примеры кода на других языках и комплексные решения, включающие векторные запросы, см. в репозитории azure-search-vector-samples GitHub.
Вы также можете использовать Search Explorer на портале Azure для запроса векторного содержимого. В представлении JSON можно добавить фильтры и указать режим фильтра.
Принцип работы фильтрации в векторных запросах
Поиск с использованием ИИ Azure использует алгоритм иерархического навигационного небольшого мира (HNSW) для поиска приблизительного ближайшего соседа (ANN), сохраняя графы HNSW в нескольких сегментах. Каждый сегмент содержит часть всего индекса.
Фильтры применяются к filterableневекторным полям( строковым или числовым), чтобы включить или исключить документы поиска на основе критериев фильтра. Векторные поля сами по себе не фильтруются, но можно использовать фильтры для других полей в том же индексе, чтобы сузить документы, которые рассматриваются для поиска векторов. Если индекс не имеет подходящих текстовых или числовых полей, проверьте метаданные документа, которые могут помочь с фильтрацией, например LastModified или CreatedBy свойствами.
Параметр vectorFilterMode управляет применением операций фильтрации на этапах поиска, что влияет на то, как результаты фильтруются в подмножество элементов (например, по категориям, тегам или другим атрибутам) и влияют на задержку, отзыв и пропускную способность. Существует три режима:
preFilterПрименяет фильтр во время обхода HNSW на каждом сегменте. Этот режим максимально увеличивает воспроизведение, но может обрабатывать больше частей графа, увеличивая использование ЦП и время ожидания для высокоселективных фильтров.postFilterвыполняет обход HNSW и фильтрацию по каждому сегменту независимо друг от друга, пересекает результаты на уровне сегментов, а затем объединяет верхнююkчасть из каждого сегмента в глобальную верхнюю частьk. Этот режим может создавать ложные отрицательные значения для высокоизбирательных фильтров или небольшихkзначений.strictPostFilter(предварительная версия) находит нефильтрованную глобальную вершинуkперед применением фильтра. Этот режим имеет самый высокий риск возврата ложных отрицательных значений для высокоизбирательных фильтров и небольшихkзначений.
Дополнительные сведения об этих режимах см. в разделе "Настройка режима фильтра".
Определение фильтра
Фильтры определяют область векторных запросов и настраиваются с помощью Documents - Search Post (REST API). Если вы не хотите использовать функцию предварительной версии, используйте последнюю стабильную версию REST API службы поиска для формирования запроса.
Этот REST API предоставляет следующие возможности:
-
filterдля критериев. -
vectorFilterMode, чтобы указать, когда фильтр применяется во время векторного запроса. Поддерживаемые режимы см. в разделе "Настройка режима фильтра".
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
}
]
}
В этом примере векторное встраивание направлено на поле contentVector, и критерии фильтра применяются к текстовому полю category, которое можно фильтровать. Поскольку используется режим preFilter, фильтр применяется перед выполнением запроса поисковой системы, поэтому во время векторного поиска рассматриваются только документы в категории Databases.
Настройка режима фильтра
Параметр vectorFilterMode определяет, когда и как фильтр применяется относительно выполнения векторного запроса. Можно использовать следующие режимы:
-
preFilter(рекомендуется) postFilter-
strictPostFilter(предварительная версия)
Примечание
preFilter — значение по умолчанию для индексов, созданных примерно после 15 октября 2023 г. Для индексов, созданных до этой даты, postFilter используется значение по умолчанию. Чтобы использовать preFilter и другие расширенные векторные функции, такие как сжатие векторов, необходимо повторно создать индекс.
Вы можете проверить совместимость, отправив векторный запрос с "vectorFilterMode": "preFilter"2023-10-01-preview версией REST API или более поздней. Если запрос завершается ошибкой, ваш индекс не поддерживает preFilter.
Предварительная фильтрация применяет фильтры перед выполнением запроса, что сокращает набор кандидатов для алгоритма векторного поиска. Затем в этом отфильтрованном наборе выбраны результаты верхнегоk уровня.
В векторном запросе preFilter является режимом по умолчанию, поскольку он отдает предпочтение отзыву и качеству вместо задержки.
Как работает этот режим
На каждом шарде примените предикат фильтра во время обхода HNSW, расширяя граф до тех пор, пока не будут найдены
kкандидаты.Создание предфильтрованных локальных результатов на
kсегмент.Агрегируйте отфильтрованные результаты в глобальный результирующий
kнабор.
Эффект этого режима
Обход расширяет пространство поиска, чтобы найти больше подходящих кандидатов, особенно если фильтр является избирательным. Это создает самые похожиеk результаты верхнего уровня во всех сегментах. Каждый сегмент определяет k результаты, удовлетворяющие предикату фильтра.
Фильтрация гарантирует, что результаты возвращаются, если они существуют в индексе. k Для высокоизбирательных фильтров это может привести к обходу значительной части графа, что увеличивает затраты на вычисления и задержку времени при снижении пропускной способности. Если фильтр является очень выборочным (имеет очень мало совпадений), рассмотрите возможность exhaustive: true использования для выполнения исчерпывающего поиска.
Таблица сравнения
| Режим | Отзыв (отфильтрованные результаты) | Вычислительные затраты | Риск ложных отрицательных значений | Когда следует использовать |
|---|---|---|---|---|
preFilter |
Очень высокий | Выше (увеличивается при выборе фильтра и сложности) | Нет риска |
Рекомендуется по умолчанию для всех сценариев, особенно если отзыв является критически важным (конфиденциальные домены поиска), при использовании выборочных фильтров или при использовании небольших k. |
postFilter |
Средний и высокий (уменьшается при выборе фильтра) | Аналогично нефильтрованным, но увеличивается сложность фильтра | Умеренный (может пропустить совпадения на сегмент) | Вариант для фильтров, которые не слишком строгие, а также для более высокихk запросов. |
strictPostFilter |
Наименьший (уменьшается быстрее при выборе фильтра) | Аналогично нефильтрованным | Самый высокий (может возвращать нулевые результаты для выборочных фильтров или небольших k) |
Вариант для фасетных приложений поиска, где отображение большего количества результатов после фильтрации приложения влияет на взаимодействие с пользователем больше, чем риск ложных отрицательных значений. Не используйте с небольшими k. |
Бенчмарковое тестирование префильтрации и постфильтрации
Важно
Этот раздел относится к префильтрации и постфильтрации, а не строгой постфильтрации.
Чтобы понять условия, при которых один режим фильтрации работает лучше, чем другой, мы выполнили ряд тестов для оценки результатов запроса по небольшим, средним и большим индексам.
- Маленький (100 000 документов, индекс 2,5 ГБ, 1 536 измерений)
- Средний (1 миллион документов, индекс 25 ГБ, 1536 измерений)
- Большой (1 миллиард документов, индекс 1,9 ТБ, 96 размерностей)
Для небольших и средних рабочих нагрузок мы использовали службу Standard 2 (S2) с одной секцией и одной репликой. Для большой рабочей нагрузки мы использовали службу Standard 3 (S3) с 12 секциями и одной репликой.
Индексы имели идентичное построение: одно ключевое поле, одно векторное поле, одно текстовое поле и одно числовое фильтруемое поле. Следующий индекс определяется с помощью синтаксиса 2023-11-01 .
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"
}
]
}
}
В запросах мы использовали одинаковый фильтр для операций предварительной фильтрации и последующей фильтрации. Мы использовали простой фильтр, чтобы гарантировать, что вариации производительности были вызваны режимом фильтрации, а не сложностью фильтрации.
Результаты измерялись в запросах в секунду (QPS).
Выводы
Префильтрация почти всегда медленнее, чем послефильтровка, за исключением небольших индексов, где производительность приблизительно равна.
При более крупных наборах данных префильтровка значительно медленнее.
Почему «prefilter» задано по умолчанию, если оно почти всегда медленнее? Предварительная фильтрация гарантирует, что
kрезультаты возвращаются, если они существуют в индексе, где предвзятость благоприятствует отзыву и точности вместо скорости.Используйте постфильтрацию, если вы:
Скорость выбора значений (послефильтровка может возвращать меньше
kрезультатов).Используйте фильтры, которые не являются чрезмерно выборочными.
Имеют индексы достаточного размера, при котором производительность префильтрации становится неприемлемой.
Детали
Учитывая набор данных с 100 000 векторами в 1536 измерениях:
При фильтрации более 30% набора данных префильтрация и постфильтрация были сопоставимы.
При фильтрации менее 0,1% набора данных предварительная фильтрация составила около 50% медленнее, чем послефильтровка.
Учитывая набор данных с 1 миллионами векторов с 1536 измерениями:
При фильтрации более 30% набора данных предварительная фильтрация стала примерно на 30% медленнее.
При фильтрации менее 2% набора данных предварительная фильтрация была примерно в семь раз медленнее.
Учитывая набор данных с 1 миллиардами векторов на 96 измерениях:
При фильтрации более 5% набора данных предварительная фильтрация составила около 50% медленнее.
При фильтрации менее 10% набора данных предварительная фильтрация была примерно в семь раз медленнее.
На следующем графике представлен относительный QPS до фильтрации, вычисляемый как QPS до фильтрации, разделенный на QPS после фильтрации.
Вертикальная ось представляет относительную производительность префильтрации по сравнению с постфильтрированием, выраженным в виде соотношения QPS (запросов в секунду). Например:
- Значение
0.0означает, что префильтровка составляет 100% медленнее, чем послефильтровка. - Значение
0.5означает, что префильтровка на 50% медленнее. - Значение
1.0означает, что префильтрация и постфильтрация эквивалентны.
Горизонтальная ось представляет скорость фильтрации или процент кандидатов среди документов после применения фильтра. Например, показатель 1.00% означает, что критерии фильтра выбрали один процент от корпуса поиска.