工程

為什麼 DanceGAI 用 Planner + Noter 生成 beatmap

ManiaGAI 不直接把音訊轉成音符,而是先用擴散模型規劃每一段的玩法,再用 MaskGIT 式 transformer 放置音符。背後的理由、取捨,以及它帶來的可能性。

要描述一個 AI beatmap 生成器,最直覺的說法是「音訊進去、經過神經網路、音符出來」。ManiaGAI 不是這樣運作的。它把工作拆成兩半:由 Planner(規劃器)決定歌曲的每個部分玩起來該是什麼感覺,再由 Noter(音符模型)決定音符究竟要放在哪裡。這篇文章說明為什麼這樣做、兩個模型各自負責什麼,以及這種拆分的代價。

beatmap 是編曲,不是採譜

緊貼音訊的譜面,不一定是好譜面。一張好的 osu! mania 譜面更接近編曲:mapper 決定哪些聲音值得放音符、一個段落該有多密、哪裡適合放 jack 或長條、譜型如何在左右手之間流動——以及這一切在同一首歌的 Easy 和 Expert 之間要如何變化。

一個直接把音訊轉成音符的單一模型,必須在每一個時間點同時做出所有這些決定:結構、難度、風格和精確的軌道位置。這類模型往往能把局部細節做對,卻失去整首歌的起伏——副歌打得不比主歌更重,間奏也沒有喘息的空間。

兩個問題,兩個模型

  1. 音樂
  2. 理解
  3. Planner
  4. Noter
  5. 驗證
  6. Beatmap

兩個模型讀取的是同一份歌曲的音樂描述:一套 timing 格線,以及一份逐拍對齊這套格線的音訊表示(來自開源的 MERT 模型)。接下來:

  • Planner 回答的是應該發生什麼。在任何音符出現之前,它會逐段規劃出整首歌的玩法結構:每個部分該有多難,以及長條、jack 和其他譜型的比例。
  • Noter 回答的是音符怎麼放。它依照規劃和音訊,把規劃化為實際的配置——放在哪幾軌、哪些是單點、哪些是長條、譜型如何銜接。

每個模型負責的工作都更聚焦,而規劃也給了音符生成一樣逐音符模型所缺少的東西:一份已經決定好的、對整首歌的全局觀。

Planner:針對整首歌的高斯擴散

Planner 是一個約 6M 參數的高斯擴散模型。它以音樂、鍵數,以及要求的難度和風格為條件,一次性地為整首歌的每個段落生成規劃。

擴散模型適合這項工作有兩個原因。規劃是對一首歌平滑、連續的描述——局部難度和譜型比例隨時間起伏——這正是擴散模型擅長處理的訊號。而把它當作整體生成、而不是一段接一段,能讓 Planner 同時兼顧整首歌的平衡:它能讓副歌衝上高點、讓橋段稍作休息,因為它兩者都看得到。

Noter:MaskGIT 式的反覆修整

Noter 是一個約 51M 參數的 MaskGIT 式非自迴歸 transformer。譜面以離散的配置 token 表示。Noter 不是從歌曲開頭到結尾一個一個寫出來,而是先填滿整張譜面,再經過好幾輪修整——確定有把握的音符,並重新檢視其餘的部分。這些輪次如何在整首歌中安排,是我們自有的方法,也是我們不公開的部分之一。

為什麼不像語言模型寫文字那樣,從左到右生成譜面?

  • 嚴格從左到右寫,代表前面的決定無法考慮到後面的音樂,而且錯誤會在長歌裡越積越多。
  • 在修整式模型中,每一輪都能看到每個段落前後兩側的脈絡,讓整首歌的譜型保持一致。
  • 整張譜面只需固定的輪數就能產生,而不是一次一個 token——這對速度也很重要。
  • 可以修改某一段,而不必重新生成後面的所有內容(下面會詳細說明)。

難度和風格是輸入,不是事後補上的

這種拆分也是讓生成可控的關鍵。ManiaGAI 接受明確的控制參數,模型也經過訓練去遵循它們:

  • 鍵數——4K 到 9K。
  • 難度——從 ★1 到 ★10 任選星數;一次執行就產出一整組 mapset。
  • 風格——五個維度:LN 比例、LN 反轉、jack、短長條(mini LN)和 delay。每個難度都能有自己的風格,並依該鍵數與星數的真實譜面校準。

這些控制作用在規劃上,也就是它們真正起作用的地方:「更難」、「更多長條」或「更多 jack」,是關於一整段樣貌的決定,而不是關於某一個音符。密度不是另外的旋鈕——它由目標難度和規劃決定。而且因為每個難度都來自對同一首歌的同一份理解,一組 mapset 讀起來會像同一家族的譜面,而不是彼此毫無關聯。

局部重新生成,是這個設計自然帶來的

生成的譜面很少會處處都錯。比較常見的是某一段不對勁——一個不搭的譜型、一段太密的區間。為了修這一段而重新生成整張譜,會把原本已經很好的部分全部丟掉。

  1. 選取
  2. 遮罩
  3. 重新生成
  4. 修整

因為 Noter 是修整整張譜面,而不是從左到右寫,它可以在固定周圍所有內容的情況下,以周圍的音符作為脈絡,重新生成選取的區域——讓新的段落融入譜面,而不是格格不入。這就是段落級編輯的基礎:一個能讓你選取不喜歡的部分、只重新生成那一段,或親手修改音符並試玩結果的譜面編輯器,目前正在內部測試中,尚未在網站上開放。

分開訓練

兩個模型是分開訓練的,各自使用自己處理的表示方式:Planner 是針對每段玩法描述的擴散模型,Noter 則以遮罩 token 預測的方式學習配置 token。訓練樣本會依鍵數和難度等級平衡,讓像 8K ★10 這樣罕見的組合不會被常見的組合淹沒。兩者背後的資料,請見深入 AI osu! mania mapper 背後的資料集。

拆分的代價

分層架構不是免費的。以下是我們接受的取捨:

  • 要訓練兩個模型,並讓它們保持同步。規劃是兩者之間的介面;只要它的定義改變,兩邊都得跟著改。
  • Noter 的表現,取決於它拿到的規劃。如果規劃誤判了某一段,Noter 拿到的就是錯誤的指示。
  • 規劃只能描述我們選擇描述的東西。段落級的難度和譜型比例,已經能捕捉一張譜面給人感覺的大部分因素,但無法涵蓋 mapper 的所有意圖。

我們沒有宣稱的事

我們沒有拿這個設計,和用同樣資料訓練的單一端到端模型做過基準比較,所以我們不宣稱它比較好。我們能說的是:它讓我們能更乾淨地分別建模長程結構和局部音符配置,為難度和風格控制提供了自然的位置,而且模型可以只修改譜面的一段而不動到其他部分。作譜風格目前仍透過少數幾個維度控制;用範例而不是滑桿來描述風格,是我們正在努力的方向。

技術頁面說明了兩個模型在完整流程中的位置,而我們如何讓生成變快則介紹了執行它們需要什麼。