소소한 컴퓨터 이야기

Re-ranking (이론)

by Cori

해당 포스트는 Medium 'Florian June'이 작성한 Advanced RAG 포스트 시리즈 그 네번째 내용을 정리하며, RAG의 Re-Ranking 기술을 소개하고, 두 가지 방법을 사용하여 해당 기능을 통합하는 방법에 대해 다루고 있다.


재랭킹은 Retrieval Augmented Generation (RAG) 과정에서 중요한 역할을 한다. 단순한 RAG 접근법에서는 많은 문맥이 검색될 수 있지만, 이들 모두가 질문과 관련이 있는 것은 아니다. 재랭킹은 문서의 순서를 재정렬하고 필터링하여 관련 문서를 최상단에 배치한다.

 

Introduction to Re-ranking

검색기가 인덱스된 컬렉션에서 여러 문맥을 검색할 때, 이러한 문맥들은 사용자 쿼리와의 관련성이 다를 수 있다. 일부 문맥은 매우 관련성이 높을 수 있고, 다른 문맥들은 약간 관련이 있거나 심지어 무관할 수도 있다. 재랭킹 작업의 목적은 이러한 문맥들의 관련성을 평가하고, 정확하고 관련성 있는 답변을 제공할 가능성이 높은 문맥들을 우선시하는 것이다.

 

Using re-ranking model as reranker

재랭킹 모델은 임베딩 모델과 달리 쿼리와 문맥을 입력으로 받아 직접 유사도 점수를 출력하며, 임베딩을 출력하지 않는다. 재랭킹 모델은 교차 엔트로피 손실을 사용하여 최적화되므로, 특정 범위에 제한되지 않고 심지어 음수일 수도 있는 관련성 점수를 제공할 수 있다. 현재 사용할 수 있는 재랭킹 모델은 많지 않으며, Cohere에서 API를 통해 접근할 수 있는 온라인 모델이 대표적이다. 또한, bge-reranker-base와 bge-reranker-large와 같은 오픈 소스 모델들도 있다.

The evaluation results using the Hit Rate and Mean Reciprocal Rank (MRR) metrics, https://medium.com/towards-artificial-intelligence/advanced-rag-04-re-ranking-85f6ae8170b1

사용된 임베딩 모델과 관계없이, 리랭킹은 더 높은 히트율과 MRR을 보여준다. 임베딩 모델과 리랭킹 모델의 조합이 Hit Rage와 MRR 값에 영향을 미칠 수 있으므로, 개발자는 실제 과정에서 다양한 조합을 실험해 볼 필요가 있다.

bge-reranker를 이용해 리랭킹을 해보자. 

Step 1. Environment Configuration

import os
from llama_index import VectorStoreIndex, SimpleDirectoryReader
from llama_index.postprocessor.flag_embedding_reranker import FlagEmbeddingReranker
from llama_index.schema import QueryBundle

os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"
dir_path = "YOUR_DIR_PATH"

Step 2. Using LlamaIndex to build a simple retriever

documents = SimpleDirectoryReader(dir_path).load_data()
index = VectorStoreIndex.from_documents(documents)
retriever = index.as_retriever(similarity_top_k = 3)

Step 3. Basic Retrieving

from llama_index.schema import ImageNode, MetadataMode, NodeWithScore
from llama_index.utils import truncate_text

def display_source_node(
    source_node: NodeWithScore,
    source_length: int = 100,
    show_source_metadata: bool = False,
    metadata_mode: MetadataMode = MetadataMode.NONE,
) -> None:
    """Display source node"""
    source_text_fmt = truncate_text(
        source_node.node.get_content(metadata_mode=metadata_mode).strip(), source_length
    )
    text_md = (
        f"Node ID: {source_node.node.node_id} \n"
        f"Score: {source_node.score} \n"
        f"Text: {source_text_fmt} \n"
    )
    if show_source_metadata:
        text_md += f"Metadata: {source_node.node.metadata} \n"
    if isinstance(source_node.node, ImageNode):
        text_md += "Image:"
    print(text_md)
    
query = "Can you provide a concise description of the TinyLlama model?"
nodes = retriever.retrieve(query)
for node in nodes:
    print('----------------------------------------------------')
    display_source_node(node, source_length = 500)   # llama index 소스 코드 수정

쿼리와 유사도가 높은 노드들을 몇 개 추출해보면 다음과 같다. 

Step 4. Re-ranking

bge-reranker를 사용하여 노드들을 리랭킹해보자

reranker = FlagEmbeddingReranker(
    top_n = 3,
    model = "BAAI/bge-reranker-base",
)

query_bundle = QueryBundle(query_str=query)
ranked_nodes = reranker._postprocess_nodes(nodes, query_bundle = query_bundle)
for ranked_node in ranked_nodes:
    print('----------------------------------------------------')
    display_source_node(ranked_node, source_length = 500)

리랭킹 결과 노드들은 다음과 같이 정렬되며, 2등이었던 노드가 1등으로 올라간 것을 볼 수 있다. 


Using LLM as Reranker

RankGPT 논문은 세 가지 실현 가능한 방법을 제시한다. Query generation과 Relevance generation은 전통적인 방법으로, 각 문서에 점수를 부여한 다음 이 점수를 기준으로 모든 구절을 정렬한다. 세 번째 방법인 순열 생성(permutation generation)은 LLM의 의미 이해 능력을 직접 활용하여 모든 후보 구절의 관련성 순위를 매긴다. 단, 일반적으로 후보 문서의 수는 매우 많은 반면, LLM에 입력할 수 있는 양은 제한되어 있어 모든 텍스트를 한 번에 입력하는 것은 불가능하다.

다음은 슬라이딩 윈도우를 사용하여 8개의 구절을 재랭킹하는 예시로, 윈도우 크기는 4이고 스텝 크기는 2이다. 파란색은 처음 두 개의 윈도우를 나타내고, 노란색은 마지막 윈도우를 나타낸다. 슬라이딩 윈도우는 뒤에서 앞으로의 순서로 적용되며, 이전 윈도우의 첫 번째와 두 번째 구절이 다음 윈도우의 재랭킹에 참여한다.

RankGPT를 활용해 Re-ranking을 적용해보자

from llama_index.postprocessor import RankGPTRerank
from llama_index.llms import OpenAI
reranker = RankGPTRerank(
    top_n = 3,
    llm = OpenAI(model="gpt-3.5-turbo-16k"),
    # verbose=True,
)

전반적으로, 이 글은 재랭킹의 원리와 두 가지 주류 방법을 소개한다. 이 중 재랭킹 모델을 사용하는 방법은 경량이며 오버헤드가 적다. 반면, LLM을 사용하는 방법은 여러 벤치마크에서 성능이 뛰어나지만 비용이 더 많이 든다. 특히 ChatGPT와 GPT-4를 사용할 때 성능이 우수하지만, FLAN-T5 같은 다른 오픈 소스 모델을 사용할 때는 성능이 떨어진다.


Ref. 

https://medium.com/towards-artificial-intelligence/advanced-rag-04-re-ranking-85f6ae8170b1

블로그의 정보

코딩하는 오리

Cori

활동하기