d3ro-voice/docs/phases/phase-4.md
Yun Chan e24bb8378c 초기 프로젝트 설정: 하네스 시스템 + 설계서 + 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개 문서
2026-04-05 01:03:03 +09:00

5.6 KiB

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 인터페이스 초기 정의:
    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 미가용 시 원본 텍스트 삽입으로 폴백