BM25 — функция, которая по паре «запрос и документ» выдаёт число: насколько документ подходит. Она не понимает смысла и не знает языка. Всё её поведение объясняется двумя множителями, и их достаточно, чтобы предсказывать результаты поиска.
#Множитель первый: частота слова в документе
Чем чаще слово встречается в документе, тем документ релевантнее. Но не линейно: рост насыщается. Второе вхождение слова добавляет много, десятое — почти ничего.
Это решает практическую проблему: документ, где слово повторено сорок раз, не выигрывает автоматически у документа, где оно встречается трижды по делу.
#Множитель второй: редкость слова в коллекции
Слово, встречающееся почти в каждом документе, не помогает различать документы, поэтому его вклад стремится к нулю. Слово, встречающееся в трёх документах из десяти тысяч, — почти безошибочный указатель, и его вклад велик.
Разберём на примере. В архиве личных заметок ищется встреча с подрядчиком по кровле:
| Слово | В скольких заметках | Вклад в оценку |
|---|---|---|
с |
почти во всех | практически нулевой |
по |
почти во всех | практически нулевой |
встреча |
в сотнях | небольшой |
подрядчиком |
в десятках | заметный |
кровле |
в единицах | решающий |
Вывод из таблицы прямой: результат вашего поиска определяет самое редкое слово запроса. Отсюда рабочий приём — добавляйте в запрос конкретное: фамилию, номер, название, а не общие слова.
Третий параметр формулы — нормализация по длине документа. Без неё длинные тексты выигрывали бы просто потому, что в них больше слов.
#Где путают
Заблуждение первое: BM25 понимает синонимы. Не понимает вовсе. Запрос автомобиль не найдёт документ, где написано машина, а запрос оплата не найдёт платёж. Это принципиальное ограничение лексического поиска, и лечится оно только добавлением второго механизма — разбор в тексте про семантический поиск против ключевых слов.
Заблуждение второе: оценка BM25 сравнима между разными запросами. Не сравнима. Число зависит от статистики коллекции и от состава запроса, поэтому «порог релевантности 5,0» бессмыслен: для одного запроса это отличное совпадение, для другого — мусор. Сравнивать можно только документы внутри одного запроса.
Заблуждение третье: чем выше число, тем лучше — всегда. В SQLite реализация возвращает отрицательное значение, где лучшему совпадению соответствует наименьшее число. Сортировка не в ту сторону — типовая ошибка, из-за которой поиск «выдаёт ерунду»; подробнее — в справке про FTS5.
Заблуждение четвёртое: BM25 устарел, есть же векторы. Он остаётся сильной базой и выигрывает там, где важно точное совпадение: имена, номера, коды, редкие термины. Правильный ответ обычно не «или», а «и» — как объединяют два списка результатов, разобрано в тексте про гибридный поиск BM25 и векторов и в разборе RRF.
#Частые вопросы
#Что означает аббревиатура BM25?
Best Matching, двадцать пятая по счёту формула из серии экспериментов, начатых ещё в восьмидесятых. Номер исторический и никакого содержательного смысла не несёт.
#Нужно ли настраивать параметры формулы?
В большинстве случаев нет: значения по умолчанию подобраны на больших коллекциях и работают разумно. Настройка имеет смысл при сильном перекосе в длине документов — например, когда рядом лежат заметки в одну строку и стенограммы на десять страниц.
#Почему поиск не находит документ, который точно есть?
Три частые причины: слово в документе стоит в другой форме, в нём латинская буква вместо кириллической после распознавания, либо запрос состоит только из частых слов. Первая проверяется поиском с префиксом, третья — добавлением редкого слова.
#Можно ли повысить вес заголовка по сравнению с телом документа?
Можно: поля индексируются отдельно, и итоговая оценка складывается с коэффициентами. Это стандартный приём — совпадение в заголовке обычно значимее совпадения в середине текста.
Остальные термины — в глоссарии терминов ИИ.