"싼 검색이 넓은 그물을 던져. reranker 는 이미 잡은 물고기만 가까이 들여다보는 비싼 눈이야."
모델이 관련성을 판단하는 두 방식
관련성 모델엔 두 모양이 있고, 그 차이가 전부야. bi-encoder(벡터 검색이 쓰는 것) 는 쿼리와 각 문서를 따로 벡터로 임베딩하고 비교해. 문서를 미리 임베딩할 수 있어서 빠르고 수백만으로 확장돼 — 근데 쿼리와 문서가 모델 안에서 실제로 만난 적이 없어. cross-encoder(reranker) 는 쿼리 와 문서를 함께 모델에 넣고 쌍을 함께 점수 매겨. 모델이 둘을 한 번에 attend 해서, 분리된 비교가 놓치는 미묘한 관련성을 잡아.
더 낫고 더 느린 건 같은 속성이야
cross-encoder 가 더 정확한 건 바로 쿼리와 문서를 함께 보기 때문이고 — 그게 정확히 비싼 이유야. 아무것도 미리 계산 못 해: 모든 쿼리-문서 쌍이 새 모델 호출이야. 천 개 후보를 rerank 하면 천 번의 forward pass 를, 지금, 캐싱 불가능하게. 정확하게 만드는 바로 그것(joint attention) 이 코퍼스 전체에 돌리기엔 너무 비싸게 만드는 거야. 그래서 안 해.
심화 패턴: 넓게 검색, 좁게 rerank
해결은 2단계 파이프라인이야. 먼저 싼 방법 — BM25 와 벡터, 융합된 — 으로 평소보다 넓은 후보 풀을 당겨: 상위 8 대신 상위 50 을 가져와. 이 싼 검색기는 순서가 거칠어도 recall(옳은 답을 풀 어딘가에 넣기) 에 뛰어나. 그다음 비싼 cross-encoder 를 그 50 에만 돌리고, 그 상위 8 을 잡아. 백만이 아니라 50 번의 모델 호출을 썼고, 정밀도로 순위된 결과를 얻어. 넓고 싸게 검색하고, 좁고 비싸게 rerank 해.
Opt-in, 그리고 못 돌릴 땐 정직
rerank 는 진짜 모델 호출이 드니까, Lantern 은 기본으로 꺼둬 — 추가 정밀도가 값할 때 켜는 쿼리별 플래그. 그리고 모델 서버를 부르니, 벡터 검색과 같은 정직 규칙을 따라: reranker 가 안 닿으면, 요청이 degrade 하고 그렇다고 말해, rerank 안 된 순서를 rerank 된 것처럼 꾸며서 조용히 돌려주는 대신. 심화는 눈 뜨고 opt-in 하는 능력이지, 조용히 실패하는 숨은 단계가 아냐.