Fine-tune bge-m3-hse-v2 + 3-way бенчмарк
30 апреля — день между pilot run миграции (28-29 апр) и основной миграцией Lyumi (2-3 мая). Сделан полный sprint fine-tune embedding модели на казахстанских HSE-кодексах + честный 3-way бенчмарк (e5-large baseline vs bge-m3 vanilla vs наш fine-tune).
Затраты: $5-6 на vast.ai за 8+ часов R&D. Кредит $0.22 сохранён.
Кратко — что сделано
- v1 fine-tune утром на RTX 6000 Ada (1ч 13мин, ~$2-3) — 34К synthetic triplets из 4518 структурированных чанков 8 кодексов РК (ТК/УК/КоАП/ЭК/ЗК/ВК/КЗ/КН).
- v2 fine-tune днём на RTX PRO 5000 Blackwell (88мин, $0.87) — 45К triplets с hard negatives (cross-code same number + adjacent articles) + natural language anchors из exam_qa и penalties.
- ONNX export — модель в HF под двумя репо (PyTorch + ONNX FP32, identical accuracy cos=1.0).
- Re-embed 164,496 чанков на v2 — chroma_v2 готова к деплою на AX41.
- Honest 3-way benchmark на полной 164K базе с тем же скриптом и теми же тестами. Результат — обнаружен trade-off, см. ниже.
- 398К triplets для будущего v3 (через 1-2 месяца) — hard negatives mining через cross-collection nearest neighbours.
Артефакты
HuggingFace (private under LyumiHSE)
LyumiHSE/bge-m3-hse-v2— PyTorch FP32, 2.27 GB safetensors. Для GPU/cloud inference.LyumiHSE/bge-m3-hse-v2-onnx— ONNX FP32, идентичная точность. Для CPU production на AX41.
На AX41 (готовое к субботе)
/opt/lyumi/chroma_v2.tar.gz(1.6 GB) — embeddings от bge-m3-hse-v2 на 164,496 чанках./opt/lyumi/chroma_20260430.tar.gz(3.6 GB) — backup старой e5-large базы для rollback.
На маке в Карточки Core New/hse_copilot/research/2026-04-30/
- 3 eval лога:
eval_e5_full.log,eval_vanilla_full.log,eval_v2_full.log triplets_v3_full.jsonl(398К triplets, 1.5 GB) — для будущего v3 fine-tunetriplets_v3_seed.jsonl(43К triplets) — sample seedduplicates_top200.json+outliers_top300.json+cluster_map.json(UMAP 25K чанков, 62 кластера)eval_baseline_full.py,reembed_vanilla.py— рабочие скриптыeval.log,duplicates.log,outliers.log,cluster.log,triplets.log,hard_neg_full.log— логи всех экспериментов
⭐ Финальная eval таблица (полная 164K база, единый скрипт keyword-matching)
| Сет | e5-large baseline | bge-m3 vanilla | bge-m3-hse-v2 (наш) |
|---|---|---|---|
| Golden v1 (14, короткие "ст. N кодекс") | 36% | 43% | 79% ⭐ |
| Exam holdout (41, длинные natural language) | 66% | 63% | 39% |
| Penalty holdout (72, описания нарушений) | 86% | 82% | 38% |
| Total weighted (127) | 74% | 72% | 43% |
Что увидели: - Наш fine-tune доминирует на коротких структурированных запросах: Hit@5 +43pp над baseline (36% → 79%). - Но проигрывает baseline на длинных natural language: -27pp на exam, -48pp на penalty. - Это catastrophic forgetting от full fine-tune через TripletLoss на синтетических anchors. - Vanilla bge-m3 ≈ e5-large на длинных запросах (72% vs 74% weighted average).
⚠️ Главный вывод — НЕ просто замена, а HYBRID retriever
Если в субботу просто заменить e5-large на bge-m3-hse-v2, пользователи с длинными запросами получат деградацию (с 74% до 43%). Это плохо.
Правильный подход — гибрид по типу запроса:
import re
SHORT_STRUCTURED = re.compile(
r'\bст\.?\s*\d+|\bстатья\s+\d+|приказ\s+№?\s*\d+|пункт\s+\d+',
re.IGNORECASE
)
def select_model(query):
if SHORT_STRUCTURED.search(query):
return 'bge-m3-hse-v2' # наш fine-tune, 79% golden
return 'bge-m3-vanilla' # или e5-large, ~70-75% на длинных
Vanilla или e5-large для длинных: - Они почти равны (72% vs 74%), разница в пределах шума. - Vanilla имеет ту же архитектуру (XLM-RoBERTa, 1024-dim) что и наш fine-tune → проще production. - Vanilla лучше на golden (43% vs 36%); e5 чуть лучше на penalty (86% vs 82%). - Рекомендация: vanilla для consistency (один base весов в проде), e5 как backup если vanilla окажется медленнее на CPU.
TODO для миграции в субботу 2-3 мая
1. Pull модель и chroma на AX41
pip install huggingface_hub
hf auth login # токен LyumiHSE/lyumi-vast-upload
hf download LyumiHSE/bge-m3-hse-v2-onnx --local-dir /opt/lyumi/models/bge-m3-hse-v2-onnx
tar -xzf /opt/lyumi/chroma_v2.tar.gz -C /opt/lyumi/
2. Реализовать hybrid retriever в retriever.py
Regex selector + двухпуть retrieval:
- Короткие structured queries → bge-m3-hse-v2 + chroma_v2
- Длинные natural language → bge-m3 vanilla (или e5-large как сейчас) + старая chroma_db
- Объединение через RRF (reciprocal rank fusion)
- Cohere reranker поверх объединённого top-20
3. Speed bench локально на AX41 CPU (бесплатно)
Измерить latency single query: - PyTorch bge-m3-hse-v2 - ONNX bge-m3-hse-v2 - Vanilla bge-m3 Цель: short_structured query <100ms на CPU AX41 (12 threads, Ryzen 5 3600).
4. INT8 quantization ONNX (опционально, +30 минут)
optimum-cli onnxruntime quantize --avx512_vnni \
--onnx_model /opt/lyumi/models/bge-m3-hse-v2-onnx \
-o /opt/lyumi/models/bge-m3-hse-v2-onnx-int8
Ускорит CPU inference в 3-5x. ~600 MB вместо 2.2 GB. Точность теряет ~1-2pp — приемлемо.
5. Cohere Reranker test (важно)
У тебя в /opt/lyumi/.env уже есть COHERE_API_KEY. Прогнать тот же eval_baseline_full.py, но top-20 кандидатов от каждой модели отдавать в Cohere Rerank 4 Fast перед оценкой.
Гипотеза: reranker компенсирует weakness'ы embedding-модели на длинных запросах. Может оказаться что bge-m3-hse-v2 + reranker = 70%+ даже на penalty/exam — тогда гибрид не нужен, одна модель + reranker делает всю работу.
Если подтвердится — упрощает архитектуру в production.
Зоны роста — v3 fine-tune через 1-2 месяца
- Mixed dataset — synthetic anchors (текущий подход) + natural language anchors (exam + penalties + 1000+ из query_logs проды). Решит catastrophic forgetting на длинных queries.
- LoRA вместо full fine-tune — меньше catastrophic forgetting, не теряем generalization. Память тоже меньше требует.
- Подзаконные акты в chroma — Приказ 1019 (обучение по БиОТ), ППБ 55 (пожарка), ЗРК 188-V (гражданская защита), СТ РК. Сейчас они не покрыты структурированными чанками. Цель: ~30K дополнительных чанков с metadata code_type/code_articles.
- Hard negatives с context — сейчас просто "одинаковый номер в другом кодексе", добавить семантические негативы (close embeddings но другая тема).
- Trigger для v3: когда накопится 100+ 👎 в feedback на новой v2, или 1000+ запросов в логах с low retrieval score (через 4-6 недель работы в проде).
Зачем 7B модель НЕ нужна сейчас
Есть мысль перейти на e5-mistral-7B-instruct, gte-Qwen2-7B, NV-Embed-v2 (топ MTEB).
Проблема: 7B даёт +3-7% на benchmarks, но требует: - $300-500/мес за GPU server для production (AX41 только CPU, 7B на нём не работает). - LoRA минимум для training (full fine-tune не влезет в 48GB VRAM RTX 6000 Ada). - В 5-10x дороже за весь sprint vs текущие $5.
ROI отрицательный при 48 пользователях. Имеет смысл при 5000+ платящих и 100K+ запросов/месяц. Сейчас bottleneck — дистрибуция и feedback, не качество модели.
Реалистичный путь: bge-m3 + smart fine-tune + reranker → 6-12 месяцев → если станет узко по качеству, тогда LoRA на 7B с classifier-based routing (только сложные запросы → 7B).
Honest assessment
Что получили: - В 2x точнее baseline на короткой задаче ("ст.156 УК" → 79% vs 36%). - Готовая инфраструктура continuous learning ($1-2 за итерацию через 1-2 месяца). - Чистый 3-way benchmark — знаем где модель сильна, где слаба, без розовых очков. - Hybrid strategy — production план, не "ура замена".
Что НЕ получилось: - Fine-tuned модель проиграла baseline на длинных запросах (catastrophic forgetting обнаружен). - Holdout 25-39% на v2 на natural language — синтетика не покрывает реальные запросы. - В одиночку наш fine-tune не подходит для production — нужен гибрид.
Взрослая инженерная позиция: знаем trade-off → планируем гибрид → не заменяем e5 в проде наобум. Если бы поверили утренним 86% Hit@5 на узкой подвыборке — пользователи получили бы regression на длинных запросах после миграции.
Цифры измерили честно. Это и есть ценность сегодняшнего дня — не просто 79% Hit@5, а карта сильных и слабых сторон для production.
Связанные страницы
- [[lyumi/migration_ax41]] — основной план миграции CPX62 → AX41. Раздел "Fine-tune bge-m3" обновлён ссылкой сюда.
- [[lyumi/lookup_tool_design]] — детерминистичный lookup для exact-match запросов (дополнение к hybrid retriever).
- [[lyumi/strategy_2026]] — общая стратегия Lyumi на год.
- [[lyumi/fact_check_apr29]] — fact-check кодексов РК, источник expected_keywords для golden_retrieval_v1.