docs(readme): document the operational voice-server, emotion TTS, and dashboard

Records what's now built beyond the original plan: real GPU STT/brain/TTS via
the voice-server, bracketed-emotion TTS (pitch/speed), and the dashboard's
prompt editing, bot control bar, whitelist/blacklist, 3-row turns, and log dock,
plus the dashboard<->bot control plane.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
EJClaw
2026-08-22 12:07:04 +09:00
parent 441ab4831f
commit 50838ef602

View File

@@ -5,8 +5,11 @@
STT → 두뇌 → TTS부터 완성**하는 단계다. STT → 두뇌 → TTS부터 완성**하는 단계다.
- 실행 위치: 이 리눅스 호스트(.9, RTX 5050 8GB / ffmpeg / node v22 있음) - 실행 위치: 이 리눅스 호스트(.9, RTX 5050 8GB / ffmpeg / node v22 있음)
- 현재 상태: 음성 루프 뼈대 동작 — 파이프라인이 **눈 없이(화면공유 없이)** 돌아간다 - 현재 상태: 음성 루프 **실엔진 동작** — GPU STT(faster-whisper), Claude 두뇌(Haiku),
(`python -m wsai --voice`). STT/TTS/두뇌는 아직 mock이며, 실제 엔진 연결이 다음 목표. GPU TTS(MeloTTS, 감정 톤 반영)가 모두 붙었고 디스코드 봇과 왕복하는 **voice-server**
(`python -m wsai --voice-server`)가 실서비스로 돈다. 상태 대시보드(:8787)에서 봇 정보·
서버/음성채널 선택·참여자·발화자·로그·프롬프트·화이트/블랙리스트를 실시간 제어한다(9장).
남은 것은 실제 사람 발화로 오디오 왕복을 눈으로 확인하는 최종 라이브 검증뿐.
- 보류 중: 화면공유 **비디오** 수신(눈). 단, STT 입력은 **디스코드 보이스로 유저 음성을 - 보류 중: 화면공유 **비디오** 수신(눈). 단, STT 입력은 **디스코드 보이스로 유저 음성을
수신**하므로 보이스 접속 자체는 지금도 쓴다(비디오만 미룸). 이 보이스 접속은 수신**하므로 보이스 접속 자체는 지금도 쓴다(비디오만 미룸). 이 보이스 접속은
**공식 Discord 봇**(`dave/bot.mjs`, discord.js + @discordjs/voice)으로 하며 DAVE/MLS **공식 Discord 봇**(`dave/bot.mjs`, discord.js + @discordjs/voice)으로 하며 DAVE/MLS
@@ -212,3 +215,52 @@ ffmpeg 디코드 → 프레임. DAVE는 `@snazzah/davey`(Rust NAPI), 수신은 `
- **M3** faster-whisper STT(부분전사+VAD) → **M4** Claude OAuth(Haiku) 두뇌 - **M3** faster-whisper STT(부분전사+VAD) → **M4** Claude OAuth(Haiku) 두뇌
- **M5** 한국어 TTS 첫 구절 청크를 보이스로 송신(DAVE 암호화) + barge-in - **M5** 한국어 TTS 첫 구절 청크를 보이스로 송신(DAVE 암호화) + barge-in
- **M6** 통합 + 워밍업 + .9 GPU 도커 이미지화, 채널 라이브 테스트 - **M6** 통합 + 워밍업 + .9 GPU 도커 이미지화, 채널 라이브 테스트
---
## 9. 운영 음성 서버 + 대시보드 (구현됨)
디스코드 봇이 발화 wav를 `POST /api/voice-turn`으로 올리면, voice-server가 GPU STT →
Claude 두뇌 → GPU TTS를 돌려 응답 wav를 돌려주고 봇이 채널에 재생한다. 같은 서버가
:8787에 상태 대시보드(단일 HTML, 외부 자산 없음)를 띄운다.
```bash
.venv/bin/python -m wsai --voice-server --host 0.0.0.0 --port 8787 # 실서비스(wsai-voice.service)
```
### 감정 TTS (대괄호 태그)
- 두뇌가 답변에 `[감정]` 태그를 넣으면 그 태그는 **읽지 않고** 뒤 문장의 피치·속도를 바꿔
감정을 표현한다. 답변 중간에 감정이 바뀌면 그 지점부터 톤이 바뀐다.
예: `[속상함] 정말 힘들었겠다. [힘차게] 하지만 넌 할 수 있어!`
- 감정 어휘는 Azure Neural TTS speaking styles + Ekman 기본감정을 한국어로 매핑
(`wsai/backends/emotion.py`). 감정 단어가 아닌 대괄호(예: `[1번]`)는 내용을 그대로 읽는다.
- 음성이 아닌 잡음으로 판단되면 답변을 `[잡음]`으로 두고 아무것도 재생하지 않는다.
- 구현: 세그먼트별 합성 후 librosa 피치 시프트로 이어붙임(`melo_worker.py`), 시작 시 예열.
### 대시보드 기능
- **봇 프롬프트 실시간 수정** — 상단 "📝 프롬프트" 팝업에서 현재 시스템 프롬프트를 보고
수정→저장하면 다음 답변부터 즉시 반영(빈칸 저장 시 기본값 복원). `prompt_store` 영속화.
- **봇 제어 바** — 봇 정보/연결 상태, 참여 가능 서버 선택(상단 "없음"), 선택 서버의 음성채널
선택(상단 "없음"), 현재 음성채널 참여자(말하는 사람 🔊).
- **화이트/블랙리스트** — 팝업에서 서버의 유저/역할을 검색해 추가/제거. 화이트리스트가 있으면
그 대상만 청취(비어있으면 전체), 블랙리스트는 제외. 봇이 발화자 SSRC→유저/역할로 필터
(`dave/filter.mjs``isAllowed`).
- **대화 카드** — 들음 / 생각(감정 톤 계획) / 답변 3분할, 발화자(🗣) 표시, 단계별·총 소요시간.
- **로그 패널** — 하단 고정 VSCode 터미널식, 열고닫기, 시작부터 기록. 텍스트/레벨 검색,
전체·라인별 삭제/수정(`/api/logs/{clear,delete,edit}`).
### 대시보드 ↔ 봇 제어 채널
봇은 아웃바운드 HTTP만 쓴다. 봇이 상태(정체성·서버·음성채널·참여자·역할·멤버)를
`POST /api/bot/report`로 올리면, 응답에 대시보드가 쌓아둔 **명령**(채널 join/leave)과
**청취 필터**가 실려 온다. 서버/채널 선택은 `POST /api/bot/select`, 필터는
`POST /api/bot/lists`로 저장한다(`wsai/bot_control.py`).
### 관련 파일
| 경로 | 역할 |
|------|------|
| `wsai/dashboard.py` | voice-turn 엔드포인트 + 상태 대시보드(HTML/JS) + 모든 API |
| `wsai/monitor.py` | 턴/스텝/이벤트 텔레메트리 (thought·speaker·이벤트 id 포함) |
| `wsai/backends/emotion.py` | `[감정]` 태그 파싱 + 감정→피치/속도 매핑 |
| `wsai/prompt_store.py` | 실시간 편집되는 시스템 프롬프트 영속화 |
| `wsai/bot_control.py` | 대시보드↔봇 제어 플레인(상태·명령·화이트/블랙리스트) |
| `dave/filter.mjs` | 청취 화이트/블랙리스트 판정(`isAllowed`, 순수 함수) |