AnySpeechRecognizer 및 AnyDecisionModel 소개: Apple 플랫폼용 음성 및 의사결정 오픈 모델
언어 모델(Language models)은 많은 것을 할 수 있습니다. 글을 쓰고, 요약하고, 번역하며, 도구를 호출할 수도 있습니다. 하지만 그것들은 머신러닝이 할 수 있는 일의 작은 일부일 뿐입니다.
고객센터에 고객이 전화했다고 가정해 봅시다.
먼저, 무엇을 말했는지 알아야 합니다(음성 인식).
그다음, 어디로 보내야 할지 결정해야 합니다(의사결정).
두 가지 모두를 언어 모델에 맡길 수도 있지만,
각각의 목적에 맞게 구축된 모델들이
더 좋고, 더 빠르며, 비용도 적습니다.
AnyLanguageModel 1.0 요약본에서 우리는 Swift로 구현된 로컬 및 호스팅 모델들을 지난 1년간 살펴보았습니다. AnyLanguageModel과 swift-huggingface가 이제 1.x 버전 출시를 했으므로, 이 접근 방식을 음성 및 의사결정 분야로 확장합니다: 익숙한 Swift API와 선택 가능한 모델을 제공합니다.
오늘 저희는 두 가지 패키지를 발표합니다:
- AnySpeechRecognizer는 Apple의 새로운 speech-to-text API를 구현하며, NVIDIA의 Parakeet과 Alibaba의 Qwen3-ASR을 포함하여 다양한 인식 엔진 중 하나를 선택할 수 있고, Core ML에서 로컬로 실행됩니다. 또한 누가 언제 말하는지 추적하는 화자 분리(speaker diarization) 기능을 추가합니다.
- AnyDecisionModel은 텍스트를 생성하는 대신 모델의 확률로부터 각 답변을 도출하여 예/아니오, 객관식, 평점 척도 질문에 대한 결과를 타입으로 제공하고 확률을 함께 제공합니다. 이 모델은 장치에서 MLX, Core AI 또는 llama.cpp를 사용하거나 Jev 또는 Ollama의 의사결정 모델을 사용하여 작동합니다.
두 패키지 모두 Hugging Face Hub에서 오픈 모델을 다운로드하여 기기에서 실행할 수 있습니다.
컴퓨터는 수십 년 동안 음성을 전사해 왔으며,
지난 몇 년 동안 이 분야에서 매우 뛰어난 성능을 보여주었습니다.
Apple 플랫폼은 이미 이를 위한 API를 가지고 있습니다.
macOS 26과 iOS 26에서는 Apple의 새로운 speech-to-text API인 SpeechAnalyzer가 도입되었습니다.
사용자는 SpeechTranscriber와 SpeechDetector 같은 모듈을 분석기(analyzer)에 추가하고,
파일 또는 오디오 버퍼 스트림을 제공하며,
도착하는 대로 비동기 시퀀스(async sequences)에서 결과를 읽습니다.
AssetInventory는 모델들을 설치하므로, 앱이 언제 다운로드를 수행할지 결정합니다.
이는 잘 설계된 API이지만, 그 기반 엔진은 Apple의 것을 사용합니다. AnySpeechRecognizer는 이 API를 유지하면서 어떤 엔진을 사용할지 선택할 수 있게 합니다:
- import Speech
+ import AnySpeechRecognizer
이 패키지는 기본 엔진으로 Apple의 Speech 프레임워크를 사용하여 SpeechAnalyzer, SpeechTranscriber, DictationTranscriber, SpeechDetector, 그리고 AssetInventory를 미러링합니다. 만약 코드가 이 공유 API를 사용한다면, import 구문만 변경하면 됩니다.
대신 Parakeet을 사용하려면, 트랜스크라이버 생성 방식만 변경하면 됩니다:
let transcriber = SpeechTranscriber(
model: ParakeetSpeechModel(variant: .v3),
transcriptionOptions: [],
...
에셋 설치 단계, 분석기 실행 및 결과 읽기는 동일하게 유지됩니다. README에는 전체 예제가 포함되어 있으며 Apple 프레임워크와의 차이점을 나열하고 있습니다.
Parakeet v3는 NVIDIA의 Parakeet TDT 0.6B v3입니다.
이는 다국어 지원(polyglot) 모델로, 유럽 언어 25개를 인식하며 어떤 언어를 듣고 있는지 스스로 파악하기 때문에 로케일(locale)을 전달할 필요가 없습니다.
Parakeet Ultra는 Moondream이 v3를 기반으로 후처리한 버전입니다. 측정된 대부분의 경우에서 더 높은 정확도를 보였습니다.
Parakeet Unified는 NVIDIA의 영어 전용 Parakeet 모델입니다.
세 가지 Parakeet 모두 패키지 자체의 Core ML 런타임에서 실행되며, 이 런타임은 파일 및 실시간 입력, 휘발성 결과(volatile results), 단어 타이밍, 그리고 단어 신뢰도를 지원합니다.
Qwen3-ASR은 Alibaba의 음성 모델로, 0.6B와 1.7B 크기로 제공됩니다. 이 모델은 Parakeet이 지원하지 않는 만다린, 광둥어, 일본어, 한국어를 포함하여 총 30개 언어와 22개의 중국 방언을 인식합니다.
자동으로 언어를 감지하거나 사용자가 직접 설정할 수 있습니다:
let transcriber = SpeechTranscriber(
model: QwenSpeechModel(variant: .large, language: Locale.Language(identifier: "yue")),
transcriptionOptions: [],
...
Qwen3-ASR은 최대 40초 길이의 각 세그먼트에 대해 휘발성 결과나 단어 타이밍, 신뢰도 없이 최종 결과를 하나만 제공합니다. 이 모델은 GPU에서 실행되며 Parakeet보다 느리기 때문에 실시간 입력보다는 파일을 전사하는 데 더 적합합니다.
다른 엔진을 추가하려면 구성 설정을 위해 SpeechRecognitionModel을 구현하고, 하나의 모듈 세션을 위해 SpeechRecognitionExecutor를 구현해야 합니다.
README에는 시작하는 데 도움이 되는 플레이스홀더 텍스트를 보고하는 작은 프로바이더가 포함되어 있습니다.
이러한 모델들을 앱에서 실행하기 위해 Core ML로 변환하여 허브(Hub)에 게시했습니다:
| Model | Core ML conversion | Original checkpoint | License |
|---|
| Parakeet TDT 0.6B v3 | mattt/parakeet-tdt-0.6b-v3-coreml | nvidia/parakeet-tdt-0.6b-v3 | CC BY 4.0 |
| ... | | | |
각 리포지토리는 소스 체크포인트와 모든 파일에 대한 체크섬을 기록하며, 패키지는 이를 고정된 리비전(revision)에 고정합니다. Parakeet 리포지토리에는 실시간 입력을 위한 8초 인코더가 추가되어, 다소 높은 단어 오류율(word error rate)의 대가로 실시간 분석 시간을 약 3분의 1로 줄입니다. 해당 리포지토리에는 변환 워크플로우도 포함되어 있으며, 대부분은 FluidInference의 mobius 스크립트를 따르고 각 변환을 원본 모델과 비교합니다.
다운로드는 앱이 요청할 때만 발생합니다: 각 Parakeet에 대해 약 600MB, 실시간 인코더에 대해 약 590MB, Qwen3-ASR에 대해 0.9~2.4GB, 그리고 Sortformer에 대해 약 250MB가 필요합니다. 파일은 표준 Hugging Face 캐시에 저장되므로, 샌드박스 외부의 Mac 앱이 Python 및 기타 Hugging Face 도구와 공유할 수 있습니다.
대화를 전사(transcribe)할 때, 누가 무엇을 말했는지 알고 싶을 때가 많습니다. 이것이 화자 분리화(speaker diarization)이며, Apple의 Speech 프레임워크에는 이를 위한 모듈이 없기 때문에 AnySpeechRecognizer가 추가했습니다.
SpeakerDiarizer는 Apple 또는 Parakeet 전사기와 함께 동일한 타임라인에서 Core ML 상의 NVIDIA Streaming Sortformer를 실행합니다:
let diarizer = SpeakerDiarizer(model: SortformerDiarizationModel())
if let request = try await AssetInventory.assetInstallationRequest(
supporting: [transcriber, diarizer]
...
이 분리화기는 사람들이 서로 말을 겹치더라도 최대 네 명의 화자를 추적합니다.
SpeakerTimeline
결과를 수집하고 각 시간 기록된 단어를 화자에게 할당하여, 화자별 발언 단위로 전사(transcript)를 인쇄할 수 있습니다. AnyLanguageModel의 이미지 지원과 마찬가지로, 이는 현재 Apple API가 제공하는 범위를 넘어섭니다.
디아라이저(diarizer)는 기본적으로 Sortformer v2를 사용합니다. 또한 NVIDIA가 더 많은 회의 데이터로 훈련시켰고 측정 결과에서도 회의에서 더 정확했던 v2.1을 선택할 수도 있습니다.
저희는 패키지를 M4 Max Mac Studio와 macOS 27.0.1에서 hear 명령줄 도구를 사용하여 측정했습니다. LibriSpeech 파일(3분~8분)에 대한 단어 오류율은 다음과 같습니다:
| Transcriber | test-clean | test-other |
|---|
| Parakeet v3, file | 1.55% | 2.78% |
| ... | | |
Parakeet은 Core ML이 모델을 컴파일한 후 약 100MB의 메모리로 파일에서 오디오 1시간 분량을 약 2040초 만에 전사하거나, 실시간으로 약 1.52.5분 동안 처리할 수 있습니다. Qwen3-ASR은 훨씬 느리고 몇 기가바이트의 메모리가 필요합니다. 회의는 모두에게 어렵습니다: 사람들이 서로 말을 끊는 AMI 녹음 파일에서는 테스트한 모든 엔진이 23% 이상의 단어 오류율을 보였습니다.
이 수치들은 단일 장비와 몇 가지 데이터셋에서 나온 것이므로, 사용자의 하드웨어 및 오디오로 측정해 보십시오. hear evaluate는 자체 파일에서 작동하며, 저장소의 natural-speech-eval.py 도구가 이러한 측정을 재현합니다. 현재까지는 iPhone이 아닌 macOS 27에서만 테스트했습니다.
다음으로, macOS 27 및 iOS 27의 Core AI를 포함하여 더 많은 엔진을 추가하고자 합니다.
AnyDecisionModel은 이야기가 다릅니다. 매핑할 Apple 프레임워크가 없으며, 의사결정 모델(decision models) 자체가 새롭지는 않습니다. 프랑스의 Décision 지역에서 온 경우에만 의사결정 모델이며, 그렇지 않으면 단순한 제로샷 분류(zero-shot classification)입니다.
새로운 것은 이름, 많은 관심(hype), 그리고 결정을 내리도록 훈련된 모델들의 집합입니다. 저희는 이것이 앞으로 나아갈 방향이라고 생각했기 때문에, 이를 위한 Swift API를 원했습니다.
앱들은 종종 언어 모델에게 결정을 내리도록 요청합니다.
*이 메시지는 긴급한가요?
*어떤 팀이 이 티켓을 처리해야 할까요?
*이 고객은 얼마나 좌절했나요?
일반적인 접근 방식은 언어 모델에 프롬프트를 보내고 그것이 생성한 텍스트를 파싱하는 것입니다. 이것은 하나의 답변을 제공하지만, 대안들에 할당된 확률을 보여주지는 않습니다.
Swift에서 결정이 어떻게 보이는지 살펴보겠습니다:
import AnyDecisionModel
enum Department: String, Choosable {
case billing, technical, sales
...
}
'urgent'는 Double입니다.
'team'은 선택된 케이스, 각 옵션에 대한 확률, 그리고 신뢰 값을 포함하는 Choice<Department>입니다.
'anger'는 예상 수준, 각 수준에 대한 확률, 그리고 신뢰 값을 포함하는 Score입니다.
Department가 Choosable을 준수하기 때문에, team.value는 포괄적인 switch문에서 사용할 수 있는 Department입니다.
Foundation Models나 AnyLanguageModel을 사용해 본 적이 있다면, 모델-및-세션(model-and-session) 패턴이 익숙하게 느껴질 것입니다. DecisionSession은 텍스트 또는 JSON일 수 있는 단일 상태를 보유하며, 모든 질문은 그 상태에 관한 것입니다. 질문들은 독립적입니다: 답변이 나중 질문의 입력값이 되는 경우는 없습니다. 여러 질문을 한 번에 하려면, 이들을 배치(batch)로 decide(_:)에 전달합니다.
각 질문에 대해, MLX 백엔드는 허용된 답변 각각에 대한 원 토큰 레이블을 가진 프롬프트를 구축한 다음, 단일 순전파(forward pass)에서 각 레이블의 확률을 읽어옵니다.
Emoji Magnet은 343개의 이모지 더미 위에 텍스트 필드가 있는 macOS 앱입니다. "입고하는 물건"과 같은 구문을 입력하면, 일치하는 이모지가 더미에서 떠오릅니다. 이를 "겨울에 입는 물건"으로 다듬으면, 더 이상 일치하지 않는 이모지는 다시 가라앉습니다.
이 앱은 내장된 키워드 규칙이 없으며, 모델이 추론 시간(inference time)에 모든 것을 결정합니다. 타이핑을 멈추면, 각 이모지에 대해 모델에게 하나의 예/아니오 질문을 합니다. 예를 들어:
Statement: a heavy winter coat fits the description "things you wear". Is this statement true?
세션의 상태(state)가 구문(phrase)을 보유합니다.
위의 데모는 호스팅된 Jev 백엔드를 사용하며, 이 백엔드는 343개의 모든 질문에 대해 단일 요청으로 답변하므로, 각 구문당 이모지가 약 반 초 만에 정착됩니다.
TYPESAFE_AI_API_KEY가 없으면, 앱은 MLX 백엔드를 사용하여 사용자의 Mac에서 Qwen3 4B를 실행합니다.
해당 백엔드는 프리픽스 캐싱(prefix caching)을 사용하여 상태를 한 번 평가한 다음, 순전파(forward pass)당 16개의 질문에 답변합니다. M4 Max에서는 모델 로드 후 16개 그룹이 약 0.45초가 걸립니다. 모든 343개의 이모지를 통과하는 전체 과정은 약 10초가 걸리며, 각 그룹의 결과는 도착하는 즉시 표시됩니다.
Emoji Magnet은 AnyDecisionModel-Examples 리포지토리(repository)에 있습니다.
다음 토큰 확률(next-token probabilities)을 읽는 것은 범용 언어 모델(general-purpose language models)에서 작동하지만, 해당 모델들은 의사결정(decisions)을 하도록 훈련되지 않았습니다. Cloudflare의 Clef 모델은 더 새로운 접근 방식의 예시입니다. 이 모델은 학습된 결정 헤드(trained decision head)를 가지고 있어 상태와 유형화된 질문 스키마(schema of typed questions)를 의사결정으로 변환하고, 단일 순전파 과정에서 모든 허용 가능한 옵션에 대한 확률을 반환합니다. Clef-Flash는 9B 버전입니다.
AnyDecisionModel은 MLX를 사용하여 Mac에서 Clef-Flash를 실행합니다:
let model = MLXHeadDecisionModel(
modelID: "mlx-community/clef-flash-4bit",
head: .jointSchema
...
사용자는 동일한 세션과 질문을 사용하지만, MLXHeadDecisionModel은 다음 토큰 확률 대신 Clef의 학습된 결정 헤드에서 각 결정을 읽어옵니다. 이 4비트 모델은 6.2 GB의 다운로드 용량이며, 모델 카드(model card)는 최소 16 GB 메모리를 가진 Mac을 권장합니다. Clef는 이미지와 비디오를 읽을 수 있지만, 이 백엔드는 텍스트(text)와 JSON 상태만 허용합니다.
언어 모델에서 나오는 원시 확률(raw probabilities)은 종종 과신적입니다(overconfident). 로컬 백엔드는 Calibration을 수용하며, 이는 모든 답변에 온도(temperature)를 적용하고 예/아니오 답변에는 편향(bias)을 적용합니다. 보정(calibration)을 수행하고 결과를 평가하기 위해 별도의 데이터셋을 사용하십시오.
언어 모델은 또한 목록에서의 위치 때문에 특정 옵션을 선호할 수 있습니다. MLX, Core AI, 그리고 llama.cpp 다음 토큰 백엔드에서는 rotationDebiasing을 활성화하십시오.
선택 질문을 할 때 옵션의 각 회전마다 한 번씩 수행하고 확률을 평균화합니다.
이는 회전당 하나의 프롬프트 평가(prompt evaluation) 비용이 듭니다.
각 로컬 선택 및 점수에는 또한 확률의 엔트로피(entropy)를 기반으로 한 신뢰도 값(confidence value)이 포함됩니다. 이는 답이 맞는지 여부가 아니라 확률이 얼마나 집중되어 있는지를 측정하므로, 임계값(threshold)을 설정하기 전에 자체 데이터에서 오류율을 확인해야 합니다. 다음 토큰 백엔드(next-token backends)의 진단 기능은 모델이 허용된 답변에 얼마나 많은 확률을 할당했는지 보고합니다. 낮은 값은 모델이 대부분의 확률을 다른 곳에 할당했다는 의미입니다.
AnyDecisionModel은 6개의 백엔드를 가지고 있습니다: