From 1b90f58585351af30c5e883f02a5de0f76677f87 Mon Sep 17 00:00:00 2001 From: joungmin Date: Fri, 12 Jun 2026 16:09:09 +0900 Subject: [PATCH] =?UTF-8?q?[06-Reviewer]=20#218=20sticky=20cache=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20+=20reference=20doc=20nit=203=EA=B1=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코드 결함 1건 + 문서 정확성 nit 3건. 사용자 동작에 영향 있는 건 (1) 번만, 나머지는 문서 정정. (1) _LazyLlmService._delegate sticky cache 수정 (main.dart) - 기존: 첫 호출 시점에 잡힌 delegate (Mock vs Gemma) 가 앱 재시작까지 유지 — 옵트인 OFF 상태에서 첫 suggestFrame 호출 → Mock 잡힘 → 사용자 옵트인 ON + 다운로드 완료 후에도 같은 Mock 만 반환 (사용자는 AI 가 켜진 줄 알고 mock 응답 받음). - 수정: 매 _resolve() 호출마다 checkAvailability 재평가. 캐시는 (Gemma↔Mock 종류) + (Gemma 의 modelPath) 모두 일치할 때만 재사용 → state 변화 시 자동 교체. flutter_gemma installModel 자체가 idempotent 라 반복 resolve 비용 무시 가능. (2) reference doc nit 3건 — 04-QA round 2 가 08-Documenter 로 인계한 nit 를 Reviewer 가 직접 정정: - L184: "device_info_plus 로 systemFeatures / totalMem 조회" → 실 구현은 MethodChannel `life_helper/device_caps`. device_info_plus 는 deps 에 있지만 4GB 임계 측정엔 미사용 (isLowRamDevice 는 ~1GB). - L186: F1 후속 이슈 번호 "#222 등" → "#219 별도 이슈". - L191: follow-up 매핑 — 임의 "#219 ProGuard rules 정제" 항목 제거. Planner OOS 기준 #219=F1 unload, #220=F2 purge, #221=AC10 corpus, #222=production keystore 로 정정. 검증: flutter analyze 무이슈, flutter test 88/88 통과. Refs #218 --- app/lib/main.dart | 18 +++++++++++++----- docs/reference/215-ai-frame-suggest.md | 6 +++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/app/lib/main.dart b/app/lib/main.dart index ac2c052..e3c38c2 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -40,13 +40,21 @@ class _LazyLlmService implements LlmService { LlmService? _delegate; Future _resolve() async { - if (_delegate != null) return _delegate!; final avail = await lifecycle.checkAvailability(); final path = await meta.find(AiMetaKeys.modelPath); - if (avail == ModelAvailability.ready && path != null) { - _delegate = GemmaLlmService(modelPath: path); - } else { - _delegate = MockLlmService(); + final wantGemma = avail == ModelAvailability.ready && path != null; + // Re-resolve every call so opt-in / opt-out state changes are reflected + // without an app restart. Repeat-resolve of the same kind reuses the + // cached instance (Gemma's flutter_gemma installModel is idempotent; + // Mock has no setup), but the kind itself flips when availability does. + final keep = _delegate != null && + (wantGemma == (_delegate is GemmaLlmService)) && + (!wantGemma || + (_delegate as GemmaLlmService).modelPath == path); + if (!keep) { + _delegate = wantGemma + ? GemmaLlmService(modelPath: path) + : MockLlmService(); } return _delegate!; } diff --git a/docs/reference/215-ai-frame-suggest.md b/docs/reference/215-ai-frame-suggest.md index 97edfd7..3830f78 100644 --- a/docs/reference/215-ai-frame-suggest.md +++ b/docs/reference/215-ai-frame-suggest.md @@ -181,13 +181,13 @@ abstract class LlmService { ## 8. 알려진 제약 -- **#218 AC-6 (디바이스 게이트)**: 저사양 단말 (RAM < 4GB) 에서는 SettingsScreen 의 AI 토글 disabled + "이 단말의 RAM 이 부족합니다 (필요: 4GB+)" 안내. `device_info_plus` 로 `AndroidDeviceInfo.systemFeatures` / `totalMem` 조회. iOS 는 #218 범위 밖. +- **#218 AC-6 (디바이스 게이트)**: 저사양 단말 (RAM < 4GB) 에서는 SettingsScreen 의 AI 토글 disabled + "이 단말에서는 AI 도움을 사용할 수 없어요 (RAM 4GB 이상 필요)" 안내. RAM 조회 = MethodChannel `life_helper/device_caps` → `MainActivity.kt` 에서 `ActivityManager.MemoryInfo.totalMem`. `device_info_plus` 도 deps 에 있지만 RAM 임계 (4GB) 측정엔 미사용 (해당 패키지는 `isLowRamDevice` ≈ 1GB 만 제공). iOS 는 #218 범위 밖. - **#218 AC-7 (실 단말 E2E)**: cold-start ≤ 8s / opt-in→ready→suggestFrame 시나리오는 실 Android 8GB+ 단말 필요. Host CI 는 검증 불가 → 별도 디바이스 랩 단계. -- **F1**: 설계서 §8.8 / §9 의 "60초 idle 시 `unload()`" 미구현. 운영 모니터링 후 #222 등으로 후속 — 단발 호출 후 즉시 unload 가 안전한 기본값. +- **F1**: 설계서 §8.8 / §9 의 "60초 idle 시 `unload()`" 미구현. #219 별도 이슈 — 단발 호출 후 즉시 unload 가 안전한 기본값. - **#221 AC10 corpus 품질 평가**: 30+ 한국어 라이브 입력 corpus 로 L2 ≥ 70% / L3 ≥ 50% 측정. 실 모델 통합 후 별도 이슈. ## 9. 다음 단계 / 확장 포인트 -- **#219 ProGuard rules 정제** + **#220 lifecycle observer 기반 unload** + **#221 corpus 평가** + **#222 멀티 모델 슬롯 (E2B + E4B)**: #215 follow-up 5 이슈 중 #218 다음 작업들. +- **#215 follow-up 4 이슈** (#218 다음): **#219** 60s idle auto-unload (F1), **#220** purge hardening (F2), **#221** AC10 한국어 corpus 품질 평가 (≥70%), **#222** production keystore / Play Store 준비. - 시나리오 #2~#6 (앵커 추출 / dose variants / if-then / lapse 구조화 / 주간 요약): 모두 `LlmService.generateStructured` 에 새 schema 추가하는 형태로 확장. 도메인 함수는 `lib/domain/ai/` 에 신규 파일. - 멀티 모델 슬롯 (E2B + E4B): ADR-0004 후보.