AnySpeechRecognizer 與 AnyDecisionModel 推出 Apple 平台語音辨識及決策套件
Introducing AnySpeechRecognizer and AnyDecisionModel: Open Models for Speech and Decisions on Apple Platforms
AnySpeechRecognizer 與 AnyDecisionModel 兩個 Swift 套件正式公佈,分別為 Apple 平台提供可選擇辨識引擎的語音轉文字功能,以及輸出型別化答案和機率的決策 API。
文章列出語音模型的測試結果、下載體積及平台限制,讓讀者可比較 Apple 裝置本機部署的取捨。
語言模型能做到很多事。 它們可以寫作、摘要、翻譯和呼叫工具。 不過,這只是機器學習所能做到的一小部分。
假設有客戶致電你的支援熱線。 首先,你要知道對方説了甚麼(語音識別)。 然後,你要決定把對方轉接到哪裏(決策)。 你可以把這兩項工作都交給語言模型處理, 但也有專為每項工作打造的模型, 表現更好、速度更快、成本更低。
在我們的AnyLanguageModel 1.0 回顧中, 我們回顧了 Swift 中一整年的本機及託管模型。 現在 AnyLanguageModel 和 swift-huggingface 均已推出 1.x 版本, 我們將同一做法延伸至語音和決策: 提供熟悉的 Swift API,並可選擇模型。
今天我們宣佈推出兩個套件:
- AnySpeechRecognizer 實作 Apple 全新的語音轉文字 API,並可選擇識別引擎, 包括在 Core ML 上本機執行的 NVIDIA Parakeet 和 Alibaba Qwen3-ASR, 並加入説話者分離功能,以追蹤各人在何時發言。
- AnyDecisionModel 可回答是非題、選擇題和評分量表問題, 並提供型別化結果和機率。 它根據模型的機率得出每個答案, 而非生成文字; 你可以使用透過 MLX、Core AI 或 llama.cpp 在裝置上執行的模型, 或 Jev 或 Ollama 提供的決策模型。
兩個套件都可以從 Hugging Face Hub 下載開放模型, 並在裝置上執行。
AnySpeechRecognizer
電腦轉錄語音已有數十年歷史,
而在過去幾年,這項技術的表現已大有進步。
Apple 平台本身已提供相關 API。
macOS 26 和 iOS 26 推出了SpeechAnalyzer,
這是 Apple 全新的語音轉文字 API。
你可以將SpeechTranscriber和SpeechDetector等模組加入 analyzer,
向它提供檔案或一串音訊緩衝區,
再從非同步序列讀取陸續傳回的結果。
AssetInventory負責安裝模型,
因此你的應用程式可以決定何時下載。
這個 API 設計完善, 但背後唯一的引擎是 Apple 的引擎。 AnySpeechRecognizer 保留這套 API,並讓你選擇引擎:
- import Speech
+ import AnySpeechRecognizer
這個套件仿照SpeechAnalyzer、SpeechTranscriber、DictationTranscriber、
SpeechDetector和AssetInventory,
預設使用 Apple 的 Speech framework 作為引擎。
如果你的程式碼使用這套共用 API,只需更改 import 即可。
若要改用 Parakeet,
只需更改建立轉錄器的方式:
let transcriber = SpeechTranscriber(
model: ParakeetSpeechModel(variant: .v3),
transcriptionOptions: [],
reportingOptions: [.volatileResults],
attributeOptions: [.audioTimeRange]
)
安裝資源、執行 analyzer 和 讀取結果的步驟都維持不變。 README 提供完整範例,並列出與 Apple framework 的差異。
認識這些模型
Parakeet v3 是 NVIDIA 的 Parakeet TDT 0.6B v3。 它是一款多語言模型: 可識別 25 種歐洲語言,並會判斷所聽到的語言, 因此你無須傳入語系。
Parakeet Ultra 是 Moondream 對 v3 進行後訓練的版本。 在我們大部分的測試中,它的準確度都更高。
Parakeet Unified 是 NVIDIA 的 僅支援英文的 Parakeet。
三款 Parakeet 均使用套件自有的 Core ML 執行環境, 支援檔案和即時輸入、暫定結果、詞語時間戳記, 以及詞語信心度。
Qwen3-ASR 是 Alibaba 的語音模型, 提供 0.6B 和 1.7B 兩種規模。 它可識別 30 種語言和 22 種中文方言, 包括普通話、廣東話、日語和韓語,Parakeet 則不支援這些語言。 它會自動偵測語言,你也可以自行設定:
let transcriber = SpeechTranscriber(
model: QwenSpeechModel(variant: .large, language: Locale.Language(identifier: "yue")),
transcriptionOptions: [],
reportingOptions: [],
attributeOptions: []
)
Qwen3-ASR 每段最長 40 秒的音訊只會產生一個最終結果,不會提供會變動的結果、詞語時間資訊或信心分數。它在 GPU 上執行,速度比 Parakeet 慢,因此更適合轉錄檔案,而非即時輸入。
如要加入另一個引擎,請為其設定實作 SpeechRecognitionModel,並為其中一個模組的工作階段實作 SpeechRecognitionExecutor。README 提供一個小型提供者,會回報佔位文字,助你開始使用。
Hub 上的 Core ML 模型
為了在 app 中執行這些模型,我們將它們轉換成 Core ML,並發佈到 Hub:
| 模型 | Core ML 轉換 | 原始檢查點 | 授權 |
|---|---|---|---|
| Parakeet TDT 0.6B v3 | mattt/parakeet-tdt-0.6b-v3-coreml | nvidia/parakeet-tdt-0.6b-v3 | CC BY 4.0 |
| Parakeet Ultra | mattt/parakeet-ultra-coreml | moondream/parakeet-ultra | CC BY 4.0 |
| Parakeet Unified EN 0.6B | mattt/parakeet-unified-en-0.6b-coreml | nvidia/parakeet-unified-en-0.6b | NVIDIA Open Model License |
| Qwen3-ASR 0.6B | mattt/qwen3-asr-0.6b-coreml | Qwen/Qwen3-ASR-0.6B-hf | Apache 2.0 |
| Qwen3-ASR 1.7B | mattt/qwen3-asr-1.7b-coreml | Qwen/Qwen3-ASR-1.7B-hf | Apache 2.0 |
| Streaming Sortformer 4spk v2 | mattt/diar-streaming-sortformer-4spk-v2-coreml | nvidia/diar_streaming_sortformer_4spk-v2 | CC BY 4.0 |
| Streaming Sortformer 4spk v2.1 | mattt/diar-streaming-sortformer-4spk-v2.1-coreml | nvidia/diar_streaming_sortformer_4spk-v2.1 | NVIDIA Open Model License |
每個儲存庫都記錄其來源檢查點,以及每個檔案的校驗和;套件則固定使用指定版本。Parakeet 儲存庫加入了一個供即時輸入使用的 8 秒編碼器,可將即時分析時間縮短約三分之一,但詞錯誤率會稍高。儲存庫亦包含轉換工作流程,大部分沿用 FluidInference 的mobius指令碼,並會逐一比對轉換結果與原始模型。
只有 app 要求下載時才會下載:每個 Parakeet 約 600 MB,另加即時編碼器約 590 MB;Qwen3-ASR 為 0.9 至 2.4 GB,Sortformer 則約 250 MB。檔案會存放在標準的 Hugging Face 快取中,因此沙盒以外的 Mac app 可與 Python 及其他 Hugging Face 工具共用這些檔案。
説話者分離
將對話轉錄成文字時,你通常會想知道每句話是誰説的。這就是説話者分離。Apple 的 Speech framework 沒有提供相關模組,因此 AnySpeechRecognizer 加入了一個。SpeakerDiarizer會在 Core ML 上執行 NVIDIA 的Streaming Sortformer,並與 Apple 或 Parakeet 轉錄器在同一時間軸上並行運作:
let diarizer = SpeakerDiarizer(model: SortformerDiarizationModel())
if let request = try await AssetInventory.assetInstallationRequest(
supporting: [transcriber, diarizer]
) {
try await request.downloadAndInstall()
}
let analyzer = SpeechAnalyzer(modules: [transcriber, diarizer])
説話者分離器最多可追蹤四位説話者,即使他們同時説話也能處理。SpeakerTimeline會收集分離器的結果,並將每個帶有時間資訊的詞語歸屬至相應的説話者,讓你可以按説話者輪次輸出逐字稿。如同 AnyLanguageModel 的圖像支援,這項功能超越了 Apple API 目前提供的能力。
説話者分離器預設使用 Sortformer v2。你亦可選用v2.1;NVIDIA 使用更多會議資料訓練了這個版本,而我們的測試結果亦顯示,它在會議上的準確度較高。
效果如何?
我們在一部配備 macOS 27.0.1 的 M4 Max Mac Studio 上,使用套件的hear命令列工具進行測試。以下是 LibriSpeech 中長 3 至 8 分鐘的檔案所得出的詞錯誤率:
| 轉錄器 | test-clean | test-other |
|---|---|---|
| Parakeet v3,檔案 | 1.55% | 2.78% |
| Parakeet v3,即時 | 4.73% | 4.29% |
| Parakeet Ultra,檔案 | 1.66% | 2.55% |
| Parakeet Ultra,即時 | 2.65% | 3.28% |
| Parakeet Unified,檔案 | 1.43% | 2.19% |
| Parakeet Unified,即時 | 1.45% | 2.42% |
| Apple 的轉錄器,檔案 | 2.12% | 3.97% |
Parakeet 只需約 20 至 40 秒便可轉錄檔案中的一小時音訊;即時轉錄則約需 1.5 至 2.5 分鐘。Core ML 編譯模型後,記憶體用量約為 100 MB。Qwen3-ASR 慢得多,而且需要數 GB 記憶體。對所有引擎來説,會議錄音都是難題:在 AMI 錄音中,人們會互相插話,我們測試的每個引擎詞錯誤率都高於 23%。
這些數據來自一部機器和少量數據集,因此請使用自己的硬件和音訊進行測量。hear evaluate 可處理你自己的檔案,而儲存庫的 natural-speech-eval.py 工具可重現這些測量結果。目前我們只在 macOS 27 上測試過,尚未在 iPhone 上測試。
接下來,我們希望加入更多引擎,包括 macOS 27 和 iOS 27 上的 Core AI。
AnyDecisionModel
AnyDecisionModel 是另一回事。沒有可對應的 Apple 框架,而且決策模型也不算是新事物。
只有來自法國 Décision 地區的模型才算是決策模型;否則,它就是氣泡版的零樣本分類。
新的是這個名稱、大量炒作,以及一批經訓練來作出決策的模型。我們認為這是未來的發展方向,因此希望提供一個為它們作好準備的 Swift API。
應用程式經常要求語言模型作出決策。這則訊息是否緊急?這張支援單應由哪個團隊處理?這位客戶有多沮喪?一般做法是向語言模型輸入提示詞,再解析它生成的文字。這樣只能得到一個答案,卻看不到模型為其他選項評定的機率。
以下是在 Swift 中呈現決策的方式:
import AnyDecisionModel
enum Department: String, Choosable {
case billing, technical, sales
}
let ticket = "I was charged twice for my order, and now the app logs me out when I try to ask for a refund."
let model = MLXDecisionModel(modelID: "mlx-community/Qwen3-4B-Instruct-2507-4bit")
let session = DecisionSession(model: model, state: .text(ticket))
let urgent = try await session.probability(of: "Does this convey urgency?")
let team = try await session.choice("Which team?", from: Department.self)
let anger = try await session.score(
"How frustrated?",
levels: ["Calm", "Frustrated", "Very angry"]
)
urgent 是一個 Double。team 是一個 Choice<Department>,內含所選案例、每個選項的機率,以及信心值。anger 是一個 Score,內含預期級別、每個級別的機率,以及信心值。由於 Department 符合 Choosable,team.value 是一個 Department,可用於窮盡式 switch。
如果你用過 Foundation Models 或 AnyLanguageModel,模型與工作階段的模式會很熟悉。DecisionSession 只保存一個狀態,可以是文字或 JSON,而每個問題都圍繞該狀態。問題彼此獨立:答案不會成為之後問題的輸入。如要一次提出多個問題,請將它們作為一批傳給 decide(_:)。
對於每個問題,MLX 後端會建立提示詞,為每個允許的答案設定一個單詞元標籤,然後在一次前向傳遞中讀取每個標籤的機率。
試玩:Emoji Magnet
Emoji Magnet 是一款 macOS 應用程式,文字欄位下方是一堆 343 個 emoji。輸入一句短語,例如「你會穿戴的物品」,相符的 emoji 就會從堆中浮起。將短語細化為「冬天會穿戴的物品」後,不再相符的 emoji 就會落回堆中。
這款應用程式沒有內置關鍵字規則;所有事情都由模型在推理時決定。停止輸入片刻後,應用程式會就每個 emoji 向模型提出一個是非問題,例如:
Statement: a heavy winter coat fits the description "things you wear". Is this statement true?
工作階段的狀態保存了這句短語。上方示範使用託管的 Jev 後端,在一次請求中回答全部 343 個問題,因此每句短語只需約半秒,emoji 就會排好。沒有 TYPESAFE_AI_API_KEY 時,應用程式會透過 MLX 後端在你的 Mac 上執行 Qwen3 4B。該後端會使用前綴快取,只評估一次狀態,然後在每次前向傳遞中回答 16 個問題。在 M4 Max 上,模型載入後,每組 16 個問題約需 0.45 秒。完整處理全部 343 個 emoji 約需 10 秒,而每組結果一到達便會顯示。
Emoji Magnet 位於 AnyDecisionModel-Examples 儲存庫中。
決策頭與 Clef
讀取下一個 token 的機率適用於通用語言模型,但這些模型並非以作出決策為訓練目標。Cloudflare 的 Clef 模型是較新方法的一個例子:模型配備經訓練的決策頭,可將狀態和一份列明各問題及其類型的結構描述轉換為決策,並在一次前向傳遞中,為各問題的所有允許選項回傳機率。Clef-Flash 是 9B 版本。
AnyDecisionModel 透過 MLX 在 Mac 上執行 Clef-Flash:
let model = MLXHeadDecisionModel(
modelID: "mlx-community/clef-flash-4bit",
head: .jointSchema
)
你使用相同的工作階段和問題,但 MLXHeadDecisionModel 會從 Clef 經訓練的決策頭讀取每項決策,而不是依據下一個 token 的機率。4-bit 模型的下載大小為 6.2 GB,其模型卡建議使用至少配備 16 GB 記憶體的 Mac。Clef 可以讀取圖片和影片,但此後端只接受文字和 JSON 狀態。
校準及檢查機率
語言模型輸出的原始機率往往過度自信。本機後端接受 Calibration,用來為每個答案套用温度,並為是非答案套用偏差值。使用不同的數據集來擬合校準參數及評估結果。
語言模型也可能因選項在列表中的位置而偏向某個選項。在 MLX、Core AI 和 llama.cpp 的下一個 token 後端中,啟用 rotationDebiasing,讓每個選擇題都按選項的每種輪換方式提問一次,並將機率取平均。每種輪換方式都要進行一次提示詞評估。
每個本機選擇和評分亦包含一個根據其機率熵計算的信心值。它衡量的是機率分佈有多集中,而非答案是否正確,因此在選擇閾值前,請先檢查自有數據上的錯誤率。下一個 token 後端的診斷資訊會顯示模型分配給允許答案的機率總量。數值偏低表示模型將大部分機率分配到其他地方。
後端
AnyDecisionModel 有六個後端:
- MLX 透過 mlx-swift-lm 在 Apple silicon 上執行小型語言模型,並從 Hub 下載模型。
- MLX 決策頭執行配備自身經訓練決策頭的模型,例如 Clef。
- Core AI 在 macOS 27 和 iOS 27 上使用 Core AI 模型,執行與 MLX 相同的功能。
- llama.cpp 透過 llama.swift 從本機 GGUF 模型讀取決策。
- Jev 透過 System One API 呼叫 TypeSafe 的 Jev,或任何實作該 API 的伺服器,例如 Kev。
- Ollama 會在本機 Ollama 伺服器或 Ollama 雲端中呼叫 System One 決策模型。需要 Ollama 0.35.0 或更新版本;若使用雲端模型,則需要 0.40.5 或更新版本。
下一個 token 後端會將答案標記為 "yes" 和 "no"、A 至 Z 或 0 至 9,因此選擇題最多可有 26 個選項,而評分最多可有 10 個層級。決策頭則沒有限制。
和 AnyLanguageModel 一樣,這個套件使用 Swift 套件 traits。未啟用 traits 時,套件沒有第三方相依項目。你會取得核心類型以及 Jev 和 Ollama 後端;這些後端亦可在 Linux 上建置。啟用 MLX、CoreAI 或 Llama trait,以使用本機後端。
開始使用
兩個套件均需要 Swift 6.2 或更新版本,以及 macOS 26 或更新版本,或 iOS 26 或更新版本。 Parakeet 和 Sortformer 執行環境及 MLX 後端需要 Apple silicon。 AnyDecisionModel 的 MLX 建置工作需要 Xcode 內的 Swift 6.4 或更新版本,以及 Metal 工具鏈;Core AI 則需要 Xcode 27 及 OS 27 執行環境。
將套件加入你的 Package.swift:
dependencies: [
.package(url: "https://github.com/mattt/AnySpeechRecognizer", from: "0.1.0"),
.package(
url: "https://github.com/mattt/AnyDecisionModel",
from: "0.6.0",
traits: ["MLX"]
),
]
目前,AnyDecisionModel 的 CoreAI 特性不能與 AnySpeechRecognizer 一起使用,
因為 coreai-kit 0.7.3 要求 swift-huggingface 版本低於 1.0,
而 AnySpeechRecognizer 則要求 1.x。
每個 README 都有更多範例,以及有關需求和後端的詳細資料。
AnySpeechRecognizer 亦包含命令列工具 hear,
可轉錄本機檔案、標註説話者,並評估結果。
每個 hear 指令都需要 --backend apple、--backend parakeet 或 --backend qwen;
請在分析前使用相同的後端和模型選項執行 hear prepare,
以安裝所需資源。
歡迎在你的應用程式中試用這些套件,並告訴我們哪些可行、哪些不可行。 歡迎在兩個儲存庫提交問題和 pull request。
連結
- GitHub 上的 AnySpeechRecognizer
- GitHub 上的 AnyDecisionModel
- GitHub 上的 AnyDecisionModel-Examples
- GitHub 上的 AnyLanguageModel
- GitHub 上的 swift-huggingface
感謝 NVIDIA 提供 Parakeet、Sortformer 和 NeMo,感謝 Moondream 提供 Parakeet Ultra, 感謝 FluidInference;其 FluidAudio 和 mobius 專案記錄了 Parakeet 執行環境和 Core ML 轉換所遵循的慣例, 感謝 Cloudflare 提供 Clef, 並感謝所有為 AnyLanguageModel 作出貢獻的人, 兩個套件都借鑑了該專案的設計模式。
來源:Hugging Face Blog · huggingface.co