검색 임베딩을 만드는 인코더의 종류와 필요성을 이해해보자
bi-encoder와 cross-encoder가 계산 횟수와 속도에서 왜 다른지 목(mock) 인코더로 비교하고, 검색과 재정렬을 왜 나눠 쓰는지 정리했다
검색 임베딩을 만드는 인코더의 종류와 필요성을 이해해보자
검색 임베딩을 만드는 인코더의 종류와 필요성을 이해해보자
벡터 검색을 하려면 텍스트를 벡터로 바꿔줄 무언가가 필요한데, 그 “인코더”에도 종류가 있고 용도가 다르다는 걸 나중에야 알았다.
1. 서론 (Introduction)
- 문제/상황 (Problem): 벡터 검색을 붙이려고 자료를 보다 보니 bi-encoder, cross-encoder라는 말이 둘 다 “인코더”인데 쓰임이 다르다고 나왔다. 왜 하나로 통일해 쓰지 않는지 이해가 안 됐다.
- 목적 (Purpose): bi-encoder와 cross-encoder가 구조적으로 뭐가 다르고, 그 차이가 계산 비용에 어떤 영향을 주는지 확인해 왜 둘을 용도별로 나눠 쓰는지 정리한다.
- 대상 (Target Audience): 벡터 검색에 재정렬(rerank) 단계를 추가하려는 개발자.
2. 방법 및 과정 (Methods & Process)
배경 조사 및 데이터 (Data Collection): 두 인코더의 구조 차이를 정리했다.
구분 bi-encoder cross-encoder 입력 질의·문서를 각각 독립적으로 인코딩 질의+문서를 한 쌍으로 묶어 인코딩 벡터 재사용 문서 벡터를 미리 계산해 캐싱, 질의만 새로 계산 재사용 불가 — 쌍마다 매번 새로 계산 속도 빠름(문서당 1회 + 질의당 1회) 느림(질의x문서 쌍마다 1회) 정확도 상호작용을 못 봐서 상대적으로 낮음 질의-문서 상호작용을 직접 보므로 높음 용도 대량 문서 대상 1차 검색 소수 후보만 골라 재정렬(rerank) bi-encoder는 질의와 문서를 완전히 독립적인 두 벡터로 만들기 때문에 문서가 수만~수십만 건이어도 미리 색인해두면 검색 시점엔 질의 벡터 1개만 새로 계산하면 된다. cross-encoder는 질의와 문서를 같이 넣어야 관련성 점수가 나오는 구조라 후보 하나하나마다 새로 계산해야 하고, 이 계산량이 문서 수에 정비례로 늘어난다.
- 접근 방법 (Approach Methods):
- [방법 1]: bi-encoder 방식 검증. 문서 100건의 벡터를 미리 한 번씩만 계산해 캐시에 저장해두고, 검색 시점엔 질의 벡터 1회만 추가로 계산해 캐시된 문서 벡터와 비교하는 구조로 구현했다.
- [방법 2]: cross-encoder 방식 검증. 질의와 문서를 쌍으로 묶어 매번 새로 “채점”하는 목 함수(인위적 지연 포함)를 구현하고, bi-encoder가 추린 상위 후보만 재정렬하는 데 썼다.
- 분석 및 해결 프로세스 (Analysis Flow):
- 도구/기술: 파이썬 목(mock) bi-encoder(캐싱 딕셔너리)·목 cross-encoder(쌍마다 지연 포함 채점 함수).
- 주요 단계: 문서 100건 벡터 사전 계산(bi-encoder) $\rightarrow$ 질의 벡터 계산 후 전체 검색 $\rightarrow$ 상위 10건만 추출 $\rightarrow$ 그 10건만 cross-encoder로 재정렬 $\rightarrow$ 두 단계의 계산 횟수·소요 시간 비교.
- 결과 도출 및 검증: bi-encoder는 문서 100건 검색에 계산 101회(문서 100 + 질의 1), 0.057초가 걸렸다. cross-encoder는 상위 10건 재정렬에 계산 10회, 0.031초가 걸렸다. 같은 cross-encoder로 문서 100건 전체를 처음부터 검색했다면 계산 100회, 약 0.3초가 필요했을 것으로 계산돼, bi-encoder 검색(0.057초)보다 5배 이상 느렸을 자리다.
3. 결과 (Results)
- 분석 결과 요약: bi-encoder는 문서 수가 늘어도 검색 시점엔 질의 1회 계산만 추가되는 구조라 100건 검색에 0.057초로 끝났다. cross-encoder는 쌍마다 매번 새로 계산해야 해서, 같은 규모를 전체 검색에 그대로 썼다면 약 0.3초로 5배 이상 느려졌을 것이다. 반면 이미 추려진 상위 10건 재정렬에만 쓰면 0.031초로 충분히 감당할 수준이었다.
4. 인사이트 및 액션 (Insights & Action)
- 인사이트 (Insight): bi-encoder와 cross-encoder는 우열이 아니라 “몇 건을 대상으로 하느냐”에 따라 유리한 지점이 갈린다. 문서 전체를 대상으로 하는 1차 검색엔 계산량이 문서 수에 비례하지 않는 bi-encoder가 맞고, 이미 후보가 좁혀진 재정렬엔 정확도가 높은 cross-encoder가 맞다.
- 실행 방안 (Action Plan): 검색 파이프라인을 설계할 때 “전체 대상 1차 검색”과 “소수 후보 재정렬”을 처음부터 분리한다. 1차 검색은 bi-encoder(또는 키워드 검색)로 넓게, 재정렬은 cross-encoder로 좁게 적용해야 계산 비용이 문서 수에 비례해 폭발하지 않는다.
- 한 줄 결론 (Key Takeaway): bi-encoder는 문서 벡터를 미리 계산해두니 빠르고, cross-encoder는 매번 새로 계산해 느린 대신 정확해서, 검색은 bi-encoder로 넓게 걸고 재정렬만 cross-encoder로 좁게 돌린다. 샘플 코드
- 다음 스텝 (Next Step): 이번 비교는 문서 100건, 재정렬 후보 10건이라는 작은 규모였다. 문서가 수만 건 이상으로 늘어나면 bi-encoder 쪽 초기 색인 시간과 근사 인덱싱(ANN) 필요 여부, 그리고 재정렬 후보를 몇 건까지 넓혀도 cross-encoder 지연이 감당 가능한지의 경계값은 이번 데모로는 확인이 안 된다.
This post is licensed under CC BY 4.0 by the author.