하이브리드 검색: 전체 텍스트 및 kNN 결과 결합
이제 문서 모음을 검색하는 두 가지 다른 접근 방식과 각각 고유한 이점을 살펴보았습니다. 이러한 방법 중 하나가 사용자의 요구와 일치하면 다른 방법이 필요하지 않지만, 많은 경우 각 검색 방법이 다른 방법으로는 놓칠 수 있는 중요한 결과를 반환하므로 가장 좋은 방법은 결합된 결과 집합을 제공하는 것입니다.
이러한 경우를 위해 Elasticsearch는 두 개 이상의 목록의 결과를 단일 목록으로 결합하는 알고리즘인 상호 순위 융합을 제공합니다.
RRF 작동 방식
Elasticsearch는 RRF 알고리즘을 검색 쿼리에 통합합니다. 각각 전체 텍스트 및 벡터 검색을 요청하는 query 및 knn 섹션과 이를 단일 결과 목록으로 결합하는 rrf 섹션이 있는 다음 예시를 살펴보세요.
self.es.search(
query={
# full-text search query here
},
knn={
# vector search query here
},
rank={
"rrf": {}
}
)RRF는 아무런 구성 없이도 짧은 결과 목록에 대해 상당히 잘 작동하지만, 최상의 결과를 제공하기 위해 조정할 수 있는 몇 가지 매개변수가 있습니다. 이에 대한 자세한 내용은 설명서를 참조하세요.
RRF 구현
전체 텍스트 및 벡터 검색 방법의 결과를 모두 반환하는 결합 검색을 사용하려면 handle_search() 함수에서 앞서 사용한 전체 텍스트 검색 로직을 다시 가져와야 합니다. 하이브리드 검색 전략을 구현하려면 search() 메서드에서 query 및 knn 인수를 모두 받아야 하며, 각각 별도의 쿼리를 요청해야 합니다. 위에 표시된 rank 섹션도 추가되어 결과를 단일 순위 목록으로 결합합니다.
다음은 하이브리드 검색 전략을 구현하는 handle_search() 버전입니다:
@app.post('/')
def handle_search():
query = request.form.get('query', '')
filters, parsed_query = extract_filters(query)
from_ = request.form.get('from_', type=int, default=0)
if parsed_query:
search_query = {
'must': {
'multi_match': {
'query': parsed_query,
'fields': ['name', 'summary', 'content'],
}
}
}
else:
search_query = {
'must': {
'match_all': {}
}
}
results = es.search(
query={
'bool': {
**search_query,
**filters
}
},
knn={
'field': 'embedding',
'query_vector': es.get_embedding(parsed_query),
'k': 10,
'num_candidates': 50,
**filters,
},
rank={
'rrf': {}
},
aggs={
'category-agg': {
'terms': {
'field': 'category.keyword',
}
},
'year-agg': {
'date_histogram': {
'field': 'updated_at',
'calendar_interval': 'year',
'format': 'yyyy',
},
},
},
size=5,
from_=from_,
)
aggs = {
'Category': {
bucket['key']: bucket['doc_count']
for bucket in results['aggregations']['category-agg']['buckets']
},
'Year': {
bucket['key_as_string']: bucket['doc_count']
for bucket in results['aggregations']['year-agg']['buckets']
if bucket['doc_count'] > 0
},
}
return render_template('index.html', results=results['hits']['hits'],
query=query, from_=from_,
total=results['hits']['total']['value'], aggs=aggs)이 버전에서는 각 검색 방법의 최상의 결과가 결합됩니다. 여기를 클릭하여 이러한 변경 사항이 포함된 전체 신청서를 검토하세요.