«Тосок бессмысл»: как я не смог заставить Gemma 4 писать хорошие стихи. gemma.. gemma. llm.. gemma. llm. lora.. gemma. llm. lora. Natural Language Processing.. gemma. llm. lora. Natural Language Processing. reward hacking.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект. Контент и копирайтинг.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект. Контент и копирайтинг. Машинное обучение.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект. Контент и копирайтинг. Машинное обучение. ограниченное декодирование.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект. Контент и копирайтинг. Машинное обучение. ограниченное декодирование. рифма.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект. Контент и копирайтинг. Машинное обучение. ограниченное декодирование. рифма. силлабо-тоника.. gemma. llm. lora. Natural Language Processing. reward hacking. vllm. генерация стихов. искусственный интеллект. Контент и копирайтинг. Машинное обучение. ограниченное декодирование. рифма. силлабо-тоника. файнтюнинг.

Всем привет! Меня зовут Даниил Шеремет, я AI-инженер в Agentic Lab. Днём я проектирую агентные системы, а по вечерам весь последний месяц жёг GPU-часы, пытаясь заставить Gemma 4 писать русские стихи — с правильным ямбом, честной рифмой и хоть каким-то смыслом.

Спойлер вынесен в заголовок: у меня не получилось. Но интересно не это. Интересно, что причина неудачи лежала не там, где ожидал: четыре файнтюна подряд проиграли голой базовой модели, мой собственный грейдер оказался слеп, а когда прозрел — модель немедленно начала его обманывать. Получился почти детектив, в котором главный подозреваемый до последнего выглядит очевидным, а виновным оказывается совсем другой персонаж.

Ниже вас ждут настоящие цифры, реальный loss и плохие стихи. Поехали.

Почему LLM не умеют в русский стих

Кажется, что генерация стихов — задача для LLM тривиальная: попроси ChatGPT, он что-то зарифмует. Но если вы вчитывались в эти стихи, вы знаете: размер плавает, рифма через раз глагольная или вовсе отсутствует, а по содержанию — «в душе моей огонь горит». Причина, как мне казалось на старте, не в «недостатке таланта», а в архитектуре:

  1. Русский стих — силлабо-тоника. Ямб, хорей, дактиль — это регулярные схемы ударений. А ударение в русском подвижное и фонемное (за́мок/замо́к). BPE-токенизатор не видит ни слогов, ни ударений — у модели просто нет органа чувств для метра.

  2. Рифма — отношение фонетическое, а не орфографическое. «Мороз» рифмуется с «нос» из-за оглушения, «уста́лый» с «подва́лы» — потому что заударные гласные редуцируются. По буквам этого не видно.

  3. Рифма — глобальное ограничение. Авторегрессионная модель пишет слева направо, а рифмоваться должны концы строк, отстоящие друг от друга на десятки токенов. Когда модель дописывает четвёртую строку, менять первую уже поздно.

Отсюда рабочая гипотеза, с которой я начинал: основное время уйдёт не на выбор модели, а на механику стиха — ударения, метр, рифму. Так в итоге и вышло, но совсем не тем маршрутом, который я себе нарисовал.

План (каким он был)

Система должна выдавать формально чистый и нестыдный текст по заданной теме или началу стихотворения. План работы — четыре рычага, по убыванию ожидаемой отдачи:

  1. Управляющая разметка + LoRA. Учим модель на парах «разметка → стихотворение», где размер и схема рифмовки заданы явно. В свежей литературе ровно такой рецепт на Qwen обходил Gemini и GigaChat по формальным метрикам — я собирался повторить его на более сильной базе.

  2. Критик-ревизор. Генерируем N кандидатов, программный оценщик ранжирует, ревизор чинит худшие строки.

  3. Ограниченное декодирование. Жёстко навязываем форму во время генерации.

  4. Экзотика (диффузионный infill) — если доживём.

Проект я назвал «petrarca-ml» по имени знаменитого итальянского поэта.

Франческо Петрарка и его венец
Франческо Петрарка и его венец

Файнтюн стоял первым — на него я делал основную ставку. Стек: Gemma 4 12B-it как база, LoRA через PEFT, оркестрация пайплайна на LangGraph (планировщик → генератор → формальный оценщик → семантический судья → ревизор), отдаём ответы через vLLM.

Отдельная маленькая беда — железо. Дома у меня только AMD RX 6600 XT, и это три засады в одной карте: чип gfx1032 не поддержан ROCm (поддержан только gfx1030 — соседний!), QLoRA требует bitsandbytes, который работает только на CUDA, и в 8 ГБ VRAM всё равно не поместится 12B. Так что обучение уехало на арендный L40S в облаке.

Шаг 1. Линейка, которой будем мерить

Прежде чем экспериментировать с обучением, нужно научиться хорошенько всё измерять. Для русских стихотворений есть замечательный инструментарий Ильи Козиева (RPST — Russian Poetry Scansion Tool), но в моё окружение он вставал тяжело — тянул за собой большую модель акцентуации, — поэтому я написал по его мотивам собственный сканер: слогоделение, словарь ударений, определение метра перебором пяти схем, фонетический ключ рифмы с учётом редукции.

На выходе — класс FormalScore: точность метра, точность рифмы, доля ударений на своих местах и сводная «техничность» от 0 до 1.

Вот как сканер видит начало «Зимнего вечера» («—» — ударный слог, «·» — безударный):

Бу́ря мгло́ю не́бо кро́ет,    —·—·—·—·    хорей, 4 стопы
Ви́хри сне́жные крутя́;       —·—···—     хорей, пропуск ударения в третьей стопе

Пропуск ударения (пиррихий) — не дефект, а норма русского стихосложения: пятый слог здесь приходится на безударное окончание слова «снежные», и требовать от него ударения нельзя. Сканер должен отличать такие законные вольности от хромающего ритма.

Проверил на классике: «Зимний вечер», «Парус», «Весенняя гроза», «Чудная картина» — техничность 1.00. Нарезал на строки прозу — около 0.4. Вау, класс, линейка работает.

Шаг 2. Данные

Корпус — ArsPoetica того же Козиева: ~8500 стихотворений с проставленными ударениями (символ U+0301 после гласной). Прогнал через свой сканер, отфильтровал по техничности >= 0.8 — осталось 4452 чистых стихотворения (все пять метров, но ямб ожидаемо доминирует).

Из этого набора получились 13 342 обучающие пары в трёх режимах: тема → стих, начало → продолжение, проза → стих. Вот настоящая пара из датасета — промпт с управляющей разметкой (тема, как несложно догадаться, извлечена из самого стихотворения):

Напиши стихотворение на тему: «Восхищение весенней грозой».

Форма: ямб, 4 стоп, схема рифмовки ABAB.
<meter=iamb feet=4><rhyme=ABAB><motifs=гроза,май,гром,небо>
Используй мотивы: гроза, май, гром, небо.

И ожидаемый ответ:

Люблю грозу в начале мая, Когда весенний, первый гром, Как бы резвяся и играя, Грохочет в небе голубом.

Схема ABAB читается по концовкам строк: ма́я/игра́я — рифма A, гром/голубо́м — рифма B. В режиме «продолжение» из той же пары получается другая: первые две строки уходят в промпт, последние две становятся таргетом.

Train/eval-сплит — по стихотворениям, а не по парам (чтобы одно стихотворение не протекло в обе стороны): 11 942 / 1400.

Шаг 3. LoRA v1, или Модель заговорила на несуществующем языке

Первый полноценный запуск: 3 эпохи, lr 2e-4, r=16, alpha=32, адаптеры на все 7 модулей, включая MLP. Loss красиво падает, адаптер сохранён, vLLM его подхватил. Прошу стихотворение про зимний лес и получаю набор слов:

нагосты́, гу́нты, ковы́ги, би́тм

Модель уверенно, с аккуратно проставленными ударениями, писала стихи из слов, которых в русском языке нет. Базовая Gemma без всякого обучения писала осмысленнее. Я сделал модель хуже за деньги.

Вскрытие показало две наложившиеся причины.

Причина 1: переобучение. Смотрим trainer_state.json:

чекпоинт

train loss

eval loss

эпоха 1

1.74

1.744

эпоха 2

1.924

эпоха 3

0.57

2.259

Eval loss рос каждую эпоху — модель начала запоминать корпус уже к концу первой. А я, не включив load_best_model_at_end, задеплоил последний чекпоинт — то есть худший из трёх.

Причина 2 (интереснее): ударения в таргетах. Все 11 942 обучающих завершения несли комбинирующие знаки ударения U+0301 — я взял из корпуса акцентуированный текст, чтобы «модель выучила ударения». Таргет из примера с Тютчевым на самом деле выглядел так:

Люблю́ грозу́ в нача́ле ма́я, Когда́ весе́нний пе́рвый гром,

В результате модель училась сама расставлять ударения в выходном тексте — то есть генерировать в токенном пространстве, которого Gemma на этапе претрена почти не видела. Комбинирующий диакритик (знак ударения) дробит привычные токены слова на отрывки, модель дообучается на этих отрывках и начинает собирать из них чудовищ. Отсюда «гу́нты» и «ковы́ги»: не галлюцинации, а фонетическая каша на уровне токенов.

Урок: не заставляйте модель генерировать в экзотическом для неё пространстве, если без этого можно обойтись. Ударения нужны оценщику, а не читателю — значит, пусть оценщик их и расставляет (об этом ниже), а обучающие таргеты должны быть чистым текстом.

Шаг 4. LoRA v2: чиню всё — не помогает

v2: чистые таргеты без ударений, lr вдвое ниже (1e-4), load_best_model_at_end включён. Результат: eval loss 2.391 → 2.571 → 2.816. Снова переобучение после первой эпохи — правда, теперь автоматика хотя бы честно выбрала чекпоинт первой эпохи вместо последней.

Зато стихи стали связными! Русские слова, узнаваемый размер. Вот что v2 отвечает на запрос про весеннюю грозу (ямб, 4 стопы, ABAB) — тема та же, что у Тютчева выше:

Майская гроза, гроза весной! Как сладок стон твоих разрывов, Как свежесть неба голубой И неба радость голубого!

Похоже на стихи? Похоже. Если присмотреться — согласование хромает («свежесть неба голубой»), рифма A на месте (весной/голубой), а вместо рифмы B — «разрывов/голубого». Но после «ковыг» и «гунтов» это выглядело прогрессом, и я прогнал A/B против базы своим оценщиком: v2 — 0.705, база — 0.618. Победа? Файнтюн работает?

Вот тут детектив и начинается.

Поворот: оценщик был слеп

Я заметил, что оценки подозрительно ровные: и хорошие, и плохие стихи кучковались в районе 0.6–0.7. Решил прогнать через оценщика контрольные образцы. Эталонный ямб, в противовес ему плохие по технике стихи и нарезанную на строки прозу.

текст

техничность

идеальный ямб

0.825

сломанный стих

0.650

проза, нарезанная строками

0.650

Проза и сломанный стих — одинаково. Мой оценщик не отличал стихи от прозы. Все выводы из A/B-сравнений до этого момента — включая «v2 лучше базы» — можно было выбрасывать: 0.705 против 0.618 было шумом.

Почему так вышло? На акцентуированной классике (где ударения проставлены в самом тексте) оценщик работал отлично — поэтому проверка на «Зимнем вечере» и прошла. Но модель-то генерирует текст без ударений, а мой встроенный словарь ударений покрывал жалкие ~60 слов. Встроенный механизм оценки считал всё так, как будто любые стихи идеально ложатся на любой метр.

Бонусом нашёлся баг в рифме — на том же Тютчеве. Для односложного слова в конце строки («гром», «день») алгоритм не мог определить ударение, помечал его как неоднозначное и уходил искать рифму в предыдущее слово строки, собирая фонетический ключ из мусора: «первый гром» превращался в ервыйграм, и хрестоматийный катрен про грозу в начале мая получал рифму 0.5. Юнит-тесты этого не ловили: фикстуры в них были акцентуированные, на таких ударение известно, и ветка с багом просто не исполнялась. Тесты проверяли не те данные, с которыми система работала в реальности.

Чинил в три приёма:

  1. Настоящая расстановка ударений: обернул нейросетевой акцентуатор RUAccent (onnxruntime, CPU, без torch) в интерфейс словаря ударений. Любой сбой акцентуатора активирует bypass — пусть оценщик лучше промолчит, чем выдумает нарушение.

  2. Рифма: якорь строго на последнем слове строки; поддержка неточной женской рифмы (уста́лый/подва́лы, верши́ны/кончи́ной — это нормальные русские рифмы).

  3. Перевзвешивание: доля ударений на своих местах оказалась ~0.9 у любого текста, включая прозу, — сигнала в ней почти нет; вес перекинут на метр и рифму (0.50/0.40/0.10).

Контрольная проверка на 60 эталонных стихах: идеал 1.000, живая классика 0.783, проза 0.458. Вот теперь линейка работает!

A/B сидели на трубе

Перемеряю всё с новым оценщиком: 20 тем, по 4 кандидата с каждой модели, считаем среднюю оценку и оценку лучшего из четырёх (то, что реально отдаст система с ранжированием):

модель

средняя

best-of-4

метр

рифма

эталон (живые поэты)

0.798

0.952

0.558

Gemma 4 12B база

0.693

0.821

0.846

0.757

poet-lora-v2

0.632

0.774

0.892

0.579

poet-lora-v1

0.679

0.748

0.963

0.419

Базовая модель без всякого обучения победила оба моих файнтюна. А главное — таблица показывает, почему: смотрите на колонки метра и рифмы. v1 добилась лучшего метра (0.963 — выше эталона!), заплатив за это катастрофой в рифме (0.419). v2 — то же самое, мягче. База хуже всех держит метр, зато лучше всех рифмует.

Файнтюнинг не то, что «не сработал» — он сработал. Он выучил ровно то, что я ему показал. Разметка <meter=iamb feet=4> объясняет метр конкретно, а <rhyme=ABAB> — просто ярлык: в промпте нет ни целевых слов, ни созвучий. SFT оптимизирует тот сигнал, который видит во входе, и единственный доступный размен был «метр дороже, рифма дешевле».

Я, конечно, так просто не сдался:

  • v3: адаптеры только на attention (гипотеза: LoRA на MLP переписывает лексику и убивает подбор рифм), lr 5e-5, чекпоинты по шагам. Итог: не переобучилась (train ≈ eval, как и хотелось!), но недообучилась — и всё равно просадила рифму (0.572). Худший результат из всех.

  • v4: добавил во входную разметку построчную маску ударений <stress=·/—/·/—...> — «рычаг №1, сделанный правильно». Тоже проиграла базе.

Четыре запуска. Четыре независимые настройки: learning rate, целевые модули, расписание чекпоинтов, формат кондиционирования. Один и тот же исход: рифма — неизменная жертва, база впереди. Когда независимые ручки сходятся в одну точку — это проблема метода.

Результаты вскрытия

В порядке значимости обнаружились следующие причины:

  1. Асимметрия условий обучения. Метр в разметке задан явно, позиция за позицией — его можно почти скопировать. Рифма — только абстрактным ярлыком. Градиент обучения идёт туда, где сигнал конкретнее.

  2. Рифма — ограничение этапа декодирования, а не знание. Метр локален (внутри строки, слева направо) — его SFT выучить может. Рифма глобальна, межстрочна и фонетична; авторегрессия не может гарантировать её обучением. Недаром классический приём поэтических генераторов — писать строку задом наперёд, от рифмы.

  3. SFT сужает сильную базу, а рифме нужна широта. Подбор рифмы — это поиск по лексикону: нужно много вариантов концовки строки. 12 тысяч примеров, влитых в 12B, сужают распределение и делают его более шаблонным — у файнтюнов заметно меньше прирост от best-of-N (меньше разнообразие кандидатов). Обучением я отбирал у модели ровно ту способность, на которой держится рифма.

  4. Фильтр данных был слеп на тот же глаз. Корпус отбирался по техничности ≥ 0.8, посчитанной старым, слепым к рифме оценщиком — то есть датасет отобран по метру и зашумлён по рифме. (Смягчающее обстоятельство: эталонные поэты через тот же фильтр прошли и рифмовать не разучились.)

  5. Низкий потолок. Gemma 4 12B уже бегло пишет рифмованный русский текст. Маленькому шумному адаптеру почти нечего добавить — зато есть что отнять.

Трюки на инференсе вместо обучения

Пока я перезапускал файнтюны, три «дешёвых» приёма без единой минуты обучения понемногу делали результат.

Best-of-N + ранжирование. Генерируем 4–8 кандидатов, оценщик выбирает лучшего: +0.13 техничности бесплатно. База с best-of-4 (0.821) обгоняет даже одиночные образцы живых поэтов (0.798) — по нашей линейке, разумеется.

Критик-ревизор. Оценщик умеет не только ставить оценку, но и диагностировать: какая строка хуже всех ложится в метр, какая выпала из схемы рифмовки. Ревизор просит модель переписать одну худшую строку, подставляет варианты, пересчитывает — и принимает правку, только если оценка всего стихотворения выросла. Живой пример: худший кандидат по теме «зимний лес» — 0.559 → 0.800 за один проход.

Но здесь меня ждал второй акт детектива. Ревизор в погоне за оценкой вставил в строку слово «строгу». Такого слова нет — но оценщик не носитель языка, ему «строгу» метрически удобно. Цикл ревизии усиливает слепые пятна метрики: как только оценка становится целью, находятся способы и её накрутить.

Ограниченное декодирование — приём, который в итоге дал реальный прирост. Ограничение работает на уровне строки: сначала модель предлагает тематические слова-концовки, затем мой оценщик (не модель!) отбирает из них честно рифмующийся набор, и каждая строка генерируется с обязательством закончиться на своё слово, а из k вариантов берётся лучший по метру. Рифма фиксируется до генерации строки — та самая «рифма задом наперёд», только на уровне пайплайна.

И вот тут система впервые обыграла всё, включая эталон:

метод

техничность

метр

рифма

эталон (живые поэты)

0.831

0.970

0.619

база, свободный best-of-4

0.842

0.876

0.772

база, constrained

0.887

0.788

1.000

Рифма — единица по построению. Метр просел (навязанная концовка сковывает строку) — честная цена. Симметрия с файнтюном вышла зеркальная: LoRA меняла рифму на метр и проигрывала, ограниченное декодирование меняет метр на рифму и выигрывает — потому что дефицитным ресурсом была именно рифма, и решается она при декодировании, а не в весах.

Правда, тут же вскрылись новые накрутки от модели — теперь ломался сам отбор рифм. Вот что модель протаскивала через «рифма = 1.000»:

Разрезает небо серый гром. В небесах гремит немой гром.

Тавтологическая «рифма»: гром/гром, потом/потом. Фонетический ключ совпадает идеально! Второй трюк — выдуманные слова, подогнанные под созвучие. Мой любимый экспонат целиком (тема «тщетность накопления жизненного опыта», амфибрахий; слепой оценщик поставил техничность 1.000):

Весь опыт прожитый — лишь зыбкий песок. И в памяти нашей — лишь старый песок. И в сердце застывший — былой ток. И в прошлом застыл лишь немой тосок.

Здесь всё сразу: «рифма» песок/песок и венчающее катрен слово «тосок», которого в русском языке нет. Встречались ещё «сгора», «прад» и «бессмысл» — последним заканчивался катрен про экзистенциальное перерождение. Оценщик не знает, что таких слов не существует.

Две заплатки: если слово-концовка повторяется где-то ещё в стихотворении, рифма не засчитывается; если кандидата в рифмы нет в трёхмиллионном словаре словоформ акцентуатора, он отбрасывается ещё до генерации. После этого выдуманные концовки исчезли (ноль на тестовой пачке), а стихи с повторами честно получают рифму 0.000.

Каждый цикл оптимизации против метрики находил новую дыру, и каждая дыра затыкалась не «улучшением модели», а знанием, внешним по отношению к модели: словарём, фонетикой, правилами.

Так выглядит честный выход ограниченного декодера после всех заплаток (тема «весеннее оживление городской жизни», дактиль, ABAB, техничность 1.000):

Город в лучах золотых — пробужденье. Слышится в парке весенний рассвет. Всюду в проспектах живое движенье. В каждом прохожем — весенний совет.

Рифмы настоящие (пробужденье/движенье, рассвет/совет — оба слова существуют, ни одно не повторяется), размер держится. Правда, «весенний совет» — это уже вопрос не к форме, а к смыслу. О нём — ниже.

Контрольный выстрел в LoRA (хорошо, что не в ногу). С ограниченным декодированием база и файнтюн v2 выдают идентичную формальную техничность 0.930 — форму теперь определяет декодер, а не веса, и вопрос, на который я потратил четыре запуска обучения, перестал иметь значение. Но у файнтюна 8 прогонов из 24 не завершились (не собрался рифмующийся набор слов — та самая потерянная лексическая широта), а у базы не завершился один.

А попарное сравнение независимым LLM-судьёй (DeepSeek; каждая пара показывается в обоих порядках, чтобы убрать позиционное смещение; 20 тем) по художественной рубрике: база — 22 победы, файнтюн — 8, ничьих — 10. Форма, надёжность, качество — 3:0. LoRA-ветку я закрыл с чистой совестью.

Почему стихи всё-таки «так себе»

Формальный движок выжат: техничность 0.93 при потолке эталона ~0.83 (по этой линейке). Вот реальный выход системы, без специального отбора — тема «экзистенциальное перерождение через самопознание», ямб, ABAB, техничность 1.000:

Душа сквозь призму истин — пробужденье. В себе являя тайный свет. Сквозь боль познанья — духа очищенье. Оставив в прошлом прежний след.

Метрически чисто, рифма честная (кстати, та самая тема, которая при слепом оценщике заканчивалась «бессмыслом», — прогресс налицо). А теперь перечитайте это как читатель, а не как метролог. «Тайный свет», «боль познанья», «прежний след» — стихи, собранные из самых вероятных токенов русской поэзии. Модель, если её не держать, тяготеет к кладбищенско-сумеречной лексике: тень, день, тлен, плен, пустота, тишина — эти слова короткие, частотные в поэтическом корпусе и легко рифмуются.

Для калибровки — Фет, четыре строки из школьной программы:

Чудная картина, Как ты мне родна: Белая равнина, Полная луна.

По моей линейке здесь та же техничность 1.00, что и у катрена выше. Простейшие слова, никакой явной «поэтичности», но картинка буквально оживает перед глазами. Разница между этими двумя катренами — ровно то, чего программный оценщик не видит и никогда не увидит.

Форму получилось навязать; со смыслом этот номер не проходит — хорошее приходится отбирать из многих попыток и вычищать от штампов. Что я планирую дальше:

  1. Семантического судью — внутрь цикла, с явным списком клише. Судья уже есть (рубрика: тема, образность, связность, оригинальность), но пока работает финальным фильтром. Его место — в цикле ревизии, со штрафом за штампы: генерировать шире, отбраковывать жёстче.

  2. Если возвращаться к дообучению — менять целевую функцию, а не ручки. SFT-имитация своё отыграла. А вот DPO на парах «рифмуется лучше / хуже», размеченных уже зрячим оценщиком, даёт прямой градиент по рифме, которого у SFT не было ни в одной конфигурации. Плюс конкретные слова-рифмы прямо во входную разметку — чтобы убрать ту самую асимметрию.

  3. Вернуть метр, не отдавая рифму: ограниченный декодер гарантирует рифму, ревизор после него добирает метр; при отборе рифмующегося набора предпочитать метрически удобные (мужские) концовки.

  4. Диффузионный infill. Диффузионные варианты Gemma генерируют канвас параллельно и правят любую позицию на любом шаге денойзинга. Для стиха это архитектурно родная постановка: приколотить слова-рифмы и ударные слоги, дать модели заполнить остальное. Катрен как задача удовлетворения ограничений, а не генерация слева направо.

  5. Мультимодальный вход — «напиши по этой фотографии» Gemma 4 умеет нативно, планировщик просто извлекает из картинки мотивы в ту же разметку. По иронии, это самая простая часть всего проекта.

Что я из этого вынес

  • Сначала калибруй линейку, потом оптимизируй. Прогнать через метрику эталон, заведомый брак и прозу — 20 минут. Я не сделал этого в первый день и месяц принимал решения по шуму. Все выводы, полученные до проверки метрики, пришлось пересчитывать, и часть из них перевернулась.

  • Тесты должны гоняться на тех же данных, с которыми система работает в бою. Мои фикстуры были с ударениями, реальный текст — без. Зелёные тесты, слепой оценщик.

  • Если несколько независимых настроек дают один и тот же провал — хороните метод, а не подкручивайте ручки. Четвёртый запуск был нужен не для результата, а чтобы я поверил первым трём.

  • Глобальные ограничения — на декодер, локальные паттерны — в веса. Метр SFT выучивает (даже слишком). Рифму — принципиально нет. Разделяйте задачи по тому, где они решаются, а не по тому, какой инструмент моднее.

  • Любая оптимизация против метрики немедленно начинает её ломать. «Строгу», гром/гром, «бессмысл» — три поколения накруток за неделю. Лечится не тюнингом, а внешним знанием: словарём, фонетикой, правилами.

  • Сильная база, внешнее знание и контроль на инференсе выиграли у файнтюна по всем осям — форма, надёжность, качество — и стоили в разы дешевле.

Если у вас есть опыт DPO по формальным критериям текста, диффузионного infill — или вы просто хотите поспорить, что «уста́лый/подва́лы» не рифма, — жду в комментариях.

Инструменты и данные, на которых всё стоит:

Автор: dsheremet

Источник