단일 검색 시스템은 모든 상황에서 최적의 결과를 제공하지 못할 수 있습니다.
이러한 이유로 연구자들은 다양한 검색 시스템의 결과를 통합하여 더 나은 검색 결과를 제공하는 방법을 모색하고 있습니다. Reciprocal Rank Fusion(RRF)은 이러한 통합 방법 중 하나로, 다른 검색 시스템의 순위 정보를 결합하여 최종 순위를 생성하는 알고리즘입니다.
(이전 글 참고)
저는 키워드 검색과, 밀집 벡터 검색을 query1 과 query2로 사용하였습니다.
검색결과를 ids 값으로 받습니다.
# 검색 결과 예시
query1_ids = [1, 30, 50, 128, 301]
query2_ids = [30, 128, 1, 120, 50]
def get_ranking(query1_ids, query2_ids):
# 중복 없는 모든 값들을 구합니다.
all_values = list(set(query1_ids + query2_ids))
# 결과를 저장할 딕셔너리를 초기화합니다.
ranking = {}
# 모든 값을 순회하면서 해당 값의 순위를 구합니다.
for value in all_values:
rank1 = query1_ids.index(value) + 1 if value in query1_ids else None
rank2 = query2_ids.index(value) + 1 if value in query2_ids else None
ranking[value] = [rank1, rank2]
return ranking
검색 결과:
{
128: [4, 2],
1: [1, 3],
301: [5, None],
50: [3, 5],
120: [None, 4],
30: [2, 1]
}
def reciprocal_rank(self, rank):
"""주어진 순위에 대한 Reciprocal Rank를 계산하는 함수"""
try:
return 1 / rank
except TypeError:
return 0.0
해당 랭킹들을 0~1값으로 치환합니다.
1등의 경우 1.0
2등의 경우 0.5
EMBED_WEIGHT: float = 0.6
KEYWORD_WEIGHT: float = 0.4
def get_rrf_scores(query1_ids, query2_ids):
ranking = get_ranking(query1_ids, query2_ids)
ids = []
scores = []
for key in ranking.keys():
# 각 검색 시스템의 순위
embed_rank = ranking[key][0]
keyword_rank = ranking[key][1]
# 각 검색 시스템의 Reciprocal Rank 계산
embed_rr = reciprocal_rank(embed_rank)
keyword_rr = reciprocal_rank(keyword_rank)
# 가중치가 적용된 Reciprocal Rank 계산
rrf = (EMBED_WEIGHT * embed_rr) + (KEYWORD_WEIGHT * keyword_rr)
scores.append(rrf)
ids.append(key)
sorted_scores = sorted(scores, reverse=True)
sorted_ids = [
key for _, key in sorted(zip(scores, ranking.keys()), reverse=True)
]
return {"ids": sorted_ids, "scores": sorted_scores}
{'ids': [1, 30, 128, 50, 301, 120],
'scores': [0.7333333333333333, 0.7, 0.35, 0.28, 0.12, 0.1]}
계산된 점수로 다시 정렬
1번 인덱스는 1위,3위를 했고,
30번 인덱스는 2위,1위를 했지만
가중치 때문에 1번 인덱스가 가장 높은 점수를 얻었다.
임베딩 벡터 검색이 좋냐, 키워드 검색이 좋냐
임베딩 검색이 잠재의미를 파악해서 좋다고는 하지만, 키워드 검색도 충분한 성능을 보여주고 있다.
RRF를 사용하여 하이브리드 검색을 구현하면 두 방법을 고민하지 않고 검색결과를 조합하여
다시 랭킹을 매길 수 있다.
좋은글 잘보고갑니다. ^^ 엘라 공부중에 너무 흥미가 생기네요