실무 Multi-Agent 오케스트레이션 15장 · 검색 품질 개선 3 / 7 ← 이전목차다음 → TechLead Cro

15장. 검색 품질 개선

하이브리드 검색 — 두 검색의 결과를 합친다

한 줄 요약

하이브리드 검색(hybrid search) 은 벡터 검색과 키워드 검색의 결과를 합쳐서 후보를 만드는 방법입니다. 목표는 1위를 정확히 고르는 것이 아니라 정답 청크를 후보 안에 넣는 것입니다. 우리는 두 결과를 번갈아 담습니다.


1. 무엇을 위한 단계인가

검색을 두 단계로 나눠 생각합니다.

단계 목표 중요한 것
후보 모으기 정답 청크를 빠뜨리지 않는다 넓게. 순서는 덜 중요하다
순서 매기기 후보 중 정말 쓸모 있는 것을 위로 올린다 정확하게

하이브리드 검색은 후보 모으기를 맡습니다. 벡터 검색이 놓친 청크를 키워드 검색이 건져 오면, 몇 위로 들어오든 일단 후보에 들어옵니다. 순서는 다음 단계(리랭킹)가 다시 매깁니다.


2. 합치는 코드

이번 장의 파일에 들어 있는 함수입니다.

def hybrid_search(query: str, k: int = 6) -> list[str]:
    """벡터 1위, 키워드 1위, 벡터 2위, 키워드 2위 … 순서로 담는다.
    벡터 결과를 먼저 다 담으면 k 개가 차서 키워드 결과가 전부 잘린다."""
    merged = []
    for pair in zip_longest(vector_search(query, k), keyword_search(query, k)):
        for t in pair:                     # 짧은 쪽이 끝나면 None 이 온다
            if t is not None and t not in merged:
                merged.append(t)
    return merged[:k]
코드 하는 일
zip_longest(벡터 결과, 키워드 결과) 두 목록에서 같은 순위끼리 짝을 지어 줍니다. (벡터 1위, 키워드 1위), (벡터 2위, 키워드 2위) …
if t is not None 키워드 검색은 k개보다 적게 돌려줄 수 있습니다. 짧은 쪽이 끝나면 zip_longest가 None을 주므로 건너뜁니다
t not in merged 두 검색이 같은 청크를 찾았으면 한 번만 담습니다
merged[:k] 합친 목록의 앞에서 k개를 남깁니다

담기는 순서는 벡터 1위, 키워드 1위, 벡터 2위, 키워드 2위 … 입니다.


3. 왜 번갈아 담는가

벡터 검색은 항상 k개를 돌려줍니다(13장). 그래서 벡터 결과를 먼저 다 담고 그 뒤에 키워드 결과를 이으면, 앞의 k자리를 벡터 결과가 모두 차지합니다. 번갈아 담으면 양쪽의 상위 결과가 모두 앞자리에 옵니다. 키워드 검색이 1위로 찾은 청크는 늦어도 둘째 자리에 들어옵니다.

이번 장의 질문으로 확인한 결과입니다(재작성한 문장 하나로 검색했습니다. 숫자는 청크 id의 끝 세 자리, *가 정답 청크입니다).

벡터 검색          009  010  007  006*  005  008
키워드 검색         006*  003  008  005  009  001
번갈아 담기         009  006*  010  003  007  008

정답 청크 006은 벡터 검색에서 4위였고 키워드 검색에서 1위였습니다. 번갈아 담으니 2번째 자리에 들어왔습니다.


4. 순위를 합치는 다른 방법 — RRF

두 검색의 점수를 그대로 더하지는 않습니다. 벡터 검색의 거리는 0.5 근처의 값이고 작을수록 좋습니다. BM25 점수는 눈금도 다르고 클수록 좋습니다. 눈금과 방향이 다른 두 숫자는 그대로 더할 수 없습니다. 그래서 점수 대신 순위를 씁니다.

순위를 합치는 방법으로 널리 쓰이는 것이 RRF(Reciprocal Rank Fusion, 역순위 융합) 입니다. 검색마다 1 / (k + 순위)를 점수로 주고(k는 보통 60), 청크별로 더해 큰 순서로 고릅니다. 두 검색 모두에서 순위가 높은 청크가 가장 위로 옵니다.

방법 어떻게 특징
번갈아 담기 (우리 코드) 벡터 1위, 키워드 1위, 벡터 2위 … 단순하다. 양쪽의 상위 결과가 모두 앞에 온다
RRF 순위를 점수로 바꿔 더한다 양쪽 모두에 나온 청크가 더 위로 온다

번갈아 담기는 RRF에서 "두 검색에 모두 나온 청크의 점수를 더해 위로 올리는" 부분을 뺀 단순형입니다. 우리는 뒤에 리랭킹이 순서를 다시 매기므로 단순형을 씁니다. RRF는 실습문제 2에서 직접 만들어 비교합니다.


5. 하이브리드가 해 주지 못하는 것

  • 순서를 정확히 매기지 못합니다. 합친 순서는 정답에 가까운 순서가 아닙니다. 그 일은 리랭킹이 합니다.
  • 키워드 검색이 약하면 보탬도 약합니다. 앞 절에서 본 대로 공백으로만 자른 키워드 검색은 놓치는 것이 많습니다.
  • 두 검색이 모두 놓친 청크는 여전히 없습니다. 그럴 때는 질문 자체를 바꿔야 합니다. 다음 절의 쿼리 재작성입니다.

핵심 정리

  • 하이브리드 검색은 후보 모으기 단계입니다. 목표는 정답 청크를 후보에 넣는 것입니다.
  • 두 결과를 번갈아 담고, 겹치는 것은 한 번만 담고, 앞에서 k개를 남깁니다.
  • 번갈아 담으면 양쪽의 상위 결과가 모두 앞자리에 옵니다.
  • 눈금과 방향이 다른 두 점수는 그대로 더하지 않습니다. 순위를 씁니다.
  • 순위를 점수로 바꿔 더하는 표준 방법이 RRF이고, 번갈아 담기는 그 단순형입니다.
← 이전 절키워드 검색과 BM25 — 단어로 찾는 검색을 다시 꺼낸다다음 절 →쿼리 재작성과 리랭킹 — 질문을 고치고, 순서를 다시 매긴다
오명운 · macro@prag-ai.com