Hugging Face 发布 AnySpeechRecognizer 和 AnyDecisionModel:Apple 平台语音识别与决策 Swift 包
Introducing AnySpeechRecognizer and AnyDecisionModel: Open Models for Speech and Decisions on Apple Platforms
Hugging Face 发布 AnySpeechRecognizer 和 AnyDecisionModel 两个 Swift 包,让 Apple 平台开发者用熟悉 API 在设备端运行开源语音识别和决策模型。
这两个 Swift 包让 Apple 平台开发者用熟悉 API 在设备端运行多种开源语音与决策模型,扩展原生能力并支持说话人分离。
语言模型能做很多事情。 它们可以写作、总结、翻译,并调用工具。 但它们只是机器学习所能实现的一小部分。
假设一位客户拨打了你的支持热线。 首先,你需要知道他们说了什么(语音识别)。 然后,你需要决定将他们转接到哪里(决策)。 你可以将这两项任务都交给语言模型, 但针对每项任务都有专门构建的模型, 它们更好、更快且成本更低。
在我们的 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 之类的模块,
给它一个文件或音频缓冲区流,
并随着结果到达从异步序列中读取它们。
AssetInventory 负责安装模型,
因此由你的应用决定何时发生下载。
这是一个设计良好的 API, 但其背后的唯一引擎是 Apple 的。 AnySpeechRecognizer 保留了该 API,并让你可以选择引擎:
- import Speech
+ import AnySpeechRecognizer
该软件包镜像了 SpeechAnalyzer、SpeechTranscriber、DictationTranscriber、
SpeechDetector 和 AssetInventory,
默认使用 Apple 的 Speech 框架作为引擎。
如果你的代码使用该共享 API,只需更改导入即可。
若要改用 Parakeet,
只需更改创建转录器的方式:
let transcriber = SpeechTranscriber(
model: ParakeetSpeechModel(variant: .v3),
transcriptionOptions: [],
reportingOptions: [.volatileResults],
attributeOptions: [.audioTimeRange]
)
安装资产、运行分析器 以及读取结果的步骤保持不变。 README 包含一个完整示例, 并列出了与 Apple 框架的差异。
认识这些模型
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 模型
要在应用中运行这些模型, 我们将其转换为 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 脚本, 并将每次转换与原始模型进行核对。
下载仅在您的应用请求时发生: 每个 Parakeet 约 600 MB,实时编码器约 590 MB, Qwen3-ASR 为 0.9 到 2.4 GB,Sortformer 约 250 MB。 文件位于标准的 Hugging Face 缓存中, 因此沙盒外的 Mac 应用可以与 Python 和其他 Hugging Face 工具共享它们。
说话人分离
当转录对话时,
您通常想知道谁说了什么。
这就是说话人分离,
而 Apple 的 Speech 框架没有相应的模块,
因此 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 使用更多的会议数据训练了该版本, 在我们的测量中,它在会议场景下也更准确。
效果如何?
我们使用其 hear 命令行工具
在运行 macOS 27.0.1 的 M4 Max Mac Studio 上测量了该包。
以下是 3 到 8 分钟 LibriSpeech 文件的单词错误率:
| 转录器 | 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 是一个你可以在穷举 switch 中使用的 Department。
如果你使用过 Foundation Models 或 AnyLanguageModel,
模型和会话模式会看起来很熟悉。
一个 DecisionSession 持有单个状态,可以是文本或 JSON,
每个问题都是关于该状态的。
问题是独立的:
一个答案永远不会成为后续问题的输入。
要同时提出多个问题,
将它们作为批次传递给 decide(_:)。
对于每个问题,MLX 后端构建一个提示, 为每个允许的答案分配一个标记标签, 然后从一次前向传播中读取每个标签的概率。
试一试:Emoji Magnet
Emoji Magnet 是一个 macOS 应用程序,文本字段上方有一堆 343 个表情符号。 输入一个短语,例如“你穿的东西”, 匹配的表情符号会从堆中升起。 将其细化为“你冬天穿的东西”, 不再匹配的表情符号会落回原处。
该应用程序没有内置的关键词规则; 模型在推理时决定一切。 当你暂停输入时,它会为每个表情符号向模型提出一个是非问题, 例如:
Statement: a heavy winter coat fits the description "things you wear". Is this statement true?
会话的状态持有该短语。
上面的演示使用托管的 Jev 后端,
它在一个请求中回答所有 343 个问题,
因此每个短语的表情符号在大约半秒内稳定下来。
如果没有 TYPESAFE_AI_API_KEY,该应用程序使用 MLX 后端在你的 Mac 上运行 Qwen3 4B。
该后端使用前缀缓存来评估一次状态,
然后每次前向传播回答 16 个问题。
在 M4 Max 上,模型加载后,一组 16 个问题大约需要 0.45 秒。
遍历所有 343 个表情符号的完整过程大约需要 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 位模型 的下载大小为 6.2 GB,其模型卡建议至少配备 16 GB 内存的 Mac。Clef 可以读取图像和视频,但此后端仅接受文本和 JSON 状态。
校准和检查概率
语言模型的原始概率往往过于自信。本地后端接受一个 Calibration,它对每个答案应用温度,对是非答案应用偏差。使用独立的数据集来拟合校准并评估结果。
语言模型也可能因为选项在列表中的位置而偏向某个选项。在 MLX、Core AI 和 llama.cpp 的下一个词元后端上,开启 rotationDebiasing 以针对选项的每次轮换询问一次选择题,并对概率取平均值。每次轮换需要一次提示评估。
每个本地选择和评分还包含一个基于其概率熵的置信度值。它衡量概率的集中程度,而不是答案是否正确,因此在选择阈值之前,请在自己的数据上检查错误率。下一个词元后端的诊断报告了模型分配给允许答案的概率有多少。低值意味着它将大部分概率分配到了其他地方。
后端
AnyDecisionModel 有六个后端:
- MLX 使用 mlx-swift-lm 在 Apple 芯片上运行小型语言模型,并从 Hub 下载。
- MLX 决策头 运行带有自己经过训练的决策头的模型,例如 Clef。
- Core AI 在 macOS 27 和 iOS 27 上使用 Core AI 模型执行与 MLX 相同的功能。
- llama.cpp 通过 llama.swift 从本地 GGUF 模型读取决策。
- Jev 通过 System One API 调用 TypeSafe 的 Jev,或任何实现它的服务器,例如 Kev。
- Ollama 调用本地 Ollama 服务器或 Ollama 云中的 System One 决策模型。它需要 Ollama 0.35.0 或更高版本,或云模型需要 0.40.5 或更高版本。
下一个词元后端将答案标记为 "yes" 和 "no"、A 到 Z 或 0 到 9,因此选择最多可以有 26 个选项,评分最多可以有 10 个级别。决策头没有这样的限制。
与 AnyLanguageModel 一样,该包使用 Swift 包特性。没有特性时,它没有第三方依赖。你获得核心类型以及 Jev 和 Ollama 后端,它们也可以在 Linux 上构建。启用 MLX、CoreAI 或 Llama 特性以使用本地后端。
开始使用
这两个软件包都需要 Swift 6.2 或更高版本,以及 macOS 26 或 iOS 26 或更高版本。 Parakeet 和 Sortformer 运行时以及 MLX 后端需要 Apple 芯片。 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
以安装所需的资源。
在你的应用中尝试它们,并告诉我们哪些有效,哪些无效。 欢迎在两个仓库中提交问题和拉取请求。
链接
- AnySpeechRecognizer on GitHub
- AnyDecisionModel on GitHub
- AnyDecisionModel-Examples on GitHub
- AnyLanguageModel on GitHub
- swift-huggingface on GitHub
感谢 NVIDIA 提供 Parakeet、Sortformer 和 NeMo,感谢 Moondream 提供 Parakeet Ultra, 感谢 FluidInference,其 FluidAudio 和 mobius 项目 记录了 Parakeet 运行时和 Core ML 转换所遵循的约定, 感谢 Cloudflare 提供 Clef, 以及感谢所有为 AnyLanguageModel 做出贡献的人, 这两个软件包都借鉴了其模式。
来源:Hugging Face Blog · huggingface.co