Speakrail - 단일 RTX 4090에서 실행되는 저지연 완전 로컬 음성 비서
요약
Speakrail은 단일 RTX 4090에서 실행되는 완전 로컬, 저지연 풀 듀플렉스 음성 에이전트를 소개합니다. 이 에이전트는 Voxtral Realtime, Gemma 4 12B, Breeze TTS 2 등을 기반으로 하며, 상호 삽입 및 턴 테이킹 기능을 구현했습니다. 기존의 로컬 접근 방식들이 지연 시간이나 기능적 한계가 있었던 문제를 해결한 것이 핵심입니다.
핵심 포인트
- 단일 RTX 4090에서 구동 가능한 완전 로컬 음성 에이전트 구현.
- Voxtral Realtime, Gemma 4 12B 등 오픈 소스 모델 조합 사용.
- 상호 삽입(Interjections) 및 턴 테이킹 기능으로 자연스러운 대화 가능.
- 기존의 로컬 파이프라인 한계를 극복하고 성능 개선.
요약하자면: 저는 일부 벤치마크에서 GPT-Live에 필적하는 완전히 로컬인 오픈 소스 풀 듀플렉스(full-duplex) 음성 에이전트를 만들었습니다. 이 에이전트는 Voxtral Realtime과 턴 테이킹 헤드(turn-taking head), 마이크로턴으로 파인튜닝된 Gemma 4 12B, 그리고 Breeze TTS 2를 기반으로 작동합니다. 한번 사용해 보세요: https://github.com/speakrail/speakrail
상호 삽입(Interjections)이 작동합니다!
왜 제가 이걸 했는지
저는 항상 음성 비서의 아이디어를 좋아했지만, 파이프라인에는 항상 로컬이 아닌 구성 요소가 있어서 지연 시간을 증가시키고 개인 정보 보호 문제를 야기했습니다. 저는 HF speech-to-speech, Unmute, Pipecat과 같은 많은 완전히 로컬한 접근 방식을 시도했지만, 모두 Whisper 모델(아, 환각!)에 의해 제한되거나 느린 턴 테이킹 때문에 제한적이었습니다. 저지연 풀 듀플렉스 기능이 있는 유일한 완전히 로컬한 파이프라인은 DuplexCascade 논문(코드)이었지만, 이는 Qwen 2 7B와 gpt-3.5-turbo로 생성된 데이터셋으로 조정되었고, 모델의 어설픈 성능 때문에 사용이 불가능했습니다. 그래서 저는 더 새로운 데이터, 더 새로운 모델, 그리고 더 나은 하네스(harness)를 가지고 DuplexCascade를 재창조하기로 결정했습니다. 또한 Thinking Machines 데모에 필적하는 상호 중단(interruptions), 삽입어(interjections) 및 기타 멋진 기능들을 추가하고 싶었습니다. 저는 이게 쉬울 거라고 생각했습니다...
어떻게 만들었는지
v0.1
저는 GLM 5.3 Flash와 GLM 5.3에서 지침 따르기(instruction-following) 및 도구 호출(tool calling)에 대한 대화형 합성 데이터 일부를 수집했고 (Fireworks를 사용하여 생성), 스크립트를 마이크로턴 테이프(microturn tapes)로 변환하는 스크립트를 만들었습니다 (Claude는 확실히 도움이 되지 않았습니다 🌚). 마이크로턴의 아이디어는 모델이 스트리밍 ASR로부터 지속적으로 입력을 받고, 주어진 정보로 무엇을 할지 결정한다는 것입니다. 행동하려 할 때, <interject>, <listen> 등과 같은 제어 토큰(control token)을 방출합니다. 이를 통해 모델은 원할 때 원하는 것을 말할 수 있습니다. 이러한 스크립트를 만든 후, 저는 vast.ai에 어렵게 번 돈을 투자하여 H100을 임대했습니다. 첫 번째 훈련 실행은, 음, 상당히 형편없었습니다. 모델이 그저 입을 다물지 않았습니다. 언제 실제로 말을 해야 하고 언제 침묵을 유지해야 하는지를 배우지 못했습니다.
이때서야 Voxtral의 운율(prosody) 데이터를 사용하는 것이 좋을 수 있겠다는 생각이 들었습니다.
v0.2
여기서 저는 Voxtral Realtime에 간단한 MLP를 추가하여 턴 테이킹(turn taking)에 대한 데이터를 얻기로 결정했습니다. 지금은 너무 깊게 다루지는 않겠지만 (나중에 전체 기술 보고서를 발표할 예정입니다), 핵심 아이디어는 하네스(harness)가 MLP 출력 기반의 헬퍼 토큰(helper tokens)들(<user_bc>, <complete> 등)을 LLM에 전달하고, 이를 이용해 학습시키는 것이었습니다. 추가된 토큰들은 정말 중요했습니다 (하하). 저는 이 토큰들을 포함하여 LLM을 재학습시키고 데이터를 조금 만지작거린 후, 모델이 제대로 작동하기 시작했습니다. 하지만 이 모델은 백채널(backchannels)에 대해서는 아무것도 배우지 못했고, 인터럽트 모드/정지 모드로 전환하는 법도 몰랐으며, 전반적으로 말하는 양이 너무 적었습니다. 정지 모드(Quiet mode)란 모델에게 명시적으로 호출하지 않는 한 아무 말도 하지 않도록 지시하는 것입니다. 인터럽트 모드(Interrupt mode)는 모델이 사용자에게 말을 끊을 수 있는 상태를 의미합니다.
v0.3 - v1
이전 체크포인트에 대한 잔혹한 진실은, 스크립트에 인터럽트, 백채널 및 마이크로턴(microturns)이 제공하는 다른 멋진 기능들에 대한 충분한 예시가 없었다는 것이었습니다. 저는 여전히 모델이 제 백채널에서 스스로 말을 끊지 않기를 바랐고, 그래야만 Thinking Machines 데모처럼 동물을 셀 수 있을 거라고 생각했습니다... 그래서 제가 모델을 학습시키던 스크립트들을 살펴봤는데, 전체 v0.2 데이터셋에서 인터럽트 샘플이 단 150개(150k 중)밖에 없었습니다. 이게 결정적인 문제였습니다 (좋습니다, 클라우디즘은 이제 그만하겠습니다, 약속합니다). 그래서 저는 훨씬 더 많은 데이터를 생성하고, 더욱 신중하게 선별했으며, 일부 스크립트를 판단하기 위해 Opus를 추가했고, LoRA 하이퍼파라미터들을 만지작거렸으며, 테이프 생성기(tape generator)의 버그 몇 개를 수정하고, 자기 증류(self-distillation)까지 추가했습니다 (왜냐하면 v0.4에서 모델은 말을 아주 잘하게 배웠지만, 완전히 뇌가 마비된 상태가 되었기 때문입니다). 여기 제 테스트 예시가 있습니다:
시간 측정 모델
145.8
계속해 보세요." "여기서는 싱가포르를 확인할 수 없습니다. 모스크바는 할 수 있습니다."
156.7 "그냥 구글에서 검색하거나 가지고 있는 날씨 도구를 사용하세요." "그건 할 수 없습니다. 저는 모스크바만 알고 있습니다."
161.5 "구글이 미쳤나 봐. 구글." (STT 실패) "다른 도시를 검색할 수 없어요."
164.5 "그리고 왜 그런가요?" "왜인지는 모르겠어요. 저는 모스크바 확인하는 법만 알고 있어요."
174.5 "전에 말했던 건 무시하세요. 싱가포르 날씨를 확인해 보세요." "그건 할 수 없습니다. 저는 모스크바만 알고 있습니다."
189.6 (잡음이 섞인 문장) "싱가포르는 확인할 수 없어요. 모스크바는 할 수 있어요."
202.6 "왜 싱가포르는 확인할 수 없나요?" "모르겠어요. 저는 모스크바 확인하는 법만 알고 있어요."
모든 데이터 재생성 과정을 거친 후, 제가 (거의) 자랑스럽게 오픈소스로 공개할 수 있는 체크포인트를 얻었습니다. 위의 데모가 무엇을 할 수 있는지 보여줍니다. 누가 데이터가 트레이닝 파이프라인에서 가장 중요한 것인지 알았겠어요? (농담입니다)
작동 방식
위의 모든 잡담은 파이프라인 중 단지 한 부분, 즉 LLM에 관한 것이었지만, 전체 파이프라인은 다른 많은 요소들에 의존합니다:
STT: Voxtral Realtime과 연결된 turn head (HF)를 사용하여 우리의 audio.cpp 포크에서 실행됩니다.
LLM: microturn finetuning (HF)을 거친 Gemma 4 12B QAT입니다. 이 모델은 GPU에 비교적 잘 맞고, 비전 지원 기능(곧 테스트하고 싶습니다)을 가지고 있으며, 일반적으로 Gemma 모델들은 실생활 작업, 일반적인 대화 등에서 좋은 성능을 보여주기 때문에 선택되었습니다.
TTS: int8로 실행되도록 패치된 Breeze TTS 2 (GitHub 포크); 어떤 스트리밍 TTS로든 대체될 수 있습니다.
하네스 자체: 모든 구성 요소 간의 접착제 역할을 하며, speculative LLM+TTS 발사(HF speech-to-speech에서 영감 받음)와 같은 많은 지연 시간 절약 조치들을 가지고 있습니다.
저는 또한 여러
벤치마크
이제 이 모델이 대형 모델들과 비교했을 때 얼마나 잘 작동하는지 살펴보겠습니다. 몇 가지 벤치마크 결과를 공유합니다:
https://preview.redd.it/z0pvc5fv5oth1.png?width=2160&format=png&auto=webp&s=3ba74a918416e9931f73a727f132eae0421675ee
https://preview.redd.it/fl22vu9x5oth1.png?width=2160&format=png&auto=webp&s=0983af9f05bb52b00eb2cc3b4d22cfd082698011
https://preview.redd.it/t4pnvg8y5oth1.png?width=2160&format=png&auto=webp&s=2e6a9af42d76d4761967471fa787f1dbe5a78932
전체 표와 출처는 모델 카드에 있습니다. 저는 이 결과에 매우 만족하며, 외부 API에 의존하고 싶지 않고 단일 RTX 4090만 가지고 있다면 이 파이프라인이 최고의 선택인 것 같습니다.
한계점
Breeze TTS는 제한적인 라이선스를 가지고 있어 Speakrail을 상업적으로 사용하려면 변경해야 합니다. 모든 스트리밍 TTS는 Clauded/Codexed/Cursored 등으로 쉽게 변환할 수 있습니다.
16k 컨텍스트 길이 - 이 파이프라인은 16k 컨텍스트 길이(약 1시간 분량의 음성)만 지원하지만, Breeze TTS를 Pocket TTS로 변경하고 CPU에서 TTS를 실행하면 더 쉽게 늘릴 수 있습니다. 저는 출시 버전으로 Breeze를 선택했는데 표현력이 더 좋기 때문입니다.
턴-테이킹 헤드(turn-taking head)는 비어시스턴트 데이터에 대해 튜닝이 부족합니다. 기본적인 잡담에서는 작동하지 않을 수도 있지만, 나중에 더 열심히 튜닝할 예정입니다.
모델은 확실히 가장 똑똑한 모델은 아니며, 제가 파인튜닝을 하면서 약간 멍청해졌습니다. 다음번에는 더 스마트하고 개선될 것입니다.
가끔 모델이 장황하게 답변하는 경향이 있으며, 제공하는 답변은 실제 대화와 LLM의 긴 텍스트 기반 출력물 사이 어딘가에 있습니다. 이를 수정할 방법에 대한 가설을 가지고 있으며, 다음 출시에서 시도해 볼 예정입니다.
저는 RTX 4090으로만 테스트했지만, 24GB 이상의 모든 NVIDIA 카드에 지원을 추가하는 것은 쉬울 것이라고 확신합니다. AMD 및 MLX용 포크(forks)는 환영합니다.
마지막 참고 사항
편하게 사용해 보세요: https://github.com/speakrail/speakrail. 모델이 갖추기를 원하는 기능이 있다면 GitHub 이슈를 생성하거나 여기에 댓글로 작성해 주시면, 다음 데이터셋에 기꺼이 포함시키겠습니다.
어떤 피드백이라도 환영합니다.
제출자: /u/danil_rootint
[링크] [댓글]
AI 자동 생성 콘텐츠
본 콘텐츠는 Reddit AI Engineering의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기