Русский BM25 для zvec поверх dashtext. Пока SparseVectorEncoder.default("ru") не добавлен в dashtext официально.
pip install nltk mmh3dashtext и zvec уже должны быть установлены.
Скопируйте в свой проект два файла:
tokenizer_ru.py— токенизатор (Snowball + 1,585 стоп-слов ru/en/zh)bm25_ru_default.json— предобученная модель (93 МБ, 2M документов русской Wikipedia)
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, ...}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("поиск документов в компании")Если у вас специфичный домен (юридические документы, медицинские статьи) — обучите на своём корпусе:
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("расторжение договора аренды")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| Компонент | Значение |
|---|---|
| Стемминг | NLTK SnowballStemmer("russian") |
| Нормализация | ё → е |
| Стоп-слова RU | 458 (stopwords-iso + Qdrant/bm25 + ручная курация) |
| Стоп-слова EN | 245 (NLTK + dashtext) |
| Стоп-слова ZH | 882 (Qdrant/bm25) |
| Фильтр мусора | стеммы < 2 символов отбрасываются |
| Хеш | mmh3 (совместим с dashtext) |
| Параметр | Значение |
|---|---|
| Корпус | Русская 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 — методология предобработки русского текста