jaysnote
7분

RAG 검색의 세 단계: 바이 인코더, 크로스 인코더, LLM rerank

RAG 검색에서 바이 인코더, 크로스 인코더, LLM rerank가 후보 검색과 정밀한 문서 선택을 어떻게 나누어 맡는지 설명합니다.

질문과 문서를 검색 시스템에 넣었을 때, 가장 먼저 필요한 일은 수백만 개 문서에서 후보를 줄이는 일이다. 그 다음에는 후보 문서가 질문에 실제로 답하는지 더 자세히 판단해야 한다. 한 모델로 두 일을 모두 해결하려고 하면 빠른 검색과 정밀한 비교 중 하나를 포기하게 된다.

예를 들어 질문이 고양이가 개를 쫓았는가?라고 하자. 문서에 개, 고양이, 쫓다가 모두 들어 있어도 개가 고양이를 쫓았다라는 문서는 질문의 답이 아니다. 단어가 겹치는지 보는 것과 두 문장의 관계를 확인하는 것은 다른 문제다.

RAG 검색에서는 이 문제를 여러 단계로 나눈다.

바이 인코더, 크로스 인코더, LLM rerank를 거쳐 답변을 만드는 검색 파이프라인

바이 인코더는 넓게 찾는다

바이 인코더는 질문과 문서를 각각 따로 인코딩한다. 질문을 인코더에 넣어 벡터를 만들고, 문서도 같은 방식으로 벡터를 만든다. 두 벡터의 유사도를 계산해 질문과 가까운 문서를 찾는다.

질문 → Encoder A → 질문 벡터
문서 → Encoder B → 문서 벡터

질문 벡터 ↔ 문서 벡터 → 유사도 점수

문서 벡터는 질문이 들어오기 전에 미리 계산해 벡터 데이터베이스에 저장할 수 있다. 사용자가 질문을 보내면 질문 벡터만 만든 뒤, Approximate Nearest Neighbor 검색으로 가까운 문서 벡터를 빠르게 찾는다. 수백만 개 문서에서 상위 50개나 100개 후보를 고르는 단계에 잘 맞는 이유다.

바이 인코더의 장점은 속도와 확장성이다. 문서마다 매번 질문과 함께 Transformer를 실행하지 않아도 된다. 새 문서가 추가될 때 문서 벡터를 한 번 계산해 저장하면 된다.

대신 비교가 마지막 벡터 유사도에 의존한다. 질문과 문서의 단어 관계, 부정, 숫자, 주어와 목적어 순서가 벡터 하나에 압축되면서 세밀한 차이가 약해질 수 있다. 그래서 바이 인코더의 결과를 최종 답변에 바로 쓰기보다 정밀 비교를 위한 후보 목록으로 사용한다.

크로스 인코더는 좁혀진 후보를 함께 읽는다

크로스 인코더는 질문과 문서를 각각 따로 벡터로 만들지 않는다. 두 텍스트를 하나의 입력으로 이어 붙여 Transformer에 넣는다.

[CLS] 질문 [SEP] 문서 [SEP]

바이 인코더와 크로스 인코더의 입력 구조 비교

이 입력은 하나의 self-attention 공간에서 처리된다. 질문의 겨울 토큰은 문서의 겨울 토큰을 참고할 수 있고, 날씨 토큰은 문서의 춥고 건조하다와 연결될 수 있다. 각 층을 지나면서 토큰의 표현이 상대 텍스트의 문맥을 반영하도록 바뀐다.

크로스 인코더의 입력, self-attention, 관련성 점수 계산

마지막에는 보통 [CLS] 토큰의 표현을 꺼내 분류 head나 선형 계층에 넣는다. 출력은 두 텍스트가 얼마나 관련 있는지를 나타내는 점수다.

[CLS]의 최종 표현
→ 분류 head
→ 관련성 점수

학습 데이터에는 같은 질문에 대한 관련 문서와 무관한 문서가 함께 들어간다. 관련 문서에는 높은 점수, 무관한 문서에는 낮은 점수를 주도록 학습하거나, 관련 문서가 오답 문서보다 높은 순위를 갖도록 pairwise loss를 사용한다.

크로스 인코더가 정확한 이유는 두 텍스트가 마지막에만 만나는 것이 아니라 Transformer의 각 층에서 계속 상호작용하기 때문이다. 고양이가 개를 쫓았다와 개가 고양이를 쫓았다처럼 단어는 비슷하지만 관계가 다른 문장도 비교할 수 있다.

대신 질문과 문서의 모든 토큰을 함께 처리해야 한다. 질문 길이를 m, 문서 길이를 n이라고 하면 attention 계산량은 대략 전체 길이 (m+n)의 제곱에 비례한다. 후보 문서가 100개면 같은 계산을 100번 반복해야 한다. 수백만 개 문서 전체에 크로스 인코더를 적용하지 않는 이유다.

LLM rerank는 복합적인 판단을 맡는다

크로스 인코더는 학습된 관련성 기준으로 빠르고 일관되게 점수를 낸다. 그런데 실제 서비스에서는 관련성 외에도 다음 조건을 함께 봐야 할 때가 있다.

  • 질문의 모든 조건을 문서가 충족하는가
  • 문서가 실제 답변에 사용할 근거를 포함하는가
  • 같은 내용을 반복하는 후보가 여러 개 들어왔는가
  • 서로 충돌하는 문서 중 어느 쪽을 우선해야 하는가
  • 질문이 요구한 형식이나 범위를 지키는가

이런 판단은 LLM에 후보 문서 몇 개를 함께 보여 주고 최종 순서를 정하게 할 수 있다. 예를 들면 다음과 같은 요청이다.

질문: 서울의 겨울 날씨와 옷차림을 알려줘.

후보 문서 1: 서울의 겨울 평균 기온과 강수량
후보 문서 2: 서울 여행에서 준비할 옷
후보 문서 3: 한국의 사계절 개요

질문에 직접 답할 수 있는 순서대로 정렬하고,
각 문서의 점수와 짧은 근거를 JSON으로 출력하라.

LLM rerank는 세 가지 방식으로 구성할 수 있다.

방식LLM에게 주는 입력장점한계
pointwise질문과 문서 한 쌍구현이 단순함후보마다 호출하거나 긴 입력을 반복함
pairwise질문과 문서 두 개어느 문서가 더 나은지 비교하기 쉬움비교 횟수가 늘어남
listwise질문과 후보 목록 전체전체 순위와 중복을 함께 판단함입력이 길어지고 순위가 흔들릴 수 있음

LLM의 출력은 자유로운 문장보다 점수, 순위, 근거를 담은 구조화된 JSON으로 제한하는 편이 운영하기 쉽다. 그래도 LLM 점수는 크로스 인코더 점수처럼 항상 같은 기준으로 재현된다고 보장하기 어렵다. 모델 버전, 프롬프트, 후보 순서에 따라 결과가 달라질 수 있고, 호출 비용과 지연 시간도 추가된다.

그래서 LLM rerank는 기본 검색기를 대체하는 단계가 아니라, 후보가 적고 판단 기준이 복잡한 경우에 선택적으로 붙이는 단계로 보는 것이 안전하다.

세 단계는 어떻게 이어질까

실제 RAG 검색은 다음 순서로 구성할 수 있다.

1. 바이 인코더로 Top 100 후보 검색
2. 크로스 인코더로 Top 20 재정렬
3. 필요하면 LLM으로 Top 5 최종 판단
4. 선택된 문서를 LLM의 context로 넣어 답변 생성

각 단계는 앞 단계보다 느리고 비싸지만, 처리해야 할 문서 수는 작아진다. 전체 문서를 LLM에 보내지 않고, 먼저 값싼 검색으로 후보를 줄이는 이유다.

상황더 맞는 구성이유
문서가 매우 많고 응답 시간이 짧아야 함바이 인코더문서 벡터를 미리 만들고 빠르게 후보를 찾을 수 있음
검색 결과의 순위가 중요함바이 인코더 + 크로스 인코더빠른 후보 생성과 정밀한 쌍별 비교를 결합함
여러 문서의 중복, 충돌, 답변 가능성을 판단해야 함크로스 인코더 + 선택적 LLM rerank문서 간 관계와 복합적인 기준을 함께 볼 수 있음
후보가 적고 비용보다 품질이 중요함LLM rerank 추가사람이 읽고 고르는 판단에 가까운 기준을 적용할 수 있음

작은 예제로 보면

질문이 서울의 겨울 날씨와 여행 준비물을 알려줘라고 하자. 벡터 검색은 다음 세 문서를 후보로 가져올 수 있다.

  1. 서울의 겨울 평균 기온과 강수량
  2. 겨울철 서울 여행 준비물
  3. 한국의 사계절을 소개하는 일반 문서

바이 인코더는 세 문서가 질문과 의미적으로 가깝다고 판단할 수 있다. 크로스 인코더는 질문의 날씨와 준비물이 각각 어느 문장에 근거를 갖는지 확인해 1번과 2번을 위로 올린다. LLM rerank를 추가하면 1번과 2번이 서로 다른 정보를 제공한다는 점을 반영하고, 3번은 넓은 배경 설명일 뿐 직접적인 답변 근거가 약하다고 판단할 수 있다.

이 결과를 생성 모델에 넣을 때는 1번과 2번을 우선 context로 사용한다. 검색 단계에서 순위를 잘못 정하면 생성 모델이 아무리 유창해도 필요한 근거를 놓칠 수 있다.

어디에서 멈출지 평가해야 한다

크로스 인코더나 LLM을 추가할 때는 “더 복잡한 모델이 더 좋다”는 가정부터 하지 않는 편이 좋다. 실제 질문 세트를 고정하고 단계별 결과를 비교해야 한다.

  • Recall@K: 정답 문서가 상위 K개 후보 안에 들어오는가
  • MRR: 첫 번째 정답 문서가 얼마나 앞에 오는가
  • nDCG: 여러 정답 문서의 순위 품질이 어떤가
  • 답변 정확도: 최종 생성 답변이 근거와 질문을 제대로 반영하는가
  • 지연 시간과 비용: 품질 개선이 추가 계산량을 감당할 만한가

바이 인코더에서 정답 문서가 후보 목록에 들어오지 않으면 뒤의 rerank 모델은 이를 복구할 수 없다. 반대로 후보가 충분히 좋은데도 크로스 인코더나 LLM을 계속 추가하면 지연 시간만 늘어날 수 있다. 먼저 바이 인코더의 후보 재현율을 확인하고, 그 다음 크로스 인코더의 순위 개선 폭, 마지막으로 LLM rerank의 실제 답변 개선 폭을 따로 측정해야 한다.

바이 인코더는 넓게 찾고, 크로스 인코더는 두 텍스트를 함께 읽어 정밀하게 비교하며, LLM rerank는 필요한 경우 여러 후보를 복합적인 기준으로 판단한다. RAG에서 세 모델은 경쟁 관계라기보다 서로 다른 비용과 판단 범위를 맡는 계층형 검색 구성 요소다.

관련 글

← 목록으로