Gemini 3.1 Flash Live 지원 + MiniCPM-o 4.5 vLLM 도전 — Naia OS의 S2S 실시간 음성 AI 개발기
이후 한동안 글도 업데이트를 올리지 못했습니다.그 동안 좀 많은 일이 있었습니다. 넥스테인이 한국의 기독교 포털(www.onmam.com)의 운용을 맡아 AI적용에 대해 지원을 이야기하고 있었고 한국의 정부과제에 선정되어 Naia의 서비스도 탄력을 받을 수 있게 되었습니다. Vroid Hub의 기본 아바타가 아닌 진짜 Naia의 아바타를 선보일 수 있게 될 것 같습니다.
그리고 이전 글 끝에서 다음주에는 그래픽카드를 좀 빌려서 하기로 했으니 좀 상황이 쉬워지리라 생각합니다 라고 적었었는데, 그 약속을 이제서야 지킬 수 있게 되었습니다. RTX 3090 두 장 환경에서 MiniCPM-o 4.5를 vllm-omni로 포팅하고 Naia 클라이언트에 연결, 실시간 영어 대화 오디오 레퍼런스(voice cloning) 까지 1차 동작 검증을 끝냈습니다.
참고로 MiniCPM-o 4.5 를 vllm-omni 에 올린 건 저희가 처음이며 해외에서도 어디까지 됬는지에 대해 궁금하시는 분들도 있더군요.. upstream 의 > #1182 에 다른 분의 시도가> 있긴 한데 머지된 적은 없고, 우리도 별도 트랙으로 진행해왔습니다. 적당히 굴러가는 수준> 까지는 와있고, 지금은 업스트림 메인테이너가 받아줄 수준 으로 정리하는 단계입니다.
왜 MiniCPM-o 4.5를 목표 했나?
이전 글에서 적었지만 다시 정리하면, 개인이 RTX 3090 한 장 수준에서 돌릴 수 있으면서 오디오 레퍼런스(voice cloning)와 파인튜닝이 동시에 가능한 옴니 모델은 현재 MiniCPM-o 4.5 가 사실상 유일합니다.
- GPT-4o / Gemini Live — 클라우드 전용, 가중치 비공개, 파인튜닝 불가
- Moshi — 오픈소스이고 풀듀플렉스 우수, 그러나 영어/프랑스어 위주 + 커뮤니티 비활성
- Qwen3-Omni-30B — 30B 라 양자화 없이는 24 GB 한 장에 안 들어가고, 양자화하면 음성 출력이 깨짐
- MiniCPM-o 4.5 — 9B (Whisper-medium + Qwen3-8B + CosyVoice2 + SigLip2 결합), 24 GB늦지 않게 지켜보는 중입니다. 한 장으로 돌고, 오디오 레퍼런스로 voice clone, 그리고 파인튜닝 가능
하지만 아직은 한국어 미지원이 단점이자 저희가 기여할 수 있는 바 일 것 같습니다. 그래서 이번 AI챔피언에서는 "너를 기억해"라는 팀 이름으로 vLLM-omni 한글 파인튜닝 작업과 Naia-Memory를 이용한 버튜버 서비스를 해보겠다고 제출해보기도 했습니다. 독파모는 저희가 원하는 수준의 옴니 모델이 없어 '국내'카테고리로 지원하지는 못했습니다.
"내 PC에서 나를 기억하고 나만의 목소리로 이야기하는 AI버튜버는 누구나 가지고 싶지 않을까요?" 이걸 가능하게 위해 아래의 기술들이 필요로 하다고 생각해서 아래의 기술에 집중 중에 있습니다.
- 로컬에서 도는 옴니 모델 — STT/LLM/TTS 파이프라인이 아니라 음성-음성 end-to-end.파이프라인 방식은 누적 지연과 운율 손실이 너무 큽니다. → MiniCPM-o 4.5
- 오디오 레퍼런스(voice cloning) — "이 목소리로 말해" 한 번 들려주면 그 음색으로 대화. → CosyVoice2 의 spk_emb 기반 클로닝
- 장기 기억 — 세션마다 초기화 안 되는, 사용자를 기억늦지 않게 지켜보는 중입니다.하는 메모리 시스템. → 저희가 별도로 만들고 있는 Naia Memory (4-tier 뇌과학 영감 기억 시스템)
- 한국어 — 위 셋이 한국어로 동작해야 일상에서 씀. → CosyVoice2 한국어 파인튜닝 (AIHub 데이터 확보 완료, GPU 지원 시 즉시 착수)
그리고 추가적으로 곧 공개할 또 다른 트랙도 있습니다. naia-sing — 이름에서 뭔지 아실 것 같긴 합니다. 기대해주세요. 아래는 실제 구동 데모와 기술적인 내용도 추가 공유합니다.
데모 1 — Naia 클라이언트에서 대화
데모 영상에서 제가 영어를 잘 못하는 점은 양해 부탁드립니다.
vllm-omni에 MiniCPM 4.5-o 를 포팅하고 Naia 데스크톱 앱에 연결해 대화를 테스트한 영상입니다. 하드웨어는 RTX-3090 ×2 (2-way), 양자화 없이 bf16. 옴늦지 않게 지켜보는 중입니다. 옴니 모델(S2S, end-to-end speech-to-speech)의 특징답게 부드럽게 흘러가는 대화 흐름과 자연스러운 감정 표현이 그대로 살아납니다. 현재는 영어와 중국어를 지원합니다.
데모 2 — MiniCPM-o 데모 페이지 + 오디오 레퍼런스
MiniCPM-o 4.5 의 공식 데모 페이지를 vllm-omni 백엔드로 연결한 포크입니다. 오디오 레퍼런스 (voice cloning) 동작 예시를 함께 담았습니다. WAV 파일을 업로드하면 그 목소리의 음색·억양으로 응답을 합성합니다. 서버 측에서 SHA-256 키 LRU 캐시로 동일 레퍼런스 재계산을 피해 첫 응답 후에는 추가 오버헤드가 거의 없습니다.
구현 내역 요약
세 개의 리포지토리에서 작업해습니다.
| 리포 | 역할 |
|---|---|
nextain/vllm-omni | vllm-omni 포크 — MiniCPM-o 4.5 모델 모듈 + Thinker→Talker→Code2Wav 3-stage 파이프라인 + voice clone (session.update.ref_audio) 추가 |
nextain/MiniCPM-o-Demo-forvLLM-omni | 공식 PyTorch 데모의 포크 — backend=vllm_omni 모드 추가, audio-duplex 페이지에서 vllm-omni URL 직접 입력/검증 가능 |
nextain/naia-os | Naia 데스크톱 앱 — MiniCpmOConfig.refAudio first-class 필드 추가, 브라우저(Tauri 웹뷰)에서 AudioContext → 16 kHz mono → base64 WAV 인코더 |
Naia 클라이언트는 데모 게이트웨이를 거치지 않고 vllm-omni의 /v1/realtime (OpenAI Realtime API 호환) 에 직결합니다. WebSocket 으로 PCM16 16 kHz 오디오를 흘려보내고, 24 kHz mono PCM16 으로 응답을 받습니다. 전 작업은 Claude Code 로 진행됐습니다. 모델 코드,stage 설정 YAML, stage_input_processor, 데모 백엔드 프록시, Naia의 TypeScript 클라이언트 + WAV 인코더 + vitest까지.
- Naia는 전면 개편중입니다. Naia-os의 일부는 naia-agent로 유연성을 갖는 cli를 백엔드를 두는 구조가 될 것 같고, Naia-memory와 Naia-ADK와 결합 예정입니다.
하지만 AI slop 은 아직
이전 글에서 "이 작업의 목적은 AI-native Opensource 생태계의 실현, AI가 ai slop 없이 오픈소스에 올바르게 기여할 수 있다는 것이 가능해하게 하고 싶어 하는 실험" 이라고 적었는데, 현재도 그 부분이 가장 어렵고 최종 점검 하니 역시 또 문제점이 나타났습니다. 하지만 한시라도 빨리 공유 드리고 싶어 이 문제를 해결하기 전에 먼저 이 포스팅을 썼습니다.
지난 며칠 동안 다른 AI 에이전트를 적대적 리뷰어로 4번 돌렸습니다. 1차에서는 2 BLOCKER + 13 MAJOR. 그중 한 건은 "예제 클라이언트가 동작 안 함 — 백엔드는 오디오 입력 기반인데text-driven으로 작성됨" 같은 명백한 거짓말. 2차에서 1 MAJOR (예제가 Python 3.13에서 제거된 stdlib audioop 사용). 3·4차에서 클린 패스. 우리 룰 (2 연속 클린) 충족. 그런데 거기서 멈추지 않고 vllm-project 메인테이너 시점 으로 한 번 더 돌렸는데 여전하네요.
- 3 BLOCKER:
- 단일 모델 기능 위해
chunk_transfer_adapter.py의 cross-cutting invariant (whitelist→blacklist) 변경 prompt_len_override가 MiniCPM-o 전용인데 shared infra 에 위치chat_template_kwargs.ref_audio사이드채널은 layer 위반 — 옆에 first-class 필드 precedent 있음
- 단일 모델 기능 위해
- 5 MAJOR + 8 MINOR
내부 룰은 통과하지만 외부 메인테이너 기준으로는 첫 라운드에 머지가 안될거라고 합니다. 거기에 더해 upstream/main 이 우리 fork 의 merge-base 이후 또 업데이트되어 머징작업을 추가 진행중입니다.
다음 작업
- 업스트림 관점 BLOCKER/MAJOR 수정 — 진행 중
- upstream/main 머지 + 충돌 해소 — 곧
- PR 제출 — 위 2개 끝나면. 단일 PR vs 2 PR 분할 (모델 모듈 / voice clone) 결정 보류 중
- 한국어 파인튜닝 — 모델 자체. CosyVoice2 (Code2Wav 백본) 가 한국어로 학습 안된 게 가장 큰 장벽. 현재 한국어 텍스트 생성은 정상이나 음성 합성이 깨져서 들립니다.
이어지는 작업은 또 정리해서 공유드리겠습니다. AI도 오픈소스에 기여를 할 수 있다는 것을 보여드리겠습니다. 댓글이나 GitHub Issue 환영합니다.
Repos
Naia: https://naia.nextain.io