STT·LLM 외부 엔진을 Factory와 추상 베이스 클래스 뒤로 숨겨, 비즈니스 로직 수정 없이 .env 설정만으로 교체 가능하게 한 설계. STT 3종(Faster-Whisper / WhisperLive / Google STT), LLM 3종(Ollama / LM Studio / Gemini)을 동일 인터페이스로 갈아끼운다.
STT 3종
LLM 3종
Factory + ABC
설정 교체
로컬/클라우드
공통 4메서드
공통 추상 3메서드
인터페이스 통일
엔진 · 제공자 설정 2개
비용·보안 선택
왜 이 설계가 필요했는가 (Problem)
구조
핵심 설계 결정
1. STT Factory — 설정값으로 엔진 주입
# STT Factory — 설정값에 따라 엔진 모듈 주입기본 엔진 불러오기(): if 엔진 설정 == "faster-whisper": 엔진 = Faster-Whisper 구현 elif 엔진 설정 == "whisperlivekit": 엔진 = WhisperLive 구현 else: 오류("지원하지 않는 STT 엔진")세그먼트 전사(오디오 바이트, 초기 프롬프트): return 엔진.세그먼트 전사(오디오 바이트, 초기 프롬프트) # 호출부는 엔진 종류를 모른다
2. LLM 추상 베이스 클래스 (ABC)
# LLM 추상 베이스 — 모든 구현체가 상속하는 계약class LLM 서비스(ABC): @abstractmethod 연결 확인() -> bool @abstractmethod 요약(대화록) -> dict @abstractmethod 도메인 요약(대화록) -> dict
3. 설정 기반 교체 + 성능 튜닝
# 설정값 — 엔진 · 모델 · 디바이스 · 정밀도STT 엔진 = "faster-whisper" # | "whisperlivekit"모델 크기 = "base" # tiny ~ large-v3디바이스 = "cuda" # auto | cpu | cuda | mps연산 정밀도 = "float16" # int8 | float16 | float32LLM 제공자 = "ollama" # | "lmstudio" | "gemini"
엔진 비교
STT 엔진
배포
특징
Faster-Whisper (기본)
로컬 GPU/CPU
RMS 무음 필터 + 환각 필터 내장, 초기 프롬프트로 문맥 유지
WhisperLive
로컬
연결마다 독립 인스턴스, diarization 옵션
Google STT
클라우드
파일 크기·길이로 동기/비동기 API 자동 선택
LLM 엔진
배포
특징
Ollama (기본)
로컬
JSON 출력 형식 강제 + 3회 재시도(온도 단계 상향)
LM Studio
로컬
OpenAI 호환, 마크다운 제거 후 정규식 JSON 추출
Gemini
클라우드
공식 SDK, 타입 안전 설정
구현 범위와 한계
만든 것
항목
상태
STT 3종 공통 인터페이스 (Faster-Whisper / WhisperLive / Google STT)
동작
LLM 3종 추상 베이스 (Ollama / LM Studio / Gemini)
동작
.env 설정 두 개(STT 엔진 · LLM 제공자)만으로 엔진 교체
동작
작업 메타데이터의 모드 값으로 건별 동적 선택
동작
만들지 않은 것
미구현
이유
자동 폴백 (엔진 장애 시 대체 엔진으로 격하)
어느 엔진으로 처리됐는지가 결과 품질과 데이터 소재지를 바꿔버린다. 민감한 음성 데이터가 자동으로 클라우드로 넘어가면 보안 전제가 깨진다 — 의도적으로 보류했다
엔진별 품질·비용 비교 지표
✅2026-08-30 배포 환경에서 측정함 (아래 「설정 매트릭스 실측」). 단, 로컬 모델 간 비교에 한정되며 클라우드(Google STT·Gemini) 은 호출하지 않았다 — 따라서 “클라우드가 고품질” 은 여전히 통념이지 측정치가 아니다
자동 검증(테스트)
아래 사유
설정 매트릭스 실측 (2026-08-30 · 배포 환경)
설정
RTF
추론(s)
유사도
1. small · int8 · beam1 (현재 설정)
0.150
4.5
0.892
2. small · int8 · beam5
0.188
5.6
0.877
3. small · int8_float32 · beam5
0.186
5.6
0.877
4. medium · int8 · beam5
0.532
15.9
1.000
5. medium · int8_float32 · beam5 (기준)
0.535
16.1
1.000
6~8. turbo 계열
0.143~0.145
4.3~4.4
🔴 0.126
발견
의미
beam 5 가 오히려 정확도를 낮춘다 (0.892 → 0.877)
🔴 이 해석은 철회한다. 측정값은 맞지만 결론을 지탱하지 못한다 — CPU 배포 설정의 워커 주석에 「그리디(1)는 “가정”→“과정” 류 오인식 발생」 이라는 실사용 관찰이 이미 기록돼 있고 배치 경로는 beam 5 를 쓴다. 내 지표는 특정 단어 오인식을 잡지 못한다(표본 1개 · 실제 도메인이 아닌 오디오 · medium 을 정답으로 가정한 상대 유사도). 실사용 관찰을 뒤집을 강도가 아니다.
int8 ↔ int8_float32 차이 없음 (유사도 동일 · RTF 0.188 vs 0.186)
정밀도를 올릴 이유가 없다. 다만 새 발견이 아니라 재확인이다 — 배포 설정 주석에 「int8_float32 는 출력이 문자단위로 동일하고 속도도 같아 무의미」 라고 같은 결론이 이미 적혀 있었다. CPU 경로에서는 int8 로 고정해도 무방하다
🔴 turbo 는 8자만 출력하고 사실상 실패
가장 빠르지만(0.143) 쓸 수 없다. 6·7·8 이 동일하므로 설정이 아니라 모델·호환성 문제로 보인다 — 원인 미규명
medium 도 실시간 가능 (RTF 0.532 < 1.0)
small 을 쓰는 게 속도 때문에 어쩔 수 없어서가 아니다. 동시 세션 수를 고려한 선택으로 설명해야 정확하다