모바일 앱이나 웨어러블 기기에서 음성을 텍스트로 변환하려면 보통 클라우드 API를 호출하거나, 기기에 올리기엔 부담스러울 만큼 큰 모델을 써야 했습니다. 캑터스컴퓨트(Cactus Compute)가 공개한 Whistle은 이 문제를 정면으로 겨냥한 음성인식(STT) 모델로, 파일 크기가 단 16.9MB에 불과하면서도 오픈AI의 Whisper base(145.3MB)보다 여러 벤치마크에서 더 나은 성능을 보였다고 밝혀 눈길을 끕니다. 특히 이 모델은 같은 회사가 만든 텍스트 생성 모델 Needle과 동일한 C++ 엔진, 동일한 양자화 방식을 공유해 하나의 바이너리로 음성 인식과 텍스트 생성을 모두 처리할 수 있다는 점이 핵심입니다.
Needle과 몸체를 공유하는 설계
Whistle은 독자적인 음성 전용 아키텍처를 새로 만든 것이 아니라, Needle이 쓰는 블록 구조를 그대로 재활용했습니다. 인코더는 Needle과 동일한 8개의 ‘Simple Attention’ 블록(4개의 mHC 잔차 레인과 피드포워드 대신 Monarch Hadamard MLP)으로 구성되고, 디코더 역시 Needle의 ‘Laddered Simple Attention’ 블록을 레이어 수만 다르게 가져왔습니다. 디코더는 폭 512, 쿼리 헤드 8개 대 KV 헤드 2개 구조에 Q·K·V에 3-tap 인과적 컨볼루션을 적용하고, 3번째와 7번째 레이어에는 18,432개 슬롯을 가진 엔그램(engram) 조회 기능까지 넣었습니다.
음성 모델다운 추가 요소는 레이어마다 하나씩 들어간 게이트 교차 어텐션(gated cross attention)입니다. 디코더의 각 레이어가 인코더 출력을 읽어올 때 학습된 게이트 값으로 신호를 조절하는 방식인데, 이때 K와 V는 오디오 클립이 들어올 때 단 한 번만 계산되고 디코딩 내내 재사용됩니다. 덕분에 5개의 빔(beam)으로 탐색해도 오디오를 5번 다시 분석하는 게 아니라 짧은 텍스트 캐시만 5개 두는 것으로 끝나, 연산 비용이 크게 줄어듭니다.
오디오를 텍스트로 바꾸는 과정
Whistle의 전처리 과정은 16kHz 모노 오디오를 25ms 윈도우, 10ms 홉으로 쪼개 80개의 로그멜 빈(log-mel bin)으로 변환하는 것에서 시작합니다. 250~3500Hz 대역으로 제한하고 채널별 정규화를 거치면 30초 분량 오디오가 3,000프레임이 되는데, 128채널·커널 9짜리 컨볼루션 스템이 이 프레임 수를 세 차례 절반씩 줄여 최종적으로 80ms당 1프레임, 총 375프레임으로 압축합니다. 이후 모든 인코더·디코더 연산은 이 압축된 비율로 돌아갑니다.
디코딩 단계에서는 길이 정규화된 로그 확률로 점수를 매기는 5개의 빔 서치를 사용하고, 사용자가 지정한 키워드를 Aho-Corasick 오토마타로 추적해 해당 단어가 나올 가능성이 있을 때 확률을 끌어올리는 키워드 바이어싱 기능도 들어 있습니다. 전사 결과는 최대 320토큰까지 생성되며, 어휘는 8,192개의 텍스트 조각과 7개 언어 토큰으로 구성돼 있어 감지된 언어 자체가 별도 필드가 아니라 토큰으로 출력됩니다. 무음 구간은 디코더가 아예 작동하지 않고 빈 전사와 빈 언어를 즉시 반환하도록 설계해 불필요한 연산을 막았습니다.
‘래더’ 구조로 속도와 정확도를 동시에 조절
Whistle의 또 다른 특징은 디코더에 적용된 ‘래더(ladder)’ 구조입니다. 2개 레이어부터 시작하는 모든 깊이가 각각 독립된 모델처럼 학습되어 있어서, 실행 시 --audio-depth 옵션으로 원하는 깊이를 선택할 수 있습니다. 반면 인코더는 깊이와 무관하게 8개 블록이 항상 전부 실행됩니다. 즉 디코더 깊이를 조절해 기기 성능이나 응답 속도 요구에 맞게 모델을 탄력적으로 운용할 수 있다는 의미입니다.
벤치마크 결과와 Whisper 대비 위치
원문에 따르면 Whistle은 LibriSpeech test-clean·test-other, SPGISpeech, Earnings-22, FLEURS 평균에서 더 앞선 성적을 냈고, Whisper base는 TED-LIUM, AMI, MLS 평균에서 더 나은 결과를 보였습니다. 각 모델은 자체 공식 런타임과 기본 설정으로 측정됐는데, Whistle은 C++ 엔진에서 5빔으로, Whisper는 openai-whisper로, Moonshine은 non-streaming 방식으로 전체 오디오를 한 번에 처리했습니다.
속도 차이도 뚜렷합니다. Whisper는 모든 입력을 30초로 패딩하기 때문에 클립 길이와 무관하게 첫 토큰까지 걸리는 시간이 일정한 반면, Whistle은 클립 길이에 비례해 5초 클립에서 5.9ms, 10초에서 11.1ms, 30초에서 36.3ms로 첫 토큰 생성 시간이 달라집니다. 단어 오류율(WER)은 Whisper 정규화 기준으로 측정됐으며, Whistle은 86,174개 발화로 직접 측정한 반면 Whisper와 Moonshine 수치는 각 저자가 발표한 다국어 체크포인트 기준 공개 수치를 인용한 것이어서 측정 조건이 완전히 동일하지는 않다는 점은 참고할 필요가 있습니다. 테스트 오디오가 학습·검증 데이터에 포함되지 않았다는 점은 오디오 체크섬과 화자 ID 비교로 검증했다고 밝혔습니다.
한국 개발자 입장에서 살펴볼 지점
Whistle이 흥미로운 이유는 단순히 크기가 작다는 점보다, Needle과 같은 컨테이너·같은 양자화로 하나의 바이너리에서 음성과 텍스트 처리를 함께 할 수 있다는 구조적 특징에 있습니다. needle_load 함수가 .cact 파일에 담긴 모델 종류를 읽어 음성 모델이든 텍스트 모델이든, 혹은 둘 다든 같은 방식으로 로드한다는 설명은, 오디오 클립을 받아 바로 도구 호출(tool call)로 연결하는 파이프라인을 온디바이스에서 구현하려는 개발자에게 특히 유용할 수 있습니다.
국내에서도 저전력 IoT 기기, 차량용 음성 인터페이스, 스마트홈 허브 등 네트워크 연결 없이 음성 명령을 처리해야 하는 제품군에서 이런 초경량 모델에 대한 수요가 꾸준히 있었습니다. 다만 현재 공개된 자료만으로는 라이선스 조건, 실제 배포 형태(SDK, API, 가중치 공개 여부), 한국어 지원 포함 여부 등이 명확하지 않으므로, 실제 적용을 검토한다면 캑터스컴퓨트의 공식 문서와 라이선스 조건을 먼저 확인하는 것이 안전합니다.

답글 남기기