초기 프로젝트 설정: 하네스 시스템 + 설계서 + RE 노하우

- CLAUDE.md: 프로젝트 규칙, 기술 스택, 코딩 규칙, 페이즈 로드맵
- .claude/settings.json: 권한, 강제 훅 (매 프롬프트 설계서 규칙 주입)
- .claude/skills/: implement-phase, review-phase, scaffold, test-commit, debug
- .claude/agents/: electron-architect, voice-pipeline-expert, ui-specialist
- docs/design/00-09: 마스터 아키텍처, 서비스 명세(16개), IPC(113채널),
  DB스키마, UI컴포넌트, 검증리포트, 외부엔진연동, 갭분석,
  VoiceMode패턴, 디자인시스템, 히스토리팝업
- docs/phases/1-7+3.5: 전체 구현 페이즈 문서
- docs/re-findings/: Speakly RE 노하우 5개 문서
This commit is contained in:
Yun Chan 2026-04-05 01:03:03 +09:00
commit e24bb8378c
35 changed files with 11452 additions and 0 deletions

115
docs/phases/phase-4.md Normal file
View file

@ -0,0 +1,115 @@
# Phase 4: Ollama LLM 연동 (텍스트 다듬기, 번역)
## 목표
Ollama REST API를 통해 로컬 LLM과 연동하여, 전사된 텍스트를 다듬기(polishing)하거나 번역(translate)할 수 있는 상태. 스트리밍 응답을 UI에 실시간 표시하고, 커스텀 명령어의 기본 구조를 갖춘다.
## 태스크
### 4.1 LocalLLMService 구현
- `src/main/services/LocalLLMService.ts`
- Ollama REST API 연동 (`/api/generate`, `/api/chat`, `/api/tags`)
- 싱글톤 + EventEmitter 패턴
- 상태 머신: `Unavailable → Available → Generating → Available` (서비스 명세 LLMState 참조)
- Ollama 가용성 폴링 (5초 간격, `OLLAMA_CONFIG.pollIntervalMs`)
- `availability-changed` 이벤트로 UI에 상태 전파
- ConfigService에서 `llm.serverUrl`, `llm.defaultModel` 읽기
### 4.2 비스트리밍 생성 (`generate`)
- `POST /api/generate` 호출 (stream: false)
- GenerateOptions 지원: model, temperature, maxTokens, topP, topK, systemPrompt
- GenerateResult 반환: text, model, promptTokens, completionTokens, totalDuration
- 타임아웃 처리 (AbortController, 기본 120초)
### 4.3 스트리밍 생성 (`stream`)
- `POST /api/generate` (stream: true) → NDJSON 파싱
- fetch + ReadableStream으로 청크 처리
- `token` 이벤트를 통해 점진적 토큰 전달
- AbortController로 중간 취소 지원
- 버퍼 관리: 불완전한 JSON 라인 처리
### 4.4 텍스트 다듬기 모드 (Polishing)
- PostProcessCommand `{ type: 'polish', style?: 'formal' | 'casual' }` 처리
- 시스템 프롬프트 설계:
```
[formal] 다음 음성 전사 텍스트를 자연스럽고 격식 있는 문어체로 다듬어주세요.
원래 의미를 유지하면서 문법 오류를 수정하고, 불필요한 반복이나 필러를 제거하세요.
다듬어진 텍스트만 출력하세요. 설명이나 부가 문구를 붙이지 마세요.
[casual] 다음 음성 전사 텍스트를 자연스러운 구어체로 다듬어주세요.
원래 의미와 톤을 유지하면서 문법 오류만 수정하세요.
다듬어진 텍스트만 출력하세요.
```
- VoiceModeService의 Processing 상태에서 호출
### 4.5 번역 모드 (Translate)
- PostProcessCommand `{ type: 'translate', targetLanguage: string }` 처리
- 시스템 프롬프트 설계:
```
다음 텍스트를 {targetLanguage}로 번역해주세요.
자연스럽고 정확한 번역만 출력하세요. 원문이나 설명을 붙이지 마세요.
```
- 감지 언어 → 대상 언어 자동 전환 (한국어 감지 시 영어로, 영어 감지 시 한국어로)
- ConfigService에서 기본 대상 언어 설정 지원
### 4.6 커스텀 명령어 기본 구조
- PostProcessCommand `{ type: 'custom', prompt: string }` 처리
- 사용자가 직접 시스템 프롬프트를 지정하여 LLM에 전달
- CustomInstruction 인터페이스 초기 정의:
```typescript
interface CustomInstruction {
id: string;
name: string;
prompt: string;
isBuiltin: boolean;
createdAt: number;
}
```
- Phase 6에서 완전 구현 (CRUD, 프리셋, 핫키 바인딩)
### 4.7 스트리밍 응답 UI 표시
- RecordingTipWindow에 `processing` 상태 추가
- Thinking 프로그레스 바 (점근 수렴 패턴: `min(95, (1 - 1/(1+1.5*t)) * 100)%`)
- 스트리밍 토큰이 도착하면 텍스트 실시간 표시
- ResultPopupWindow에 스트리밍 텍스트 영역 추가
- 토큰 도착 시 점진적 텍스트 추가
- 완료 시 복사 버튼 활성화
- IPC 채널:
- `llm:streamToken` (main→renderer, 스트리밍 토큰)
- `llm:streamComplete` (main→renderer, 생성 완료)
- `llm:streamError` (main→renderer, 에러)
### 4.8 VoiceModeService LLM 통합
- RecognitionState.Processing 상태에서 LLM 호출
- 전사 완료 → postProcessCommand에 따라 분기:
- `none`: 바로 텍스트 삽입
- `polish` / `translate` / `custom`: LLM 스트리밍 호출 → 완료 후 텍스트 삽입
- `processing-update` 이벤트를 통해 UI에 진행 상황 전달
- LLM 미가용 시 postProcess를 `none`으로 폴백 + 사용자 알림
### 4.9 에러 처리
- Ollama 서버 미실행: `LLM_CONNECTION_FAILED` 에러, UI에 "Ollama가 실행 중이 아닙니다" 표시
- 모델 미설치: `LLM_MODEL_NOT_FOUND` 에러, UI에 모델 설치 안내 표시
- 생성 실패/타임아웃: `LLM_GENERATION_FAILED`, 원본 텍스트로 폴백 옵션 제공
- 네트워크 에러: 재시도 없이 즉시 에러 표시 (로컬이므로 재시도 불필요)
### 4.10 IPC 채널 추가
- `llm:getStatus` — LLM 가용 상태 조회
- `llm:getModels` — 설치된 Ollama 모델 목록
- `llm:generate` — 비스트리밍 텍스트 생성
- `llm:stream` — 스트리밍 텍스트 생성 시작
- `llm:cancelStream` — 스트리밍 취소
- `llm:checkConnection` — Ollama 연결 테스트
## Speakly RE 참조
- GensparkService: 클라우드 LLM 호출 패턴 (D3RO는 로컬 Ollama로 대체)
- CustomInstructionService: 명령어 구조, 프롬프트 템플릿
- VoiceModeService: Processing 상태 전이, 후처리 파이프라인
- RecordingTip: thinking 상태 프로그레스 바, 점근 수렴 패턴
## 완료 조건
- [ ] Ollama 가용성 자동 감지 및 UI 표시
- [ ] 전사된 텍스트를 다듬기(polish) 모드로 LLM 처리 가능
- [ ] 전사된 텍스트를 번역(translate) 모드로 LLM 처리 가능
- [ ] 커스텀 프롬프트로 자유 LLM 처리 가능
- [ ] 스트리밍 토큰이 UI에 실시간 표시됨
- [ ] Ollama 미실행/모델 미설치 시 적절한 에러 메시지 표시
- [ ] LLM 미가용 시 원본 텍스트 삽입으로 폴백