feat(desktop): LLM 기본 모델 qwen3:4b → gemma4:e4b 전면 전환 + think:false 안전장치
qwen3:4b가 reasoning 모델이라 <think>...</think> 블록을 길게 생성 → stripReasoningBlocks 후 빈 문자열 → 원본 transcript fallback으로 끝나면서 LLM refine이 42초 걸리는 병목 발견. Google Gemma 4 e4b(4.5B effective params, 2026-04-02 릴리스)로 교체. non-reasoning 기본 + Ollama v0.20+ think: false 파라미터로 2중 방어. 실측 결과: 받아쓰기 한 사이클 51.4s → 5.5s (9.3배 빠름). STT 500ms + LLM 3,925ms + insert 1,092ms. refine 품질 정상 동작 확인: "테스트하는 중입니다" → "테스트하고 있습니다". - LocalLLMService: 3개 fallback 기본값 변경(generate / streamGenerate / chatStream) + Ollama 요청 body에 think: false 명시 추가. non-reasoning 모델은 무시, reasoning 모델은 thinking 토큰 차단. NO_THINK 주석을 legacy 설명으로 업데이트 — qwen3/deepseek-r1 수동 선택자를 위한 3중 방어(/no_think + think:false + stripReasoningBlocks) 명시. - OnboardingModal / OllamaGuideModal: pull 명령어 갱신 - 테스트 fixture 갱신 - 12개 i18n locale JSON: settings.ollamaHint / ollama.step2.alt 키 업데이트 (qwen3:4b → gemma4:e4b, qwen3:8b → gemma4:26b) - 10개 site i18n locale TS + HowItWorks.tsx 파이프라인 시각화 — detail 문자열 'qwen3 / llama3 / gemma3' → 'gemma4 / llama3.2 / phi4', 파이프라인 라벨 'qwen3:4b @ localhost' → 'gemma4:e4b @ localhost' - 설계서 00 LLMConfig 기본값 + CONFIG_DEFAULTS - 설계서 05: 6개 API 스키마 예시, 2개 OllamaClient 코드 예시, LLM 모델 추천 표 재정렬(gemma4:e4b 최상위, qwen3는 reasoning 경고와 함께 후순위), 권장 JSON 설정에 think:false 추가 - phase-14 meeting mode 컨텍스트 윈도우 표 갱신 - V2-5 Mac 부트스트랩 가이드 pull 커맨드 갱신 - project_status.md Part 7 전체 섹션 추가
This commit is contained in:
parent
a744551442
commit
d397bcbf57
32 changed files with 153 additions and 65 deletions
|
|
@ -1,8 +1,85 @@
|
|||
# D3RO-VOICE 프로젝트 현황
|
||||
|
||||
> 마지막 갱신: 2026-04-11 (빅뱅 Phase 5 Part 6 — Voice Conversation 몰입 패널 구현)
|
||||
> 마지막 갱신: 2026-04-11 (빅뱅 Phase 5 Part 7 — Bug 13 전면 해소 + Gemma4 전환)
|
||||
> 규칙 13: 작업 완료 즉시 이 파일 갱신 의무
|
||||
|
||||
## 빅뱅 Phase 5 Part 7 (2026-04-11) — Bug 13 전면 해소 + Gemma4 기본 모델 전환 ✅
|
||||
|
||||
Part 6에서 Voice Conversation 몰입 패널까지 가고 남은 숙제였던 **Bug 13 전면 해소**와 사용자 실측에서 발견된 **LLM refine 42.9초 병목**(qwen3 reasoning 모델 strip empty fallback)을 한 사이클에 정리. 받아쓰기 한 바퀴 51초 → 기대 7~10초로 대폭 단축 예상.
|
||||
|
||||
### 7-A. Voice Conversation 에러 배너 UI (Part 6 후속)
|
||||
|
||||
`VoiceConversationPage.tsx`의 `onError` 콜백이 기존에는 주석만 있고 UI 피드백이 없었음. MUI `Snackbar + Alert(severity="warning" variant="filled")` 하단 중앙 4초 auto-hide 배너 추가. 에러 매핑 헬퍼 `formatErrorMessage`:
|
||||
|
||||
- `phase === 'stt' && message.startsWith('no speech')` → i18n `conversation.error.noSpeech`
|
||||
- 그 외 → `${phaseLabel}: ${rawMessage}` (phaseLabel 3종 i18n)
|
||||
|
||||
**i18n 키 4개 추가** (ko/en): `conversation.error.phase.{stt,llm,tts}` + `conversation.error.noSpeech`
|
||||
|
||||
### 7-B. Dictation Bug 13 가드 (VoiceModeService)
|
||||
|
||||
`_transcribe()`에 2중 가드 추가 — VoiceConversationService와 동일 패턴.
|
||||
|
||||
1. **minBytes 가드** (16kHz 16bit mono 기준 0.5초 = 16000 bytes 미만) → `_handleError(STTAudioTooShort, 'No speech detected...')` → recording-tip popup이 'error' 상태로 전환 → 3초 자동 숨김
|
||||
2. **빈 result.text 가드** → `_handleError(STTNoAudioData, 'No speech detected...')` (동일 경로)
|
||||
|
||||
실측 로그에서 확인된 기존 버그: `1.5초 무음 오디오 → VAD 전체 filter → 빈 전사 → LLM 5초 대기 → 빈 session completed → 빈 history entry 생성` 시퀀스가 모두 차단됨.
|
||||
|
||||
### 7-C. Recording Tip hide 타이머 leak 수정 (VoiceModeService)
|
||||
|
||||
사용자 실측에서 발견된 추가 버그 — "받아쓰기 꾹 누르고 있는데 2초 뒤에 popup이 사라짐". 원인은 `_handleError`의 `setTimeout(() => hideRecordingTip(), 3000)`이 핸들로 보관되지 않아 다음 세션 시작 후에도 예약대로 발사되어 현재 진행 중인 recording tip을 hide 시킴. Bug 13 가드 추가로 에러 경로가 자주 타면서 드러난 기존 잠재 버그.
|
||||
|
||||
**수정**: `_errorHideTimer: NodeJS.Timeout | null` 필드 추가 → `_handleError`에서 핸들 보관 + 기존 타이머 clearTimeout 후 재예약, `_startSession` 초기화 블록에서 `_errorEmitted = false`와 함께 clearTimeout, `dispose()`에서도 leak 방지용 cleanup. 실측 확인: 4.5초 hold 성공, 전사 `"Hey, yeah, yeah..."` 정상 완료.
|
||||
|
||||
### 7-D. LLM 기본 모델 전면 교체 — qwen3:4b → gemma4:e4b ⭐
|
||||
|
||||
**발견한 병목**: 받아쓰기 한 사이클 51.4초 = STT 7.4초(PyTorch 미설치, CPU int8) + **LLM 43초(!)** + insert 1초. LLM 43초의 원인은 `qwen3:4b`가 reasoning 모델이라 `<think>...</think>` 블록을 길게 생성 → `stripReasoningBlocks` 후 **빈 문자열 → 원본 transcript fallback**. 즉 43초를 기다렸는데 결과는 원본 그대로.
|
||||
|
||||
**해결**: 2026-04-02 릴리스된 Google **Gemma 4 e4b** (4.5B effective params)를 기본으로 교체. non-reasoning 기본 동작 + Ollama v0.20+ `think: false` 파라미터로 2중 방어.
|
||||
|
||||
**변경된 위치** (한 번에):
|
||||
- `LocalLLMService.ts` — 3개 default fallback (`generate`/`streamGenerate`/`chatStream`) + Ollama 요청 body에 `think: false` 명시 추가 + NO_THINK 주석 업데이트(legacy 표기)
|
||||
- `OnboardingModal.tsx:246` + `OllamaGuideModal.tsx:133` — pull 명령어 변경
|
||||
- `packages/i18n/src/locales/{12개}.json` — `settings.ollamaHint`, `ollama.step2.alt` 2개 키 (qwen3:4b → gemma4:e4b, qwen3:8b → gemma4:26b)
|
||||
- `site/src/i18n/locales/{10개}.ts` — 마케팅 페이지 detail 문자열 `qwen3 / llama3 / gemma3` → `gemma4 / llama3.2 / phi4`
|
||||
- `site/src/sections/HowItWorks.tsx:47` — 파이프라인 시각화 `qwen3:4b @ localhost` → `gemma4:e4b @ localhost`
|
||||
- `apps/desktop/tests/main/services/VoiceModeService.test.ts:58` — test fixture `llmModelId`
|
||||
- `docs/design/00-master-architecture.md` — `LLMConfig.model` 주석 + `CONFIG_DEFAULTS.llm.model`
|
||||
- `docs/design/05-external-engine-integration.md` — 6개 API 스키마 예시 + 2개 OllamaClient 코드 예시 + LLM 모델 추천 표(gemma4:e4b를 최상위로 재정렬, qwen3를 reasoning 경고와 함께 후순위로) + 권장 JSON 설정(think:false 추가)
|
||||
- `docs/phases/phase-14-meeting-mode.md` — 컨텍스트 윈도우 표 갱신
|
||||
|
||||
**리서치 경로**: Ollama 라이브러리 확인 → gemma4는 E2B(2.3B), E4B(4.5B), 26B MoE, 31B Dense 4종 + 31b-cloud. Thinking은 `<|think|>` 토큰을 system prompt에 넣어야 켜지는 opt-in 방식. 기본 추천 E4B. 사용자는 이미 Ollama 0.20.5 사용 중(gemma4 요구 0.20+).
|
||||
|
||||
### 변경 파일 (대규모) — 40+ 파일
|
||||
|
||||
| 영역 | 파일 수 | 성격 |
|
||||
|---|---|---|
|
||||
| 코드 (메인) | 1 | LocalLLMService.ts |
|
||||
| UI 컴포넌트 | 3 | OnboardingModal, OllamaGuideModal, VoiceConversationPage |
|
||||
| 서비스 (버그 수정) | 1 | VoiceModeService |
|
||||
| 테스트 | 1 | VoiceModeService.test |
|
||||
| i18n (desktop) | 12 | ko/en/ja/zh/zh-TW/es/fr/de/pt/ru/vi/th |
|
||||
| i18n (site) | 10 | ko/en/ja/zh/es/fr/de/pt/ru/vi |
|
||||
| 마케팅 컴포넌트 | 1 | HowItWorks.tsx |
|
||||
| 설계 문서 | 3 | 00-master, 05-external-engine, phase-14 |
|
||||
|
||||
### 검증 게이트
|
||||
|
||||
| 게이트 | 결과 |
|
||||
|---|---|
|
||||
| desktop `tsc --noEmit` | ✅ EXIT 0 |
|
||||
| Bug 13 Dictation minBytes 가드 | ✅ 로그 확인 (전에 빈 history entry 생성되던 경로 차단) |
|
||||
| Bug 13 Conversation 배너 UI | ✅ Snackbar severity=warning filled 노출 |
|
||||
| Recording tip hide 타이머 leak | ✅ 4.5초 hold 성공, 전사 정상 |
|
||||
| 기본 모델 gemma4:e4b 전환 | ⏳ **사용자 수동 pull + 실측 대기** |
|
||||
|
||||
### 다음 세션 액션
|
||||
|
||||
1. 사용자 `ollama pull gemma4:e4b` (~4.5GB)
|
||||
2. 받아쓰기 한 사이클 실측 → refine 지연 측정 → **43초 → 몇 초 기대**
|
||||
3. 결과 컨펌되면 커밋 정리 + 빅뱅 8/8 마지막 1개(`Phase 3.2 PREMIUM_LLM`)로 전환
|
||||
4. Phase 3.2 선행 조건: 사용자가 `supabase secrets set ANTHROPIC_API_KEY=... OPENAI_API_KEY=...`
|
||||
|
||||
## 빅뱅 Phase 5 Part 6++ (2026-04-11) — U1/U3/U4 남은 이슈 정리 ✅
|
||||
|
||||
### U1 — Realtime TIMED_OUT 자동 재구독 (CloudSyncService.ts)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue