데이터 탐색하기
데이터 탐색하기 (Explore the Data)
기본 검색을 익혔다면 이제 다른 방식으로 데이터를 탐색해 볼 차례예요. Qdrant는 유사한 벡터를 다른 방식으로 찾고, 반대로 가장 비유사한 벡터도 찾게 해주는 API 스택을 제공해요. 이 도구들은 추천 시스템, 데이터 탐색, 데이터 정제에 유용해요.
출처: 공식문서 - Explore
Recommendation API (추천 API)
일반 검색 외에도 Qdrant는 여러 개의 긍정·부정 예시를 기반으로 검색하게 해줘요. 이 API를 recommend라 부르고, 예시는 포인트 ID로 쓸 수 있어서 이미 인코딩된 객체를 활용할 수 있어요. v1.6부터는 raw 벡터도 입력으로 쓸 수 있어 포인트로 업로드하지 않고 즉석에서 벡터를 만들 수 있죠.
추천 API는 Query API의 Recommend Query로 노출돼요. 추천을 얻는 알고리즘은 사용 가능한 strategy 옵션에서 선택하며, 각자 장단점이 있으니 자기 사례에 맞는 걸 실험해서 골라야 해요.
Average Vector 전략
Qdrant에 추가된 기본·첫 번째 전략으로 average_vector라 불러요. 입력 예시를 전처리해 검색에 쓸 단일 벡터를 만들죠. 전처리가 매우 빨라 성능은 일반 검색과 비슷해요. 각 벡터 컴포넌트가 데이터의 독립적인 특성을 나타내므로, 예시를 평균하면 좋은 추천을 얻을 수 있다는 직관에 기반해요.
검색 벡터는 긍정·부정 예시를 각각 따로 평균한 뒤 다음과 같이 결합해 만들어요:
avg_positive + avg_positive - avg_negative
부정 예시가 없으면 검색 벡터는 단순히 avg_positive와 같아요. 이 전략은 암시적으로 기본값으로 설정되지만, 요청에 "strategy": "average_vector"로 명시할 수도 있어요.
Best Score 전략
v1.6.0부터
best_score는 긍정 예시에 가까운 벡터를 찾으면서 부정 예시에 가까운 것은 피하는 방식이에요. 각 후보를 모든 예시에 대해 측정한 뒤 최고 긍정 점수와 최고 부정 점수를 선택해, 시그모이드 함수로 0~1 사이로 정규화한 최종 점수를 뽑아요:
// Sigmoid function to normalize the score between 0 and 1
let sigmoid = |x| 0.5 * (1.0 + (x / (1.0 + x.abs())));
let score = if best_positive_score > best_negative_score {
sigmoid(best_positive_score)
} else {
-sigmoid(best_negative_score)
};
성능은 예시 개수에 선형으로 영향받아요 — 예시가 많을수록 검색이 느려져요. 대신 임베딩에 덜 의존적이라 더 강력할 수 있어요. 정확도에 영향이 있을 수 있으니 ef 검색 파라미터를 기본 16보다 높게(예: "params": { "ef": 64 }) 올리면 훨씬 좋아져요. 사용하려면 "strategy": "best_score"로 설정하세요.
부정 예시만 쓰기 — best_score 전략의 유용한 부수 효과로, 부정 예시만 써서 제공한 벡터들과 가장 비유사한 벡터를 찾을 수 있어요. 데이터의 이상치(outlier)를 찾거나 특정 벡터와 가장 비유사한 벡터를 찾는 데 유용하죠. 부정 예시만 + 필터링 조합은 데이터 탐색과 정제에 강력한 도구가 돼요.
Sum Scores 전략
여러 쿼리 벡터를 동시에 쓰는 또 다른 전략은 후보에 대한 점수를 그냥 합산하는 sum_scores예요. 관련성 피드백을 후속 검색에 통합하기 위해 사용됐던 방식이에요. 공식은 다음과 같아요:
$$s_i = \sum_{v_q\in Q^+}s(v_q, v_i) - \sum_{v_q\in Q^-}s(v_q, v_i)$$
여기서 $Q^+$는 긍정 예시 집합, $Q^-$는 부정 예시 집합, $s(v_q, v_i)$는 벡터 $v_q$가 벡터 $v_i$에 대한 점수예요. best_score와 마찬가지로 부정 예시만 쓰는 것도 가능해요.
여러 벡터 / 다른 컬렉션 벡터
- v0.10.0부터 — 컬렉션이 여러 벡터로 만들어졌다면 추천 요청에 벡터 이름을 지정해야 해요.
using파라미터가 추천에 쓸 저장 벡터를 지정해요. - v0.11.6부터 — 같은 차원의 벡터를 가진 컬렉션들 사이에서,
lookup_from파라미터로 다른 컬렉션의 벡터를 기반으로 추천을 찾을 수 있어요. 아이템-투-유저 추천 시나리오에 유용한데, 사용자와 아이템 임베딩이 같은 벡터 파라미터(거리 타입·차원)를 가지지만 보통 다른 컬렉션에 저장되기 때문이에요. 벡터는positive와negative목록에 주어진 id로 외부 컬렉션에서 가져와요.
Batch Recommendation API
v0.10.0부터
배치 검색 API와 쓰임새·장점이 비슷하게, 추천 요청을 배치로 묶을 수 있게 해줘요. 결과는 요청당 하나의 배열을 담아요.
Discovery API
v1.7부터
이 API에서 Qdrant는 context라는 개념을 도입해요. 컨텍스트는 공간을 나누는 데 쓰이는데, 긍정-부정 쌍의 집합이며 각 쌍이 공간을 긍정 구역과 부정 구역으로 나눠요. 이 모드에서 검색은 포인트가 얼마나 많은 긍정 구역에 속하는지(또는 부정 구역을 얼마나 피하는지)에 따라 포인트를 선호해요.
Discovery API는 두 가지 새로운 유형의 검색을 가능하게 해요:
- Discovery search — 컨텍스트(긍정-부정 벡터 쌍)와 타깃을 사용해 타깃과 더 유사하면서 컨텍스트로 제약된 포인트를 반환
- Context search — 컨텍스트 쌍만 사용해 손실이 최소화되는 최적 구역에 사는 포인트를 얻음
긍정·부정 예시를 컨텍스트 쌍에 어떻게 배치할지는 완전히 사용자 몫이라, 모델과 데이터에 따라 다양한 치환 기법을 시도해 볼 수 있어요. 검색 속도는 쿼리에 제공한 예시 개수에 선형으로 비례해요.
Discovery search
멀티모달·벡터 제약 검색을 결합할 때 특히 잘 동작해요. Qdrant는 payload 기반의 필터로 검색을 이미 폭넓게 지원하지만, discovery search를 쓰면 검색이 수행되는 벡터 공간 자체를 제약할 수도 있어요. discovery 점수는 시그모이드로 정규화된 타깃 유사도에 개별 랭크 합을 더해 계산돼요:
$$\text{discovery score} = \text{sigmoid}(s(v_t)) + \sum \text{rank}(v_i^+, v_i^-)$$
각 랭크는 긍정 예시 유사도가 부정 예시 유사도 이상이면 1, 아니면 -1이 돼요. 즉 개별 랭크의 합이 포인트가 몇 개의 긍정 구역에 있는지를 결정하고, 가까움의 계층이 그다음으로 온다는 뜻이에요. 주의점:
- 예시로 id를 제공하면 그 id들은 결과에서 제외돼요.
- 메트릭과 무관하게 점수는 항상 내림차순(클수록 좋음)이에요.
- 공간이 컨텍스트로 강하게 제약되므로 기본 설정에서 정확도가 떨어지기 쉽고,
ef를 기본 16보다 높게(예:"params": { "ef": 128 }) 올리면 훨씬 좋아져요.
Context search
타깃이 없는 경우, HNSW 같은 근접 그래프를 쓸 때 정수 단위의 함수는 검색에 큰 가이드가 되지 못해요. 그래서 context search는 모델 훈련에서 흔히 쓰는 triplet-loss 개념에서 파생된 함수를 사용해요. 검색을 부정 예시가 적은 영역으로 이끄는 방식이죠. 점수 함수는 손실 함수와 직접 연결되는데, 0.0이 포인트가 가질 수 있는 최대 점수로 긍정 영역에만 있다는 뜻이에요. 포인트가 부정 예시에 가까워지면 손실은 긍정·부정 유사도의 차이가 돼요:
$$\text{context score} = \sum \min(s(v^+_i) - s(v^-_i), 0.0)$$
이런 검색을 쓰면 출력이 반드시 단일 포인트 주변에 있지는 않고, 부정 예시에 가깝지 않은 아무 포인트나 될 수 있어 제약된 다양한 결과를 만들어요. 주의점:
- 예시로 id를 제공하면 그 id들은 결과에서 제외돼요.
- 점수는 항상 내림차순(클수록 좋음)이에요.
- 최고 가능 점수는
0.0이며 많은 포인트가 이 점수를 받는 게 정상이에요.
Distance Matrix (거리 행렬)
v1.12.0부터
거리 행렬 API는 벡터의 샘플링된 쌍 사이의 거리를 계산해 희소 행렬로 반환하게 해줘요. 유사 벡터 클러스터링, 연결의 시각화, 차원 축소 같은 데이터 탐색 용례를 가능하게 해주죠. 입력 요청 파라미터는 다음과 같아요:
sample- 샘플링할 벡터 수limit- 샘플당 반환할 점수 수filter- 샘플을 제약할 필터
예를 들어 sample=100, limit=10이면 엔진이 컬렉션에서 100개의 무작위 포인트를 선택하고, 각 선택 포인트마다 샘플 내에서 가장 가까운 상위 10개를 계산해요. 총 1000개의 점수를 희소 행렬로 만들어 효율적으로 처리하죠. 두 가지 출력 형식이 있어요:
- Pairwise Format — 포인트
ids쌍과 각각의 점수 목록으로 반환 - Offset Format — 4개 배열로 반환:
offsets_row와offsets_col은 행렬에서 0이 아닌 거리 값의 위치,scores는 거리 값,ids는 거리 값에 대응하는 포인트 id