У нас есть открытый бенчмарк https://github.com/csylabs-org/lii-sport-bench-ru для оценки русскоязычных LLM на спортивном домене — ЛИИ-Спорт-Bench-RU, 655 экспертных вопросов по 35 видам спорта. В прошлой статье мы выбрали базовую модель: Gemma 4 31B. После этого начался главный вопрос — как сделать её лучше под домен.
Две недели мы пытались обогнать собственную базу. Файнтюном. Потом ещё раз файнтюном на переделанном корпусе. Потом — RAG. Все три раунда базовая версия выиграла.
Это статья про отрицательный результат. Я считаю, он полезнее победы — потому что его можно воспроизвести (и научиться на моих ошибках) и он объясняет, какой инструмент лучше бы подошел под какую задачу. Дальше — цифры, стек и три разбора «почему не взлетело».
Вводные: что и на чём измеряли
Бенчмарк — 655 вопросов, 8 категорий (правила, методика, биомеханика, психология, регуляторика, история, антидопинг, сценарные ситуации), три уровня сложности. Для итераций гоняли пилотный срез на 200 вопросах.
Судейство — классический для наших подходов ансамбль из трёх независимых моделей: Claude Opus 4.7, Gemini 3.1 Pro, GPT-5.5. Каждый ответ оценивается по рубрике (точность / полнота / бонус / русский язык), берётся среднее по трём судьям. Self-judging bias раскрыт: Opus и Gemini одновременно и кандидаты в других прогонах, и судьи здесь — смещение замерено и зафиксировано.
Железо — арендованный сервер с RTX PRO 6000 Blackwell на 96 ГБ. Софтовый стэк — llama.cpp (server-cuda), Q8_0, контекст 32K, KV-кэш тоже Q8. Важная деталь: и базу, и все дообученные варианты гоняли на одном и том же стеке (llama.cpp Q8), чтобы сравнение было честным — а не «база через OpenRouter против нашего GGUF» (честно, сначала так и сделал, OR самый простой вариант, но похоже там BF16).
Точка отсчёта:
base gemma-4-31b-it (llama.cpp Q8, 200 вопросов, ансамбль из 3 судей) overall 7.84
Раунд 1. SFT (LoRA): дообучили — стало хуже
Первый подход — supervised fine-tuning. LoRA через Unsloth (Gemma 4 со своим head_dim=512 не дружит с обычным FlashAttention-2 — Unsloth со своими ядрами это закрывает; обычный LoRA, не DoRA, иначе ломается merge в GGUF). Корпус — около 5 тысяч пар «вопрос-ответ», собранных из открытых источников по домену.
base 7.84v0.1 (LR 2e-4) 6.08 (−1.76)v0.2 (LR 5e-5) 6.92 (−0.93)
Минус 1.76 балла. Дообучили — стало заметно хуже.
Первая гипотеза была про скорость обучения (2e-4 слишком агрессивно — на 5e-5 действительно стало легче). Но копнули глубже и нашли две причины:
→ Корпус был собран в довольно кратком формате изложения. Средняя длина эталонного ответа в корпусе — около 114 токенов. Модель научилась отвечать коротко. А бенчмарк (и судьи) вознаграждают полноту: база выдавала развёрнутые ответы на 1138 токенов и набирала на полноте и бонусе.
→ Сам бенчмарк смещён в сторону многословности. Одни и те же веса при разном способе генерации давали разброс 7.08–7.84. Это честный методологический баг нашего харнеса — рубрику нужно нормировать по длине. Так, зафиксировали.
Половину провала объясняла длина, половину — агрессивный LR и форма данных. Вывод раунда: дело не в параметрах, дело в корпусе.
Раунд 2. Корпус v0.3 (плотный, дистиллированный) — и сдвиг на «мышление»
Переделали корпус. Каждый краткий ответ переписан в более детальный, с подтверждением источниками, вариант через дистилляцию (Gemini 3.5 Flash, batch-режим, ~$40 за весь прогон). Получили 5298 развёрнутых ответов. Дообучили заново на мягком LR.
v0.3 (плотный корпус) 6.98 (−0.86 к базе 7.84)
Лучше, чем v0.1/v0.2 — но всё ещё ниже базы. И тут возник честный вопрос: а сравнение-то корректное?
Gemma 4 — reasoning-модель. Базу я гонял с включённым «мышлением» (модель тратит токены на цепочку рассуждения перед ответом — то, чего лишились дообученные варианты). Это нечестное преимущество базы. Перегнали базу в режиме прямого ответа:
base (мышление ВКЛ) 7.84base (мышление ВЫКЛ) 7.63 (мышление дает +0.22)v0.3 6.98
Честное сравнение — v0.3 против base-no-think — это −0.64. И, что важно, база-без-мышления отвечала КОРОЧЕ (555 токенов против 653 у v0.3) и всё равно выигрывала. Значит, это уже не про длину и не про мышление. Это про точность: 7.59 против 6.59.
Разобрали ответы поштучно. v0.3 галлюцинирует на фактах: выдуманные имена членов Зала славы ФИБА, несуществующие медали, придуманные нормативы. База эти же вопросы берёт правильно — на одном вопросе она даже поправила ошибку в нашем собственном эталонном ответе (неловкий момент).
Механизм — как по учебнику. Это «Fine-Tuning or Retrieval?» (Ovadia et al., arXiv 2312.05934) и катастрофическая забывчивость: нельзя дёшево поднять качество сильной frontier-модели на её же сильной стороне маленьким SFT на данных слабее её собственных претрейн-знаний. (длинно получилось, но по другому суть не могу сформулировать, модель крайне умна). Дистиллированный Flash-корпус добавил уверенной, но неточной выдумки — то есть научил модель ошибаться, но ошибаться грамотно и красиво.
Тут стоит оговориться, чего мы НЕ делали: полноценный CPT (continual pretraining) на большом домен-корпусе. Это правильный инструмент для внедрения полноценно знаний — но он требует большого корпуса и вычислительных мощностей другого порядка (и в данном случае я даже не уверен стоит ли это того).
Раунд 3. RAG — и почему он тоже проиграл (на этом бенчмарке)
Если файнтюн — не тот инструмент для знаний, логичный следующий шаг — retrieval. Не дообучать модель, а подкладывать ей правильные факты в контекст, я честно говорю сразу — про RAG было предвзятое мнение у меня лично, и оно изменилось, но в конкретно данной ситуации — помочь не смогло.
Собрали суверенный RAG-стек целиком:
→ эмбеддер — BGE-M3 (dense + sparse в одной модели, мультиязычный, self-hosted) → векторное хранилище — pgvector с PostgreSQL 18 → поиск — гибрид: dense-косинус + BM25 (tsvector с русской конфигурацией), слияние через RRF (reciprocal rank fusion) → генерация — та же база Gemma 4 31B через llama.cpp, мышление выключено → индекс — авторитетные исходники (правила видов спорта, приказы Минспорта, ФССП, материалы РУСАДА), ~2200 чанков, эмбеддинг на GPU.
Прокси, OpenAI-совместимый: на вход вопрос → эмбеддинг → гибридный поиск top-k → инъекция чанков в системный промпт с инструкцией «отвечай по источникам, цитируй конкретный документ» → llama.cpp. Харнес бенчмарка при этом не меняли ни строкой — он просто ходит на другой адрес.
На простом вопросе всё красиво: «в каких дисциплинах проводятся соревнования по волейболу» → ответ с точной ссылкой на приказ Минспорта № 834, раздел I, пункт 3. Прямо из найденного чанка. Это G2 — проверяемая цитата.
А потом — общий прогон:
base (мышление ВЫКЛ) 7.63base + RAG (v1.0) 6.81 (−0.82)
Снова минус. RAG проиграл по всем категориям — даже на правилах и регуляторике, где у нас больше всего исходников. Разобрали 110 вопросов, где база победила RAG. Два механизма провала:
→ Отказы (17% ответов). Несмотря на инструкцию «если в источниках нет — отвечай своими знаниями», модель при промахе поиска всё равно писала «на основании предоставленных источников ответ дать невозможно». Вопросы, которые база знала назубок без всякого поиска (требования к тренерскому составу, возраст допуска к стрельбам в биатлоне), RAG превращал в отказ.
→ Отвлечение (остальные потери). Даже когда модель отвечала, подложенные частичные чанки уводили её от сильного собственного ответа к худшему, «по источнику». На методике это било больнее всего: вместо чёткого протокола реабилитации база давала ответ как по книжке, а RAG — расплывчатый «согласно ФССП».
Посчитали потолок. Если бы у нас был ИДЕАЛЬНЫЙ гейт релевантности (магически знающий, когда подключать RAG, а когда — чистую базу):
идеальный oracle-гейт (недостижимо) 7.78 (+0.16 к базе)
Даже недостижимый идеал даёт +0.16. Реальный гейт + реранкер дотянули бы примерно до паритета. Вывод: на ЭТОМ бенчмарке RAG не может существенно обогнать базу — потому что база уже знает общий материал, а RAG добавляет ценность только там, где база чего-то не знает.
И вот это — ключ.
Что мы на самом деле выяснили про инструменты
Бенчмарк проверяет ОБЩИЕ знания по домену — а сильная frontier-база ими уже владеет. Поэтому ни SFT, ни RAG её на этом не обходят. Но 12 вопросов RAG всё-таки выиграл — и они показывают, где он реально работает:
ВОЛ-СМ-003 база 2.0 → RAG 8.4БОР-ПР-007 база 3.8 → RAG 7.9 (весовые категории — точные данные)ФУТ-МТ-002 база 3.0 → RAG 6.0 (приказ ФССП по футболу)
RAG выигрывает ровно там, где база СЛАБА и в источнике есть точный факт: конкретный номер приказа, таблица ФССП, частное правило. Это узкая, но ценная зона — и на общем бенчмарке она тонет.
Отсюда — карта инструментов, которая, мне кажется, и есть главный результат:
→ SFT — это про поведение и формат, а не про знания. Маленьким SFT не закачать знания в сильную базу — получишь катастрофическое забывание. → CPT — правильный инструмент для знаний, но дорогой (большой корпус + компьют). Его мы ещё не запускали. → RAG — для фактов, которых у базы быть НЕ МОЖЕТ: свежие регламенты, узко-юрисдикционные нормы, документы конкретной организации. На общих знаниях, которыми база уже владеет, RAG скорее мешает (отвлечение + отказы). → База как есть — там, где она уже сильна. Иногда лучший «тюнинг» — не трогать.
И отдельный технический урок про RAG-инженерию: на сильной базе наивный always-inject вредит. Нужен гейт релевантности (подключать контекст только при уверенном попадании) и кросс-энкодер-реранкер — иначе плохой поиск делает модель хуже, чем она была без него.
Что дальше
Бенчмарк, код харнеса, промпты и сырые оценки судей — будут открыты в репозитории. Следующая итерация методологии — нормировка рубрики по длине ответа (тот самый verbosity-bias) и кросс-энкодер + реранкер в RAG-контуре.
Отрицательный результат — не просто тоже результат, а один из главных инструментов роста, если он воспроизводимый. Этот кейс объяснил лично мне то, за чем я гонялся давно — какой инструмент лучше использовать под какую задачу. Файнтюн, RAG и база — это не простая лесенка «лучше-хуже», а три разных инструмента под три разные задачи. Перепутаешь — проиграешь собственной базе три раунда подряд.
ссылка на оригинал статьи https://habr.com/ru/articles/1040322/