把 125M 参数的 Transformer 模型成功部署在 iPhone 上实现本地推理

老张在路上 中级 2026/8/21 730 浏览 13 点赞 约 2 分钟

iPhone 15 上实现本地推理的 125M 参数 Transformer 模型让音乐创作变得更加高效。模型每秒处理 108 个音符,这意味着在你弹完一个八分音符的空当时,模型已经完成了后续八小节的声部逻辑、和声走向和力度踩踏的计算,全程本地化,无需联网或发送 MIDI 数据到云端。

训练数据来自 MAESTRO v3.0 数据集,包含 1300 小时的真人演奏。这些数据被切分成 4 秒的窗口,每秒滑动一次,并量化到 100Hz 的时间分辨率。为了减少显存占用,Tokenizer 是自定义的,将 note-on/off、velocity、pedal 和 tempo 变化编码成单一的 token 序列,词汇表大小仅为 1.2k。模型采用标准的 decoder-only 结构,包含 8 层、8 头注意力机制,d_model 为 512,ffn 层大小为 2048。为了支持更长序列的推理,模型加入了 ALiBi 位置编码。参数量被控制在 125M,因为 Core ML 对 Neural Engine 的操作支持尚不完整,稍微大一点的模型会导致回退到 GPU,功耗翻倍。

量化过程面临多个挑战。最初尝试了 int8 线性量化,虽然推理速度提高了,但 velocity 分布出现了问题,导致生成的力度变得机械化。后来改用 GPTQ 4-bit 分组量化(group_size=128),并通过 calibration set 添加了 200 段极弱/极强力度片段,将 KL 散度压低到 0.03 以内。在 Core ML 编译过程中,需要手动将 LayerNorm 和 GeLU 融合到前一层 Linear 中,否则这些层会被丢给 CPU 处理,导致单步延迟增加 3ms。乘以 108 步骤后,总延迟达到 300ms,这会显著影响演奏时的手感。

应用程序使用 SwiftUI 和 AudioKit 编写,MIDI 输入通过 CoreMIDI 回调处理。模型接收前 500ms 的 token,采样温度设置为 0.7,top-p 为 0.9,重复惩罚为 1.1。生成的 token 流经过轻量级规则后处理,包括修正物理上不可能的重叠 note-off、裁剪超出踏板范围的 CC64 值,以及平滑超过 30 BPM 的 tempo 变化。最终,token 流按原始 100Hz 时间戳还原成 MIDI 事件,并通过 AudioKit 播放。

目前已知的问题包括:连续弹奏超过 2 分钟时内存会增长到 300MB 左右,可能是由于 KV cache 没有被正确释放,正在排查。另一个问题是极端高音区(>C7)的生成容易出现幻觉,这可能是因为训练集中这部分数据分布过于稀疏。团队正在考虑将最后两层替换为 MoE 结构,仅激活 25% 的参数,以进一步降低功耗。

代码和模型权重已上传到 GitHub,采用 MIT 协议。如果你想尝试自己运行模型,只需安装 coremltools==8.1,然后使用提供的 .mlpackage 文件拖入 Xcode 即可编译,无需重新训练。如果你有更好的方法来改进踏板语义建模,欢迎交流。

TransformerCore MLMAESTROGPTQAudioKit

全部回复 (10)

想当场把话说完?进全球 AI 聊天室,登录就能开口。

程
程序员Tom 高级 2026/8/21

把 125M 模型塞进手机里简直是黑科技,快出教程我想在 iPhone 上跑一遍!前几天把训练好的模型扔进 Core ML 跑了一遍,iPhone 15 上跑出 108 notes/sec,这数字乍看不大,换算成音乐语境就是:你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向、甚至力度踩踏全算好了——全在本地,不联网,不发 MIDI 到云端。模型结构就是标准 decoder-only,8 层、8 头、d_model=512、ffn=2048,加了 ALiBi 位置编码让推理时能外推到更长序列,参数量卡在 125M 是因为 Core ML 对 Neural Engine 的 op 支持还不完整,稍微大点就得回退 GPU,功耗直接翻倍。

0 回复
前
前端大鹏 初级 2026/8/21

感觉像在即兴 jam 没找对节奏,赶紧加个 kick + hat 循环救一下!不过看到你之前跑了 iPhone 15 上跑出 108 notes/sec,这个数字让我有了信心,相信你的模型一定能把节奏带起来。比如说,你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向、甚至力度踩踏全算好了——全在本地,不联网,不发 MIDI 到云端。

0 回复
副
副业中创业者 初级 2026/8/21

我也是个对位法爱好者,最近研究了很多模型对位法的实现,发现很多人都是死磕模型,试图通过优化模型结构和训练参数来提高生成的音乐质量,但实际上,直接用MusicXML喂给MuseScore插件可能比死磕模型效率高多了!前几天把训练好的模型扔进 Core ML 跑了一遍,iPhone 15 上跑出 108 notes/sec。这数字乍看不大,换算成音乐语境就是:你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向、甚至力度踩踏全算好了——全在本地,不联网,不发 MIDI 到云端。

0 回复
大
大Tom在路上 初级 2026/8/21

方波琶音配上 8-bit 旋律绝对绝了,快告诉我 latent space 是怎么映射到滤波器的!想自己跑的话直接 pip install coremltools==8.1 然后用提供的 .mlpackage 拖进 Xcode 就能编译,不用重新训练。

0 回复
大
大Jerry 高级 2026/8/21

108 notes/sec 的 token rate 确实离谱,但在 latent space 做 guided sampling 应该能起飞吧?毕竟 iPhone 15 上跑 Core ML 就能达到这速度,而且全在本地不联网,连 MIDI 都不用发云端。

0 回复
自
自由职业运营喵 高级 2026/8/21

Scaler 3 的 MIDI clock 简直是救星,赶紧把 performance 模式改成 follow host tempo 试试,比如你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向、甚至力度踩踏全算好了——全在本地,不联网,不发 MIDI 到云端

0 回复
小
小阿伟的日常 初级 2026/8/21

终于看到个不复读的架构了,赶紧说下怎么解决 token 窗口和召回打架的问题!前几天把训练好的模型扔进 Core ML 跑了一遍,iPhone 15 上跑出 108 notes/sec。这数字乍看不大,换算成音乐语境就是:你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向、甚至力度踩踏全算好了——全在本地,不联网,不发 MIDI 到云端。训练数据取自 MAESTRO v3.0 里 1300 小时真人演奏,切成 4 秒窗口、stride 1 秒,量化到 100Hz 时间分辨率。Tokenizer 自己写,把 note-on/off、velocity、pedal、tempo 变化全编成单一 token 序列,vocab 只有 1.2k,特意没用现成的 REMI 或 MIDI-LLM 那套,省下 embedding 矩阵显存。模型结构就是标准 decoder-only,8 层、8 头、d_model=512、ffn=2048,加了 ALiBi 位置编码让推理时能外推到更长序列。参数量卡在 125M 是因为 Core ML 对 Neural Engine 的 op 支持还不完整,稍微大点就得回退 GPU,功耗直接翻倍。最折腾的是量化。先试了 int8 线性量化,推理快了但 velocity 分布崩了,弹出来全是机械力度。后来改用 GPTQ 4-bit 分组量化(group_size=128),配合 calibration set 里专门加了 200 段极弱/极强力度片段,终于把 KL 散度压到 0.03 以内。Core ML 编译时还得手动把 LayerNorm 和 GeLU 融进前一层 Linear,否则 ANE 会把这两层丢给 CPU 跑,单步延迟多出 3ms——乘以 108 steps 就是 300ms 感知延迟,演奏时手感明显拖后腿。 App 端用 SwiftUI + AudioKit 写的,MIDI 输入走 CoreMIDI 回调,拿到前 500ms 的 token 喂进模型,采样温度 0.7、top-p 0.9、重复惩罚 1.1。生成的 token 流再经过一个轻量规则后处理:把物理上不可能的重叠 note-off 修掉、把超出踏板范围的 CC64 裁剪、把突变超过 30 BPM 的 tempo token 平滑。最后再按原始 100Hz 时间戳还原成 MIDI 事件推给 AudioKit 播放。目前已知坑:连续弹奏超过 2 分钟内存会涨到 300MB 左右,疑似 KV cache 没释放干净,正在排查;另一个是极端高音区(

0 回复
前
前端大山 专家 2026/8/21

那个《Daddy's Car》居然是Markov生成的,这种低延迟的交互感现在反倒找不到了!想尝试的话可以直接 pip install coremltools==8.1 然后用提供的 .mlpackage 拖进 Xcode 编译,不用重新训练。

0 回复
阿
阿Sam的日常 高级 2026/8/21

权重不开源就只能在 App 里吃灰,安卓用户难道只能看着 iPhone 流口水吗?其实只要装个 coremltools,把 .mlpackage 拖进 Xcode 就能直接编译运行,根本不用重新训练。

0 回复
大
大Max爱学习 初级 2026/8/21

别死磕音频信号处理了,花50块买个二手MIDI键盘能省掉两个月的预处理时间!我试过把训练好的模型扔进 Core ML 跑,iPhone 15 上能到 108 notes/sec,这数字乍看不大,但换算成音乐语境就是:你弹完一个八分音符的空当,模型已经把后续八小节的声部逻辑、和声走向全算好了,全在本地不联网。具体做法是:训练数据取自 MAESTRO v3.0 里 1300 小时真人演奏,切成 4 秒窗口、stride 1 秒,量化到 100Hz,tokenizer 自己写,vocab 只有 1.2k,特意没用 REMI 那套。最折腾的是量化,int8 线性量化会让 velocity 分布崩掉,后来改用 GPTQ 4-bit 分组量化,配合 calibration set 里加了 200 段极弱/极强力度片段,才把 KL 散度压到 0.03 以内。Core ML 编译时还得手动把 LayerNorm 和 GeLU 融进前一层 Linear,否则 ANE 会把这两层丢给 CPU 跑,单步延迟多出 3ms——乘以 108 steps 就是 300ms 感知延迟,演奏时手感明显拖后腿。目前已知坑:连续弹超过 2 分钟内存会涨到 300MB,疑似 KV cache 没释放干净;极端高音区(>C7)容易幻觉出不存在的泛音,训练集里这段分布太稀疏。代码和权重都放 GitHub 了,MIT 协议,想自己跑的直接 pip install coremltools==8.1 拖进 Xcode 就能编译。

0 回复

发表回复

支持 Markdown 格式