工程
我們如何讓 AI beatmap 生成快到像即時互動
一整組 osu! mania mapset 只需約 20 秒 GPU 時間,而不是一分鐘以上:一次 ManiaGAI 請求的時間花在哪裡,以及從瀏覽器到批次生成難度,我們如何把時間省下來。
要等上好幾分鐘的生成器,是批次作業。你送出一首歌,去做別的事,回來再看它做出了什麼——如果不喜歡,想換個風格或換一組難度,就得再等一次。幾秒內就有回應的生成器,才是工具:你可以試、聽、調整,然後再試一次。
正是因為這個差別,在 ManiaGAI 第 2 版中,我們把延遲當成貫穿整個系統的設計限制,而不是最後才來優化的項目。第 1 版生成一組 mapset 要一分鐘以上。第 2 版在一般歌曲上生成一整組 mapset,只需約 20 秒的 GPU 時間——通常是 13 到 25 秒,視歌曲和要求的難度而定。以下是這些時間花在哪裡,以及我們如何把其餘的時間省下來。
拆解一次請求
- 你的瀏覽器
- Timing ∥ 音樂特徵
- Planner
- Noter
- 驗證
- 下載
以 v2 上線時實測的一次正式環境執行為例:一首 2:50 的歌、5 個難度,在 NVIDIA T4 GPU 上——總共 12.7 秒。
| 階段 | 時間 |
|---|---|
| Timing + 音樂特徵(同時執行) | 3.8 s |
| 規劃(所有難度) | 1.0 s |
| 音符生成(全部 5 個難度) | 6.1 s |
| 整次執行 | 12.7 s |
v2 上線系統(2026 年 10 月 1 日)上一首歌的 GPU 運算時間,不含上傳、排隊或下載。
1. 在按下「建立」之前,就先處理好音訊
每首上傳的歌,都必須先解碼、做響度標準化,再重新編碼成統一的格式,模型才能使用。在伺服器上,這是幾秒鐘的工作,GPU 只能乾等。在 ManiaGAI 裡,這一步在你的瀏覽器中進行,從你選好檔案的那一刻就開始——當你還在挑鍵數和難度時。等你按下「建立」,通常已經處理完了。如果在較慢的裝置上處理歌曲超過 20 秒,就會改由伺服器接手,所以這項優化永遠不會拖慢任何人。
2. timing 和音樂理解同時進行
開始規劃之前,必須先知道歌曲的兩件事:它的 timing 格線(來自開源的 Beat This 模型,加上我們自己的格線擬合),以及它的音樂特徵(來自 MERT 音樂模型)。兩者互不依賴,所以不必互相等待:GPU 執行 Beat This 和 MERT 的同時,格線擬合也在 CPU 上進行。在上面那次執行中,整個理解階段花了 3.8 秒。
3. 所有難度一次生成
一組 ManiaGAI mapset 最多有十個難度。一個接一個生成,時間就會乘上難度的數量。所以我們改為把所有要求的難度放在同一次批次 GPU 運算中,一起規劃、一起生成——它們共用同一首歌和同一份音樂特徵,只有目標不同。這就是為什麼在上面那次執行中,五個難度的音符生成只花了 6.1 秒。
4. 修整整張譜面,而不是一個音符一個音符地寫
音符模型是非自迴歸的:它用固定輪數的修整產生整張譜面,而不是從歌曲開頭到結尾一次寫一個 token——所以不管譜面最後有多少音符,模型的步數都是固定的。(模型為什麼這樣運作,又是另一個故事了:Planner + Noter 一文。)
5. 從快照啟動,而不是從零開始
生成是在 serverless GPU worker 上執行的,也就是說,請求進來時不一定有 worker 正在運作。從零開始載入模型、完成暖機,會讓第一個請求多花好幾秒。所以我們改為從記憶體快照還原 worker——這份快照是在所有東西都載入並暖機完成後拍下的——讓一個全新的 worker 大約一秒就能就緒,而不必把時間花在載入模型上。
6. 終點線前不再等待
最後幾個步驟過去會額外增加延遲。現在,可下載的 .osz 會在譜面完成的那一刻就打包好,而完成的譜面會在生成結束的瞬間存進「我的譜面」——即使你已經離開頁面也一樣。生成器上的進度會顯示每次生成實際所在的階段,所以等待從來不是一團謎。
再快一倍,譜面完全相同
2026 年 10 月 8 日,我們推出了更快的生成系統實作:現在生成譜面的速度大約快了兩倍,而譜面完全相同——同樣的輸入,同樣的輸出。我們為這次改動訂下一條鐵則:會改變模型寫出內容的加速,就是模型的改動,必須當成模型改動來評估。唯一變短的,只有等待時間。
速度帶來了什麼
速度改變了 ManiaGAI 的使用方式。它讓試第二種風格或換一組難度只是幾秒鐘的事,讓「先預覽、再下載」的流程變得自然,也讓維持免費方案成為可能。這也是為什麼我們優化的是整個請求——從瀏覽器到下載——而不只是模型本身:玩家感受到的是等待,而不是 GPU 時間。