介绍 AnySpeechRecognizer 和 AnyDecisionModel:Apple 平台上的语音与决策开放模型
语言模型(LLM)通常被用于写作、总结、翻译或调用工具,但这仅是机器学习应用的一小部分。在实际场景中,例如处理客户支持电话,系统首先需要识别语音内容(语音识别),随后根据内容决定路由策略(决策)。针对这类任务,存在比通用 LLM 更高效、更快速且成本更低的专用模型。

在回顾 AnyLanguageModel 1.0 时,我们探讨了 Swift 中本地及托管模型一年的发展现状。随着 AnyLanguageModel 和 swift-huggingface 进入 1.x 版本,我们将这一熟悉的 Swift API 模式扩展至语音和决策领域。今日宣布推出两个新软件包:AnySpeechRecognizer 和 AnyDecisionModel。两者均支持从 Hugging Face Hub 下载开放模型并在设备端运行。
- AnySpeechRecognizer:实现了 Apple 新的语音转文本 API,允许用户选择识别引擎。支持在 Core ML 上本地运行 NVIDIA 的 Parakeet 和阿里巴巴的 Qwen3-ASR,并新增扬声器日记功能以追踪说话人身份。
- AnyDecisionModel:通过输出类型化结果和概率来回答是/否、多选及评分尺度问题。它直接从模型概率中提取答案而非生成文本,利用设备端的 MLX、Core AI 或 llama.cpp 运行模型。
AnySpeechRecognizer:多引擎语音识别
计算机语音转录已有数十年历史,而近年来技术进展显著。macOS 26 和 iOS 26 推出了 SpeechAnalyzer,这是 Apple 全新的语音到文本 API。开发者可通过添加语音转录器和检测器等模块,向分析器传入文件或音频缓冲区,由应用程序控制下载时机。
尽管该 API 设计精良,但其背后默认仅使用 Apple 自有引擎。AnySpeechRecognizer 保留了相同的 API 结构,但允许用户切换底层引擎:
- import Speech
+ import AnySpeechRecognizer
该软件包模拟了 SpeechAnalyzer、SpeechTranscriber、SpeechDetector 和资产库,默认引擎仍为 Apple 语音框架。若代码遵循共享 API,仅需修改导入语句即可。若要使用 Parakeet,只需更改转录器的创建方式:
let transcriber = SpeechTranscriber(
model: ParakeetSpeechModel(variant: .v3),
transcriptionOptions: [],
reportingOptions: [.volatileResults],
attributeOptions: [.audioTimeRange]
)
安装资产、运行分析器及读取结果的步骤保持不变。README 提供了完整示例并列出了与 Apple 框架的差异。
支持的模型详解
NVIDIA Parakeet TDT 0.6B v3:可识别 25 种欧洲语言,并能自动检测所听语言。Moondream 对其进行了训练后优化,在多数测量指标中准确率更高。
Parakeet Unified EN 0.6B:NVIDIA 推出的英语专用版本。
上述三种 Parakeet 模型均在包内的 Core ML 运行时上执行,支持文件输入和实时输入,提供波动结果、单词定时及置信度信息。
Qwen3-ASR:阿里巴巴的语音模型,提供 0.6B 和 1.7B 两种尺寸。支持识别 30 种语言和 22 种中文方言(包括普通话、粤语、日语和韩语)。可自动检测语言或手动指定:
let transcriber = SpeechTranscriber(
model: QwenSpeechModel(variant: .large, language: Locale.Language(identifier: "yue")),
transcriptionOptions: [],
reportingOptions: [],
attributeOptions: []
)
Qwen3-ASR 每段最长 40 秒提供一个最终结果,不支持波动结果、单词时间或置信度。由于其在 GPU 上运行速度较慢于 Parakeet,更适合文件转录而非实时输入。
如需添加其他引擎,需实现 SpeechRecognitionModel 用于配置,以及 SpeechRecognitionExecutor 用于会话管理。仓库中包含一个小型提供者示例,报告占位符文本以帮助起步。
Hugging Face Hub 上的 Core ML 模型
团队将这些模型转换为 Core ML 格式并发布在 Hub 上:
| 模型名称 | Core ML 转换仓库 | 原始检查点 | 许可证 |
|---|---|---|---|
| TDT 0.6B v3 | mattt/-tdt-0.6b-v3-coreml | nvidia/parakeet-tdt-0.6b-v3 | Creative Commons Attribution 4.0 |
| Ultra | /ult-ultra-coreml | moondream/ult-ultra | Creative Commons Attribution 4.0 |
| Unified EN 0.6B | /parakeet-unified-en-0.6b-coreml | nvidia/parakeet-unified-en-0.6b | NVIDIA Open Model License |
| Qwen3-ASR 0.6B Other | mattt/qwen3-asr-0.6b-coreml | Qwen/Qwen3-ASR-0.6B-hf | Apache 2.0 |
| Qwen3-ASR 1.7B Other | mattt/qwen3-asr-1.7b-coreml | Qwen/Qwen3-ASR-1.7B-hf | Apache 2.0 |
| Streaming Sortformer 4spk v2 | /sortformer-streaming-4spk-v2-coreml | nvidia/diar_streaming_sortformer_4spk-v2 | Creative Commons Attribution 4.0 |
| Streaming Sortformer 4spk v2.1 | /sortformer-streaming-4spk-v2.1-coreml | nvidia/diar_streaming_sortformer_4spk-v2.1 | NVIDIA Open Model License |
每个仓库记录其源检查点和文件校验和,包将固定到特定修订版。Parakeet 仓库添加了一个用于实时输入的 8 秒编码器,这将实时分析时间缩短约三分之一,但代价是文字错误率略有上升。该仓库还包含转换工作流程,大多数遵循 FluidInference 的 mobius 脚本,并与原始模型对比验证每个转换。
下载仅在应用程序请求时发生:每个 Parakeet 模型约 600MB(加上现场编码器约 590MB),Qwen3-ASR 约 0.9 至 2.4GB,Sortformer 约 250MB。文件存储在标准的 Hugging Face 缓存中,因此沙箱外的 Mac 应用可与 Python 及其他 Hugging Face 工具共享缓存。
扬声器日记化(Speaker Diarization)
在录制对话时,确定“谁说了什么”至关重要。Apple 语音框架缺乏此模块,AnySpeechRecognizer 对此进行了补充。SpeakerDiarizer 可与 Apple 或 Parakeet 转录器并行运行,在 Core ML 上使用 NVIDIA 的 Streaming Sortformer:
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])
日记化器可追踪多达四个扬声器,即使他们同时说话。时间线收集结果并将每个单词归因于特定演讲者,从而按轮次打印成绩单。这超出了 Apple API 目前提供的范围。
默认使用 Sortformer v2。也可选择 v2.1 版本,NVIDIA 使用更多会议数据进行训练,在测试中准确率更高。
性能评估
在 M4 Max Mac Studio 上,使用命令行工具对 3 到 8 分钟的 LibriSpeech 文件进行了单词错误率(WER)测量:
| 转录器 | 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 框架可供映射,且决策模型本身并非全新概念。所谓“决策模型”,实质上是经过专门训练以做出判断的零样本分类模型。新之处在于 Swift API 的设计,旨在适应这一趋势。
应用程序常要求语言模型做出决策,例如:“这条消息紧急吗?”、“哪个团队应处理此工单?”、“客户有多沮丧?”。通常的做法是提示 LLM 并解析生成的文本。这种方法只能给出一个答案,却无法展示分配给各个选项的概率。
以下是 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 返回一个可在详尽 switch 中使用的 Department 枚举值。
如果使用过 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,应用则在 Mac 上使用 MLX 后端运行 Qwen3 4B。该后端使用前缀缓存评估状态,每次前向传播回答 16 个问题。在 M4 Max 上,加载模型后每组 16 个问题耗时约 0.45 秒。遍历所有 343 个 emoji 的全流程约需 10 秒,各组结果随到达即显示。
Emoji Magnet 位于 AnyDecisionModel-Examples 仓库中。
决策头与 Clef 模型
读取下一令牌概率适用于通用语言模型,但这些模型并非专为决策训练。Cloudflare 的 Clef 模型代表了一种新方法:模型拥有训练好的决策头,将状态和类型化问题模式转化为决策,在一次前向传播中返回所有允许选项的概率。Clef-Flash 是其中的 9B 变体。
AnyDecisionModel 可在 Mac 上使用 MLX 运行 Clef-Flash:
let model = MLXHeadDecisionModel(
modelID: "mlx-community/clef-flash-4bit",
head: .jointSchema
)
使用相同的会话和问题,但 MLXHeadDecisionModel 从 Clef 的训练决策头读取决策,而非下一令牌概率。4-bit 模型下载大小为 6.2 GB,模型卡推荐至少 16 GB 内存的 Mac。虽然 Clef 可读图像和视频,但该后端仅接受文本和 JSON 状态。
概率校准与去偏
语言模型的原始概率往往过度自信。本地后端接受 Calibration 参数,对所有答案应用温度,并对是/否答案应用偏差。建议使用独立的数据集来拟合校准并评估结果。
此外,语言模型可能因选项在列表中的位置而产生偏好。在 MLX、Core AI 和 llama.cpp 的下一令牌后端中,启用 rotationDebiasing 以轮换提问顺序,从而消除位置偏差。





