Всем привет! Меня зовут Даниил Шеремет, я AI-инженер в Agentic Lab. Днём я проектирую агентные системы, а по вечерам весь последний месяц жёг GPU-часы, пытаясь заставить Gemma 4 писать русские стихи — с правильным ямбом, честной рифмой и хоть каким-то смыслом.
Спойлер вынесен в заголовок: у меня не получилось. Но интересно не это. Интересно, что причина неудачи лежала не там, где ожидал: четыре файнтюна подряд проиграли голой базовой модели, мой собственный грейдер оказался слеп, а когда прозрел — модель немедленно начала его обманывать. Получился почти детектив, в котором главный подозреваемый до последнего выглядит очевидным, а виновным оказывается совсем другой персонаж.
Ниже вас ждут настоящие цифры, реальный loss и плохие стихи. Поехали.
Почему LLM не умеют в русский стих
Кажется, что генерация стихов — задача для LLM тривиальная: попроси ChatGPT, он что-то зарифмует. Но если вы вчитывались в эти стихи, вы знаете: размер плавает, рифма через раз глагольная или вовсе отсутствует, а по содержанию — «в душе моей огонь горит». Причина, как мне казалось на старте, не в «недостатке таланта», а в архитектуре:
-
Русский стих — силлабо-тоника. Ямб, хорей, дактиль — это регулярные схемы ударений. А ударение в русском подвижное и фонемное (за́мок/замо́к). BPE-токенизатор не видит ни слогов, ни ударений — у модели просто нет органа чувств для метра.
-
Рифма — отношение фонетическое, а не орфографическое. «Мороз» рифмуется с «нос» из-за оглушения, «уста́лый» с «подва́лы» — потому что заударные гласные редуцируются. По буквам этого не видно.
-
Рифма — глобальное ограничение. Авторегрессионная модель пишет слева направо, а рифмоваться должны концы строк, отстоящие друг от друга на десятки токенов. Когда модель дописывает четвёртую строку, менять первую уже поздно.
Отсюда рабочая гипотеза, с которой я начинал: основное время уйдёт не на выбор модели, а на механику стиха — ударения, метр, рифму. Так в итоге и вышло, но совсем не тем маршрутом, который я себе нарисовал.
План (каким он был)
Система должна выдавать формально чистый и нестыдный текст по заданной теме или началу стихотворения. План работы — четыре рычага, по убыванию ожидаемой отдачи:
-
Управляющая разметка + LoRA. Учим модель на парах «разметка → стихотворение», где размер и схема рифмовки заданы явно. В свежей литературе ровно такой рецепт на Qwen обходил Gemini и GigaChat по формальным метрикам — я собирался повторить его на более сильной базе.
-
Критик-ревизор. Генерируем N кандидатов, программный оценщик ранжирует, ревизор чинит худшие строки.
-
Ограниченное декодирование. Жёстко навязываем форму во время генерации.
-
Экзотика (диффузионный 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. Юнит-тесты этого не ловили: фикстуры в них были акцентуированные, на таких ударение известно, и ветка с багом просто не исполнялась. Тесты проверяли не те данные, с которыми система работала в реальности.
Чинил в три приёма:
-
Настоящая расстановка ударений: обернул нейросетевой акцентуатор RUAccent (onnxruntime, CPU, без torch) в интерфейс словаря ударений. Любой сбой акцентуатора активирует bypass — пусть оценщик лучше промолчит, чем выдумает нарушение.
-
Рифма: якорь строго на последнем слове строки; поддержка неточной женской рифмы (уста́лый/подва́лы, верши́ны/кончи́ной — это нормальные русские рифмы).
-
Перевзвешивание: доля ударений на своих местах оказалась ~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, целевые модули, расписание чекпоинтов, формат кондиционирования. Один и тот же исход: рифма — неизменная жертва, база впереди. Когда независимые ручки сходятся в одну точку — это проблема метода.
Результаты вскрытия
В порядке значимости обнаружились следующие причины:
-
Асимметрия условий обучения. Метр в разметке задан явно, позиция за позицией — его можно почти скопировать. Рифма — только абстрактным ярлыком. Градиент обучения идёт туда, где сигнал конкретнее.
-
Рифма — ограничение этапа декодирования, а не знание. Метр локален (внутри строки, слева направо) — его SFT выучить может. Рифма глобальна, межстрочна и фонетична; авторегрессия не может гарантировать её обучением. Недаром классический приём поэтических генераторов — писать строку задом наперёд, от рифмы.
-
SFT сужает сильную базу, а рифме нужна широта. Подбор рифмы — это поиск по лексикону: нужно много вариантов концовки строки. 12 тысяч примеров, влитых в 12B, сужают распределение и делают его более шаблонным — у файнтюнов заметно меньше прирост от best-of-N (меньше разнообразие кандидатов). Обучением я отбирал у модели ровно ту способность, на которой держится рифма.
-
Фильтр данных был слеп на тот же глаз. Корпус отбирался по техничности ≥ 0.8, посчитанной старым, слепым к рифме оценщиком — то есть датасет отобран по метру и зашумлён по рифме. (Смягчающее обстоятельство: эталонные поэты через тот же фильтр прошли и рифмовать не разучились.)
-
Низкий потолок. 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, что и у катрена выше. Простейшие слова, никакой явной «поэтичности», но картинка буквально оживает перед глазами. Разница между этими двумя катренами — ровно то, чего программный оценщик не видит и никогда не увидит.
Форму получилось навязать; со смыслом этот номер не проходит — хорошее приходится отбирать из многих попыток и вычищать от штампов. Что я планирую дальше:
-
Семантического судью — внутрь цикла, с явным списком клише. Судья уже есть (рубрика: тема, образность, связность, оригинальность), но пока работает финальным фильтром. Его место — в цикле ревизии, со штрафом за штампы: генерировать шире, отбраковывать жёстче.
-
Если возвращаться к дообучению — менять целевую функцию, а не ручки. SFT-имитация своё отыграла. А вот DPO на парах «рифмуется лучше / хуже», размеченных уже зрячим оценщиком, даёт прямой градиент по рифме, которого у SFT не было ни в одной конфигурации. Плюс конкретные слова-рифмы прямо во входную разметку — чтобы убрать ту самую асимметрию.
-
Вернуть метр, не отдавая рифму: ограниченный декодер гарантирует рифму, ревизор после него добирает метр; при отборе рифмующегося набора предпочитать метрически удобные (мужские) концовки.
-
Диффузионный infill. Диффузионные варианты Gemma генерируют канвас параллельно и правят любую позицию на любом шаге денойзинга. Для стиха это архитектурно родная постановка: приколотить слова-рифмы и ударные слоги, дать модели заполнить остальное. Катрен как задача удовлетворения ограничений, а не генерация слева направо.
-
Мультимодальный вход — «напиши по этой фотографии» Gemma 4 умеет нативно, планировщик просто извлекает из картинки мотивы в ту же разметку. По иронии, это самая простая часть всего проекта.
Что я из этого вынес
-
Сначала калибруй линейку, потом оптимизируй. Прогнать через метрику эталон, заведомый брак и прозу — 20 минут. Я не сделал этого в первый день и месяц принимал решения по шуму. Все выводы, полученные до проверки метрики, пришлось пересчитывать, и часть из них перевернулась.
-
Тесты должны гоняться на тех же данных, с которыми система работает в бою. Мои фикстуры были с ударениями, реальный текст — без. Зелёные тесты, слепой оценщик.
-
Если несколько независимых настроек дают один и тот же провал — хороните метод, а не подкручивайте ручки. Четвёртый запуск был нужен не для результата, а чтобы я поверил первым трём.
-
Глобальные ограничения — на декодер, локальные паттерны — в веса. Метр SFT выучивает (даже слишком). Рифму — принципиально нет. Разделяйте задачи по тому, где они решаются, а не по тому, какой инструмент моднее.
-
Любая оптимизация против метрики немедленно начинает её ломать. «Строгу», гром/гром, «бессмысл» — три поколения накруток за неделю. Лечится не тюнингом, а внешним знанием: словарём, фонетикой, правилами.
-
Сильная база, внешнее знание и контроль на инференсе выиграли у файнтюна по всем осям — форма, надёжность, качество — и стоили в разы дешевле.
Если у вас есть опыт DPO по формальным критериям текста, диффузионного infill — или вы просто хотите поспорить, что «уста́лый/подва́лы» не рифма, — жду в комментариях.
Инструменты и данные, на которых всё стоит:
-
RPST — Russian Poetry Scansion Tool, датасет RIFMA и корпус ArsPoetica Ильи Козиева
-
Automated Evaluation of Meter and Rhyme in Russian Generative and Human-Authored Poetry — статья про метрику «техничности», на идеях которой построен мой оценщик
-
RUAccent — нейросетевая расстановка ударений с обработкой омографов
-
Gemma 4 12B-it, LoRA через PEFT, сервинг vLLM, оркестрация LangGraph, обучение на Modal (L40S)
Автор: dsheremet
