Поиск по базе знаний с ИИ обещают как одну кнопку: спросил своими словами – получил ответ по всем документам компании. Внутри у этой кнопки две разные машины, и от того, как их соединили, зависит, найдёт система нужное или выдаст похожее.
Ниже – что именно должен находить такой поиск, почему модный «гибридный» режим у нас проиграл обеим своим половинам и как проверить это на своих вопросах до приёмки. Все цифры – из замера на клиентской базе в 18 тысяч контактов, 138 вопросов, четыре режима поиска.

Два вопроса, которые вы будете задавать базе
Все запросы к рабочей базе делятся на два типа, и разница между ними важнее любой технологии.
«Найди вот это». Сделка «Ремонт кровли, вторая очередь». Договор с конкретной компанией. Задача с номером. Вы знаете, что документ существует, и знаете, как он называется. Система должна поставить его на первое место, а не показать двадцать похожих.
«Что у нас есть про…». Про срыв сроков. Про жалобы на монтаж. Про запросы рассрочки. Здесь вы не знаете ни одного конкретного документа и не знаете, какими словами это записано: один менеджер написал «задержка», другой «не успели», третий «клиент недоволен графиком». Система должна собрать всё это вместе.
Первый тип вопросов закрывает поиск словами: он сравнивает слова запроса со словами документов и учитывает, насколько слово редкое. Второй тип закрывает поиск по смыслу: каждый документ заранее превращён в набор чисел, запрос превращается в такой же набор, и система ищет ближайшие. Слово «задержка» и слово «не успели» окажутся рядом, потому что рядом их поставила модель.
Это два разных механизма, а не две настройки одного. И работают они противоположно.
Что показал замер: каждый механизм силён в своём
Мы взяли 138 вопросов трёх видов и прогнали через четыре режима поиска. Вопросы собирала программа по фиксированному правилу, чтобы набор нельзя было подогнать: 60 запросов по точному названию записи, те же 60 названий внутри человеческого вопроса и 18 тематических запросов по девяти темам, по-русски и по-английски.
Вот главные две строки всего замера.
| Тип вопроса | Поиск словами | Поиск по смыслу |
|---|---|---|
| «Найди запись по названию» (первое место) | 100 % | 28 % |
| «Что есть по теме» (точность первой десятки) | 59 % | 71 % |
Разрыв не пограничный. На вопросах по названию поиск словами не ошибся ни разу за 60 попыток, а поиск по смыслу нашёл меньше трети. На тематических вопросах порядок переворачивается.
У поиска по смыслу обнаружилась ещё одна особенность, важная на практике. Он либо ставил нужную запись на первое место, либо не показывал её вообще: доля попаданий в первую позицию и в первые десять совпала – 28 % и 28 %. Промежуточного «нашёл, но на седьмом месте» у него нет. Значит, ошибку такого поиска нельзя вылечить тем, что вы покажете пользователю больше строк.
Дальше – про то, что происходит, когда эти два механизма пытаются объединить.
Гибридный поиск: почему объединение ухудшило результат
Стандартный способ соединить две ветки – взять места, которые каждая ветка присвоила документу, и сложить по формуле, где вес места равен единице, делённой на позицию с поправкой. Метод старый, описан в работе Кормака, Кларка и Бюттхера 2009 года и действительно обыгрывает отдельные ветки – когда ветки сопоставимы по качеству.
У нас они несопоставимы, и результат получился такой:
| Режим | Найти запись по названию (первое место) | Тематический вопрос (точность десятки) |
|---|---|---|
| Только поиск словами | 100 % | 59 % |
| Только поиск по смыслу | 28 % | 71 % |
| Объединение двух веток | 57 % | 70 % |
| Объединение плюс второй проход | 98 % | 71 % |
Объединение проиграло лучшей ветке на каждом типе вопросов. Причина простая: формула работает с местами, а не с уверенностью. Она не знает, что одна ветка вернула шестьдесят точных попаданий, а вторая – шестьдесят посторонних записей. Первое место слабой ветки весит ровно столько же, сколько первое место сильной.
Практический вывод отсюда неприятный для многих коммерческих предложений: «у нас гибридный поиск» само по себе не означает лучшего качества. Это означает, что две ветки сложили. Стало ли от этого лучше – вопрос замера на ваших данных.

Второй проход: дорогая починка того, что сломали
Последняя строка таблицы выглядит убедительно: объединение дало 57 %, а с добавлением второго прохода стало 98 %. Плюс сорок два пункта. Именно так такие цифры и показывают на демонстрациях.
Второй проход – это отдельная модель, которая берёт четыре десятка уже найденных документов, читает каждый вместе с вопросом и переставляет их заново. Она точнее, потому что видит текст целиком, а не сжатый набор чисел.
Вопрос в том, с чем сравнивать её прибавку. Сравним не с объединением, а с лучшей одиночной веткой – с тем, что можно было получить без всей конструкции:
| Тип вопроса | Лучшая одиночная ветка | Объединение плюс второй проход | Разница | Сколько времени добавил второй проход |
|---|---|---|---|---|
| Найти запись по названию | 100 % (поиск словами, 0,012 с) | 98 % | −2 пункта | +3,1 с |
| То же название внутри вопроса | 67 % (поиск словами, 0,014 с) | 97 % | +30 пунктов | +5,2 с |
| Тема, русский запрос | 71 % (поиск по смыслу, 0,098 с) | 71 % | 0 | +7,2 с |
| Тема, английский запрос | 54 % (поиск по смыслу, 0,121 с) | 51 % | −3 пункта | +56,7 с |

Три строки из четырёх – ноль или минус. Весь большой выигрыш второго прохода оказался починкой поломки, которую внесло объединение веток.
Одна строка при этом честно положительная: когда название записи спрятано внутри обычного человеческого вопроса вроде «кто ведёт сделку такую-то и на каком она стадии», поиск словами падает со 100 % до 67 % – лишние слова вопроса сбивают его. Здесь второй проход добавляет тридцать пунктов за пять секунд, и это уже осмысленная сделка.
И отдельно про время. Поиск словами отвечает за 12 миллисекунд. Второй проход добавляет от трёх до пятидесяти семи секунд, причём цена растёт с длиной запроса: короткий вопрос стоит около пяти секунд, длинное описание темы – около минуты. Замеряли на машине, где больше ничего не работало; под нагрузкой будет хуже.
Как проверить поиск по базе знаний с ИИ на своих вопросах
Порядок, который стоит потребовать от подрядчика. Технических знаний он не требует.
-
Соберите 30–50 своих настоящих вопросов и разделите их на два типа: «найди вот это» и «что у нас есть про такую-то тему». Перекос в одну сторону сделает замер бессмысленным.
-
Для каждого вопроса заранее запишите, какой документ считается правильным ответом. Без этого списка любая цифра качества – самооценка системы.
-
Потребуйте замер каждой ветки по отдельности, а потом их комбинации. Одна общая цифра качества скрывает, какая половина конструкции работает.
-
Смотрите на две метрики раздельно: доля вопросов, где нужное оказалось на первом месте, и доля попаданий в первую десятку. Для вопросов «найди вот это» важна первая, для тематических – вторая.
-
Требуйте время ответа рядом с каждой цифрой качества. Три секунды на запрос – это другая система, чем двенадцать миллисекунд, даже если качество одинаковое.
-
Проверьте вопросы на том языке, на котором их будут задавать. У нас тот же тематический вопрос по-английски искался заметно хуже, чем по-русски: 32 % против 59 % у поиска словами.
Отдельным пунктом – перестройка индекса. Смысловой индекс строится один раз, и каждую запись нужно прогнать через модель. У нас 68 413 записей заняли около 88 минут на сервере без видеокарты. После каждой большой перезаливки базы это повторяется. В планах работ этот час обычно не заложен, а он есть.
Что это меняет в вашем проекте
Три правила, которые я забрал себе из этого замера. Они применимы к любому проекту, где делают поиск по базе знаний с ИИ.
Сначала простое, потом сложное. Обычный поиск словами дал сто процентов на трети вопросов и стоил двенадцать миллисекунд. Начинать стоит с него, а сложную конструкцию добавлять там, где он доказанно не справляется.
Каждый слой оправдывает себя отдельно. Прибавку слоя нужно считать не от предыдущей конструкции, а от самого дешёвого варианта, который решает ту же задачу. Иначе получается то, что вышло у нас: слой чинит поломку, внесённую соседним слоем, и обе цифры выглядят прекрасно.
Поиск – это и есть тот слой, который защищает модель от базы. Соблазн отдать модели всё разом велик: окна контекста большие, выгрузка под рукой. Но модель прочитает столько, сколько поместилось, обобщит это на остальное и не сообщит, какую долю базы видела. А на длинном тексте она вдобавок теряет точность: в замере NoLiMa 11 моделей из 13 на 32 тысячах токенов упали ниже половины собственного результата на коротком тексте. Поиск нужен ровно затем, чтобы в окно попали пятьдесят нужных записей, а не пятьдесят тысяч случайных.
Тип вопроса определяет механизм. Если система обслуживает оба типа вопросов одной веткой, половина запросов будет обслужена неподходящим механизмом. Это не настраивается порогами – это разные машины.
Про то, откуда вообще берутся такие проверки и что спросить у подрядчика до подписания договора, я подробно разобрал в статье про подключение ИИ к CRM. Соседняя часть цикла – про то, почему найденная запись может оказаться устаревшей и система этого не заметит. А рекомендации, из-за которых мы вообще включили объединение веток, пришли из отчётов глубокого исследования: как их проверять – отдельный разговор.
Границы этого замера
Считаю обязательным сказать, где мои цифры не работают.
Замер сделан на одной базе – клиентской CRM с короткими записями, медианная длина текста 11 знаков. На базе договоров или технических описаний расклад между ветками может оказаться другим. Проверять надо на своих данных, и в этом весь смысл предыдущего раздела.
Тематические вопросы сверялись с нашей же прошлой разметкой тем. То есть они показывают согласие с ней, а не попадание в истину. Настоящего эталона для вопроса вроде «на что жалуются клиенты» у нас нет: чтобы его собрать, человек должен прочитать и ответить сам, а выдумывать такой эталон я не стал.
Модели поиска по смыслу и второго прохода – открытые, bge-m3 и её парный переоценщик. На платных облачных моделях числа будут другими, но развилка «два механизма под два типа вопросов» от этого не исчезнет.
И последнее. Слабость поиска по смыслу на точных названиях – не наша находка. Это известный результат: в сравнении BEIR на восемнадцати наборах данных обычный поиск словами оказался сильным соперником для нейросетевых моделей, особенно на данных, которых модель не видела при обучении. Ваша база – ровно такие данные.
Замеры, которые отменяют наши же решения, я выкладываю в телеграм-канале по мере того, как они появляются. Хотите разобрать свой случай – пишите напрямую, @maslennikovig.
Наши замеры моделей, которые обновляются из базы, лежат в разделе бенчмарков. Про то, почему пилоты не дают эффекта, есть отдельный разбор.

