본문으로 건너뛰기

RAG eval 측정 chain — 18 PR · baseline 0.000 → recall 0.119

2026-05-18~19 자율 + 사용자 delegation 세션. RAG eval (scripts/eval-rag-merge.ts) baseline 0.000 진단 부터 4 option ablation 을 거쳐 hybrid + LLM rerank + per-recoveryType pool 정밀화 까지 18 PR shipped.

핵심 발견

1. text-embedding-004 의 조문 번호 grouping 한계

factPattern "약정금 사실관계" → top-10 retrieved 가 모두 "제N조" 동일 조문 번호 grouping (민법 제500조 · 상법 제500조 · 채무자회생법 제500조). 의미보다 숫자 토큰이 강한 signal.

2. 단일 옵션의 한계 (option ablation)

Optionrecall결론
baseline0.000시작점
query expansion (PR #2387)0.000null — 키워드 suffix 가 grouping 못 이김
hybrid only (#2390 ablation)0.024candidate 추가만, top-10 cut 은 embedding rank — 효과 limited
LLM rerank only (#2389)0.024의미 매칭 가능, 후보 안 정답 없으면 무의미

3. 두 메커니즘 결합 시 시너지 (PR #2390)

hybrid (BM25-lite, lawName 키워드) + LLM rerank (Gemini 의미 평가) → recall 0.077 (baseline 의 ∞배).

  • hybrid: candidate pool 다양성 → 정답 statute 후보 안 진입
  • rerank: pool 에서 의미 매칭 top-10 선택
  • 둘 다 필요 — 단일 옵션은 한쪽만 해결

4. Pool size signal/noise trade-off

poolcomplaint recalldivorce recall평균
300.0830.2500.077
1000.0000.5000.060

도메인별 적정 pool 다름 — 단순 uniform 보다 lawName count heuristic (single=30/multi=60) 가 평균 개선. 명시 override (divorce=100) 로 정밀.

5. 점진 정밀화 결과 (5 단계)

PRprecisionrecallMRR누적
baseline0.0000.0000.000
#2390 hybrid + rerank uniform0.0210.0770.179
#2393 pool 100 ablation0.0210.0600.143regression
#2394 heuristic0.0290.1010.250+31%
#2395 RECOMMENDED override0.0360.1190.250+18%

PR chain (18)

PR산출
#2378tenant-rag-self 3축 metric + per-docKind + --json
#2379dashboard TenantRagSelfBreakdownCard
#2380corpus 8→16 — sampling artifact 노출
#2381eval-rag-merge byDocKind + 카드 generic 화
#2382eval-rag-merge MRR + pure 모듈 추출
#2383A-답변서 종결어미 정합
#2384launchd plist template
#2385production --apply chain closure + 2 silent bug fix
#2386baseline 0.000 진단 (조문 번호 grouping)
#2387query expansion null result
#2388LLM rerank v1 (분모 artifact)
#2389LLM rerank v2 (분모 정상화)
#2390hybrid + rerank → 3x baseline 돌파
#23914-option summary docstring
#2392launchd hybrid + rerank flag 자동 활성
#2393--hybrid-pool=N + trade-off 노출
#2394per-recoveryType heuristic
#2395RECOMMENDED_POOL override → recall 0.119

부수 발견

dynamic ESM import + NODE_PATH 비호환 (PR #2385)

await import("firebase-admin/firestore") 가 dry-run 통과 + apply fail silent bug. top-level static import 만 안전. memory feedback_static_import_safer_than_dynamic 저장.

@/ alias resolution cwd 의존

eval-rag-merge.ts 가 root cwd 에서 fail. apps/web cwd 강제 패턴이 정답. launchd cd {{REPO_PATH}}/apps/web.

A-답변서 종결어미 통찰 (PR #2383)

formal verb ending ("인정합니다") vs 명사형 ("다툼 없음") 차이가 임베딩 분리 야기. 한국 답변서 template style 일관성이 RAG retrieval 품질에 영향. 사무소 학습 corpus 작성 시 명사형 ending 권장.

measurement validity warning

  • 작은 corpus 의 perfect score = artifact (PR #2380 8건 → 16건 확장 시 0.958→0.937)
  • precision 분모 항상 k 고정 (LLM 응답 짧을 때 fallback fill — PR #2389)

남은 한계 — 다음 chain 후보

embedding 단계의 본질 한계

text-embedding-004 의 조문 번호 grouping 은 후처리 (hybrid + rerank) 로 완전 해소되지 않음. baseline 0.119 recall 도 14 cases 중 4 case 만 매칭. 나머지 10 case 는 expected statute 가 후보 pool 에 도달 못함.

후보 option (큰 scope)

  1. embedding model 교체 — text-embedding-005 또는 multilingual-e5-large. 단점: 10,508 docs 재임베딩 비용
  2. Firestore stride sampling — articleNumber prefix range query 로 더 다양한 후보 (예: 민법 제7XX 명시 sample)
  3. publicDocuments label 풍부화 — 조문 의미 키워드를 label 에 항상 포함 (e.g., "민법 제741조 (부당이득)" 처럼) → embedding 의 의미 신호 강화
  4. 사무소 학습 데이터로 fine-tune — 한 줄 본질 정합. 가장 큰 leverage 지만 큰 scope.

산출물 위치

종류위치
Pure 모듈apps/web/lib/eval/ranked-retrieval-metrics.ts · rag-merge-evaluator.ts · llm-reranker.ts · candidate-pool-hybrid.ts · query-expansion.ts
Scriptscripts/eval-rag-merge.ts · scripts/eval-tenant-rag-self.ts
Corpusapps/web/lib/eval/tenant-rag-self-corpus.ts (16건)
Dashboard 카드apps/ops/app/(ops)/dashboard/page.tsx RagBreakdownCard
자동화scripts/launchd/com.neohollo.rag-eval-daily.plist.template
진단 도구scripts/check-eval-statute-coverage.ts · --verbose flag

결론 (PR #2378~#2400, 18 PR)

measurement 인프라 완성 + baseline 5.7x recall 돌파 — 18 PR chain 누적. embedding 본질 한계로 추가 incremental 마진은 감소 중. 다음 chain 은 embedding 자체 또는 publicDocuments label 풍부화 같은 큰 lever 후보.

후속 chain (PR #2402~#2404) — embedding model 교체

retrospective 작성 후 사용자 명시 요청으로 option 4 진행:

PRPhase산출
#2402Phase 15 mirror NEXT constant + spot-check 정량 (margin -0.067 → +0.136)
#2403Phase 2A--embedding-model=X flag + 5 doc smoke
2B(background)re-embed 10,279 docs · 92분 · 실패 0
#2404Phase 2C5 mirror EMBEDDING_MODEL_VERSION 004 → 002 swap

Phase 3 eval ablation 결과 (text-embedding-004 vs text-multilingual-embedding-002):

Metric004 (PR #2398 best)002 (PR #2404)변화
precision0.0430.071+65%
recall0.1430.292+104%
MRR0.3210.536+67%

per-docKind dramatic 개선:

  • complaint (n=6): recall 0.083 → 0.472 (5.6x) — 가장 큰 leverage
  • share-claim: recall 0.333 → 0.667
  • title-transfer: 0.000 → 0.500 (전혀 새로 매칭)

핵심 통찰

Chain 의 진짜 ceiling 이 embedding 본질이었음을 직접 입증. 18 PR 의 retrieval 후처리 (hybrid · pool tuning · LLM rerank · coverage) 모두 의미는 있었으나, embedding 모델 swap 한 번에 retrieval 후처리 전체 합보다 큰 효과. spot-check 정량 (margin -0.067 → +0.136) 이 사전 예측 정확.

22 PR chain 최종 산출

production launchd 매일 09:00 KST 자동 측정 (--hybrid --llm-rerank) → dashboard 카드 자동 노출. 새 baseline 0.292 recall · 0.536 MRR.

사무소가 자기 데이터로 자기 AI 학습 + 활용 → 소송 더 정확하게 관리 의 측정 layer 가 의미있는 baseline 도달.

후속 chain — gemini-2.5-flash thinking tokens 발견 (PR #2406+#2407)

docgen quality 정성 검증 중 truncation 발견 → 근본 원인 정량 추적:

PR #2406 (docgen 검증) — Gemini docgen 출력 119~125자 mid-cut 발견.

PR #2407 (thinkingBudget=0 fix)gemini-2.5-flash 의 internal thinking tokens 가 maxOutputTokens 소모 발견. thinkingConfig.thinkingBudget: 0 으로 thinking 비활성 → 응답 토큰 전체 출력 할당.

SettingprecisionrecallMRR
002 swap (PR #2404)0.0710.2920.536
+ thinkingBudget=0 (PR #2407)0.107 (+51%)0.405 (+39%)0.536
  • divorce-complaint: recall 0.500 → 1.000 (전체 expected 매칭!)
  • division-petition: 0.333 → 0.667 (2x)

회고적 통찰 — chain 의 silent overhead

22 PR chain 의 LLM rerank 관련 negative ablation (#2389 LLM=1, #2399 LLM=2~3, #2400) 의 진짜 원인은 thinking tokens starvation 이었을 가능성. PR #2389 의 fillRerankFallback 도 thinking-truncated 응답을 위해 만든 workaround — 근본 원인이 일찍 드러났으면 #2391~#2400 의 6 PR 노력의 일부는 절감 가능.

Phase 1+2+3 cumulative impact: baseline 0.000 → recall 0.405 (∞x), MRR 0.536 (∞x). divorce 전체 매칭, complaint 5.6x.