Whistle: 16.9 MB 크기의 음성 인식 모델 소개
요약
Whistle는 모바일, 웨어러블 등 다양한 장치 환경을 위해 설계된 경량 음성 인식 모델입니다. 단일 16.9 MB 파일 크기로 의존성 없이 CPU에서 실행되며, 전사(Transcription), 단어 타임스탬프, 음성 임베딩 세 가지 기능을 제공합니다. 이 모델은 기존의 Needle과 동일한 C++ 엔진 및 양자화 기술을 활용하여 효율성을 극대화했습니다.
핵심 포인트
- 16.9 MB 크기의 경량 모델로 다양한 엣지 디바이스에 최적화됨.
- CPU에서 의존성 없이 실행 가능하며, 전사/타임스탬프/음성 임베딩을 지원함.
- Needle과 동일한 C++ 엔진 및 양자화 기술을 사용하여 효율성을 확보함.
- 다국어(영어, 독일어 등)를 지원하며 언어 자동 감지 기능이 포함됨.
오늘 저희는 모바일 기기, 웨어러블 장치, 로봇, 스마트 홈, 자동차 및 마이크로컨트롤러를 위한 음성 인식 모델인 Whistle를 출시합니다. 이 모델은 단일 16.9 MB 파일이며, 의존성 없이 CPU에서 실행되고, Needle과 동일한 C++ 엔진에 로드되며, 동일한 컨테이너와 양자화(quantisation)를 사용합니다.
Whistle는 장치 상에서 세 가지 작업을 수행합니다:
전사(Transcription). 16 kHz 모노 오디오로 한 번의 패스로 최대 30초까지 영어, 독일어, 프랑스어, 스페인어, 이탈리아어, 네덜란드어 및 폴란드어로 지원합니다. 언어를 지정하지 않으면 자동으로 감지됩니다.
단어 타임스탬프(Word timestamps). 디코더의 어텐션으로부터 시작 시간, 끝 시간 및 확률을 가진 모든 단어에 대한 정보가 제공됩니다.
음성 임베딩(Speech embedding). 전사 결과 없이 80 ms 프레임당 한 행으로 구성된 인코더 출력입니다.
--audio-depth는 디코더 레이어를 선택하며, 인코더는 항상 여덟 개를 실행합니다. 프론트 엔드(The front end). 16 kHz 모노 오디오는 25 ms 창과 10 ms 스텝으로 프레임화되고, 80개의 로그-멜 빈(log-mel bins)에 걸쳐 250-3500 Hz로 대역 제한되며 채널별로 정규화됩니다. 30초는 3,000 프레임입니다. 128채널과 커널 크기 9개 반으로 구성된 컨볼루션 스템(convolutional stem)이 세 번 계산되어 375개의 프레임을 남기고, 이는 80 ms당 하나를 의미합니다. 이 이후의 모든 단계는 해당 비율로 실행되며, embed는 프레임당 한 행을 반환합니다.
인코더(The encoder). 네 개의 mHC 잔차 레인과 피드포워드 네트워크 대신 Monarch Hadamard MLP가 배치된 여덟 개의 단순 어텐션 블록으로 구성되어 있으며, 이는 Needle이 사용하는 것과 동일한 블록입니다. 이 어텐션은 인과적(causal)이지 않습니다. 3초의 프레임은 12초의 프레임에 주의를 기울입니다.
디코더(The decoder). 너비 512인 여덟 개의 계단식 단순 어텐션 블록, 쿼리 헤드 8개 대 KV 헤드 2개, 48차원의 쿼리와 키, 64차원의 값, Q, K 및 V에 대한 3-탭 인과 컨볼루션, 그리고 레이어 3과 7에서 18,432 슬롯에 걸친 엔그램 조회(engram lookups)로 구성되어 있습니다. 이는 다른 레이어 수를 가진 Needle의 블록 목록입니다.
음성 특화 부분은 각 레이어마다 하나의 추가 요소가 있습니다. 각 디코더 레이어는 게이티드 교차 어텐션(gated cross attention)을 통해 인코더를 읽습니다: x ← x + σ(g) · softmax(q̂ K̂ᵀ/√d) V
, 레이어별로 학습된 게이트를 사용하고 K와 V는 클립에서 가져옵니다. 이 투영(projections)은 클립이 도착할 때 한 번 실행되며, 8개 레이어에 걸쳐 375 프레임 동안 진행되고, 이후 전체 디코딩 과정 동안 유지됩니다. 따라서 다섯 개의 빔(beams)을 사용하면 오디오를 다섯 번 통과하는 것이 아니라 다섯 개의 짧은 전사 캐시(short transcript caches)만 필요합니다.
디코딩(Decoding). 길이 정규화된 로그 확률로 다섯 개의 빔이 점수 매겨집니다. 키워드 바이어싱(Keyword biasing)은 사용자가 제공한 구문들을 Aho-Corasick 오토마타를 통해 따라가며, 이 과정에서 빔과 함께 진행되고 오토마타가 전진함에 따라 그 로그 확률을 높입니다. 전사(transcript)는 320 토큰으로 제한됩니다. 어휘집은 8,192개의 텍스트 조각(text pieces)과 언어 토큰 7개(언어별 하나씩)로 구성되어 있어, 감지된 언어는 비정규적인 방식으로 반환되는 대신 토큰으로 방출됩니다.
래더(ladder)는 디코더에 있습니다. 깊이(depth)가 2 레이어부터인 모든 단계는 자체 모델로 학습되었으며, --audio-depth 옵션은 로드 시점에 하나를 선택합니다. 인코더는 절대 잘리지 않습니다: 모든 여덟 개의 블록이 모든 깊이에서 실행됩니다.
침묵(Silence). 엔진은 디코더가 시작하기 전에 클립의 음량 범위를 측정합니다. 임계값(threshold) 아래에 있으면 빈 전사 및 빈 언어를 반환하고 빔 검색(beam search)을 수행하지 않습니다.
Whistle는 LibriSpeech test-clean과 test-other, SPGISpeech, Earnings-22, 그리고 FLEURS 평균에서 앞서 나갑니다. Whisper base는 TED-LIUM, AMI, MLS 평균에서 앞서 나가며, 16.9 MB 대비 145.3 MB입니다.
각 모델은 공식 실행 환경과 기본 설정으로 실행되었습니다: Whistle의 C++ 엔진은 5개 빔을 사용했고, openai-whisper와 moonshine-voice는 전체 오디오에 대해 비스트리밍 방식으로 작동했습니다. 첫 번째 토큰까지 걸리는 시간(Time to first token)은 오디오 입력부터 첫 번째 토큰까지의 시간을 의미합니다. 디코딩 시간은 그 이후 벽시계 시간으로 나눈 토큰 수이므로, 인코더가 두 번 계산되지 않습니다. Whisper는 모든 입력을 30초로 패딩하므로, 첫 번째 토큰까지 걸리는 시간이 클립 길이에 관계없이 일정합니다. Whistle는 클립을 추적하며: 5초일 때 5.9 ms, 10초일 때 11.1 ms, 30초일 때 36.3 ms를 기록했습니다.
단어 오류율은 Whisper normalizers를 사용하여 점수화합니다. Whistle의 성능은 86,174개의 발화를 통해 측정되었습니다. Whisper와 Moonshine의 수치는 저자들이 다국어 체크포인트(multilingual checkpoints)를 기준으로 발표한 것이지, 영어 전용(English-only) 체크포인트를 기준으로 한 것은 아닙니다. 모든 테스트 오디오는 Whistle의 훈련 또는 검증 데이터에 포함되지 않았으며, 이는 보고된 모든 테스트 세트에서 오디오 체크섬 및 화자 ID 비교를 통해 확인되었습니다.
needle_load
.cact 파일을 담고 있는 어떤 모델이든 읽어오기 때문에, 같은 바이너리가 음성(speech), 텍스트(text) 또는 둘 다를 처리합니다:
needle --model whistle.cact --audio clip.wav
needle --model needle3.cact --tools tools.json --prompt "turn off the kitchen lights"
needle --model needle3.cact --model whistle.cact --tools tools.json --audio clip.wav
세 번째 줄에서 needle_complete는 클립(clip)을 직접 받습니다. 엔진은 이를 전사하고, 획득한 전사를 사용자의 도구와 비교하여 답변하며, 호출 내용과 음성 필드를 포함하는 하나의 JSON 객체를 반환합니다. 여기서 음성 필드는 audio_로 접두사가 붙습니다. 호출자(caller)는 어떤 전사도 처리하지 않습니다.
{"function_calls":[{"name":"set_lights","arguments":{"room":"kitchen","on":false}}],
"confidence":0.94,
"audio_text":"turn off the kitchen lights",
...}
pip install cactus-needle
import needle
print(needle.transcribe("clip.wav")["text"])
# turn off the kitchen lights
16 kHz WAV 또는 원시 샘플은 기본 설치만으로 충분합니다. 다른 샘플 속도와 마이크 캡처를 위해서는 [mic] 추가가 필요하며, 이는 soxr과 sounddevice를 추가합니다.
모든 호출은 텍스트, 언어, 첫 토큰까지의 밀리초(milliseconds), 그리고 이후 디코더의 초당 토큰 수를 반환합니다. word_timestamps=True는 각 단어와 그 시간 및 확률을 추가합니다. `keywords=[
터미널의 마이크에서 음성을 전사하고, needle whistle compare를 실행합니다.
이 명령어는 동일한 클립을 Whistle, Whisper, 그리고 Moonshine으로 나란히 통과시키면서 각 모델의 시간 정보를 비교합니다.
이 엔진은 macOS와 Linux부터 Android, iOS, watchOS, ARM용 Windows, RISC-V, MIPS, 브라우저, WASI 컴포넌트에 이르기까지 열일곱 개의 타겟을 위해 미리 빌드되어 배포됩니다. 각 폴더에는 needle 바이너리, libneedle.a, 그리고 needle.h가 포함되어 있으며, 사용자가 제공하는 모든 .cact 파일을 로드합니다.
needle download macos-arm64
needle download whistle
./macos-arm64/needle --model whistle.cact --audio clip.wav --audio-word-timestamps
needle_load, needle_transcribe, 그리고 needle_embed는 전체 음성 C API입니다. 이 엔진은 환경 변수를 읽지 않습니다. 모든 동작은 컴파일된 기본값 또는 명시적인 플래그로 처리됩니다.
가중치(Weights)는 Hugging Face에 있으며, 엔진 및 플랫폼 폴더는 Cactus-Compute/needle3에 있고, 소스 코드는 GitHub에 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Lobste.rs AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기