Инженерия

Почему DanceGAI генерирует beatmap с помощью Planner + Noter

Вместо «аудио → ноты» ManiaGAI сначала планирует геймплей каждого участка диффузионной моделью, затем ставит ноты трансформером в стиле MaskGIT. Логика, компромиссы и что это даёт.

Проще всего описать ИИ-генератор beatmap так: «на входе аудио, посередине нейросеть, на выходе ноты». ManiaGAI работает иначе. Он делит задачу на две части: Planner решает, каким по ощущениям должен быть каждый участок песни, а Noter решает, куда именно встанут ноты. В этой статье — почему так, что делает каждая модель и чего стоит такое разделение.

Beatmap — это аранжировка, а не транскрипция

Чарт, который точно следует за аудио, — не обязательно хороший чарт. Хорошая карта для osu! mania ближе к аранжировке: маппер решает, какие звуки заслуживают нот, насколько плотным должен ощущаться участок, где уместен jack или длинная нота, как паттерны перетекают между руками — и как всё это меняется между Easy и Expert одной и той же песни.

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

Два вопроса — две модели

  1. Музыка
  2. Понимание
  3. Planner
  4. Noter
  5. Проверка
  6. Beatmap

Обе модели читают одну и ту же музыкальную картину песни: сетку тайминга и представление аудио, выровненное по ней бит за битом (из открытой модели MERT). Дальше:

  • Planner отвечает на вопрос что должно происходить. Ещё до появления первой ноты он раскладывает игровую структуру всей песни по участкам: насколько сложной должна быть каждая часть и какое в ней сочетание длинных нот, jack’ов и других типов паттернов.
  • Noter отвечает на вопрос как идут ноты. Он превращает план в реальную расстановку — какие колонки, какие ноты обычные, а какие длинные, как соединяются паттерны, — следуя и плану, и аудио.

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

Planner: гауссова диффузия по всей песне

Planner — это гауссова диффузионная модель примерно на 6 миллионов параметров. Она генерирует план для всех участков песни совместно, с учётом музыки, количества клавиш, а также заданных сложности и стиля.

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

Noter: уточнение в стиле MaskGIT

Noter — это неавторегрессионный трансформер в стиле MaskGIT примерно на 51 миллион параметров. Чарты представлены дискретными токенами паттернов. Вместо того чтобы писать их по одному от начала песни до конца, Noter заполняет весь чарт и уточняет его за несколько проходов, фиксируя ноты, в которых уверен, и возвращаясь к остальным. То, как эти проходы распределяются по песне, — наш собственный метод и одна из вещей, которые мы не раскрываем.

Почему бы не генерировать чарт слева направо, как языковая модель пишет текст?

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

Сложность и стиль — входные данные, а не доработка задним числом

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

  • Количество клавиш — от 4K до 9K.
  • Сложность — любой набор звёздных рейтингов от ★1 до ★10; один запуск создаёт целый mapset.
  • Стиль — пять измерений: доля длинных нот, inverse-длинные ноты, jack’и, короткие длинные ноты и delay. Каждая сложность может получить свой стиль, откалиброванный по реальным чартам с тем же количеством клавиш и звёздным рейтингом.

Эти настройки действуют на план — там, где они имеют значение: «сложнее», «больше длинных нот» или «больше jack’ов» — это решения о форме участка, а не об отдельной ноте. Плотность — не отдельная ручка: она следует из целевой сложности и плана. А поскольку каждая сложность генерируется из одного и того же понимания песни, mapset читается как одно семейство чартов, а не как набор не связанных друг с другом карт.

Локальная перегенерация вытекает из самой архитектуры

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

  1. Выделить
  2. Замаскировать
  3. Перегенерировать
  4. Уточнить

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

Раздельное обучение

Две модели обучаются раздельно, каждая на своём представлении: Planner — как диффузионная модель над описанием игрового характера каждого участка, Noter — через предсказание замаскированных токенов паттернов. Примеры балансируются по количеству клавиш и уровням сложности, чтобы редкие сочетания вроде 8K на ★10 не тонули среди частых. Данные, на которых обучены обе модели, описаны в статье Внутри датасета ИИ-маппера для osu! mania.

Чего стоит разделение

Иерархия не бесплатна. Вот компромиссы, с которыми мы живём:

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

Чего мы не утверждаем

Мы не сравнивали эту архитектуру с единой сквозной моделью, обученной на тех же данных, поэтому не утверждаем, что она лучше. Сказать мы можем другое: она даёт нам более чистый способ моделировать дальнюю структуру и локальную расстановку нот по отдельности, естественное место для настроек сложности и стиля и модель, которая может переделать один участок чарта, не трогая остальное. Стиль маппинга по-прежнему задаётся горсткой измерений; описание стиля на примере, а не ползунками, — направление, в котором мы движемся.

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