Настройка гибридного поиска с векторными и текстовыми полями в Azure AI Search
Пошаговое руководство по созданию индекса, генерации эмбеддингов и выполнению гибридных запросов, сочетающих полнотекстовый и векторный поиск с использованием Azure AI Search.
В этом материале
Короткий ответ
Гибридный поиск настраивается путем добавления векторных полей в схему индекса, генерации эмбеддингов для текстового содержимого и формирования запроса с параметрами search и vectorQueries. Результаты объединяются с помощью алгоритма Reciprocal Rank Fusion (RRF), а при необходимости можно включить семантический реранкер для переранжирования. Основные шаги: определение схемы индекса, генерация эмбеддингов, настройка параметров k и oversampling, формирование запроса с фильтрами и фасетами, необязательное включение семантического реранкера, тестирование и мониторинг квот и затрат.
1. Определение схемы индекса с векторными и текстовыми полями
Для начала создается индекс Azure AI Search, содержащий как обычные текстовые поля для полнотекстового поиска, так и векторные поля для семантического поиска. Векторные поля хранят числовые эмбеддинги, полученные из текстового содержимого документа. Индекс должен содержать хотя бы одно текстовое поле, предназначенное для поиска, и одно векторное поле. При создании индекса через портал или REST API векторные поля объявляются с типом "Edm.Single" и атрибутом "searchable": true, однако они не используются для обычного полнотекстового поиска; их роль - вычисление схожести векторов.
Пример из документации Microsoft Learn демонстрирует гибридный запрос, где параметр search сочетается с vectorQueries, указывающими на поля DescriptionVector и Description_frVector. Это позволяет выполнять одновременно ключевое слово-поиск и семантический поиск в одном запросе, с результатами, объединяемыми алгоритмом RRF.
Важно: векторные поля нельзя использовать напрямую в фильтрах. Для метаданных (например, категория, география) требуется отдельное текстовое или числовое поле, помеченное атрибутами filterable и/или facetable.
POST https://my-service.search.windows.net/indexes/hotels-vector-quickstart/docs/search?api-version=2026-04-01\ncontent-type: application/JSON\n{\n "count": true,\n "search": "historic hotel walk to restaurants and shopping",\n "select": "HotelId, HotelName, Category, Description, Address/City, Address/StateProvince",\n "filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",\n "vectorFilterMode": "postFilter",\n "facets": ["Address/StateProvince"],\n "vectorQueries": [{\n "kind": "vector",\n "vector": [0.1,0.2,…],\n "k": 50,\n "fields": "DescriptionVector",\n "exhaustive": true,\n "oversampling": 20\n }],\n "skip": 0,\n "top": 10,\n "queryType": "semantic",\n "queryLanguage": "en-us",\n "semanticConfiguration": "my-semantic-config"\n}2. Генерация или импорт эмбеддингов для текстовых полей
Эмбеддинги можно генерировать двумя способами: с использованием встроенных возможностей Azure AI Search (pipeline индексатора с Azure OpenAI) или внешних моделей (OpenAI эмбеддинги, SBERT и т.д.), после чего векторы загружаются напрямую в индекс. В первом случае конфигурируется набор навыков, который автоматически разбивает текст и вызывает модель эмбеддинга. Во втором случае эмбеддинги создаются вне системы и передаются через API при создании или обновлении документов.
Документация рекомендует использовать Azure OpenAI для генерации эмбеддингов, конкретно модель text-embedding-ada-002. Эмбеддинги должны иметь одинаковую размерность (например, 1536 для Ada), и этот параметр указывается при создании векторного поля.
При импорте данных через «Импорт данных» можно выбрать опцию векторизации, и сервис автоматически сгенерирует эмбеддинги для загруженного контента, если правильно настроен источник данных и набор навыков.
/* Example call to Azure OpenAI for obtaining an embedding */\nPOST https://my-openai-resource.openai.azure.com/openai/deployments/text-embedding-ada-002/embeddings?api-version=2024-02-15\nHeaders: api-key: YOUR_API_KEY\n{\n "input": "historic hotel walk to restaurants and shopping"\n}3. Настройка параметров поиска векторов (k, oversampling, exhaustive)
Параметр k в vectorQueries определяет, сколько ближайших соседей будет возвращено для каждого вектора. Рекомендуется устанавливать k >= 50, если используется семантический реранкер, чтобы он имел достаточно кандидатов для переранжирования.
Параметр oversampling определяет дополнительный процент кандидатов, которые будут извлечены за пределами k, что помогает повысить качество результатов при использовании HNSW-индексов. Типичные значения от 10 до 50 обеспечивают хороший баланс между задержкой и точностью.
Параметр exhaustive указывает, следует ли использовать полный просмотр для поиска ближайших соседей. Установка exhaustive: true гарантирует нахождение истинных k ближайших соседей, но увеличивает задержку. По умолчанию false, и для большинства сценариев HNSW достаточно.
В примере из документа hybrid-search-overview показаны два vectorQueries: один с exhaustive=true и oversampling=20, другой с exhaustive=false и oversampling=10. Конфигурация зависит от размера индекса и требований к релевантности.
Примечание: увеличение k и oversampling повышает точность, но также увеличивает задержку запроса. Всегда тестируйте значения на представительном наборе данных.
"vectorQueries": [{\n "kind": "vector",\n "vector": <array> ,\n "k": 50,\n "fields": "DescriptionVector",\n "exhaustive": true,\n "oversampling": 20\n }]4. Формирование гибридного запроса с search и vectorQueries
Гибридный запрос объединяет параметр search (полнотекстовый запрос) и один или несколько vectorQueries. Запрос отправляется как единственный HTTP POST-запрос на конец индекса с api-version=2026-04-01 (или актуальной версии).
Сервер выполняет полнотекстовый и векторный поиск параллельно, затем объединяет результаты с помощью алгоритма Reciprocal Rank Fusion (RRF). Алгоритм RRF присваивает каждому документу комбинированную ранговую оценку на основе его позиции в обоих списках результатов, позволяя объединять преимущества точного ключевого поиска и семантической схожести.
В запросе можно указать queryType: semantic, чтобы включить семантический реранкер, который использует машинное чтение для анализа объединенных результатов RRF и переранжирует их на основе семантического соответствия запросу. Это особенно полезно для концептуальных запросов, где важнее смысл, чем совпадение слов.
Фильтры и фасеты применяются к полям, отличным от векторных. Например, геопространственные фильтры geo.distance или фильтры по категориям работают на объединенном результате после RRF. Важно протестировать поведение vectorFilterMode (preFilter против postFilter), поскольку порядок применения фильтра влияет на производительность и набор возвращаемых документов.
Полный пример запроса представлен в разделе 1 и включает фасеты, фильтр, vectorQueries и semanticConfiguration.
POST https://my-service.search.windows.net/indexes/hotels-vector-quickstart/docs/search?api-version=2026-04-01\ncontent-type: application/JSON\n{\n "count": true,\n "search": "historic hotel walk to restaurants and shopping",\n "select": "HotelId, HotelName, Category, Description, Address/City, Address/StateProvince",\n "filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",\n "vectorFilterMode": "postFilter",\n "facets": ["Address/StateProvince"],\n "vectorQueries": [{\n "kind": "vector",\n "vector": [0.1,0.2,…],\n "k": 50,\n "fields": "DescriptionVector",\n "exhaustive": true,\n "oversampling": 20\n }],\n "skip": 0,\n "top": 10,\n "queryType": "semantic",\n "queryLanguage": "en-us",\n "semanticConfiguration": "my-semantic-config"\n}5. Применение фильтров и фасетов к полям, отличным от векторных
После объединения RRF фильтры и фасеты применяются к окончательному набору документов. Это позволяет сохранить существующую функциональность поиска: геопространственные фильтры, фильтры по атрибутам, фасетные группы для навигации.
Фильтры в гибридном запросе применяются после выполнения полнотекстового и векторного поиска (по умолчанию postFilter), но могут быть настроены как vectorFilterMode: preFilter, если документы нужно исключить до векторного поиска. Тестирование показывает, что postFilter часто дает лучшую релевантность, так как фильтр не ограничивает кандидатов до векторного поиска.
Фасеты (facets) можно использовать для разделения результатов по полям, например, Address/StateProvince, как в примере. Результаты фасетов отражают распределение среди объединенных результатов, а не только среди одного компонента поиска.
Важно помнить, что векторные поля нельзя фильтровать напрямую. Любые условия выборки по метаданным должны основываться на отдельных текстовых или числовых полях, помеченных соответствующими атрибутами при создании индекса.
"filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",\n "facets": ["Address/StateProvince"]6. Необязательно: Включение семантического реранкера для переранжирования
Семантический реранкер доступен при добавлении queryType: semantic и указании semanticConfiguration в запросе. Реранкер использует машинное чтение для анализа объединенных результатов RRF и переранжирует их на основе семантического соответствия запросу.
Это улучшает качество поиска для запросов, где важна концептуальная близость (например, синонимы, многозначный поиск). Сравнительные тесты показывают, что гибридный поиск с семантическим реранкером обеспечивает значительное повышение релевантности по сравнению с чистым векторным или ключевым поиском.
Конфигурация семантического реранкера устанавливается на уровне индекса (раздел «semantic configurations»). В запросе указывается имя конфигурации, а также язык запроса (queryLanguage).
Если семантический реранкер не нужен, запрос можно отправить без queryType: semantic. В этом случае результаты ранжируются только на основе RRF, объединяя BM25 (для текста) и HNSW/eKNN (для векторов).
"queryType": "semantic",\n "queryLanguage": "en-us",\n "semanticConfiguration": "my-semantic-config"7. Тестирование и настройка k, oversampling и поведения фильтров
После развертывания необходимо экспериментировать с k, oversampling и поведением фильтров (preFilter/postFilter), чтобы найти оптимальный баланс скорости и точности для вашей области.
Тестируйте различные значения k (например, 10, 50, 100) и oversampling (10, 20, 50) на представительной выборке запросов. Обратите внимание на изменения @search.rerankerScore и порядок документов в ответе.
Сравнивайте результаты с и без семантического реранкера. Если k слишком мал, семантический реранкер получит недостаточно кандидатов, и переранжирование будет менее эффективным.
Мониторьте задержку запроса: увеличение k и oversampling увеличивает время ответа. Найдите минимальное значение k, которое обеспечивает приемлемую релевантность при использовании семантического реранкера.
Используйте инструменты отладки Azure Portal или REST API: параметр count: true позволяет увидеть общее количество совпадений, а поле @search.rerankerScore показывает оценку семантического реранкера.
/* Example checking results with count */\n{\n "count": true,\n "search": "...",\n "vectorQueries": [{"kind": "vector", "vector": [...], "k": 50, ...}],\n "top": 10\n}8. Развертывание и мониторинг квот и затрат на векторные индексы
Убедитесь, что ваш сервис поиска был создан после 3 апреля 2024 года - такие сервисы предлагают более высокие квоты на векторные индексы. Если сервис старее, его можно обновить для получения больших квот.
Генерация эмбеддингов через Azure OpenAI или другие модели подразумевает оплату от поставщика модели. Эти расходы следует учитывать при планировании объема данных и частоты обновлений.
Мониторьте использование векторных индексов через метрики Azure Monitor: количество векторных полей, размерность, количество документов. Превышение квот может привести к ошибкам индексации или запросов.
Для гибридного поиска мониторьте задержку запроса: большие значения k и oversampling увеличивают нагрузку. Если задержка становится неприемлемой, уменьшите oversampling или перепроверьте конфигурацию HNSW.
Рекомендуется настроить уведомления при превышении квот и регулярно проверять состояние индекса, особенно после больших партий документов.
/* Checking service version and quotas */\nGET https://my-service.search.windows.net?api-version=2026-04-01\nHeaders: api-key: YOUR_API_KEYЧто проверить
- Индекс содержит хотя бы одно текстовое поле, предназначенное для поиска, и одно векторное поле с соответствующей размерностью эмбеддингов.
- Эмбеддинги сгенерированы и загружены в векторные поля (через индексатор или прямой API).
- Гибридный запрос включает параметры search и vectorQueries с правильными значениями k и fields.
- При использовании семантического реранкера установлены queryType: semantic и semanticConfiguration.
- Фильтры и фасеты относятся к текстовым или числовым полям, а не к векторным полям напрямую.
- Версия сервиса не старше 3 апреля 2024 года для увеличенных квот на векторы.
- Мониторинг затрат на эмбеддинги и задержку запроса включен.
Границы применения
Векторные поля нельзя использовать напрямую в фильтрах. Для метаданных (например, категория, география) требуется отдельное текстовое или числовое поле, помеченное атрибутами filterable и/или facetable при создании индекса.