Naia 모델을 코드에서 직접 쓰는 개발자용 안내입니다. 4.4 Naia 모델 다운로드로 모델을 띄운 뒤, 로컬에서 직접 제공되는 OpenAI 호환 API를 그대로 사용합니다. OpenAI SDK·도구라면 접속 주소(baseURL)만 이 모델로 바꾸면 됩니다.
naia-os(쉘) 전용이 아닙니다 — OpenAI Realtime/Chat/Audio/Embeddings를 쓰는 어떤 코드든 그대로 붙고, 이 모델 위에서 새로운 애플리케이션을 개발·응용할 수 있습니다.
1. 접속 · 인증
- REST 베이스:
http://<host>:8892/v1(같은 PC면127.0.0.1) - Realtime(WS):
ws://<host>:8892/v1/realtime(베이스ws://<host>:8892만 줘도 자동으로/v1/realtime+ 기본 model 적용) - 연결: 로컬(
127.0.0.1)·Tailscale에선 인증 불필요 — 컨테이너가 라이선스로 자체검증합니다. 키 필드가 필요한 클라이언트(OpenAI SDK 등)는 아무 값(naia)을 넣으면 됩니다. 원격 노출 시 §4.4 Tailscale/VPN을 앞단에.
🔑 키는 하나 — 구독 인증키
- 구독 인증키 — 포털에서 받는 구독 키. 컨테이너 구동(활성화) 시에만 씁니다 (
-e NAIA_ACCOUNT_TOKEN=<구독 인증키>). 구독을 확인하고 시한부 라이선스(인증서)를 받는 용도입니다. - 연결할 때는 별도 키가 없습니다. 한 번 활성화되면 컨테이너가 인증서로 로컬에서 자체검증하므로, 클라이언트(naia-os·OpenAI SDK)는 URL로 연결만 하면 됩니다 — 같은 PC면
127.0.0.1, 다른 기기면 Tailscale/VPN(§4.4)으로. 연결마다 게이트웨이를 호출하지 않습니다. - 아래 예제의
api_key는 자리만 채우는 값입니다(OpenAI SDK 필수 필드) — 오프라인 컨테이너는 이 값을 검사하지 않으니"naia"등 아무 값이나 넣으면 됩니다.
2. 엔드포인트 (OpenAI 호환)
| 엔드포인트 | 용도 |
|---|---|
GET /health | 준비 상태 {"ready":true} (인증 불필요) |
GET /v1/models | 모델 목록 |
WS /v1/realtime | 실시간 음성 세션 (VAD·끼어들기·감정) |
POST /v1/chat/completions | 챗 (스트리밍 지원) |
POST /v1/audio/speech | 음성 합성(TTS) |
POST /v1/audio/transcriptions | 음성 인식(STT) |
POST /v1/embeddings | 임베딩 |
챗 (curl):
curl -s http://127.0.0.1:8892/v1/chat/completions \
-H "Authorization: Bearer naia" -H "Content-Type: application/json" \
-d '{"model":"naia-0.9-omni-24g","messages":[{"role":"user","content":"안녕"}],"stream":false}'
OpenAI SDK (Python) — baseURL만 교체:
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8892/v1", api_key="naia")
print(client.chat.completions.create(
model="naia-0.9-omni-24g",
messages=[{"role": "user", "content": "안녕"}],
).choices[0].message.content)
3. 실시간 음성 — 연결 플로우 (WS)
4.3 라이브 데모가 쓰는 흐름과 동일합니다. (오프라인은 게이트웨이 대기열·배정 없이 바로 시작.)
-
연결 —
ws://<host>:8892에 접속. -
첫 프레임(인증·언어) — 브라우저 WebSocket은 헤더 불가라 첫 메시지로:
{ "setup": { "apiKey": "naia", "locale": "ko" } } -
서버가
session.created를 보내면session.update로 세션 설정:{ "type": "session.update", "session": { "modalities": ["text", "audio"], "input_audio_format": "pcm16", "output_audio_format": "pcm16", "instructions": "<페르소나(성격) 지시문>", "turn_detection": { "type": "server_vad" }, "input_audio_transcription": { "language": "ko" }, "ref_audio_url": "<따라할 목소리 샘플 URL (선택)>" } } -
주고받기
클라이언트 → 서버 음성 입력 {"type":"input_audio_buffer.append","audio":"<base64 PCM16 24kHz>"}(서버 VAD가 말 끝 감지)텍스트 입력 conversation.item.create후response.create끼어들기 response.cancel서버 → 클라이언트 response.audio.deltabase64 PCM16 24kHz 음성 조각 response.audio_transcript.delta/response.text.delta답변 텍스트(스트리밍) conversation.item.input_audio_transcription.completed내 발화 인식 결과 emotion.updated감정/지문 태그 (§5) response.done한 턴 종료
4. 언어 — 30개 언어 (기본 = 자동/글로벌)
모델은 30개 언어를 지원합니다 (Arabic, Burmese, Chinese, Danish, Dutch, English, Finnish, French, German, Greek, Hebrew, Hindi, Indonesian, Italian, Japanese, Khmer, Korean, Lao, Malay, Norwegian, Polish, Portuguese, Russian, Spanish, Swahili, Swedish, Tagalog, Thai, Turkish, Vietnamese).
- 기본(미지정) = 글로벌/자동 — 사용자가 말한 언어를 인식해 그 언어로 응답합니다(턴마다 자동).
- 특정 언어로 고정하려면
setup.locale또는session.update의input_audio_transcription.language에 ISO-639-1 코드(예ko/en/ja)를 주세요.
5. 출력 형식 (감정·운율 태그)
음성 대화에 맞게 출력 형식이 조정되어 있습니다 — 클라이언트가 알면 더 풍부하게 표현할 수 있습니다.
- prosody(운율) 태그: 답변 텍스트에
[laughing],[sigh],[breath],[pause],[hesitation]같은 소문자 영어 대괄호 태그가 감정이 바뀌는 지점에 섞여 나옵니다(발화 운율 표현용).[웃음]같은 한국어 태그·(웃으며)괄호 지문·*smiles*별표는 쓰지 않도록 모델에 지시돼 있습니다. 알려진 어휘:laughing/laugh/laughter/chuckle/giggle · sigh/exhale · breath/inhale · pause · hesitation · gasp/cough/sneeze/yawn/sniff/hum · cry/sob/moan/whisper/shout/cheer(그 외 태그도 그대로 전달). - 태그가 나올 때마다 서버가
emotion.updated이벤트를 1:1로 보냅니다 (state== 태그명, 소문자):{ "type": "emotion.updated", "state": "laughing", "tag": "[laughing]", "known": true } - TTS path 는 태그를 보존한 채 음성 합성 단계로 보내 발화 운율에 반영하고, chat
text.delta는 태그를 제거한 깨끗한 텍스트로 보냅니다. (출력에 이모지·마크다운·괄호 자기서술은 들어가지 않습니다.) - 클라이언트 매핑 (naia-os 참고 구현):
emotion.updated.state(운율 태그)를 아바타 표정으로 매핑합니다 —laughing/chuckle/giggle/cheer → happy,sigh/exhale/cry/sob → sad,gasp → surprised,shout → angry,hesitation → think.breath·pause같은 비감정 운율은 표정을 바꾸지 않습니다(직전 표정 유지 — 매 호흡마다 neutral 로 깜빡이지 않게). - 견고한 처리 권장: LLM 출력은 항상 정확하지 않습니다.
emotion.updated를 우선으로 쓰되, 누락 시 transcript 자체에서 태그(대문자[HAPPY]/ 소문자 운율 태그)나 새어 나온 지문 ((smiles)·*sigh*)을 자동으로 잡아 표정에 반영하고, 단서가 없으면 표정을 유지하는 것이 좋습니다 (참고: naia-osshell/src/lib/vrm/expression.ts의extractExpression).
6. 참고
- 참조 구현 / 샘플 코드 (오픈소스): naia-os의 voice 클라이언트
shell/src/lib/voice/(Apache 2.0) — 이 API에 직결하는 실제 클라이언트(naia-omni.ts)와 감정/운율 처리(emotion-tags.ts, 표정 매핑·견고한 추출은vrm/expression.ts)가 들어 있습니다. 새 모델 테스트·Tauri 앱 개발의 출발점으로 그대로 활용하세요. 동작 체험은 4.3 라이브 데모. - 라인업·가격: 4.1 모델 가격 정책
- 클라우드(예정): 4.6 온라인 이용