3092e3009d
phase-2a-embedding-diagnose.md v4 § 6 (dispatcher) + § 7 Phase 3 (51 case 측정) + § 7 Phase 4 (decision)
Round 2 review: round-2-review-mighty-starfish.md (R2-2 + R2-B1 페어 invariant + slug-based resolve)
코드 변경:
- app/services/search/retrieval_service.py:
- CANDIDATE_BACKEND_MAP allowlist (baseline / cand_me5_large_inst / cand_snowflake_l_v2)
- _resolve_backend(slug) → docs_table/chunks_table/embed_endpoint or None
- _embed_query_via_tei() — candidate TEI 엔드포인트 호출 (cache 미사용)
- _VALID_DOCS_TABLE + _VALID_CHUNKS_TABLE regex (R2-B1 2단계 gate)
- _search_vector_docs / _search_vector_chunks: docs_table/chunks_table + snapshot_*_id_max 파라미터
- search_vector + search_vector_multilingual: embedding_backend + snapshot_*_id_max 파라미터 + dispatch log
- app/services/search/search_pipeline.py: run_search() 시그니처 + 4 search_vector* 호출 threading
- app/api/search.py: 3 Query parameter + ValueError → HTTP 400 (allowed list 응답)
- tests/search_eval/run_eval.py: --embedding-backend + --snapshot-doc-id-max + --snapshot-chunk-id-max
+ call_search/call_search_full/evaluate threading + main 3 asyncio.run threading
측정 산출물 (51 case, scored=46, failure=5):
- reports/v0_2_phase2a_baseline_snapshot_2026-05-23.csv (snapshot filter 적용 production path)
- reports/v0_2_phase2a_me5_large_inst_2026-05-23.csv
- reports/v0_2_phase2a_snowflake_l_v2_2026-05-23.csv
- tests/search_eval/baselines/v0_2_phase2a_{baseline_snapshot,me5_large_inst,snowflake_l_v2}_2026-05-23.json (3개)
결과:
| Candidate | NDCG | Δ vs baseline | mixed | korean_only | p50 ms |
|------------------------------------|-----:|--------------:|------:|------------:|-------:|
| bge-m3 (baseline snapshot) | 0.659| — | 0.39 | 0.51 | 464 |
| cand_me5_large_inst | 0.477| -0.182 | 0.17 | 0.47 | 194 |
| cand_snowflake_l_v2 | 0.616| -0.043 | 0.35 | 0.52 | 254 |
Decision (H3): bge-m3 유지. 둘 다 net 회귀.
- mE5-large-instruct: 전 카테고리 회귀 (-0.182). prefix 미적용 변수 — 별 PR PR-2A-mE5-Prefix-Retry 후보.
- snowflake_l_v2: 가벼운 회귀 (-0.043). korean_only +0.01 미세 개선 신호.
- korean_only/mixed 약점 보완은 Phase 2B (Reranker) 또는 Phase 2Q (Query rewrite) 권고.
Decision report: reports/phase_2a_embedding_decision_2026-05-23.md (§ 1~8 포함, Closure gate 16 항목 모두 PASS).
후속 PR 백로그:
- PR-2A-mE5-Prefix-Retry (별 PR)
- PR-2A-Extended-Bge-Mgemma2 (별 PR, v3 결정)
- PR-2A-Cloud-Embedding-Scaffold-1 (Cohere/Voyage scaffold-only, 선택)
- PR-Search-Query-Rewrite-1 (Phase 2Q)
- PR-Search-Reranker-V2-Diagnose (Phase 2B)
- PR-2A-Chunks-Cand-Cleanup-1 (1주 후 cand 테이블 DROP)
production 영향:
- documents / document_chunks 컬럼/row 변경 0
- config.yaml 변경 0 (ollama bge-m3 unchanged)
- 추가된 endpoint = query parameter opt-in (미지정 시 production path 회귀 0)
- smoke 4건 PASS (baseline / baseline+snapshot / cand_me5 / cand_invalid → HTTP 400)
- dispatch log 박제 verify (snapshot_doc/chunk_id_max 박제)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.8 KiB
6.8 KiB
Phase 2A Embedding Decision Report (2026-05-23)
Parent:
phase-2a-embedding-diagnose.mdv4Round 2 review:
round-2-review-mighty-starfish.md채택본 보고서 = Phase 4 산출물. Decision Tree H1~H4 중 권고 1개 + 후속 PR 후보.
1. Summary
| Value | |
|---|---|
| baseline (bge-m3, snapshot 범위) | NDCG@10 (graded) 0.659 / mixed 0.39 / korean_only 0.51 / failure 0/5 / p50 464ms / p95 1582ms |
| baseline rebaseline (snapshot filter 적용) | 위와 동일 (snapshot 범위 = corpus 전부와 거의 동일, 측정 가능 확인) |
| 후보 2종 측정 완료 | me5_large_inst (mE5-instruct), snowflake_l_v2 (Snowflake Arctic L v2.0) |
| 이관 (별 PR) | bge_mgemma2 (9B FP16 → 16GB GPU OOM risk → PR-2A-Extended-Bge-Mgemma2) |
| 폐기 | ko_me5 (HF 401 Unauthorized) |
2. 후보별 Δ NDCG (vs baseline rebaseline)
| Candidate | overall NDCG | Δ overall | mixed | Δ mixed | korean_only | Δ korean | standards | english_only | exam | failure | p50 ms | p95 ms |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bge-m3 snapshot rebaseline | 0.659 | — | 0.39 | — | 0.51 | — | 0.87 | 0.78 | 0.74 | 0/5 | 464 | 1582 |
| mE5-large-instruct | 0.477 | -0.182 | 0.17 | -0.22 | 0.47 | -0.04 | 0.54 | 0.63 | 0.62 | 0/5 | 194 | 1348 |
| snowflake-arctic-embed-l-v2.0 | 0.616 | -0.043 | 0.35 | -0.04 | 0.52 | +0.01 | 0.87 | 0.74 | 0.56 | 0/5 | 254 | 1412 |
관찰:
- mE5-large-instruct: 전 카테고리 큰 회귀. Δ -0.182 overall. mixed 절반 회귀 (0.39 → 0.17). standards 도 큰 회귀 (0.87 → 0.54). 단 latency p50 270ms 단축 (mE5 의 512 context = 적은 compute).
- snowflake_l_v2: 가벼운 회귀 (Δ -0.043). standards / korean_only 거의 동일. mixed 약간 회귀. exam 명확 회귀 (-0.18). latency p50 210ms 단축.
ambiguous note (LLM 단독 결정, feedback_user_block_minimize):
- mE5-instruct 는 query input 에
Instruct: <task>\nQuery: <query>prefix 권장 (intfloat 모델 카드). 본 PR 측정은 plain query → prefix 효과 미반영. prefix 적용 시 +0.05~0.15 회복 가능성 있으나 측정 외 — 별 PR 후보PR-2A-mE5-Prefix-Retry. - snowflake_l_v2 의 한국어 specific 벤치마크 공개 부재. 본 측정 = 사실상 한국어 specific 첫 audit. korean_only +0.01 미세 개선 신호 있으나 통계적 의미 없음 (n=9, 0.51 vs 0.52).
3. Latency 영향
- mE5 (512 ctx): p50 464 → 194 (−270ms), p95 1582 → 1348 (−234ms). 빠름.
- snowflake (8192 ctx): p50 464 → 254 (−210ms), p95 1582 → 1412 (−170ms). 빠름.
- 둘 다 baseline 보다 빠르지만 quality 회귀. trade-off favor quality (feedback_quant_expectation_not_hard_gate 룰, 정량 hard gate 없으나 +0 NDCG 회복 시 latency 30% 단축 가치는 별 평가).
4. Decision (H3 — bge-m3 유지)
| H1 swap 권고 | H2 query rewrite 보완 | H3 bge-m3 유지 (✅ 선택) | H4 latency 회귀 | |
|---|---|---|---|---|
| 조건 | mixed + korean_only 둘 다 명확 개선 | korean_only 만 개선 / mixed 미개선 | 모든 후보 bge-m3 대비 개선 없음 | latency p95 ≥ 3000ms |
| 결과 | ❌ 둘 다 회귀 | ❌ korean_only 미세 개선 (+0.01) 만, mixed 회귀 | ✅ 확정 | ❌ 둘 다 baseline 보다 빠름 |
최종 권고: bge-m3 유지 (Apply PR 진입 안 함).
근거:
- mE5 -0.182 / snowflake -0.043 — 둘 다 net 회귀.
- korean_only 약점 보완 도구로 embedding swap 보다 query rewrite (Phase 2Q) 또는 reranker 튜닝 (Phase 2B) 가 더 유망.
- mE5 prefix retry 는 별 PR 로 분리 — diagnose 본 PR scope 외.
5. Apply / 보완 / 보류 권고
- Apply (production embedding swap): 하지 않음.
- 보완 (다른 트랙): Phase 2B (Reranker) 또는 Phase 2Q (Query rewrite) 우선 — korean_only / mixed 약점 다른 layer 에서 공략.
- 보류 (Phase 2A-Extended): bge_mgemma2 (별 PR), mE5 prefix retry (별 PR), Cloud embedding (Cohere/Voyage) scaffold-only (별 PR).
6. 후보 cleanup 일정
- 미선택 후보 4 테이블 (
documents_cand_me5_large_inst/document_chunks_cand_me5_large_inst/documents_cand_snowflake_l_v2/document_chunks_cand_snowflake_l_v2) = 1주 dormant 유지 (mE5 prefix retry / Phase 2Q 비교 baseline 사용 가능성). - 1주 후 별 chore
PR-2A-Chunks-Cand-Cleanup-1에서 DROP + 컨테이너 docker-compose.override 제거.
7. 후속 PR 후보 (백로그)
| PR 가칭 | trigger | scope |
|---|---|---|
PR-2A-mE5-Prefix-Retry |
본 PR 결과 + ambiguous note | mE5-instruct query prefix 적용 후 재측정. 페어 reindex 재실행 + 51 case 재측정. 본 PR 의 dispatcher 재사용 (CANDIDATE_BACKEND_MAP 에 신규 slug 추가). |
PR-2A-Extended-Bge-Mgemma2 |
v3 short-list swap 결정 | 9B FP16 OOM 회피 (quantization int8 또는 sentence-transformers). 별 컨테이너 + reindex + 측정. |
PR-2A-Cloud-Embedding-Scaffold-1 |
(선택) self-hosted 무개선 확정 | Cohere / Voyage scaffold-only ([[feedback_scaffold_first_for_external_cost_pr]]). 실비 0. |
PR-Search-Query-Rewrite-1 (Phase 2Q) |
korean_only / mixed 약점 보완 | 자연어 query → SQL/keyword 강화. |
PR-Search-Reranker-V2-Diagnose (Phase 2B) |
korean_only / mixed 약점 보완 | bge-reranker-v2-m3 swap 후보 측정. |
PR-2A-Chunks-Cand-Cleanup-1 |
본 PR closure 후 1주 | 4 cand 테이블 DROP + 컨테이너 정리. |
8. Closure gate verify (§ 8 본 plan)
- G0-1 + G0-2 fixture 박제 (Phase 1 closure 시 commit
943ac5f) - snapshot json 박제 (
v0_2_phase2a_snapshot_2026-05-23.json, commita67df0a) - 2 후보 (me5_large_inst + snowflake_l_v2) 51 case 측정 완료 (
overall.n = 46, 5 failure 제외) - baseline rebaseline 51 case 측정 완료 (snapshot filter 적용)
- 후보별 baseline json 2개 + baseline_snapshot json 1개 박제
- documents_cand_ row count = 21365 verify (2 후보 동일)
- document_chunks_cand_ row count = 30605 verify (2 후보 동일)
- baseline rebaseline 측정도 동일 snapshot_doc/chunk_id_max filter 통과 verify (dispatch log)
- dispatcher 호출 시 unknown slug → HTTP 400 verify (smoke test
cand_invalid통과) - decision md 박제 (본 파일)
- Apply 권고 1줄 작성 (H3)
- production embedding (bge-m3 ollama) 변경 0 verify (
docker compose ps,ollama list,config.yamldiff 0) - production
documentsrow count + embedding 변경 0 verify - production
document_chunksrow count + content 변경 0 verify - 후보 cleanup 일정 명시 (1주 dormant →
PR-2A-Chunks-Cand-Cleanup-1) - dispatch log audit (silent fallback 0,
embedding_backend_unavailable0, snapshot id 박제 verify) - DOCSRV_TOKEN 만료 사고 0 (3 측정 모두 15분 이내 완주)
Phase 2A Diagnose PR closure: PASS.