- ADR-0003: on-device LLM Gemma 4 E2B Q4_0 + flutter_gemma 도입 결정. 5개 대안(클라우드/정적확장/Llama/E4B/APK번들) 기각 사유 명시. - docs/design/215-gemma-frame-suggest/: 설계서 게이트 통과 산출물. README.md (12 섹션 전부 + AC10 + OQ6 + 함수 15개) + fn-suggest_frame.md (suggestFrame/buildFewShotPrompt/parseFrameCandidates) + fn-model_lifecycle.md (LlmService/GemmaLlmService/ModelLifecycle). - graceful degradation 전면: AI 실패 시 throw 없이 빈 리스트 + 수동 입력 유지. - LlmService 추상화로 도메인 ↔ flutter_gemma 경계 분리 (테스트 가능성). Refs #215
6.5 KiB
ADR-0003: On-device LLM 도입 — Gemma 4 E2B Q4_0 + flutter_gemma
상태: Accepted 날짜: 2026-06-12 · 결정자: [AI] Architect (사용자 Planner 채택안 수용) · 관련 이슈: #215 관련 ADR: 없음 (신규 결정)
맥락 (Context)
life-helper Phase 1 MVP(#204) 위에 사용자 입력 자동화 기능을 얹는다. 입력 마찰점은
- L0/L1 raw text → L2/L3 프레임 재작성, 2) 자유서술 → 구조화 변환이다.
기존
FramePattern30개 정적 카탈로그는 keyword exact-match 기반이라 사용자 입력 다양성(synonym, 한국어 구어체, 도메인 변형)을 흡수하지 못한다.
선택지는:
- A. 클라우드 LLM API (OpenAI / Claude / Gemini) — 품질 ↑, 비용·프라이버시·오프라인 X.
- B. On-device LLM (Gemma 4 / Llama / Phi 등) — 프라이버시·오프라인 ↑, 품질·기기 부담.
- C. 도입 X, 정적 카탈로그 확장 — 안전하지만 동적 입력 흡수 한계.
Planner(#215)가 5개 의사결정으로 B 채택안 + Gemma 4 E2B + 런타임 다운로드 + opt-in 방향을 확정했다. 본 ADR은 그 선택을 되돌리기 어려운 기술 결정으로 고정한다.
결정 (Decision)
life-helper에 on-device LLM을 도입한다. 모델은 Gemma 4 E2B (Q4_0 양자화) 단일.
런타임 통합은 flutter_gemma 패키지(LiteRT-LM Android backend) 사용.
모델 파일은 opt-in 토글 후 런타임에 백그라운드 다운로드, opt-out 시 즉시 삭제.
모든 추론은 on-device 전용이며 어떠한 형태의 클라우드 fallback도 두지 않는다.
함수 호출(function calling) 기능을 사용해 LLM 응답을 구조화된 JSON으로 받는다.
프롬프트는 정적 하드코딩이 아닌 SoT 카탈로그(FramePattern / Protocol)에서
런타임에 few-shot 예시를 동적 추출해 조립한다.
근거 (Rationale)
- 프라이버시 = SoT 원칙과 일치: life-helper는 개인 습관·중독·실패 기록을 다룬다. 사용자 자유서술이 외부로 떠나면 안 된다. on-device 전용은 비타협 요구.
- 오프라인 동작: 사용자는 새벽·이동 중·산행 등 네트워크 약한 환경에서도 체크인한다. 클라우드 의존은 R8(≤ 60초 체크인) 보장 불가.
- Gemma 4 E2B Q4_0 ≈ 1.5GB RAM: 6GB RAM mid-range Android 까지 커버. E4B(5GB)는 high-end 한정. v1은 E2B 단일로 시작해 hardware fragmentation 단순화.
flutter_gemma의 function calling: LLM 응답을 자유 텍스트가 아닌 구조화 JSON으로 강제 → 파싱 신뢰도 ↑, 도메인 모델(FrameCandidate) 직결.- SoT few-shot 동적 추출: 정적 prompt 하드코딩은 SoT(
huberman-protocols.md/FramePattern카탈로그) 변경 시 동기화 부담 발생. 런타임 조립은 SoT 1회 갱신으로 전파. - 런타임 다운로드: APK +1.5GB는 첫 진입 장벽 과대. Play Store 제한(150MB)도 위반. WiFi 권장 + 일시정지/재개 + 진행률 UX로 흡수.
- Opt-in 기본 OFF: AI 기능을 "추가 비용(스토리지·배터리)을 감내한 사용자만"이 켠다는 명시적 동의로, R6 사용자 통제권 원칙과 일치.
결과 (Consequences)
-
긍정:
- 클라우드 비용·레이트리밋·약관 변경 리스크 0.
- 사용자 자유서술이 절대 단말 밖으로 나가지 않음 → 신뢰 자산.
- 오프라인 100% 동작.
flutter_gemma가 Android(LiteRT-LM) + iOS 둘 다 지원 → Phase 2 iOS 진입 시 재사용.- Function calling 응답이 구조화 → 도메인 모델 직접 매핑, 파싱 코드 최소.
- SoT 카탈로그 갱신이 LLM 출력 품질에 즉시 반영 (정적 prompt 동기화 부담 X).
-
부정 / 비용:
- 모델 파일 1.5GB 다운로드 — UX 부담. 일시정지/재개 + 진행률 + WiFi 권장 필수.
- 첫 추론 latency 1–3초 (모델 로드 cold start). 이후 0.5–2초/응답.
- Pixel 5 이하·RAM 4GB 이하 기기는 로드 실패 가능 → 사전 사양 체크 필요.
- 배터리 0.5–1% / 추론 추정. 빈도 제한(throttle) 정책 필요.
flutter_gemma패키지 semver 변경 위험 — v1은 latest version 고정 후 pubspec.lock 동결.- 한국어 품질 미검증 — Architect 단계 prototype 통과가 게이트 조건.
-
후속 작업:
- Architect: 설계서
docs/design/215-gemma-frame-suggest/작성 (본 ADR과 한 쌍). - Architect: 한국어 prompt 프로토타입 통과 확인 (Open Question).
- Developer:
flutter_gemma의존성 추가,LlmService인터페이스 +GemmaLlmService구현. - QA: 한국어 출력 품질 평가 corpus 30 케이스, 저사양 기기(RAM 4/6/8GB) 회귀.
- Documenter: 사용자 가이드에 "AI 도움" 섹션 추가 (오프라인·프라이버시 강조).
- Architect: 설계서
검토한 대안 (Alternatives Considered)
-
A. 클라우드 LLM API (OpenAI / Claude / Gemini)
- 기각 사유: (1) 사용자 자유서술 외부 전송 → SoT 프라이버시 원칙 위반. (2) 오프라인 미지원 → R8(≤ 60초 체크인) 보장 불가. (3) API 비용·레이트리밋·약관 변경 리스크. (4) Vendor lock-in.
-
C. 도입 X, 정적 카탈로그 확장 (FramePattern 30 → 100 → 300...)
- 기각 사유: (1) 동적 입력(synonym, 구어체) 흡수 한계는 카탈로그 크기로 해결 불가. (2) 한국어 변형 폭이 너무 넓어 enumeration 비현실적. (3) Architect/Developer 유지보수 부담이 LLM 도입보다 큼 (역설).
-
D. Llama 3.2 1B / Phi-3.5 Mini
- 기각 사유: (1) Gemma 4 E2B가 한국어 성능 더 좋다는 Google 자체 벤치 + 한국 커뮤니티 보고.
(2)
flutter_gemma가 first-class 지원 — Llama용 동급 Flutter 패키지 부재. (3) Google이 LiteRT-LM Android 최적화에 직접 투자.
- 기각 사유: (1) Gemma 4 E2B가 한국어 성능 더 좋다는 Google 자체 벤치 + 한국 커뮤니티 보고.
(2)
-
E. E4B (4B parameter)
- 기각 사유: 5GB RAM 요구 → high-end Pixel 8+ / Galaxy S24+ 한정. Phase 2-A는 mid-range까지 커버가 우선. E4B는 v1.1 이상에서 토글 옵션으로 추가.
-
F. APK 번들 모델
- 기각 사유: (1) Play Store APK 제한 150MB 위반. AAB로 회피 시도 가능하나 download size 절감 효과 미미. (2) AI 미사용자에게도 1.5GB 강제 → 옵트인 원칙 위반.
추적성
- 설계서:
docs/design/215-gemma-frame-suggest/README.md+fn-*.md. - 의존: #204 Phase 1 MVP의
FramePattern30 시드 +validate_frame_level함수. - 후속 결정 가능성: ADR-0004 (E4B 토글), ADR-0005 (시나리오 #2~#6 함수 확장).