Гибридный поиск: почему семантический + полнотекстовый лучше по отдельности
- Гибридный поиск
- Семантический поиск


Гибридный поиск - это метод, при котором результаты семантического (векторного) поиска и полнотекстового (keyword) поиска объединяются для достижения максимальной точности. Ни один из подходов по отдельности не способен покрыть все сценарии: семантический поиск пропускает точные термины и артикулы, а полнотекстовый не понимает синонимы и намерения. Комбинация обоих методов с правильным ранжированием даёт качество поиска, недоступное каждому из них в отдельности. В этой статье мы разберём, как работает каждый тип поиска, почему их слабости взаимно компенсируются, какие стратегии объединения существуют, и как мы реализовали гибридный поиск в реальных проектах Промолитики - от бота для застройщика до ассистента службы поддержки.
Семантический поиск основан на сравнении векторных представлений (эмбеддингов) запроса и документов. Запрос пользователя превращается в вектор - набор из сотен или тысяч чисел, кодирующих смысл. Этот вектор сравнивается с векторами всех фрагментов в базе с помощью метрики косинусного сходства (cosine similarity). Результаты ранжируются по степени смысловой близости.
Косинусное сходство измеряет «угол» между двумя векторами в многомерном пространстве. Если два вектора указывают в одном направлении - их cosine similarity равен 1 (максимальная близость). Если они перпендикулярны - 0 (нет связи). Значение -1 означает противоположные направления (антонимы по смыслу).
На практике это означает: запрос «как оплатить подписку» и фрагмент документации «инструкция по внесению платежа за тарифный план» получат высокий балл сходства (0.85-0.92), несмотря на то что у них нет общих ключевых слов. Модель эмбеддингов (например, Voyage AI voyage-4-large) «понимает», что оплата = внесение платежа, подписка = тарифный план.
Полнотекстовый поиск - классический подход, которому больше 30 лет. Его основа - инвертированный индекс: структура данных, которая для каждого слова хранит список документов, в которых это слово встречается. При поиске система находит все документы, содержащие слова из запроса, и ранжирует их по релевантности.
BM25 (Best Matching 25) - стандартный алгоритм ранжирования для полнотекстового поиска. Он учитывает три фактора:
BM25 используется в Elasticsearch, PostgreSQL (full-text search), Apache Lucene и большинстве других поисковых систем.
Рассмотрим конкретные сценарии, в которых каждый из подходов даёт сбой.
Запрос: «Стиральная машина Bosch WAN28263». Полнотекстовый поиск найдёт точную карточку товара за миллисекунды. Семантический поиск может вернуть десяток стиральных машин разных брендов, потому что все они семантически близки к запросу «стиральная машина». Модель артикула WAN28263 для эмбеддинг-модели - бессмысленная последовательность символов.
Победитель: полнотекстовый поиск.
Запрос: «Машинка перестала отжимать бельё, гудит, но барабан не крутится». Полнотекстовый поиск будет искать документы со словами «машинка», «отжимать», «гудит», «барабан». Если в базе знаний статья озаглавлена «Диагностика неисправности привода стиральной машины: отсутствие вращения барабана при работающем двигателе» - полнотекстовый поиск её может не найти (мало общих слов). Семантический поиск легко свяжет описание симптомов с техническим описанием проблемы.
Победитель: семантический поиск.
Запрос: «Тихие квартиры в ЖК Изумрудный с видом на парк». Здесь есть и точный термин («ЖК Изумрудный»), и семантическое описание («тихие», «с видом на парк»). Полнотекстовый поиск найдёт все объекты в ЖК Изумрудный, но не поймёт, что «тихие» означает «не выходящие на оживлённую улицу», а «с видом на парк» может соответствовать описанию «панорамное остекление с видом на зелёную зону». Семантический поиск поймёт намерение, но может вернуть «тихие» квартиры из другого ЖК, проигнорировав конкретное название.
Победитель: только гибридный поиск, который объединит точное совпадение по «ЖК Изумрудный» с семантическим пониманием «тихие» и «вид на парк».
Гибридный поиск выполняет оба типа поиска параллельно, а затем объединяет результаты. Звучит просто, но дьявол в деталях: как именно объединять два списка с разными шкалами оценки?
Запрос пользователя одновременно отправляется в два поисковых движка. Семантический поиск преобразует запрос в вектор, сравнивает с индексом эмбеддингов и возвращает список фрагментов с cosine similarity (от 0 до 1). Полнотекстовый поиск выполняет BM25-ранжирование и возвращает список фрагментов с BM25-скором (от 0 до бесконечности).
Проблема: cosine similarity даёт числа от 0 до 1, а BM25-скор может быть любым положительным числом. Напрямую складывать эти значения нельзя. Нужна нормализация - приведение обоих скоров к одной шкале.
Самый распространённый подход - min-max нормализация: для каждого списка результатов минимальный скор приводится к 0, максимальный - к 1, остальные пропорционально. После нормализации оба списка имеют скоры от 0 до 1 и могут быть объединены.
Финальный скор каждого фрагмента вычисляется как взвешенная сумма нормализованных скоров:
Финальный скор = alpha * semantic_score + (1 - alpha) * keyword_score
Параметр alpha определяет баланс между семантическим и полнотекстовым поиском. При alpha = 1.0 используется только семантический поиск. При alpha = 0.0 - только полнотекстовый. Значения 0.5-0.7 обычно дают лучшие результаты для бизнес-задач.
Если фрагмент найден только одним из поисков (например, присутствует в результатах семантического, но не полнотекстового), его второй скор считается равным нулю. Это означает, что фрагменты, найденные обоими методами, получают преимущество - они «подтверждены» с двух сторон.
Взвешенное объединение - базовый подход. Для более высокого качества используются продвинутые стратегии ре-ранкинга (re-ranking) - повторного ранжирования объединённых результатов.
RRF - один из самых популярных методов объединения результатов из нескольких источников. Он не зависит от абсолютных значений скоров - использует только позиции (ранги) документов в каждом списке.
Формула: RRF_score = сумма по всем спискам (1 / (k + ранг)), где k - константа (обычно 60). Фрагмент, который стоит на первом месте в обоих списках, получает максимальный RRF-скор. Фрагмент на первом месте в семантическом поиске и на пятнадцатом в полнотекстовом - средний.
Преимущество RRF: не нужна нормализация скоров. Метод работает даже когда шкалы двух поисков несравнимы. Недостаток: не учитывает, насколько сильно один результат лучше другого - только порядок.
Самый точный, но и самый медленный метод. После первичного поиска (гибридного или семантического) топ-20-50 результатов пропускаются через специальную модель - cross-encoder. В отличие от bi-encoder (который создаёт эмбеддинги запроса и документа отдельно), cross-encoder обрабатывает пару «запрос + документ» целиком и даёт точную оценку релевантности.
Cross-encoder значительно точнее, но в 100-1000 раз медленнее, потому что для каждой пары нужен отдельный вызов модели. Поэтому он применяется только для ре-ранкинга небольшого числа кандидатов, а не для первичного поиска по всей базе.
На практике связка bi-encoder (для первичного поиска по миллионам фрагментов) + cross-encoder (для ре-ранкинга топ-50) даёт наилучшее качество при приемлемой скорости.
Ещё один подход - использовать метаданные и контекст для корректировки ранжирования. Например:
В проектах Промолитики мы используем Turbopuffer как основное векторное хранилище, которое поддерживает гибридный поиск «из коробки». Turbopuffer позволяет выполнять одновременно семантический и полнотекстовый поиск в одном запросе, а также применять фильтрацию по метаданным.
В боте для застройщика гибридный поиск работает следующим образом. Когда клиент пишет «Покажите двухкомнатные в ЖК Парковый до 9 миллионов», система:
Без гибридного подхода бот либо пропускал бы «евродвушки» (если только полнотекстовый), либо показывал бы квартиры из другого ЖК с похожим описанием (если только семантический).
В нашем PLG-боте (Product-Led Growth) для сайта promolytica.ru мы используем интересный приём - knowledge boost. Это механизм, при котором фрагменты из базы знаний получают дополнительный вес при ранжировании.
Как это работает: при гибридном поиске к семантическому скору добавляется поправка (boost). В нашем случае boost = -0.45 для distance_metric, что эквивалентно порогу cosine similarity. Это означает: только фрагменты с cosine similarity выше 0.55 (1.0 - 0.45) попадают в результаты. Фрагменты с низкой семантической релевантностью отсекаются, даже если полнотекстовый поиск нашёл в них совпадения по ключевым словам.
Зачем это нужно? Без boost бот мог включать в контекст фрагменты, которые содержат нужные ключевые слова, но не связаны с темой вопроса. Например, на вопрос «Что такое сквозная аналитика?» бот мог подтянуть фрагмент о UTM-метках, который упоминает слово «аналитика», но не отвечает на заданный вопрос. Boost отсекает такие ложные совпадения.
Для ассистента службы поддержки мы используем более сложную модель ранжирования. Финальный скор каждого фрагмента вычисляется по формуле:
score = 0.6 * semantic + 0.25 * keyword + 0.1 * recency + 0.05 * popularity
Где semantic - нормализованный cosine similarity, keyword - нормализованный BM25, recency - бонус за свежесть документа (линейная убывающая функция от возраста), popularity - бонус за частоту успешного использования фрагмента (по данным обратной связи).
Вес семантического поиска (0.6) выше, чем полнотекстового (0.25), потому что клиенты поддержки чаще описывают проблемы своими словами, чем используют технические термины. Но полнотекстовый поиск критически важен для кодов ошибок, номеров тикетов и названий функций.
Соотношение между семантическим и полнотекстовым поиском - ключевой параметр гибридной системы. Универсального значения не существует, но есть рекомендации для разных сценариев.
Подходит для сценариев, где пользователи формулируют запросы своими словами и редко используют точные термины. Клиентская поддержка, внутренние базы знаний, консультации по продуктам - здесь семантика важнее точных совпадений.
Подходит для каталогов товаров и документации, где запросы содержат и описательные фразы, и точные термины. «Мощный ноутбук Dell с RTX 4060» - тут и семантика («мощный»), и точные термины («Dell», «RTX 4060»).
Подходит для юридических документов, технических спецификаций и любых сценариев, где точность терминов критична. Поиск по номерам договоров, кодам ошибок, артикулам товаров - здесь ключевые слова важнее семантики.
Мы рекомендуем эмпирический подход:
Гибридный поиск требует инфраструктуры, которая поддерживает оба типа индексов. Рассмотрим основные варианты.
Облачная векторная база данных, которую мы используем в большинстве проектов. Turbopuffer поддерживает гибридный поиск нативно: при загрузке фрагмента можно одновременно сохранить эмбеддинг (для семантического поиска) и текст (для полнотекстового). При запросе оба типа поиска выполняются в рамках одного API-вызова с настраиваемыми весами.
Преимущества: простота интеграции (один сервис вместо двух), встроенная нормализация и RRF, высокая скорость поиска. Недостатки: облачный сервис (данные хранятся на серверах провайдера), стоимость при очень больших объёмах.
Для проектов, где данные должны оставаться в контуре компании, мы используем PostgreSQL с расширением pgvector. PostgreSQL имеет мощный встроенный полнотекстовый поиск для русского языка (с морфологическим анализатором), а pgvector добавляет поддержку векторного поиска. Оба типа поиска - в одной базе данных.
Преимущества: данные в вашей инфраструктуре, единая база для всех типов поиска, зрелый полнотекстовый поиск с поддержкой русской морфологии. Недостатки: при больших объёмах (более 1 миллиона векторов) производительность может уступать специализированным решениям, требует настройки индексов.
Elasticsearch изначально создан для полнотекстового поиска, а в последних версиях добавлена поддержка векторного поиска (kNN). Подходит для проектов, где уже используется Elasticsearch и нужно добавить семантический поиск к существующей инфраструктуре.
Чтобы понять, работает ли гибридный поиск лучше, чем каждый подход по отдельности, нужны объективные метрики.
По нашему опыту, переход от чисто семантического поиска к гибридному повышает precision@5 на 10-25% в зависимости от домена. Наибольший прирост наблюдается в сценариях с техническими терминами, кодами и именами собственными.
Гибридный поиск - не серебряная пуля. Есть ситуации, где дополнительная сложность не оправдана.
Наша рекомендация: начните с семантического поиска, запустите в эксплуатацию, соберите реальные запросы и выявите проблемные сценарии. Если видите, что поиск промахивается на точных терминах - добавьте полнотекстовый компонент и переходите на гибридный режим.
Гибридный поиск - это зрелый инженерный подход, который объединяет семантическое понимание смысла с точностью полнотекстового поиска по ключевым словам. Семантический поиск на эмбеддингах понимает синонимы, намерения и перефразирования, но пропускает точные термины, артикулы и имена. Полнотекстовый поиск на BM25 находит точные совпадения за миллисекунды, но не понимает смысл. Их комбинация даёт качество, недоступное каждому подходу в отдельности.
Ключевые решения при построении гибридного поиска: выбор стратегии объединения (взвешенная сумма, RRF, cross-encoder), настройка весов (alpha от 0.3 до 0.7 в зависимости от типа запросов) и выбор инфраструктуры (Turbopuffer для облачных решений, pgvector для on-premise). В проектах Промолитики мы используем Turbopuffer с гибридным поиском, knowledge boost -0.45 и контекстным ре-ранкингом, что позволяет ботам находить нужную информацию как по описанию проблемы своими словами, так и по точному названию продукта или номеру заказа.
Если вы хотите внедрить гибридный поиск в ИИ-ассистента, бота для продаж или внутреннюю систему знаний - свяжитесь с нами для бесплатной консультации. Мы поможем выбрать архитектуру, настроить веса и запустить систему в продакшен.
