ADR 0017 — v2 사무실 기억 검색 파이프라인 완성 (tenantEmbedding)
- 일자: 2026-04-23
- 상태: Accepted
- 연관: ADR 0015 (tenant-isolated AI learning + Phase 1b), ADR 0012 (RelatedMemoriesPanel S1 B)
배경
ADR 0015 로 도입한 Phase 1b S2 (scan 업로드 · 임베딩 생성 · guardedFindNearest · v2 core ranking) 가 S3 (자동 인용 + UI 노출) 까지 도달하지 못한 상태로 남아 있었다. 구체적 gap:
features.ai.tenantEmbedding플래그를 실제로 소비하는 Server Action 부재 — impl 은 있어도 라우팅 경로 없음.buildRelatedMemoryQuery결과로 얻은 랭킹을 UI 가 쓸 수 있는 카드 shape 로 조립하는 결선 작업 미완.- "자동 인용" (Phase 2) — ranked 메모리에서 법리 키워드 anchored 본문 발췌는 기획만 존재.
legacyDocuments.embedding.meta필드가 writer 단에서 비어 있어 v2 의 메타 보너스 랭킹이 항상 cosine 100% 로 작동.
결정
한 번의 집중 세션으로 v2 루프 전체를 닫고 플래그 ON 상태로 기본 출시 (2026-04-23 갱신: 파일럿 실측 전제 제거, mock/fixture 검증 정책 하에 기본 활성). 원칙:
- 뒤에서 앞으로 (bottom-up): pure 유틸 → impl → Server Action → UI.
- 단일 kill switch —
features.ai.tenantEmbeddingFirestore 플래그 하나. 기본 true. 비용·품질 사고 시 false 로 1-click 차단. 이전LEGACY_EMBEDDING_ENABLEDenv 2단 gate 는 파일럿 전제였고 제거됨. - v1 (Vertex AI Search) 은 유지 — dispatch action 이 플래그 OFF 또는 v2 skipped 시 v1 fallback.
- PII 무전파 — citations 도
redactedText기반이므로 1단 마스킹 후 텍스트만 본다.
결정 근거
- 전 사용자 무료 + 파일럿 실측 금지 (출시 우선 · 레이어 적층) 맥락에서, 코드를 전부 배포하되 플래그로 잠궈 두는 것이 가장 빠른 검증 가능성 + 최저 리스크 조합.
- fixture 기반 테스트가 unit + integration 양쪽을 커버하므로 파일럿 실측 없이도 알고리즘 정확성을 보장한다.
- auto-citation 은 순수 함수로 분리해 UI 변경 없이 rollout 가능 — 기존
redactedText위에 얹는 thin layer.
아키텍처 (완성본)
[UI] RelatedMemoriesPanel
│ dispatchRelatedMemoriesAction
▼
[Action] dispatch-related-memories-action (v2 우선 → v1 fallback)
│
├── flag ON → findRelatedMemoriesV2Action
│ │
│ └── findRelatedMemoriesV2Impl (DI)
│ ├── embedQueryForMemorySearch (Vertex AI text-embedding-004)
│ ├── guardedFindNearest (Firestore · COSINE)
│ ├── rankMemories (cosine × 0.7 + meta × 0.3)
│ ├── fetchDocMetas (getAll 조인)
│ └── extractAutoCitations (Phase 2)
│
└── flag OFF 또는 v2 skipped → findRelatedMemoriesForDocGenAction (Vertex AI Search)
[Cloud Fn] generateEmbeddingForLegacyDoc
├── embedText (Vertex AI REST)
├── meanPoolVectors (다중 chunk)
└── write { vector, meta: deriveEmbeddingMeta(sourceType, scannedMeta, caseData) }
주요 코드 포인트
apps/web/app/(workspace)/legacy/_lib/find-related-memories-v2-impl.ts— DI 순수 로직apps/web/app/(workspace)/legacy/_lib/auto-citation-extractor.ts— 키워드 anchored 본문 발췌apps/web/app/(workspace)/legacy/_lib/related-memories-dispatch-impl.ts— v2/v1 라우팅apps/web/app/(workspace)/legacy/_lib/embedding-meta-derivation.ts— meta 파생 (+ functions 미러)apps/web/lib/ai/embed-query.ts— Vertex AI 쿼리 임베딩 RESTapps/web/lib/firebase/find-nearest.ts—guardedFindNearest(tenant 경계 assert)functions/src/embedding-meta.ts— SSoT 미러functions/src/legacy-pipeline.ts— embedding 작성 시 meta 주입
알고리즘 세부
랭킹
finalScore = cosineScore × 0.7 + metaBonus × 0.3
cosineScore = 1 - distance / 2 (COSINE)
metaBonus 최대 1.0:
recoveryType 일치 +0.4
docType 일치 +0.3
isCommercial +0.15
principal bucket (소액/중액/고액) +0.15
자동 인용 키워드 맵 (일부)
debt:complaint: 민법 제479조 · 민법 제477조 · 변제충당 · 소멸시효debt:payment-order: 지급명령 · 변제충당 · 이자의 기산construction:complaint: 공사대금 · 도급계약 · 하자보수*:complaintfallback: 청구취지 · 청구원인
매칭된 키워드 주변 ±80자 윈도우 → contextSnippet. 매칭 없으면 선두 120자 generic excerpt.
플래그 & 롤아웃 (2026-04-23 단순화)
현재 단일 Firestore 플래그로 통일됨. 기본값은 defaults.ts SSoT.
| 플래그 | 기본 | 용도 |
|---|---|---|
features.ai.tenantEmbedding | true | 임베딩 생성 + v2 검색 kill switch |
features.ai.autoCitation | true | citations UI 섹션 kill switch (검색 유지) |
features.ai.ragSearch | true | dispatch action 이 v1·v2 모두 게이트 |
features.infraHardening.relatedMemoriesPanel | true | Panel 자체 노출 |
비상 차단: 문제 발생 시 Firestore 콘솔에서 해당 플래그 false 로 직접 수정. 배포 불필요.
대안 검토
- v2 단독 (v1 제거) — 거부. 신규 임베딩 생성까지 v2 는 쓸 카드 없음 → 빈 패널 UX 퇴보. v1 fallback 유지가 가드레일.
- citations 를 v1/v2 양쪽 지원 — 거부. v1 은 Vertex AI Search 검색 결과의 snippet 에 의존하는데 caseNumber/closedAt 조인 없이 citation 을 만들기엔 부족. v2 한정이 정직.
- UI 대신 Server Action 반환값만 확장 — 거부. 변호사 가치는 "붙여넣기 가능한 인용"을 보는 것.
Minority Report
- P7 (보안): auto-citation 은
redactedText기반이지만 키워드 매칭 주변 ±80자가 여전히 민감 맥락을 드러낼 가능성. 후속 3단 재식별 스캐너 적용 전까지 내부 dogfood 만 권장. - P1 (변호사): "민법 제479조" 같은 키워드 우선순위 순서가 실제 쟁점 분포와 어긋날 수 있음 — 로그/텔레메트리 수집 후 재조정 필요.
후속
- citations "이 쟁점 서면에 반영" 버튼 · 복사는 #567 로 완료
- 키워드 맵 텔레메트리 학습 (shown/clicked 기반 재조정)
- NER 2단 (Phase 1b S4) — Gemini 로 PII leakage 재검증