23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
안녕하세요, SK C&C AI Engineer 배준호입니다.
최근 AI 기술 분야에서는 대규모 언어 모델(Large Language Model, LLM)을 활용하여 정확하고 관련성 높은 응답을 생성하는 RAG(Retrieval-Augmented Generation)가 큰 주목을 받고 있습니다.
특히 기술 커뮤니티를 중심으로 Agentic RAG, Modular RAG 등 다양한 형태의 접근법이 활발히 논의되며 발전하고 있습니다.
이처럼 RAG의 구현 방식에는 여러 접근 방식이 존재하지만, 정보 검색(Information Retrieval)과 답변 생성(Generation)이라는 두 가지 기본 축은 변하지 않습니다.
그렇다면 RAG에서 리랭커(Reranker)는 왜 필요하고, 어떤 역할을 수행할까요?
RAG에서는 보통 사용자의 자연어 질문을 임베딩(Embedding)하여, 벡터 공간상에서 가장 유사한 정보를 찾는 벡터 검색(Vector Search)을 통해 관련성이 높은 문서를 찾게 됩니다.
하지만 벡터 검색만으로는 사용자의 질문에 가장 적합한 답변을 제공하기 어려운 부분이 있습니다.
이는 검색된 문서가 질문의 실제 의도를 정확히 반영하지 못하거나 대화의 맥락을 놓칠 수 있기 때문입니다.
따라서, 이러한 문제를 해결하기 위해 검색된 문서를 질문과의 관련성에 따라 재정렬하는 것이 리랭커(Reranker)의 핵심 역할입니다.
앞으로 리랭커가 정보 검색과 LLM 사이에서 어떤 역할을 수행하는지 구체적으로 살펴보고, 리랭커의 설계 및 적용 방법에 대해서도 함께 다뤄보겠습니다.
리랭커의 역할을 이해하기 위해 먼저 RAG 구조를 간략히 살펴보겠습니다.
RAG는 사용자의 질문에 대해 가장 관련성 높은 정보를 내부 또는 외부의 문서에서 검색하여,
이를 LLM의 입력으로 제공함으로써 답변의 정확성을 높이고 모델의 환각(Hallucination)을 줄이는 기술입니다.
특히 금융, 의료, 법률처럼 정확한 도메인 지식이 중요한 프로덕션 환경에서는 잘못된 정보가 사용자에게 제공될 경우 큰 문제가 발생할 수 있습니다.
따라서 정보 검색 단계에서 얼마나 정확하고 적절한 문서를 찾느냐가 RAG 서비스 품질을 결정하는 중요한 요인이 됩니다.
이러한 이유로, 초기 검색 결과를 다시 한 번 정밀하게 평가하여 질문과의 관련성에 따라 재정렬하는 리랭킹(Reranking) 과정이 중요하게 대두되었습니다.
즉, 리랭커(Reranker)는 질문과의 관련성이 높은 문서를 LLM 입력의 상단에 위치시킴으로써 LLM이 보다 정확하고 일관된 답변을 생성하도록 돕는 역할을 하게 됩니다.
그렇다면, 어떤 이유로 인해 문서를 LLM 입력의 상단으로 재정렬해야 할까요?
관련 연구에 따르면, LLM은 컨텍스트 내 문서의 위치에 따라 답변의 품질이 크게 달라지는 것으로 밝혀졌습니다.
특히 컨텍스트의 길이가 길어질수록, 중요한 정보가 중간에 위치하면 LLM이 이를 제대로 반영하지 못하는 'Lost in the Middle' 현상이 발생할 위험이 있습니다.
위와 같이 LLM에 전달되는 후보 문서들의 순서에 따라 응답 정확도에 차이가 발생하며, 질의에 관련한 문서가 가운데에 위치할 경우 정확도가 가장 낮아지는 것을 확인할 수 있습니다.
따라서 가장 관련성이 높은 문서를 LLM이 우선적으로 참조할 수 있도록 입력의 상단에 위치시키는 것이 필요하며, 이를 위해 리랭커를 활용한 문서 순위 재정렬이 사용됩니다.
리랭커를 구현하는 대표적 방법 중 하나는 Cross-Encoder 방식입니다.
Cross-Encoder는 질의(Query)와 문서(Document)를 독립적으로 처리하지 않고, 둘을 결합해 모델에 하나의 입력으로 제공합니다.
이 과정에서 모델은 질의와 문서 사이의 맥락적 연관성을 직접 고려하여 더욱 정확하고 세밀한 평가가 가능합니다.
아래는 Huggingface에 업로드된 Cross-Encoder 기반의 리랭커 모델인 bge-reranker를 이용한 코드 예제입니다.
import torch from transformers
import AutoModelForSequenceClassification, AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('BAAI/bge-reranker-v2-m3')
model = AutoModelForSequenceClassification.from_pretrained('BAAI/bge-reranker-v2-m3')
model.eval()
# 질의와 문서를 묶어 리스트 형태(pair)로 입력으로 준비합니다. 이때 각각의 질의-문서 쌍이 하나의 입력으로 결합됩니다.
pairs = [['코코넛이 뭐야?', '코코넛 밀크는 코코넛의 과육으로부터 얻은 달콤하고 유백색을 띠는 음식 재료이다.'], ['코코넛이 뭐야?', '코코넛은 코코야자나무의 열매이다. 풋열매나 익은 열매를 과일로 먹는다.']]
# 질의와 문서를 결합하여 하나의 텍스트로 토크나이징하고, padding 및 truncation을 적용하여 모델 입력 형식으로 변환합니다.
with torch.no_grad():
inputs = tokenizer(pairs, padding=True, truncation=True, return_tensors='pt', max_length=512)
scores = model(**inputs, return_dict=True).logits.view(-1, ).float() # 질의 문서 쌍을 모델에 전달하여 두 문서가 질의와 얼마나 관련 있는지 점수(logit)를 계산합니다.
print(scores)
>>>
# 출력된 값은 각 질의-문서 쌍의 연관성 점수이며, 점수가 높을수록 질의와 문서가 더 관련성이 높다는 의미입니다.
tensor([-1.9776, 4.5902])예제 결과에서 코코넛 밀크에 대한 첫번 째 문장보다 코코넛에 대한 두 번째 문장이 유저가 입력한 질의("코코넛이 뭐야?")와 더 관련성이 높다는 것을 알 수 있습니다.
이와 같은 방식을 통해, Cross-Encoder 리랭커는 질의와 문서 간의 맥락적 관계를 직접 평가하여 정확한 랭킹을 수행하게 됩니다.
하지만 Cross-Encoder를 이용할 경우, 모든 질의-문서 쌍을 개별적으로 모델이 계산해야 하므로 처리 속도가 상대적으로 느리다는 단점이 있습니다.
따라서 Cross-Encoder는 보통 Bi-Encoder 기반의 벡터 검색이 추출한 후보 문서(상위 K개 이하)를 대상으로 2차적으로 리랭킹할 때 사용됩니다.
Bi-Encoder 방식은 질의와 문서를 각각 독립적으로 임베딩한 후, 두 임베딩 벡터 간의 유사도를 통해 문서를 평가하는 방식입니다.
Bi-Encoder 방식을 이용하면 문서를 사전에 임베딩해 Vector DB에 저장한 뒤 빠르게 실시간 검색이 가능하지만, 세부적인 맥락을 놓칠 수 있다는 한계가 있습니다.
따라서 대부분의 RAG 시스템은 다음 두 단계를 결합하여 정보 검색 성능을 향상시키는 구조를 갖고 있습니다.
첫 번째 단계에서는 Bi-Encoder 기반의 벡터 검색을 이용해 방대한 문서 데이터베이스에서 빠르게 후보 문서를 추출합니다.
두 번째 단계에서는 Cross-Encoder 기반 리랭커가 이 후보 문서들 중 질의와의 상세한 관련성을 평가하여 보다 정확한 순위로 재정렬합니다.
다음 챕터에서는 LLM을 이용하여 리랭커를 구성하는 방법에 대해 알아보겠습니다.
최근 GPT와 같은 LLM의 성능이 크게 향상됨에 따라, LLM 자체를 리랭커로 활용하여 후보 문서들을 직접 평가하고 순위를 매기는 연구가 활발히 진행 중입니다.
LLM을 이용한 접근법은 대표적으로 Zero-shot 기반의 Pointwise 방식과 Listwise 방식이 존재합니다.
Pointwise 방식에서는 문서 각각을 독립적으로 평가해 관련성 점수를 매깁니다.
주로 이진 분류(Binary Classification) 형식으로 평가하여, 문서가 질의에 대해 답변을 제공하는지(Yes/No)를 판단하고, 이 확률을 점수로 활용하게 됩니다.
이때, 확률 p는 LLM이 출력 토큰을 생성할 때 내부적으로 계산하는 log probability 기반의 확률 값입니다.
질의와 후보 문서가 주어졌을 때, 다음과 같은 프롬프트를 LLM에 전달합니다.
prompt = "다음 문서가 주어진 쿼리에 대한 답변을 포함하고 있나요? Yes 또는 No로 답하세요."그 결과 모델은 'Yes' 또는 'No'를 출력하며, 각 응답의 확률 p(Yes), p(No)를 바탕으로 관련성 점수 s를 산출합니다.
모델이 'Yes'라고 응답하고, 그 확률이 높을수록 → 높은 점수를 받게 됩니다. (ex. 1 + 0.9 = 1.9)
모델이 'No'라고 응답하고, 그 확률이 높을수록 → 낮은 점수를 받게 됩니다. (ex. 1 - 0.9 = 0.1)
정리하면, 모델이 'Yes'에 높은 확률을 부여할수록 해당 문서가 쿼리와 관련성이 높다고 판단되어 상위에 랭킹됩니다.
반대로 'No'에 높은 확률을 부여한 문서는 관련성이 낮은 것으로 평가되어 순위가 내려가게 됩니다.
이 방식은 주로 질의-문서 쌍에 정답 여부에 대한 레이블로 학습한 지도학습 기반의 모델에서도 활용하는 리랭킹 방식입니다.
만약 LLM을 이용해 Pointwise 리랭킹을 할 경우, 특정 Domain/Task에 맞는 라벨링된 데이터 없이 사전학습된 모델만으로 문서 재정렬을 할 수 있다는 큰 장점이 있습니다.
하지만 LLM에서 출력되는 확률은 개별 문서에 대한 보정되지 않은(Uncalibrated) 확률이기 때문에 전체 문서의 재정렬 결과에 대한 신뢰도 평가가 어렵고,
API 기반 LLM에서는 출력 토큰에 대한 확률값을 얻는 데 한계가 있다는 문제점이 존재합니다.
이러한 단점을 보완하기 위해, 최근에는 후보 문서 간 상대적 우선순위를 고려할 수 있는 Listwise 방식이 널리 사용되고 있습니다.
Listwise 방식은 질의와 여러 후보 문서를 동시에 프롬프트에 포함시켜 한 번에 LLM이 전체 문서 간 상대적 관련성에 따라 직접 순서를 결정하는 방법입니다.
이 방식에서는 각 문서를 고유한 식별자(ex. [1], [2], …)와 함께 LLM에 전달한 후, 모델이 직접적으로 정렬된 순서를 출력하게 됩니다.
아래 프롬프트는 Listwise 방식의 리랭킹의 예시입니다.
prompt = '''
주어진 쿼리와의 관련성에 따라 다음 문서들의 순위를 매기세요.
[1] 후보 문서 1
[2] 후보 문서 2
[3] 후보 문서 3 ...
순위는 식별자를 사용하여 내림차순으로 나열하세요 (ex. [2] > [3] > [1] ... )
'''Listwise 방식을 이용하면, 별도의 확률 계산 없이 내림차순으로 나열된 식별자를 파싱하여 문서 재정렬에 사용할 수 있다는 장점이 있습니다.
따라서 LLM의 출력을 직접적으로 문서 재정렬에 사용할 수 있어 편리하나, 토큰 길이 제한 때문에 한 번에 평가할 수 있는 문서 수가 제한된다는 한계가 있습니다.
이를 보완하기 위해, 많은 문서를 처리할 때 슬라이딩 윈도우(Sliding Window) 방식을 사용할 수 있습니다.
예를 들어, 벡터 검색에서 M개의 문서를 반환했다면, 문서 목록 뒤에서 앞으로 윈도우 크기 w, 스텝 크기 s 로 이동하며 점진적으로 리랭킹을 수행합니다.
먼저, 문서 끝에서부터 (M−w+1)번째부터 M번째까지 문서를 리랭킹합니다.
이후 스텝 크기 s만큼 앞으로 이동하여 리랭킹을 반복하며, 문서 목록의 맨 앞까지 진행합니다.
이와 같이 문서 목록의 끝에서부터 일정 크기(w)만큼씩 끊어서 리랭킹을 반복 수행함으로써, 입력 토큰 제한에 관계 없이 전체 문서의 순위 재정렬을 할 수 있게 됩니다.
이번 포스팅에서는 RAG에서 리랭커가 필요한 이유와 역할, 그리고 기존 리랭커 방식부터 최근 활발히 연구되고 있는 LLM 기반 리랭커까지 다뤄보았습니다.
LLM 기반 리랭커는 별도의 학습 없이도 뛰어난 성능을 보여줄 뿐 아니라, API를 이용해 간편히 RAG 프로덕트를 구성할 수 있다는 큰 장점이 있습니다.
그러나 LLM의 특성 상 input 순서에 따라 결과가 달라질 수 있고, 도메인 특화된 지식을 반영하지 못할 수 있다는 단점 역시 존재합니다.
이런 한계를 극복하기 위한 다양한 연구들이 정보 검색(IR) 분야에서 진행 중이며, 다음 포스팅에서는 이러한 최신 기술 동향을 더 깊이 다뤄보겠습니다.
또한, 특히 최근 관심이 높아지고 있는 이미지와 텍스트를 결합한 멀티모달(Multimodal) RAG와 리랭킹 기법도 함께 소개 드리겠습니다.
Chen, J., Xiao, S., Zhang, P., Luo, K., Lian, D., & Liu, Z. (2024). BGE M3-Embedding: Multi-lingual, multi-functionality, multi-granularity text embeddings through self-knowledge distillation. arXiv preprint arXiv:2402.03216.
Liang, P., Bommasani, R., Lee, T., Tsipras, D., Soylu, D., Yasunaga, M., ... & Koreeda, Y. (2022). Holistic evaluation of language models. arXiv preprint arXiv:2211.09110.
Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F., & Liang, P. (2024). Lost in the middle: How language models use long contexts. Transactions of the Association for Computational Linguistics, 12, 157-173.
Ma, X., Zhang, X., Pradeep, R., & Lin, J. (2023). Zero-shot listwise document reranking with a large language model. arXiv preprint arXiv:2305.02156.
Qin, Z., Jagerman, R., Hui, K., Zhuang, H., Wu, J., Yan, L., ... & Bendersky, M. (2023). Large language models are effective text rankers with pairwise ranking prompting. arXiv preprint arXiv:2306.17563.
Sun, W., Yan, L., Ma, X., Wang, S., Ren, P., Chen, Z., ... & Ren, Z. (2023). Is ChatGPT good at search? Investigating large language models as re-ranking agents. arXiv preprint arXiv:2304.09542.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.