Tan Kim

naive-merge

Naive Merge

Naive Merge는 복수의 retriever 또는 RAG 파이프라인이 반환한 문서 목록을 별도의 점수 계산이나 재정렬 없이 단순히 이어 붙이는(concatenate) 가장 기본적인 병합 방식이다. 구현이 극도로 단순하며, 다른 병합 전략의 비교 베이스라인으로 사용된다.

핵심 개념

Naive Merge의 전제는 "각 retriever가 반환한 순서 자체가 충분히 좋은 랭킹이다"라는 가정이다. 오케스트레이터는 각 파이프라인의 결과를 순서대로 받아 중복만 제거하고 LLM 컨텍스트에 넣는다.

def naive_merge(results: list[list[Document]]) -> list[Document]:
    seen_ids = set()
    merged = []
    for result_list in results:
        for doc in result_list:
            if doc.id not in seen_ids:
                seen_ids.add(doc.id)
                merged.append(doc)
    return merged

동작 방식

순서 우선 방식 (First-come)

retriever 목록의 순서를 우선순위로 취급한다. 예를 들어 RAG-A 결과를 먼저 넣고, RAG-B 결과를 이어 붙인다. 이 경우 RAG-A에 암묵적인 가중치가 부여된다.

라운드로빈 방식

각 retriever에서 한 건씩 번갈아 가져와 병합한다. 특정 retriever가 결과를 독점하지 못하도록 고르게 섞는다.

def round_robin_merge(results: list[list[Document]]) -> list[Document]:
    from itertools import zip_longest
    merged, seen = [], set()
    for group in zip_longest(*results):
        for doc in group:
            if doc and doc.id not in seen:
                seen.add(doc.id)
                merged.append(doc)
    return merged

장단점

항목 내용
장점 구현이 단순, 추가 레이턴시 없음, 디버깅이 쉬움
단점 각 retriever 스코어 무시, 관련성 낮은 문서가 상위에 올 수 있음
단점 LLM 컨텍스트 길이 낭비 가능 (중요 문서가 뒤에 묻힘)

적합한 상황

  • 각 retriever가 완전히 다른 문서 집합을 반환하는 경우 (중복이 거의 없을 때)
  • 결과 병합보다 파이프라인 연결 자체를 먼저 검증하는 프로토타입 단계
  • 각 retriever의 결과 품질이 이미 매우 높아 재정렬이 불필요한 경우

주의사항

LLM은 컨텍스트의 앞부분에 더 집중하는 경향(Lost in the Middle 현상)이 있다. Naive Merge에서 retriever 순서가 결과 품질에 직접 영향을 미치는 이유다. 순서 설계를 신중히 해야 한다.

관련 개념

  • Score Fusion: 각 retriever의 점수를 정규화하고 가중합산하는 방식
  • Reciprocal Rank Fusion: 점수 대신 순위(rank)를 기반으로 병합하는 방식
  • Reranker-centric: 병합 후 reranker 모델로 최종 정렬하는 방식