multilingual-e5-small-ru-law
intfloat/multilingual-e5-small (118M параметров, 384 измерения), дообученная для поиска статей законов РФ по вопросам людей: на синтетических вопросах к статьям Трудового, Гражданского, Жилищного кодексов и КоАП, с дистилляцией знаний из ai-forever/FRIDA (823M). Всё обучение занимает 19 минут на одной RTX 3070.
Результат: на тесте RuLawRetrieval nDCG@10 растёт с 0.802 до 0.859 (+0.057, 95% ДИ [+0.042; +0.073]). Это уровень multilingual-e5-large (560M, 0.859; разница +0.001 [−0.016; +0.017], то есть модели статистически неотличимы) при задержке на CPU в 6.8 раза меньше и индексе в 2.7 раза меньше. На трудном наборе бытовых и поисковых вопросов по ТК прирост ещё больше: 0.710 → 0.820 (+0.109 [+0.091; +0.128]).
English summary: multilingual-e5-small fine-tuned on synthetic Russian legal questions with knowledge distillation from FRIDA (823M). On the RuLawRetrieval test set nDCG@10 goes 0.802 -> 0.859, matching multilingual-e5-large (560M) while being 6.8x faster on CPU; on the harder TK set 0.710 -> 0.820. Training takes 19 minutes on one RTX 3070. The largest gains are on colloquial questions (0.569 -> 0.701).
Код, данные и все эксперименты: github.com/alekseevpavel04/ru-law-retrieval.
Использование
Префиксы обязательны, как у исходной e5: query: для вопроса и passage: для документа.
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("alekseevpavel04/multilingual-e5-small-ru-law")
query = ["query: меня уволили, пока я был на больничном, это законно?"]
passages = [
"passage: Трудовой кодекс РФ, Статья 81. Расторжение трудового договора по инициативе работодателя\n"
"Не допускается увольнение работника по инициативе работодателя (за исключением случая ликвидации организации "
"либо прекращения деятельности индивидуальным предпринимателем) в период его временной нетрудоспособности "
"и в период пребывания в отпуске.",
"passage: Трудовой кодекс РФ, Статья 115. Продолжительность ежегодного основного оплачиваемого отпуска\n"
"Ежегодный основной оплачиваемый отпуск предоставляется работникам продолжительностью 28 календарных дней.",
"passage: Трудовой кодекс РФ, Статья 183. Гарантии работнику при временной нетрудоспособности\n"
"При временной нетрудоспособности работодатель выплачивает работнику пособие по временной нетрудоспособности "
"в соответствии с федеральными законами.",
]
q = model.encode(query, normalize_embeddings=True)
d = model.encode(passages, normalize_embeddings=True)
print(q @ d.T) # ст. 81 уверенно первая; у исходной e5-small все три статьи почти не различаются
Абсолютные косинусы у дообученной модели ниже, чем у исходной e5: шкалу растягивает обучение с MultipleNegativesRankingLoss. Значение имеет порядок, а пороги отсечения (min_score) нужно подбирать заново.
Модель сохранена в классическом формате sentence-transformers: версии 3.3.1 и 6.1.0 дают на ней одинаковые эмбеддинги (проверено). Максимальная длина входа 512 токенов. Лучше всего работает, когда поиск идёт по фрагментам статей (500-600 символов) с заголовком статьи в начале каждого фрагмента, а score статьи равен максимуму по её фрагментам: так её обучали и оценивали.
Результаты
Бенчмарк RuLawRetrieval, протокол chunk, поиск по всем 3 786 статьям шести законов. В скобках 95% ДИ парного бутстрапа (10 000 ресэмплов).
| Модель | Параметры | test nDCG@10 | TK-hard nDCG@10 | CPU, мс/запрос |
|---|---|---|---|---|
| intfloat/multilingual-e5-small (исходная) | 118M | 0.802 | 0.710 | 25.3 |
| эта модель | 118M | 0.859 | 0.820 | 23.2 |
| intfloat/multilingual-e5-large | 560M | 0.859 | 0.820 | 158.5 |
| ai-forever/FRIDA (лучшая из 12 baseline) | 823M | 0.878 | 0.854 | 270.2 |
| Сравнение (test, chunk) | Δ nDCG@10 [95% ДИ] |
|---|---|
| против исходной e5-small | +0.057 [+0.042; +0.073] |
| против e5-large (в 4.8 раза больше параметров) | +0.001 [−0.016; +0.017] |
| против FRIDA | −0.019 [−0.036; −0.002] |
| Срез / тип вопроса (test) | исходная | эта модель |
|---|---|---|
статьи из обучения (seen) | 0.785 | 0.865 |
| отложенные статьи тех же кодексов | 0.789 | 0.847 |
| новые кодексы (СК, ЗоЗПП) | 0.837 | 0.863 |
| бытовые вопросы | 0.569 | 0.701 |
| поисковые запросы | 0.896 | 0.924 |
| вопросы юриста | 0.939 | 0.952 |
Прочее:
- три сида (42, 43, 44): test 0.855 ± 0.008, TK-hard 0.816 ± 0.008; опубликован чекпоинт с лучшим dev (seed 43);
- golden (174 вопроса с перепроверенной и множественной разметкой, размечено ИИ-агентом): 0.894 против 0.831 у исходной;
- MTEB RuBQRetrieval (общий домен, не про право): 0.659 против 0.686 у исходной.
Все числа лежат в results/ репозитория проекта.
Как обучена
Двухэтапный рецепт, все решения приняты по dev (results/recipe_selection.json):
- Контрастное обучение (
CachedMultipleNegativesRankingLoss, батч 128, мини-батч 32, 3 эпохи, lr 3e-5, bf16, таблица эмбеддингов словаря заморожена):- 16 тыс. синтетических вопросов (Qwen3-8B, два прохода с разными промптами) к 3.2 тыс. статей четырёх кодексов, три стиля: бытовой, поисковый, юридический;
- позитивный фрагмент внутри своей статьи выбирает учитель FRIDA, он же майнит по одному hard negative (фрагменты эталонной статьи исключены, кандидаты со score ≥ 0.95 от позитива отброшены как вероятные ложные негативы);
- вопросы, для которых учитель не находит свою статью в топ-50, отбрасываются как шум генерации (5%);
- свой батч-сэмплер: в одном батче не бывает двух строк про одну статью.
- Дистилляция (
DistillKLDivLoss, 1 эпоха, lr 1e-5, батч 32): ученик повторяет ранжирование учителя FRIDA по 8 кандидатам на вопрос (позитив и 7 статей из его топа), температура учителя 0.02.
Обучение: 10.7 мин (этап 1) и 7.9 мин (этап 2) на RTX 3070 8 ГБ, пик памяти 2.9 ГБ. Время включает оценку на dev каждые 1/4 эпохи.
Ограничения
- Обучена на синтетических вопросах; на реальных вопросах качество может отличаться.
- Одна редакция законов (сентябрь 2026). На кодексах, которых не было в обучении (СК, ЗоЗПП), прирост меньше: +0.026 [−0.000; +0.052].
- Общий поиск проседает: RuBQ −0.027. Для смешанного сервиса стоит сравнить обе модели.
- Модель ищет статьи, а не даёт юридические консультации.
Лицензия
MIT, как у исходной модели. Обучающие вопросы сгенерированы Qwen3-8B (Apache-2.0), учитель при дистилляции: ai-forever/FRIDA (MIT).