← 回到 OnVoice

DEVELOPMENT NOTE

為什麼 OnVoice 的 Qwen3-ASR 改用 GGUF Runtime

一次關於模型冷啟動、記憶體,以及本機語音輸入產品取捨的紀錄。

做本機語音輸入時,模型跑得快不夠,還要考慮它平常佔不佔記憶體。

OnVoice 原本用 MLX 跑 Qwen3-ASR。這條路很好用:模型資料可以直接整合,也很適合測試不同模型。但實際做成常駐在 menu bar 的工具後,問題變得很生活化:模型一直留在記憶體裡,對不常使用語音輸入的人有點浪費;但如果把它卸載,下一次按下快捷鍵又得等模型回來。

我想要的是:不用時盡快釋放,需要時也不要讓人等太久。

兩條路徑

參考 Handy 的實作後,我注意到它使用 GGUF 模型搭配 ggml-based runtime 跑 ASR。於是我把 OnVoice 的 Qwen3-ASR 也接到 transcribe.cpp 路徑,並在相近量化條件下比較模型冷載入與首次可用時間。

原本
Qwen3-ASR safetensors → MLX → Metal

現在
Qwen3-ASR GGUF → transcribe.cpp / ggml → Metal

兩者最後都會使用 Mac 的 GPU 和 Metal。差別不在於有沒有用 GPU,而是模型在開始前要做多少準備。

為什麼這條路在 OnVoice 較快

MLX 是通用型機器學習框架。它很適合整合新模型、調整 tensor 流程,或做模型實驗;不過第一次載入時,需要完成較完整的模型初始化。

GGUF 則比較像為部署推論整理好的模型包。量化、權重與必要 metadata 已經整理好;當 runtime 本來就認得這個模型架構,就能更直接地把模型準備成可推論的狀態。

MLX
讀取模型 → 建立通用模型物件與 tensor → 準備運算 → 推論

GGUF runtime
讀取部署模型包 → 依既定架構準備推論 → 推論

實測後,GGUF 搭配 transcribe.cpp 在 OnVoice 的冷載入情境中更快。這不代表 GGUF 永遠比 MLX 快,也不代表 MLX 有問題;只是對一個希望模型能閒置卸載、又必須快速恢復的語音輸入工具來說,這條路比較符合需求。

這次的選擇

  • 平常不讓 ASR 模型一直佔著記憶體。
  • 使用者開始錄音時,在背景準備所需模型。
  • 使用 GGUF 加上專用 runtime,縮短重新載入的等待。
  • 保留 MLX 作為未來測試新模型或調整推論流程的工具。

我學到的事

選 runtime 不只是比較每秒能跑多少 token。對產品來說,更重要的問題常常是:使用者真正感覺到的等待發生在哪裡?而我們能不能在不使用時,把資源還給電腦?

對 OnVoice 目前的 Qwen3-ASR 路徑而言,GGUF runtime 是比較合適的答案。