# InsuWiki 약관AI 시스템 아키텍처 (2026-03-03 기준)

## 1. 기술 스택
- Frontend: Next.js + TypeScript + TailwindCSS (Vercel 배포)
- Backend: Next.js API Routes + Firebase Cloud Functions
- DB: Firestore (Blaze plan)
- AI: Gemini 2.0 Flash (생성) + text-embedding-004 (임베딩, 768차원)
- 파일 저장: Google Drive (원본 PDF)
- 배포: Vercel (Next.js) + Firebase Functions (asia-northeast3)

## 2. 핵심 파이프라인

### 2-1. PDF 업로드 파이프라인
- 경로: `nextapp/src/app/api/admin/drive-upload/route.ts`
- 흐름: 관리자 업로드 → Magic Bytes 검증 → 파일명 파싱({회사}_{상품}_{YYMM}.pdf) → Drive 업로드(01_약관/{카테고리}/{회사}/) → insurance_metadata 생성 → jobs 문서 생성(index_pdf)
- 보안: Bearer 토큰 인증, 50MB 제한, 분산 락(productId 단위, 30분 TTL)
- 카테고리 자동분류: 회사명 키워드 기반 (화재/손보→손해보험, 변액→변액보험, 기본→생명보험)
- 회사명 정규화: company_aliases 컬렉션 조회

### 2-2. PDF 인덱싱 파이프라인
- 경로: `functions/src/pdfIndexing.ts`
- 트리거: Firestore jobs 컬렉션 (type: index_pdf, status: pending)
- 리소스: 메모리 1GB, 타임아웃 540초
- 흐름:
  1. Drive에서 PDF 다운로드
  2. pdf-parse로 텍스트 추출 (Y좌표 기반 줄바꿈)
  3. 스캔 PDF 감지 (페이지당 평균 50자 미만 → 거부)
  4. 보험료/환급금 테이블 필터링 (정규식 패턴)
  5. 청킹: 500-800자, 최소 50자, Overlap 100자
  6. 대용량 PDF(500p+): 200페이지 분할 처리
  7. text-embedding-004로 임베딩 (배치 10개 병렬, 지수 백오프 재시도)
  8. Firestore 배치 커밋 (400문서 단위)
  9. gemini-2.0-flash로 보험 용어 자동 추출 (verified: false)
  10. 재인덱싱 시 기존 chunks 삭제 후 재생성

### 2-3. 벡터 검색 + 질의응답 파이프라인
- 경로: `nextapp/src/app/api/ai/vector-search/route.ts`
- 쿼리 라우터: `nextapp/src/lib/ai/queryRouter.ts`
  - A형(TABLE_QUERY): 보험료 테이블 → TODO (미구현)
  - B형(VECTOR_SEARCH): 약관 RAG 검색 → 구현 완료
  - C형(DEEP_QUERY): 장문맥 분석 → Cloud Function
  - D형(COMPLEX): 복합 질의 → 분해 후 순차처리
- B형 검색 흐름:
  1. 용어 확장 (insurance_terms 별칭으로 쿼리 보강)
  2. 쿼리 임베딩 (text-embedding-004)
  3. Firestore 벡터 검색 (COSINE, TOP 10)
  4. 유사도 게이트: ≥0.85 TRUST / 0.70-0.85 AMBIGUOUS / <0.70 REJECT
  5. Disambiguation: 신뢰 결과 0개 + 애매 결과 있으면 후보 제시
  6. 컨텍스트 조립 (상위 5개 청크)
  7. gemini-2.0-flash로 답변 생성

### 2-4. 3중 할루시네이션 방지
- Layer 1: 유사도 임계값 게이트 (0.85/0.70)
- Layer 2: 시스템 프롬프트 (원문 근거만 답변, 추정 금지, 출처 필수)
- Layer 3: 답변 검증 필터 (불확실 표현 감지 + 출처 누락 체크)
- 면책 문구 자동 삽입: "실제 보험금 지급은 보험사 심사 기준에 따릅니다"

## 3. Firestore 컬렉션 구조

### insurance_chunks (핵심)
- id: companyId_productId_chunk_N
- companyId, companyName, productId, productName
- pageNumber, chunkText
- embedding: number[768]
- coverageNames: string[] (TODO: 미구현)
- sourceType: 'policy'
- effectiveDate, driveFileId, createdAt

### insurance_metadata
- productId (문서 ID)
- companyId, companyName, productName, category
- driveFileId, driveFileName
- effectiveDateRange: { start, end? }
- isSalesStopped, isActive, updatedAt

### insurance_terms
- term, definition, commonAliases[], icdCodes[]
- pageNumber, companyId, productId
- verified: boolean (관리자 승인 필요)

### 기타: jobs, summary_jobs, query_logs, upload_locks, company_aliases

## 4. 벡터 인덱스
- insurance_chunks.embedding: 768차원, FLAT
- youtube_knowledge.embedding: 768차원, FLAT
- 복합 인덱스: (sourceType, companyId, productId)

## 5. 보안 규칙 (firestore.rules)
- insurance_chunks: 서버 전용
- insurance_metadata: 공개 읽기, 관리자 쓰기
- insurance_terms: 서버 전용
- query_logs: 관리자 읽기, 서버 쓰기

## 6. 관리자 UI
- /admin/upload: PDF 업로드 (드래그앤드롭, 배치, 실시간 진행)
- /admin/terms: 상품 목록 (필터/검색)
- /admin/terms/[productId]: 3단계 요약 뷰어 + 재인덱싱 + 히스토리
- /admin/terms/stats: 통계 대시보드

## 7. 현재 미구현 항목 (출시 전 검토 필요)
- A형(TABLE_QUERY): 보험료 테이블 DB (TODO: Step 9)
- 3단계 요약 생성: summary_jobs 처리 Cloud Function
- OCR 파이프라인: 스캔 PDF 처리
- D형(COMPLEX): AI 기반 쿼리 분해
- coverageNames 자동 태깅
- 용어 검증 관리자 UI (벌크 승인/편집)
- 쿼리 결과 캐싱

## 8. 최근 개선 완료 (2026-03-03)
- task-150.1: 약관 업로드 24개 항목 개선 (Phase 1-4)
  - Magic Bytes 검증, 카테고리 확장, YYMM 검증, 분산 락
  - 재인덱싱 시 chunks 삭제, 임베딩 재시도, 스캔 PDF 감지
  - 실시간 파싱 미리보기, 통계 대시보드, 버전 히스토리
  - 대용량 PDF 분할, 회사명 정규화, Overlap 100자
- task-145.1: YouTube 3-Layer 요약 (방안 B 개선안)
- task-136.1: YouTube 파이프라인 버그 4건 수정
