BM25 · ПОИСК ПО СЛОВАМ
Классический поиск, который до сих пор стоит внутри Elasticsearch и почти любой RAG-системы. Он не понимает смысл, а считает слова: чем реже слово в коллекции и чем чаще оно в документе, тем выше документ.
01 · индекс тот же тендер, что на странице chunking
Каждое предложение здесь — отдельный чанк. Текст режется на слова, служебные слова выбрасываются, окончание множественного числа срезается. Для каждого слова запоминается, в скольких чанках оно встречается.
02 · запрос
search ›
IDF — вес редкости. Слово, которое есть в 1 чанке из 20, говорит о документе много. Слово, которое есть почти везде, почти ничего.
03 · ранжирование top-5 из 20
04 · откуда счёт у №1 k1 = 1.2 · b = 0.75
score = Σ IDF · tf·(k1+1) / (tf + k1·(1 − b + b·len/avgdl))
len/avgdl — поправка на длину: совпадение в коротком чанке весит больше, чем то же слово в длинном. tf — сколько раз слово есть в чанке; рост счёта от повторов быстро насыщается, поэтому повторить слово 10 раз не помогает.
05 · вердикт сверка с разметкой тем
…
Всё на странице вычисляется в браузере по формуле Okapi BM25: токенизация, частоты, IDF и счёт. Разметка тем — та же, что я сделал для страницы chunking, её алгоритм не видит.
~/ai $ bm25.search(query)