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:
윤찬 2026-04-12 09:47:08 +09:00
parent a744551442
commit d397bcbf57
32 changed files with 153 additions and 65 deletions

View file

@ -862,7 +862,7 @@ export interface TTSConfig {
export interface LLMConfig {
serverUrl: string; // 기본: 'http://localhost:11434'
model: string; // 기본: 'qwen3:4b' (권장)
model: string; // 기본: 'gemma4:e4b' (non-reasoning, 권장)
temperature: number; // 0.0~2.0, 기본: 0.3
maxTokens: number; // 기본: 2048
timeout: number; // ms, 기본: 30000
@ -905,7 +905,7 @@ const CONFIG_DEFAULTS: AppConfig = {
},
llm: {
serverUrl: 'http://localhost:11434',
model: 'qwen3:4b',
model: 'gemma4:e4b',
temperature: 0.3,
maxTokens: 2048,
timeout: 30000,

View file

@ -347,7 +347,7 @@ faster-whisper 자체는 진정한 스트리밍을 지원하지 않는다. `tran
```typescript
// 요청
interface OllamaGenerateRequest {
model: string; // 필수: "qwen3:4b"
model: string; // 필수: "gemma4:e4b"
prompt: string; // 필수
suffix?: string; // FIM (Fill-in-Middle) 지원 모델용
system?: string; // 시스템 프롬프트
@ -419,7 +419,7 @@ interface OllamaChatStreamChunk {
// GET http://localhost:11434/api/tags
interface OllamaTagsResponse {
models: Array<{
name: string; // "qwen3:4b"
name: string; // "gemma4:e4b"
model: string;
modified_at: string; // ISO 8601
size: number; // 바이트
@ -427,8 +427,8 @@ interface OllamaTagsResponse {
details: {
parent_model: string;
format: string; // "gguf"
family: string; // "qwen3"
parameter_size: string; // "4B"
family: string; // "gemma4"
parameter_size: string; // "4.5B"
quantization_level: string; // "Q4_K_M"
};
}>;
@ -440,7 +440,7 @@ interface OllamaTagsResponse {
```typescript
// 요청
interface OllamaPullRequest {
name: string; // "qwen3:4b"
name: string; // "gemma4:e4b"
stream?: boolean; // 기본 true
}
@ -457,7 +457,7 @@ interface OllamaPullStreamChunk {
```typescript
// POST http://localhost:11434/api/show
// 요청: { "name": "qwen3:4b" }
// 요청: { "name": "gemma4:e4b" }
interface OllamaShowResponse {
modelfile: string;
parameters: string;
@ -477,7 +477,7 @@ interface OllamaShowResponse {
```typescript
// DELETE http://localhost:11434/api/delete
// 요청: { "name": "qwen3:4b" }
// 요청: { "name": "gemma4:e4b" }
// 응답: 200 OK (성공) | 404 Not Found
```
@ -516,7 +516,7 @@ class OllamaClient {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: options.model ?? 'qwen3:4b',
model: options.model ?? 'gemma4:e4b',
prompt,
system: options.systemPrompt,
stream: false,
@ -555,7 +555,7 @@ class OllamaClient {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: options.model ?? 'qwen3:4b',
model: options.model ?? 'gemma4:e4b',
prompt,
system: options.systemPrompt,
stream: true,
@ -1053,25 +1053,26 @@ User HotkeyService VoiceModeService AudioCapture WhisperS
| 모델 | 크기 | 한국어 | RAM | 추천 용도 |
|------|------|--------|-----|----------|
| **`qwen3:4b`** | 2.7GB | ◎◎ 우수 | 4GB+ | **기본 추천. 한중일 강점** |
| `qwen3.5:4b` | ~3GB | ◎◎ 최상 | 4GB+ | 최신 모델, 한국어 특히 강화 |
| `gemma3:4b` | 3.3GB | ◎ 양호 | 4GB+ | Google 다국어, 140개 언어 |
| `llama3.2:3b` | 2.0GB | △ 보통 | 3GB+ | 영어 위주, 한국어 약함 |
| `phi-4-mini` | 2.5GB | △ 보통 | 3GB+ | 추론 강점, 한국어 제한적 |
| **`gemma4:e4b`** | 3.3GB | ◎◎ 우수 | 4GB+ | **기본 추천. non-reasoning, 140개 언어, Ollama think:false 지원** |
| `gemma4:e2b` | 1.8GB | ◎ 양호 | 2GB+ | 더 빠른 응답. 정제 품질은 한 끗 낮음 |
| `llama3.2:3b` | 2.0GB | ◎ 양호 | 3GB+ | 가장 빠름, Meta 소형 플래그십 |
| `phi4-mini:3.8b` | 2.5GB | △ 보통 | 3GB+ | 추론/수학 강점, 한국어 제한적 |
| `qwen3:4b` | 2.7GB | ◎◎ 우수 | 4GB+ | ⚠ reasoning 모델. strip empty 버그 유의 (think:false 필수) |
**판정:** Qwen3/3.5 계열이 한국어에서 압도적. Alibaba의 다국어 학습 데이터에 한중일이 충분히 포함됨.
**판정:** Gemma 4는 Google의 최신 non-reasoning 플래그십 소형 모델(2026-04). 한국어 포함 140개 언어 강력하고, reasoning 토큰을 기본으로 생성하지 않아 정제 파이프라인이 단순하다. Qwen3 계열은 한국어 품질은 좋지만 reasoning 모델이라 thinking block strip 후 빈 응답 fallback 이슈가 있음 — 수동 선택 시 Ollama v0.20+의 `think: false` 파라미터 필수.
**텍스트 후처리에 권장 설정:**
```json
{
"model": "qwen3:4b",
"model": "gemma4:e4b",
"think": false,
"temperature": 0.3,
"num_predict": 512,
"top_p": 0.9,
"stop": ["\n\n"]
}
```
낮은 temperature(0.3)로 원문 의미 보존, 짧은 출력으로 빠른 응답.
낮은 temperature(0.3)로 원문 의미 보존, 짧은 출력으로 빠른 응답. `think: false`는 gemma4/llama3.2는 무시하고, 사용자가 qwen3/deepseek-r1 등으로 교체했을 때 reasoning 토큰 차단.
### 6.3 TTS 음성 추천