ANN 재현율 측정
ANN 재현율 측정 (Measuring ANN Recall)
⏱️ 소요 시간 15분 | 난이도: 초급 출처: Qdrant 공식 문서 — ann-recall
여러분, 이번 튜토리얼에서는 **ANN 재현율(ANN recall)**에 집중해 볼게요. 쉽게 말하면 근사 최근접 이웃(ANN) 검색이 정확한 kNN 검색에 얼마나 가까운지를 recall@k로 측정하는 거예요.
사전 준비: 문서를 point(벡터 + 선택적 payload)로 채운 Qdrant 컬렉션이 필요해요.
검색 평가 스택 (Retrieval Evaluation Stack)
ANN 재현율은 근사 검색이 정확한 kNN에 얼마나 가까운지 측정해요. 검색 시스템의 네 가지 평가 계층 중 첫 번째예요. 각 상위 계층은 검색 시스템의 다른 속성을, 다른 도구로 측정해요.
- ANN 재현율 (이 튜토리얼). 근사 인덱스가 정확한 kNN에 가까운가?
- 검색 관련성 (검색 관련성 측정). top-k 결과가 질의 의도와 일치하는가?
- 파이프라인 출력 품질 (파이프라인 출력 품질 평가). 엔드투엔드 파이프라인(검색 + 생성기, 랭커, 또는 UI)이 올바른 출력을 만드는가?
- 비즈니스 영향. 비즈니스가 신경 쓰는 KPI가 움직이는가? 애플리케이션마다 다르므로 이 튜토리얼 범위 밖이에요.
상위 계층에서 높은 점수를 받으려면 그 아래 계층에서 수용 가능한 점수가 필요해요. 임베딩 품질(MTEB 같은 벤치마크로 별도 측정)은 모든 하위 메트릭의 상한선을 결정해요.
Web UI로 ANN 재현율 측정하기
Qdrant의 Web UI에는 ANN Recall 탭이 있어서, 평가 코드를 작성하지 않고도 근사 검색과 정확 검색 사이의 차이를 측정할 수 있어요. http://localhost:6333/dashboard (또는 Qdrant Cloud의 클러스터 대시보드)를 열고, 컬렉션으로 이동한 뒤 ANN Recall 탭을 열고 Check Index Quality를 클릭해 비교를 실행하세요.
이 탭은 평균 recall@k를 보고해요 (1.0 = 완벽한 겹침; 잘 튜닝된 HNSW에서는 0.95 이상이 일반적이에요).
검색 재현율 튜닝하기
ANN Recall 탭에서 **advanced mode(고급 모드)**를 켜면 검색 시 매개변수를 인라인으로 튜닝할 수 있어요. 핵심은 hnsw_ef — 검색 중 평가되는 후보 수예요. 값을 올리면 그래프를 더 많이 탐색해서 재현율이 좋아지지만 질의 지연이 늘어나요. 효과를 보려면 hnsw_ef를 (예: 256으로) 올리고 평가를 다시 실행해보세요.
재현율은 높아지되 질의 지연 비용이 증가해요.
hnsw_ef만으로 재현율 목표에 도달하지 못한다면, 빌드 시 매개변수인 m과 ef_construct가 근사 검색이 달성할 수 있는 재현율의 상한선을 결정해요. 이들을 바꾸려면 HNSW 인덱스를 다시 구축해야 해요. trade-off와 값을 고르는 방법은 Qdrant Essentials 과정의 HNSW 인덱싱 기초를 참고해요.
Python으로 CI 자동화하기
Web UI는 재현율을 대화형으로 확인하는 가장 빠른 방법이에요. 지속적 통합(CI)이나 스크립트 기반 회귀 테스트에서는 Qdrant 클라이언트가 search_params=models.SearchParams(exact=True)로 동일한 정확 검색 모드를 제공해요. ANN과 정확 top-k 집합을 직접 비교하고 recall@k를 계산하면 됩니다.
이 헬퍼는 질의 벡터 목록을 받아 평균 recall@k를 반환해요. 여러분 워크로드의 대표 질의 벡터 샘플(보통 20~50개, 컬렉션이 쓰는 것과 같은 모델로 임베딩)을 테스트 집합으로 사용하세요.
from qdrant_client import QdrantClient, models
def avg_recall_at_k(
client: QdrantClient,
collection_name: str,
test_vectors: list,
k: int,
) -> float:
recalls = []
for vector in test_vectors:
ann_ids = {
p.id
for p in client.query_points(
collection_name=collection_name,
query=vector,
limit=k,
).points
}
knn_ids = {
p.id
for p in client.query_points(
collection_name=collection_name,
query=vector,
limit=k,
search_params=models.SearchParams(exact=True),
).points
}
recalls.append(len(ann_ids & knn_ids) / k)
return sum(recalls) / len(recalls)
이걸 CI에 연결하고 재현율이 목표 임계값 아래로 떨어지면 작업을 실패시키세요. 이렇게 하면 임베딩 모델 교체나 인덱스 설정 변경으로 인한 회귀를 프로덕션에 도달하기 전에 잡아낼 수 있어요.
다음 단계
ANN 재현율이 목표에 도달하면, 검색 관련성 측정을 계속 진행해서 그 결과가 사용자 의도와 얼마나 잘 맞는지 확인해보세요.