Add NextGen library: index DB, thumbnails, AI culling, and CLIP search

Builds the "indexed library" foundation and first intelligent features on
top of the organizer (sql.js index, non-destructive in-place indexing).

Phase 0 — Library index:
- sql.js (WASM SQLite) index DB; contentHash-keyed assets, resumable indexing
  (skip by path+mtime), batch persistence (chosen over native better-sqlite3
  which fails to build on Node 24 / Python 3.12)
- Library folders (in place, non-destructive) + background indexer w/ progress
- Thumbnails generated in the AI worker (canvas->webp), cached in userData;
  served via photoai-media://thumb by hash; thumbnail grid w/ pagination

Phase 1 — AI quality assessment & culling:
- Focus (Laplacian variance), exposure (histogram), eyes-open (face-api EAR)
  computed in one analyze pass alongside the thumbnail
- Culling filters (candidate/rejected) + quality badges
- Adjustable thresholds (live SQL re-classification from stored raw scores,
  no re-analysis) + manual star rating (0-5) and color labels (usermeta)

Phase 2 — CLIP natural-language / similarity search:
- @huggingface/transformers (WASM/WebGPU, no native build)
- CLIP image/text embeddings (lazy-loaded); Korean queries auto-translated
  via opus-mt-ko-en into the English CLIP
- Embeddings stored as SQLite BLOBs; "build search index" batch w/ progress;
  brute-force cosine search; new Search tab
- Note: models download from HF Hub on first use; fully-offline ORT-wasm
  packaging and KO search-accuracy tuning are follow-ups

Tabs added (Organize / Library / Search). All typecheck/tests(12)/build green;
boot smoke verified across phases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 17:32:51 +09:00
parent 6dce580846
commit 72c41ae834
33 changed files with 3136 additions and 358 deletions
+25 -9
View File
@@ -124,8 +124,10 @@ Culling: Index의 품질 점수로 필터 → 후보군/제외 뷰
## 8. Phase 0 + Phase 1 상세 실행 계획 (확정 범위)
### 8.1 기술 추가 (이 단계 한정)
- **better-sqlite3** (네이티브) — 인덱스 DB. electron-builder의 `@electron/rebuild`로 ABI 재빌드(현재 빌드 파이프라인이 이미 수행).
- **썸네일은 네이티브(sharp) 없이** AI Worker(렌더러)의 canvas로 생성 → 바이트를 Main이 캐시. 네이티브 의존 최소화.
- ~~better-sqlite3(네이티브)~~ → **`sql.js`(WASM SQLite)로 확정**. 이유: 이 환경(Node 24 + Python 3.12)에서 네이티브 컴파일이 실패(distutils 제거)했고, 네이티브 모듈은 사용자 PC마다 ABI/빌드툴 문제가 재발한다. WASM은 빌드/재빌드가 전혀 없어 Windows+macOS 배포가 단순. 인메모리 DB를 `userData/index.db`로 export 영속화. (수천~수만 장 메타데이터 규모에 충분. 추후 필요 시 indexDb 추상화 뒤에서 네이티브로 교체 가능.)
- **썸네일은 네이티브(sharp) 없이** AI Worker(렌더러)의 canvas로 생성 → 바이트를 Main이 캐시. 네이티브 의존 0.
> ✅ **Phase 0-a 완료(2026-06-01)**: `indexDb`(sql.js) + asset/quality 스키마 + 영속화. Electron 부팅 시 `userData/index.db` 생성 확인. typecheck/build/스모크 통과.
- Phase 1 품질 점수는 **모델 거의 불필요**: 초점=라플라시안 분산, 노출=휘도 히스토그램, 감은 눈=face-api 랜드마크(EAR). face-api는 이미 추론창에 로드됨.
### 8.2 데이터 모델 (SQLite)
@@ -163,13 +165,27 @@ UI (신규 화면)
- 기존 정리기와 통합: 정리 잡도 인덱스(EXIF/얼굴)를 재사용하도록 점진 연결.
### 8.4 작업 순서 (체크리스트)
- [ ] Phase 0-a: better-sqlite3 도입 + `indexDb` 스키마/마이그레이션 + 빌드(ABI 재빌드) 검증
- [ ] Phase 0-b: contentHash 해셔 + 라이브러리 폴더 지정 UI + `indexer` 워크/재개 + 진행률 IPC
- [ ] Phase 0-c: AI Worker에 썸네일 생성 + 캐시 + 그리드 표시(빈 품질로 우선)
- [ ] Phase 1-a: `qualityEngine` 초점/노출 점수 → DB 저장
- [ ] Phase 1-b: 감은 눈(EAR, face-api 랜드마크) 점수 → flag 산출
- [ ] Phase 1-c: CullingView(후보/제외 그리드, 점수, 임계값 설정, 오버라이드)
- [ ] Phase 1-d: (옵션) 제외 사진 내보내기/이동 액션
- [x] **Phase 0-a 완료**: `indexDb`(sql.js로 확정) 스키마/마이그레이션 + Electron 부팅 시 DB 생성 검증
- [x] **Phase 0-b 완료**: contentHash(샘플 sha1) + 라이브러리 폴더 지정 UI(라이브러리 탭) + `indexer` 워크/재개(경로·mtime 스킵)/진행률 IPC/배치 영속화/취소. 헤드리스 파이프라인 검증(중복 0) + 부팅 스모크 통과
- [x] **Phase 0-c 완료**: AI Worker(추론창) canvas로 썸네일(webp) 생성 → `userData/thumbs/<hash>.webp` 캐시(비파괴), 색인 시 자동 생성 + 원본 치수 저장, `photoai-media://thumb` 해시 기반 보안 제공, 라이브러리 탭 썸네일 그리드(페이지네이션). typecheck/build/부팅 스모크 통과
- [x] **Phase 1-a 완료**: `qualityEngine` 초점(라플라시안 분산)/노출(히스토그램 클리핑) 점수 → DB
- [x] **Phase 1-b 완료**: 감은 눈(EAR, face-api 랜드마크, Tiny 검출기) 점수 → `classifyFlag`로 종합 분류(candidate/blurry/eyesClosed/badExposure). 색인 시 `infer:analyze`로 썸네일+품질 1회 로드 통합
- [x] **Phase 1-c (기본) 완료**: 라이브러리 그리드에 컬링 필터(전체/고품질 후보/제외) + 품질 배지. *임계값 튜닝 UI · 사진별 수동 오버라이드는 후속으로 보류*
- [ ] Phase 1-d(옵션): 제외 사진 내보내기/이동 액션 (보류)
### 8.6 Phase 1 마무리 (임계값 튜닝 + 수동 오버라이드) — 완료(2026-06-01)
- [x] 품질 임계값(초점/노출/눈)을 설정에 저장 + 슬라이더 UI. 임계값 변경 시 **저장된 원본 점수로 SQL CASE 실시간 재분류**(재분석 없음)
- [x] 별점(0~5) + 색라벨(5색) 수동 메타(`usermeta` 테이블), 썸네일 호버 편집, 별점 최소 필터
### 8.7 Phase 2 (CLIP 자연어/유사 검색) — 기본 완료(2026-06-01)
- [x] `@huggingface/transformers`(WASM/WebGPU, 네이티브 빌드 0) 도입
- [x] CLIP(`Xenova/clip-vit-base-patch32`) 이미지/텍스트 임베딩 — 추론창 lazy-load
- [x] 한국어 쿼리 자동 번역(`Xenova/opus-mt-ko-en`) → 영어 CLIP
- [x] 임베딩 SQLite BLOB 저장 + "검색 색인 생성"(임베딩 배치, 진행률/취소) — 기본 색인과 분리
- [x] 브루트포스 코사인 검색 + **검색 탭**(임베딩 상태/생성 + 검색바 + 결과 그리드)
- [x] typecheck/build/부팅 스모크 통과
> ⚠️ **Phase 2 런타임 미검증 항목**: CLIP/번역 모델은 **최초 사용 시 HF Hub에서 다운로드**(온라인 1회 필요, 이후 캐시). ONNX Runtime WASM의 **완전 오프라인 패키징**(CDN 대신 동봉)과 **한국어 검색 정확도 실측**은 후속 과제. 임베딩 생성은 이미지당 수백 ms(WASM) → 대량은 시간 소요(백그라운드).
- [ ] i18n(ko/en) · 다크모드 · 검증(typecheck/test/build/스모크)
### 8.5 리스크 (이 단계)