У нас есть открытый бенчмарк 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.84
v0.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.84
base (мышление ВЫКЛ)   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.63
base + 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 и база — это не простая лесенка «лучше-хуже», а три разных инструмента под три разные задачи. Перепутаешь — проиграешь собственной базе три раунда подряд.

Комментарии (0)