Skip to content

bugakov/bm25-ru

Repository files navigation

BM25 для русского языка в zvec

Русский BM25 для zvec поверх dashtext. Пока SparseVectorEncoder.default("ru") не добавлен в dashtext официально.

Установка

pip install nltk mmh3

dashtext и zvec уже должны быть установлены.

Файлы

Скопируйте в свой проект два файла:

  • tokenizer_ru.py — токенизатор (Snowball + 1,585 стоп-слов ru/en/zh)
  • bm25_ru_default.json — предобученная модель (93 МБ, 2M документов русской Wikipedia)

Использование

Способ 1: Через BM25EmbeddingFunction (zvec)

from zvec.extension import BM25EmbeddingFunction
from tokenizer_ru import tokenize_ru

# Корпус-заглушка — нужен, чтобы BM25EmbeddingFunction не вызывал .default("ru")
# tokenize_function пробрасывается в SparseVectorEncoder через **kwargs
bm25_ru = BM25EmbeddingFunction(
    corpus=["заглушка"],
    encoding_type="query",
    b=0.75,
    k1=1.2,
    tokenize_function=tokenize_ru,
)

# Загрузить предобученную модель (перезаписывает обучение на заглушке)
bm25_ru._encoder.load("bm25_ru_default.json")

# Готово — энкодим запросы
sparse_vec = bm25_ru.embed("поиск документов в компании")
# {1801783706: 0.29, 3162218338: 0.70, ...}

Способ 2: Через dashtext напрямую

from dashtext import SparseVectorEncoder
from tokenizer_ru import tokenize_ru

encoder = SparseVectorEncoder(b=0.75, k1=1.2, tokenize_function=tokenize_ru)
encoder.load("bm25_ru_default.json")

sparse_vec = encoder.encode_queries("поиск документов в компании")

Способ 3: Обучить на своём корпусе

Если у вас специфичный домен (юридические документы, медицинские статьи) — обучите на своём корпусе:

from dashtext import SparseVectorEncoder
from tokenizer_ru import tokenize_ru

corpus = [
    "Договор аренды нежилого помещения заключён между сторонами",
    "Акт приёма-передачи подписан арендатором",
    # ... ваши документы
]

encoder = SparseVectorEncoder(b=0.75, k1=1.2, tokenize_function=tokenize_ru)
encoder.train(corpus)

# Сохранить для переиспользования
encoder.dump("bm25_ru_custom.bin")

# Использовать
sparse_vec = encoder.encode_queries("расторжение договора аренды")

Гибридный поиск (dense + sparse)

from zvec.extension import BM25EmbeddingFunction, DefaultLocalDenseEmbedding
from tokenizer_ru import tokenize_ru

# Dense — семантический поиск
dense_emb = DefaultLocalDenseEmbedding()

# Sparse — лексический поиск BM25
bm25_ru = BM25EmbeddingFunction(
    corpus=["заглушка"],
    encoding_type="query",
    tokenize_function=tokenize_ru,
)
bm25_ru._encoder.load("bm25_ru_default.json")

query = "поисковая оптимизация"

dense_vec = dense_emb.embed(query)      # семантика
sparse_vec = bm25_ru.embed(query)       # ключевые слова

# Оба вектора можно использовать в zvec для hybrid search

Что внутри tokenizer_ru

Компонент Значение
Стемминг NLTK SnowballStemmer("russian")
Нормализация ё → е
Стоп-слова RU 458 (stopwords-iso + Qdrant/bm25 + ручная курация)
Стоп-слова EN 245 (NLTK + dashtext)
Стоп-слова ZH 882 (Qdrant/bm25)
Фильтр мусора стеммы < 2 символов отбрасываются
Хеш mmh3 (совместим с dashtext)

Модель bm25_ru_default.json

Параметр Значение
Корпус Русская Wikipedia
Документов 2,094,388
Уникальных термов 5,805,457
Средняя длина 331.2 токена
Размер 93.4 МБ
Формат идентичен bm25_en_default.json

Источники

  • dashtext — SparseVectorEncoder
  • zvec — BM25EmbeddingFunction
  • Qdrant/bm25 — стоп-слова (ru, zh)
  • stopwords-iso — стоп-слова (ru)
  • RusVectores — методология предобработки русского текста

About

Pretrained BM25 model for Russian language — compatible with dashtext SparseVectorEncoder and zvec BM25EmbeddingFunction

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors