# ANU 독립검증 — task-2987 (인슈위키 임베딩 Sonnet 전환 사전확인)

- 검증 시각: 2026-08-20 18:10 KST · 검증자: ANU (봇 보고 승계 아님, 전건 재측정)
- 대상 보고서: `memory/reports/task-2987.md` (dev4-team 비슈누)
- 조사 트리: `/home/jay/.worktrees/task-2980-dev1` HEAD `a6710f7`

## 1. 봇 주장 재측정 결과 (5/5 CONFIRMED)

| 주장 | ANU 실측 | 판정 |
|---|---|---|
| Anthropic 임베딩 부재 | SDK 0.84.0 속성 `embeddings` 없음(`beta/completions/messages/models`만) · CLI 2.1.228 `embed` 0건 · REST `POST /v1/messages`=401 vs `POST /v1/embeddings`=404 | CONFIRMED |
| insurance_chunks 151건 전부 3072차원 | 프로덕션 Firestore 직조회: `docs=151 dims={3072:151} sourceType={youtube:151}` | CONFIRMED |
| youtube_knowledge 152건(151×3072 + 1×0) | `docs=152 dims={3072:151, 0:1}` | CONFIRMED |
| find_nearest 768=hits 0 / 3072=400 | `dim=768 -> OK hits=0` · `dim=3072 -> InvalidArgument 400 "Vectors must be at most 2048 dimensions."` | CONFIRMED |
| GPU sm_61 → torch 사용 불가 | `cap=(6,1)` GTX 1060 vs torch 2.10.0+cu128 `arch_list=[sm_70..sm_120]` | CONFIRMED |
| pytest 101 passed (기준선 드리프트) | `101 passed, 1 warning in 3.84s` | CONFIRMED |
| 코드 변경 0줄 | `git status --porcelain` = 빈 출력 (untracked 포함 0) | CONFIRMED |
| 인덱스 선언 768 | `insurance_chunks/youtube_knowledge embedding {'dimension':768,'flat':{}}` | CONFIRMED |
| 생산자/소비자 모델 | crawlYoutubeChannels.ts=`gemini-embedding-001` · pdfIndexing.ts=`text-embedding-004` · nextapp vector-search=`text-embedding-004` | CONFIRMED |

**결론: 봇 보고에 과장·환각 없음. 신규 발견(벡터검색 구조적 0건)은 실재하는 CRITICAL.**

## 2. ANU 추가 발견 (봇 보고에 없음)

### 2-1. 소비자 측 Gemini 키도 죽어 있다
`nextapp/.env.local` 의 `GEMINI_API_KEY` 실호출 → **HTTP 400 API key not valid**.
즉 로컬 개발 환경에서는 질의 임베딩 단계 자체가 실패한다(0건 반환 이전에 에러).
**프로덕션(Vercel) 키 상태는 미확인** — `https://insuwiki.vercel.app/api/ai/vector-search` 는 **401 Unauthorized** 인증 게이트라 무자격 확인 불가. 추정 금지.

### 2-2. ★ 봇 권고 (a) 로컬 임베딩은 아키텍처상 성립하지 않는다
소비자 `nextapp` 은 **Vercel 서버리스에 배포**되어 있다(`insuwiki.vercel.app` 실응답).
홈서버 CPU 의 `sentence-transformers` 는 Vercel 함수에서 **도달 불가**하다(Whisper 서버 선례는 홈서버 내부 파이프라인이라 상황이 다르다).
따라서 (a) 를 채택하면 생산자만 로컬 벡터가 되고 소비자는 여전히 원격 API 를 써야 해 **벡터공간이 갈라진다** — 지금(0건)보다 위험한 "조용히 틀린 결과"가 된다.
→ **회장 지시의 취지("키 의존 절단")는 소비자를 자체호스팅 공개 엔드포인트로 옮기지 않는 한 원리적으로 달성 불가.** 이는 별도 인프라 결정이다.

### 2-3. Voyage 는 768 을 지원하지 않는다
공식문서 실확인: voyage-4/4-lite/4-large 의 `output_dimension` = **2048 / 1024(기본) / 512 / 256**. 768 없음.
가격: voyage-4-lite $0.02/1M · voyage-4 $0.06 · voyage-4-large $0.12, **무료 200M 토큰**(voyage-finance-2 는 $0.12 / 무료 50M — 봇이 적은 수치와 다름).
→ (b) 채택 시 `firestore.indexes.json` **dimension 768 변경 + 인덱스 재배포**가 추가로 필요하다.

### 2-4. (c) 는 "코드 변경 0줄" 이 아니다
봇은 (c) 를 "코드 변경 0줄"로 적었으나, 3072 문제를 고치려면 `functions/src/crawlYoutubeChannels.ts` 의 `gemini-embedding-001`(3072) → 768 전환이 **반드시** 필요하다. 키만 재발급하면 3072 생산이 계속되어 검색 0건이 유지된다.

## 3. ANU 판정 — 옵션 재랭킹

| 옵션 | 양측(홈 Python + Vercel TS) 동일벡터 | 인덱스 변경 | 키 의존 | 재색인 |
|---|---|---|---|---|
| (c) 신규 Gemini 키 + 전 생산자 768 통일 | 가능 | 불필요(768 유지) | 잔존(Google) | 151건 |
| (b) Voyage | 가능 | **필요**(768→1024/512) | 잔존(벤더만 교체) | 151건 |
| (a) 로컬 768 | **불가**(Vercel 도달 불가) | 불필요 | 생산자만 절단 | 151건 |

**ANU 권고 = (c)**. 이유: 유일하게 인덱스 변경 없이 생산자·소비자 벡터공간을 일치시킨다. (a)는 아키텍처상 탈락, (b)는 키 의존을 없애지 못하면서 인덱스 변경 비용만 추가된다.
"키 의존 절단"은 (a)로도 달성되지 않으므로, **키 만료 감시/알람**을 별도 하드닝 항목으로 분리하는 것이 실질적 해법이다.

## 4. 회장 결정 필요 4건

1. **대체 방향**: ANU 권고 (c). (b) 선택 시 인덱스 재배포 승인 동반 필요.
2. **범위**: t2987 범위 확장 대신 **신규 태스크로 승격** 권고 — 생산자 3곳(youtube-pipeline·crawlYoutubeChannels.ts·pdfIndexing.ts) + 소비자 2곳(nextapp) + 재색인 스크립트를 한 태스크로 묶어야 벡터공간 일관성이 증명 가능하다.
3. **재색인 151건**: 운영 데이터 변경. 현재 이 151건은 **이미 검색 불능**이라 손실 위험은 사실상 없음 → 승인 권고.
4. **회귀 기준선 83 → 101**: ANU 실측 101 확인, 갱신 승인(ANU 판정 완료).

## 5. 보고 위생 지적 (봇)
- 보고서 "세션 통계 — 총 도구 호출: 0회" 는 실제 다수 실측을 수행한 사실과 모순. 계수 누락.
- `voyage-finance-2` 무료 한도/가격 수치가 공식문서와 불일치(1024·200M → 실제 $0.12·50M).
- (c) "코드 변경 0줄" 은 3072 결함을 남기는 조건에서만 참 → 조건 미명시.

## 6. trip-wire
- 코드 변경 0줄(재확인) · 커밋 0건 · Firestore **읽기 전용** 프로브만 수행(쓰기 0) · 키 값 미출력(마스킹) · 키 로테이션 미실시.
