工程

为什么 DanceGAI 用 Planner + Noter 生成 beatmap

ManiaGAI 不直接把音频映射成音符,而是先用扩散模型规划每一段的玩法,再用 MaskGIT 式 transformer 放置音符。背后的思路、取舍,以及它带来的可能。

描述 AI beatmap 生成器最自然的方式是“音频进去,经过神经网络,音符出来”。ManiaGAI 并不是这样工作的。它把这项工作一分为二:Planner 决定歌曲的每一部分玩起来应该是什么感觉,Noter 则决定音符具体放在哪里。这篇文章解释为什么这样做、每个模型负责什么,以及这种拆分的代价。

beatmap 是编曲,不是扒谱

紧跟音频的谱面不一定是好谱面。一张好的 osu! mania 谱面更接近一次编曲:作谱者要决定哪些声音值得放音符、一段应该有多密、jack 或长条该放在哪里、配置如何在双手之间流转——以及同一首歌的 Easy 和 Expert 之间,这一切要如何变化。

一个把音频直接映射成音符的单一模型,必须在每一个时刻同时做出所有这些决定:结构、难度、风格以及精确的轨道位置。这类模型往往能把局部细节做对,却丢掉了歌曲的整体轮廓——副歌打得不比主歌更有力,间奏也没有喘息的空间。

两个问题,两个模型

  1. 音乐
  2. 理解
  3. Planner
  4. Noter
  5. 校验
  6. beatmap

两个模型读取的是同一幅歌曲的音乐图景:一个 timing 网格,以及与之逐拍对齐的音频表示(来自开源的 MERT 模型)。在此基础上:

  • Planner 回答应该发生什么。在任何音符出现之前,它就逐段规划出整首歌的玩法结构:每一部分该有多难,以及长条、jack 和其他配置类型的比例。
  • Noter 回答音符怎么放。它把规划变成实际的配置——用哪些轨道、哪些音符是单点哪些是长条、配置之间如何衔接——同时遵循规划和音频。

每个模型的任务都更窄了,而规划还给了音符生成一样逐音符模型所没有的东西:一个已经确定好的、关于整首歌的视野。

Planner:针对整首歌的高斯扩散

Planner 是一个约 600 万参数的高斯扩散模型。它以音乐、键数以及要求的难度和风格为条件,联合生成歌曲每一段的规划。

扩散模型适合这项工作,原因有二。规划是对一首歌平滑、连续的描述——局部难度和配置比例随时间起伏——这正是扩散模型擅长处理的信号。而且整体生成,而不是一段接一段地生成,能让 Planner 同时平衡整首歌:正因为它能同时看到副歌和桥段,才能让副歌达到高潮、让桥段得到休息。

Noter:MaskGIT 式的逐步细化

Noter 是一个约 5,100 万参数的 MaskGIT 式非自回归 transformer。谱面被表示为离散的配置 token。Noter 不是从歌曲开头到结尾一个一个地写,而是先填满整张谱面,再分几轮逐步细化——确定它有把握的音符,再回头处理其余的部分。这些轮次如何在一首歌中安排,是我们自己的方法,也是我们不公开的内容之一。

为什么不像语言模型写文字那样,从左到右生成谱面?

  • 严格从左到右写,意味着早期的决定无法考虑后面的音乐,而且在一首长歌里错误会不断累积。
  • 在细化模型中,每一轮都能看到每一段前后两侧的上下文,从而让整首歌的配置保持一致。
  • 整张谱面在固定的轮数内生成,而不是一次一个 token——这对速度也很重要。
  • 可以修改某一段,而不必重新生成它之后的所有内容(下文会详细说明)。

难度和风格是输入,而不是事后补救

正是这种拆分让生成变得可控。ManiaGAI 接受明确的控制参数,模型也经过训练来遵循它们:

  • 键数——4K 到 9K。
  • 难度——从 ★1 到 ★10 任意选择星级;一次运行就能产出一整套 mapset。
  • 风格——五个维度:长条比例、反向长条、jack、短长条和延迟。每个难度都可以有自己的风格,并根据该键数和星级下的真实谱面进行校准。

这些控制作用在规划上,也就是它们真正起作用的地方:“更难”“更多长条”“更多 jack”都是关于一段谱面整体形态的决定,而不是关于某一个音符。密度不是一个单独的旋钮——它由目标难度和规划决定。而且因为每个难度都基于对歌曲的同一种理解生成,一套 mapset 读起来就像同一家族的谱面,而不是互不相干的几张。

局部重新生成,顺理成章

生成的谱面很少处处都错。更常见的是某一段不对劲——一个不合适的配置,一段过密的区间。为了修正它而重新生成整张谱面,会把原本已经很好的部分全部丢掉。

  1. 选择
  2. 遮盖
  3. 重新生成
  4. 细化

因为 Noter 是细化整张谱面而不是从左到右书写,它可以在保持周围一切不变的情况下,重新生成选中的区域,并把周围的音符当作上下文——这样新的一段就能融入谱面,而不是与之冲突。这是分段编辑的基础:一个可以选中你不喜欢的部分、只重新生成那一段,或者自己编辑音符并试玩结果的谱面编辑器,目前正在内部测试中。网站上还不能使用。

分开训练

两个模型分开训练,各自使用自己处理的表示:Planner 作为扩散模型,学习对每一段玩法的描述;Noter 则通过对配置 token 的遮盖预测来学习。训练时会在各键数和难度级别之间平衡采样,让 ★10 的 8K 这类罕见组合不会被常见组合淹没。两者背后的数据详见《揭秘 AI osu! mania 作谱模型背后的数据集》。

拆分的代价

分层结构并不是免费的。我们需要接受的取舍有:

  • 要训练两个模型,并让它们保持同步。规划是两者之间的接口;当它的定义改变时,两边都得跟着改。
  • Noter 最多只能和它拿到的规划一样好。如果规划误判了某一段,Noter 拿到的就是错误的指示。
  • 规划只描述我们选择描述的东西。分段的难度和配置比例能捕捉到谱面手感的很大一部分,但不是作谱者意图的全部。

我们不作的断言

我们没有把这种设计与在相同数据上训练的单一端到端模型做过基准对比,所以我们不声称它比后者更好。我们能说的是:它让我们能更清晰地分别建模长程结构和局部音符配置,为难度和风格控制提供了一个自然的位置,并且得到一个能修改谱面某一段而不动其余部分的模型。目前作谱风格仍然通过少数几个维度来控制;用示例而不是滑块来描述一种风格,是我们正在努力的方向。

技术页面展示了两个模型在完整流程中的位置,我们如何让生成变快则介绍了运行它们需要什么。