dense_vector 인덱스 — 임베딩 검색을 붙인다

무엇을

지식베이스 98조항을 임베딩해 ES dense_vector 필드로 함께 적재한다. 지금 인덱스는 nori(BM25) 한 겹뿐이다.

왜 — 4주차 목표인데 티켓이 0건이었다

8주 마일스톤 4주차는 「nori 인덱스 · dense_vector · RRF 병합 · 청킹 전략 3종 비교」인데, w4- 티켓 27건 중 여기 해당하는 것이 하나도 없었다. 4주차에 실제로 한 일(콜 미디에이터·블랙리스트· 관리자 로그인·배포)은 전부 로드맵에 없던 일이고, 로드맵에 적힌 일에는 티켓이 없었다. 2026-09-15 에 로드맵을 티켓으로 옮기면서 만든다 — 착수 전이다.

모델은 이미 정해져 있다 — 다시 고르지 않는다

_project/decisions/010 이 KoE5(1024차원)로 확정했다. 같은 결정 기록이 적어 둔 실측 제약 둘 —

완료 조건

주의

임베딩이 BM25 보다 나쁘게 나와도 그대로 적는다(절대 원칙 8). 다음 티켓(RRF 병합)이 둘을 합치는 것이라, 단독 점수는 «합쳤을 때 무엇이 기여했는가» 를 읽는 기준선으로 쓰인다.


2026-09-15 — 임베딩 단독이 BM25 를 크게 앞선다: 0.833 → 0.979

측정일 2026-09-15 · 커밋 38f2fc3-dirty · 골든셋 v1-150 B 항목 n96 · 지식베이스 98조항 · 로컬 Darwin arm64
.venv/bin/python scripts/index_knowledge_base.py --to-es --recreate     # 본문 + KoE5 임베딩
.venv/bin/python scripts/compare_retrievers.py [--device mps]
결과 파일 data/processed/retrieval-compare/2026-09-15*.json (gitignore)

변형                          Recall@5   hits    MRR   top1 │ p95 CPU   p95 MPS
bm25 (run_id=2 와 같은 값)       0.833   80/96  0.659    51  │     4ms      7ms
dense (KoE5 kNN)                0.979   94/96  0.885    78  │    59ms     50ms
hybrid RRF k=60 cand=20         0.927   89/96  0.828    73  │    58ms     39ms
  k=10 / 30 / 100               0.927   89/96  0.835 / 0.828 / 0.828
rerank(bm25) cand=5             0.833   80/96  0.795    73  │   494ms    237ms
rerank(bm25) cand=20            0.906   87/96  0.860    79  │  1760ms   1068ms
rerank(dense) cand=5            0.979   94/96  0.919    84  │   521ms    289ms
rerank(dense) cand=20           0.979   94/96  0.921    84  │  1789ms   1317ms
rerank(hybrid) cand=5           0.927   89/96  0.886    82  │   529ms    373ms
rerank(hybrid) cand=20          0.979   94/96  0.916    83  │  1844ms   1197ms

토큰 수 — 「128 토큰 truncation」 은 KoE5 의 상한이 아니었다

임베딩 입력 = 제목 + 본문 · "passage: " 접두어 포함 · 98조항
최대 189 토큰 · 128 초과 2건 · 512 초과(실제 잘림) 0건

⚠ 티켓이 적은 「128토큰에서 truncation 이 실제로 일어난다」는 decisions/010 이 옛 후보 ko-sroberta-multitask (max_seq_length: 128)에 대해 적은 문장이다. KoE5 는 model_max_length: 512 라 지금 지식베이스에서 잘리는 조항은 0건이다. 128 초과 2건도 함께 적었다 — 티켓의 전제로 셌을 때의 값이다.

만든 것

⚠ 운영 ES 에는 벡터가 없다. 이 인덱스는 로컬 것이다 → _project/decisions/206 「남는 것」