Elasticsearch kNN / 벡터 검색¶
문장을 임베딩하면 "의미가 가까운 것"이 벡터 공간에서 가까워져요. 그래서 질문 벡터와 가장 가까운 상위 k개를 찾으면 의미 검색이 됩니다. Elasticsearch에서 이 kNN(근접 이웃) 벡터 검색을 하는 방법과 개념을 설명하는 페이지예요. 이 페이지는 소스 문서 Elasticsearch kNN search 를 바탕으로 해요.
개요¶
kNN 검색은 임베딩으로 만든 벡터를 저장하고, 질문 벡터와 가장 유사한 상위 k개를 찾는 기능이에요. Elasticsearch는 dense_vector 필드 타입으로 벡터를 저장하고, 근사(approximate) kNN과 정확(exact) kNN 두 가지 방식을 제공합니다. 근사 kNN은 HNSW 그래프로 빠르고 정확도도 좋지만, 정확 kNN은 script_score로 문서를 일일이 스캔해 정확하지만 큰 데이터셋에선 느려요.
핵심 개념¶
전제 조건¶
- 데이터가 벡터화돼 있어야 하고(
dense_vector필드 타입 사용), 질문 벡터와 같은 차원·같은 모델로 만든 벡터여야 합니다. - 근사 kNN에서 HNSW는 효율을 위해 벡터 데이터가 노드의 페이지 캐시에 맞아야 한다는 리소스 요구사항이 있어요.
유사도 척도와 점수¶
dense_vector의 similarity 파라미터가 벡터 유사도를 재는 척도를 정해요(기본값은 cosine). kNN 검색에서 문서의 _score는 이 유사도 척도로 계산한 질문·문서 벡터 사이의 점수예요.
근사 kNN 검색 방식¶
근사 kNN을 실행하는 방법은 세 가지가 있어요.
- 최상위
knn옵션 — 단독 kNN 검색 또는 점수 융합을 곁들인 하이브리드 검색.dense_vector필드용. knn쿼리 —bool절 안에서 다른 쿼리와 조합 가능.semantic_text필드에선 필수.knn리트리버 — 리트리버 파이프라인에서 순위·결과 병합에 사용.
필터가 있는 kNN(Filtered kNN)¶
엄밀히 나눠야 할 부분이 있어요. 근사 kNN 중에 필터를 적용하면 k개가 매칭되도록 보장하지만, 사후 필터링(post-filtering) 은 kNN 결과 뒤에 필터를 적용해 관련 문서가 충분히 있어도 k개보다 적게 반환할 수 있습니다. kNN은 항상 k개의 최근접 이웃을 반환하려 하므로, 필터로 관련 문서를 다 걸러내면 남은 것은 관련 없는 것뿐일 수 있다는 점을 주의해야 해요.
중첩(nested) kNN과 청크 검색¶
nested 필드 안에 dense_vector를 두면, 문서 상위 메타데이터를 복사하지 않고 문단(청크) 단위로 최근접 문단을 찾을 수 있어요. inner_hits를 추가하면 매칭된 각 문서에서 가장 관련 높은 문단을 뽑아낼 수 있어요. 청킹된 문서에서 "어느 문단이 가장 관련 있나"를 찾을 때 적합한 구조입니다.
양자화·리스코어링¶
근사 kNN에 양자화(quantized) 벡터를 쓰면 rescore_vector로 정확도·속도를 조절할 수 있어요. 근사 검색으로 더 큰 후보를 뽑고, 원본(비양자화) 벡터로 상위 후보를 다시 채점(리스코어)해 정확도를 되살립니다. oversample을 늘리면 정확도가 오르고(지연 증가), 줄이면 빨라집니다(정확도 감소).
실제 적용 (데이터스케쳐스)¶
- 의미 검색 — text-embedding-3-small(1536차원) 임베딩을
dense_vector필드에 저장하고, 질문 벡터로 근사 kNN을 수행합니다. - 하이브리드 검색 + RRF —
match(키워드)와 kNN(벡터)을 함께 보내고 RRF로 순위를 합칩니다. - 청크 단위 근거 —
nested+inner_hits로 문서 안에서 가장 관련 높은 문단을 뽑아 근거로 씁니다. - 메타데이터 필터링 — 근사 kNN 중에 테넌트·날짜 필터를 적용해 범위를 좁힙니다.
더 알아보기¶
- 공식 문서 (1차): Elasticsearch kNN search, dense_vector 필드, Elastic RRF
- 큐레이션/블로그 (2차): Elastic 하이브리드 검색 튜토리얼, Elastic 블로그