embeddingVersion Day 0 가드
정책 근거: ADR 0005 §3 RAG 데이터 모델
소스: apps/web/lib/ai/embedding-version.ts
왜 필요한가
임베딩 벡터는 특정 모델·차원·정규화 방식 의 산물이다. 모델이 바뀌면 (text-embedding-gecko-001 → text-embedding-004, 768차원 → 1536차원, L2 정규화 여부 변경 등) 이전 벡터와 신규 벡터는 같은 namespace 에 있어도 의미적으로 호환되지 않는다. Firestore 나 Vertex AI Vector Search 는 이를 에러로 내지 않고 조용히 의미 없는 코사인 유사도 를 돌려준다.
→ "RAG 결과가 점점 이상해지는데 원인을 찾을 수 없음" — silent corruption.
해결은 Day 0 부터 모든 벡터 저장 문서에 embeddingVersion 필드를 박고, 조회·검색 시 현재 버전과 일치하는 것만 사용.
핵심 API
import {
CURRENT_EMBEDDING_VERSION,
stampEmbeddingVersion,
filterByEmbeddingVersion,
assertEmbeddingVersion,
isCurrentEmbeddingVersion,
} from "@/lib/ai/embedding-version";
쓰기 — 반드시 stamp
// ❌ embeddingVersion 누락
await db.collection("legacyDocuments").add({
tenantId,
chunkText,
vector,
});
// ✅ stamp 통과
await db.collection("legacyDocuments").add(
stampEmbeddingVersion({ tenantId, chunkText, vector })
);
읽기 — filter 또는 assert
// (a) 관대: stale 제외 + 카운트 (일반 RAG 조회)
const { current, staleCount } = filterByEmbeddingVersion(
snap.docs.map((d) => d.data()),
);
if (staleCount > 0) {
logger.warn("embedding-version-stale", { collection, staleCount });
// 백필 큐 push 또는 Sentry 알림
}
return current;
// (b) 엄격: 불일치 시 throw (결과 정합성 필수 경로)
const doc = snap.docs[0].data();
assertEmbeddingVersion(doc, `legacyDocuments/${snap.docs[0].id}`);
대상 컬렉션 (Phase 0~1 계획)
| 컬렉션 | 도입 시점 | 용도 |
|---|---|---|
legacyDocuments (chunks 서브컬렉션) | Phase 0 Week 2~3 | 사무소 기억 RAG 청크 |
caseStrategyReports (embedding 서브필드) | Phase 0 Week 4 | 전략 보고서 유사 사건 매칭 |
ragChunks | Phase 1 | 공공 판례·조문 RAG 인덱스 |
Day 0 원칙: 이 컬렉션들은 첫 문서가 생성되는 순간부터 embeddingVersion 필드 포함. 나중에 추가하면 기존 문서가 자동으로 stale 처리되므로 전수 backfill 필요.
버전 교체 절차
모델·차원 변경 시:
CURRENT_EMBEDDING_VERSION값 증가 ("v1"→"v2")- Backfill 스크립트 작성 — 기존 문서를 신규 모델로 재임베딩 + 새
embeddingVersionstamp - 운영 모니터링 —
filterByEmbeddingVersion의staleCount가 0 으로 수렴하는지 Grafana 대시보드 - 완료 후 이전 버전 문서 TTL 삭제 또는 영구 삭제
절대 하지 말 것:
- ❌ 모델 교체하면서
CURRENT_EMBEDDING_VERSION유지 (silent corruption 직행) - ❌ Backfill 없이 버전만 올림 (모든 기존 벡터가 하루아침에 stale)
- ❌ stale 문서를 방치 (RAG 결과 축소·품질 저하 누적)
테스트 전제
apps/web/lib/ai/__tests__/embedding-version.test.ts — stamp·filter·assert 전수 검증.
모든 벡터 쓰기·읽기 경로의 단위 테스트는 이 유틸을 통과했는지 assert 로 확인.