Files
life-helper/docs/adr/0003-on-device-llm-gemma.md
joungmin d31b17f3e8 [Architect] #215 ADR-0003 + design spec for Gemma frame suggest
- 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
2026-06-12 11:16:15 +09:00

6.5 KiB
Raw Blame History

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) 위에 사용자 입력 자동화 기능을 얹는다. 입력 마찰점은

  1. L0/L1 raw text → L2/L3 프레임 재작성, 2) 자유서술 → 구조화 변환이다. 기존 FramePattern 30개 정적 카탈로그는 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 13초 (모델 로드 cold start). 이후 0.52초/응답.
    • Pixel 5 이하·RAM 4GB 이하 기기는 로드 실패 가능 → 사전 사양 체크 필요.
    • 배터리 0.51% / 추론 추정. 빈도 제한(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 도움" 섹션 추가 (오프라인·프라이버시 강조).

검토한 대안 (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 최적화에 직접 투자.
  • 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의 FramePattern 30 시드 + validate_frame_level 함수.
  • 후속 결정 가능성: ADR-0004 (E4B 토글), ADR-0005 (시나리오 #2~#6 함수 확장).