
Поиск редко сводится к одному универсальному сценарию. Пользователь, вводящий "cheap running shoes", хочет точных совпадений по ключевым словам, а пользователь, задающий "comfortable footwear for jogging", выражает то же намерение другими словами. Традиционный полнотекстовый поиск хорошо справляется с первым случаем. Векторный поиск решает второй. Гибридный поиск объединяет оба в одном запросе, так что вам не приходится выбирать.
В современных поисковых системах это часто описывается как комбинирование лексического (разреженного) поиска с семантическим (плотным) поиском. Разные термины, одна идея: точное совпадение плюс смысл.
Что такое гибридный поиск?
Гибридный поиск одновременно выполняет полнотекстовый (BM25) поиск и векторный (KNN) поиск, а затем объединяет два списка результатов в один. Документы, получившие высокий балл по любому из сигналов (или по обоим), поднимаются наверх.
Полнотекстовый поиск отлично работает с точными ключевыми словами, редкими терминами и идентификаторами. Векторный поиск понимает смысл — например, что "automobile" и "car" обозначают одну и ту же концепцию, — потому что их эмбеддинги находятся рядом в векторном пространстве.
У каждого метода есть свои слабые места:
Полнотекстовый затрудняется с синонимами и естественным языком
Векторный поиск затрудняется с точными токенами, такими как SKU, коды ошибок и идентификаторы
Гибридный поиск охватывает оба.
Как гибридный поиск вписывается в современные поисковые приложения
Гибридный поиск — это этап извлечения: часть системы, которая находит релевантных кандидатов в ваших данных.
Вместо того чтобы полагаться на один метод, гибридный поиск комбинирует совпадения по ключевым словам и семантическое сходство, чтобы сразу получать более сильный набор результатов.
На практике это означает:
Лучшее покрытие (recall) для запросов на естественном языке
Точное совпадение для идентификаторов, таких как SKU или коды ошибок
Более релевантные результаты без сложной логики запросов
Цель проста: вернуть наилучших возможных кандидатов за один проход, используя оба сигнала вместе.
Когда следует использовать гибридный поиск?
Гибридный поиск подходит, когда:
Ваши запросы сочетают намерение и детали. Поиск вроде
python error 403 forbiddenвыигрывает от точности по ключевому слову в коде ошибки и семантического понимания описания проблемы.Вы создаёте конвейер RAG. Retrieval-Augmented Generation требует подачи самых релевантных фрагментов в LLM. Гибридное извлечение постоянно находит более релевантные документы, чем любой из методов по отдельности.
Ваш каталог содержит как структурированные, так и неструктурированные данные. Товары электронной коммерции имеют точные названия и номера моделей (территория ключевых слов), но также описания, где смысл важнее точных формулировок.
Вы не можете предсказать, как пользователи будут искать. Некоторые вставят точные фразы, другие опишут, что ищут, на естественном языке. Гибридный поиск элегантно справляется с обоими случаями.
Как это работает
Manticore использует Reciprocal Rank Fusion (RRF) для объединения результатов. Идея проста: вместо попытки сравнивать сырые оценки BM25 с расстояниями KNN, которые живут на совершенно разных шкалах, RRF смотрит на позиции в ранжировании. Документ, занявший #1 в текстовых результатах и #3 в результатах KNN, получает более высокий комбинированный балл, чем документ, появившийся только в одном списке.
Вот простой пример. Предположим, что текстовый поиск и поиск KNN возвращают свои топ‑3:
Результаты текстового поиска:
Ранг | Документ |
|---|---|
1 | Doc A |
2 | Doc B |
3 | Doc C |
Результаты поиска KNN:
Ранг | Документ |
|---|---|
1 | Doc C |
2 | Doc A |
3 | Doc D |
RRF оценивает каждый документ по формуле 1 / (rank_constant + rank). При значении по умолчанию rank_constant=60:
Документ | Вклад текста | Вклад KNN | Балл RRF |
|---|---|---|---|
Doc A | 1/(60+1) = 0.0164 | 1/(60+2) = 0.0161 | 0.0325 |
Doc C | 1/(60+3) = 0.0159 | 1/(60+1) = 0.0164 | 0.0323 |
Doc B | 1/(60+2) = 0.0161 | — | 0.0161 |
Doc D | — | 1/(60+3) = 0.0159 | 0.0159 |
Doc A занимает первое место, потому что появляется почти вверху обоих списков. Doc C находится рядом по той же причине. Doc B и Doc D присутствуют только в одном списке, поэтому их баллы ниже.
Почему RRF?
Существует два распространённых способа объединения результатов:
Слияние на основе рангов (RRF) — простое, надёжное, без необходимости нормализовать оценки
Слияние на основе оценок — сначала нормализовать оценки, а затем объединять
Manticore использует RRF, потому что этот метод хорошо работает сразу из коробки и избавляет от проблем с калибровкой оценок.
Внутри гибридный запрос разбивается на независимые подзапросы: один для полнотекстового поиска, один или несколько для KNN. Они выполняются параллельно, а после завершения RRF объединяет их ранжированные списки результатов в один итоговый список.
Почему нельзя просто использовать один из методов?
Рассмотрим базу знаний поддержки со статьями о разных кодах ошибок — сбоях соединения, проблемах аутентификации и ошибках синхронизации. Пользователь видит ошибку E-5020 на экране и сообщает: "Не могу подключиться к серверу."
Векторный поиск понимает симптом, но не код ошибки. KNN по запросу "не могу подключиться к серверу" возвращает:
# | Заголовок | Расстояние KNN |
|---|---|---|
1 | Ошибка E-5030: Ошибка разрешения DNS | 0.572 |
2 | Ошибка E-2091: Превышено время загрузки приложения | 0.583 |
3 | Ошибка E-5020: Несоответствие SSL‑сертификата | 0.605 |
4 | Ошибка E-5010: Сервис недоступен | 0.622 |
5 | Ошибка E-4001: Не удалось войти | 0.665 |
Правильная статья (E-5020) оказывается только на позиции #3. KNN ставит выше ошибки DNS и таймаутов, потому что их описания семантически ближе к фразе "не могу подключиться". Реальная проблема — несоответствие SSL‑сертификата — использует совсем другую лексику, поэтому получает более низкий балл.
Можно подумать: просто добавить код ошибки в запрос KNN. Но "E-5020" и "E-5010" — это произвольные идентификаторы без семантического значения, и эмбеддинги воспринимают их как почти одинаковые токены. KNN по запросу "E-5020 не могу подключиться к серверу" действительно поднимает E-5020 на позицию #1, но лишь потому, что добавленный текст меняет семантический контекст — сам код ошибки почти ничего не весит.
Гибридный поиск решает эту проблему, отправляя каждый сигнал туда, где он работает лучше всего: код ошибки — в полнотекстовый поиск, симптом — в KNN.
SELECT title, hybrid_score() FROM support_articles WHERE knn(embedding, 'can not connect to the server') AND MATCH('E-5020') LIMIT 5 OPTION fusion_method='rrf';
# | Title | Hybrid score |
|---|---|---|
1 | Error E-5020: SSL Certificate Mismatch | 0.032 |
2 | Error E-5030: DNS Resolution Failed | 0.016 |
3 | Error E-2091: App Loading Timeout | 0.016 |
4 | Error E-5010: Service Unavailable | 0.016 |
5 | Error E-4001: Login Failed | 0.015 |
E-5020 поднимается с #3 на #1 и получает почти вдвое более высокий балл, чем остальные. Полнотекстовый поиск воспринимает «E-5020» как точную строку — не похожую на «E-5010», не "почти близкую", а просто другую. KNN при этом гарантирует, что связанные ошибки соединения всё равно остаются ниже для контекста.
Это основная ценность гибридного поиска:
Идентификаторы → полнотекстовый поиск
Смысл → векторный поиск
Каждый метод покрывает слепую зону другого.
С чего начать
Самый простой способ выполнить гибридный поиск — использовать hybrid_match(). Если в вашей таблице настроено автоматическое создание эмбеддингов, одна строка делает всё: поиск по тексту, генерацию эмбеддингов, поиск KNN и объединение через RRF.
SELECT id, hybrid_score() FROM products WHERE hybrid_match('running shoes');
JSON-эквивалент:
POST /search { "table": "products", "hybrid": { "query": "running shoes" } }
Manticore:
генерирует эмбеддинги
выполняет оба поиска параллельно
объединяет результаты
Полный контроль: явный MATCH + KNN
Если вы хотите передавать собственные векторы или настраивать отдельные подзапросы, используйте явную форму с MATCH() и KNN() в условии WHERE:
SELECT id, hybrid_score() FROM products WHERE match('running shoes') AND knn(embedding, (0.12, 0.45, 0.78, ...)) OPTION fusion_method='rrf';
POST /search { "table": "products", "knn": { "field": "embedding", "query_vector": [0.12, 0.45, 0.78, "..."] }, "query": { "match": { "title": "running shoes" } }, "options": { "fusion_method": "rrf" } }
Каждый результат включает:
hybrid_score()— объединённый балл (используется для сортировки по умолчанию)weight()— балл BM25knn_dist()— векторное расстояние
Фильтры по атрибутам (AND category = 'footwear') применяются к обоим подзапросам.
Настройка
Поведение объединения настраивается тремя опциями:
rank_constant— контролирует, насколько верхние позиции доминируют в объединённом балле. Низкие значения (например, 10) делают позицию #1 значительно более значимой, чем позицию #5. Высокие значения сглаживают кривую. См. rank_constant .fusion_weights— позволяет задать разную важность каждому подзапросу. Если релевантность текста важнее, чем векторное сходство, задайте больший вес. См. fusion_weights .window_size— сколько результатов каждый подзапрос получает до объединения. По умолчанию Manticore вычисляет это автоматически из параметров KNN и LIMIT запроса. См. window_size .
Слияние нескольких векторов
Гибридный поиск не ограничивается одним текстовым поиском и одним поиском KNN. Можно объединять несколько векторных поисков — это полезно, когда в данных есть несколько разных семантических измерений. Например, у товара в e-commerce есть текстовое описание и фотография. Пользователь, ищущий «минималистичные белые кроссовки», опирается сразу на оба сигнала: название должно соответствовать стилю, а изображение товара — выглядеть так, как он это представляет. Если закодировать название и изображение в отдельных векторных пространствах, их можно искать одновременно и позволить RRF выводить наверх товары, которые соответствуют всем трём сигналам — ключевым словам, смыслу текста и визуальному сходству:
SELECT id, hybrid_score() FROM products WHERE match('running shoes') AS text AND knn(title_vec, (0.12, 0.45, ...)) AS title_sim AND knn(image_vec, (0.88, 0.21, ...)) AS image_sim OPTION fusion_method='rrf', fusion_weights=(text=0.5, title_sim=0.3, image_sim=0.2);
Все подзапросы выполняются параллельно и объединяются вместе через RRF.
Заключение
Гибридный поиск не должен заменять полнотекстовый или векторный поиск — его задача в том, чтобы использовать оба метода там, где каждый из них работает лучше всего.
Поиск по ключевым словам даёт точность для точных терминов и идентификаторов. Векторный поиск даёт гибкость для естественного языка и смысла. По отдельности у каждого метода есть пробелы. Вместе они стабильно дают лучшие результаты для широкого спектра запросов.
С гибридным поиском в Manticore вам не нужно выбирать между двумя подходами или строить сложную логику запросов для разных случаев. Вы можете запускать оба сигнала параллельно и получать единый, унифицированный набор результатов.
Если ваш поиск должен обрабатывать и точные совпадения, и намерение пользователя, — а это характерно для большинства реальных приложений, — гибридный поиск даёт простой способ повысить релевантность без лишней сложности.
