BE 공부/검색엔진

[OpenSearch] k-NN 벡터 검색 적용하기

꼬질꼬질두부 2025. 6. 13. 14:34
반응형

OpenSearch에서 k-NN 벡터 검색 적용하기

최근 자연어 처리나 이미지 인식 등 AI 기반 검색 서비스에서는 벡터 검색이 핵심 기능이 되고 있습니다. OpenSearch는 k-NN 기능을 통해 이러한 유사도 기반 검색을 지원합니다. 이 글에서는 k-NN 벡터 인덱싱이 무엇인지부터 실제 설정, 쿼리 작성까지 쉽게 따라할 수 있도록 안내드리겠습니다.


벡터 인덱싱이란?

문장을 임베딩(embedding)하면 수백 차원의 벡터로 변환되며, 이 벡터는 문장의 의미를 수치로 표현합니다. 예를 들어,

  • "오늘 날씨 좋다"
  • "날이 맑고 화창하다"

이 두 문장은 단어는 다르지만 의미는 유사합니다. 벡터 공간상에서는 이 둘이 가까운 위치에 있게 됩니다. 이렇게 벡터를 기반으로 유사한 문서를 찾기 위해 벡터 인덱싱이 사용됩니다.

k-NN 알고리즘이란?

k-NN(k-Nearest Neighbor)은 주어진 벡터와 가장 가까운 k개의 벡터를 찾는 알고리즘입니다. OpenSearch는 빠른 처리를 위해 근사 최근접 탐색(ANN)을 사용합니다.


주요 용어 설명

용어  설명
k 반환할 최근접 이웃의 개수입니다. (예: 가장 유사한 5개 문서 찾기 → k=5)
dimension 벡터의 차원 수입니다. 저장된 벡터와 쿼리 벡터는 동일해야 합니다. (예: 임베딩 차원이 256이면 모두 256이어야 함)
space_type 유사도 계산 방식: cosinesimil(코사인 유사도), l2(유클리드 거리), innerproduct(내적).
method.name 벡터 검색 알고리즘 이름입니다. hnsw, ivf 등 선택 가능.
method.engine 벡터 검색 엔진: nmslib, faiss, lucene 중 선택.
ef_construction, m 인덱스 생성 시 정확도와 속도에 영향을 주는 하이퍼파라미터입니다.
ef_search, nprobes 검색 시 정확도와 성능을 조절하는 검색 관련 하이퍼파라미터입니다.
rescore 후보 벡터에 대한 점수 재조정을 위한 설정입니다. on_disk 모드에서 주로 사용됩니다.

1. 인덱스 세팅 설정 예시

PUT /my-index
{
  "settings": {
    "index.knn": true
  }
}

index.knn이 true로 설정되지 않으면 knn_vector 타입 필드는 사용 불가합니다.

2. 벡터 필드 매핑 예시

PUT /my-index/_mapping
{
  "properties": {
    "vector_field": {
      "type": "knn_vector",
      "dimension": 256,
      "method": {
        "name": "hnsw",
        "engine": "faiss",
        "space_type": "cosinesimil",
        "parameters": {
          "ef_construction": 128,
          "m": 16
        }
      }
    }
  }
}

! 주의 1: dimension은 색인된 벡터와 쿼리 벡터 모두 동일해야 하며, 일치하지 않으면 아래 오류가 발생합니다.

Query vector has invalid dimension: X. Dimension should be: 256

! 주의 2: knn_vector 필드는 sort, aggregation과 같은 연산에서 사용할 수 없습니다.
사용 시 다음과 같은 오류가 발생할 수 있습니다.

knn vector field doesn't support this operation

 


3. 문서 색인 예시

POST /my-index/_doc/1
{
  "vector_field": [0.05, 0.12, 0.13, ..., 0.25],
  "title": "샘플 문서 1"
}

POST /my-index/_doc/2
{
  "vector_field": [0.10, 0.20, 0.22, ..., 0.30],
  "title": "샘플 문서 2"
}

vector_field는 float형 배열이어야 하며, dimension 길이와 일치해야 합니다.

최소 k개 이상의 문서가 색인되어 있어야 의미 있는 검색이 가능합니다.


4. k-NN 검색 쿼리 예시

POST /my-index/_search
{
  "size": 2,
  "query": {
    "knn": {
      "vector_field": {
        "vector": [0.05, 0.12, ..., 0.25],
        "k": 2,
        "filter": { "term": { "category": "A" } },
        "method_parameters": { "ef_search": 150 },
        "rescore": { "oversample_factor": 1.0 }
      }
    }
  }
}

예시: k=2, size=2로 설정하면 각 샤드에서 유사한 문서 2개를 찾고, 그 중 상위 2개의 결과만 반환합니다.


5. 발생 가능한 오류 및 해결 방법

오류 메시지 원인 해결 방법
Query vector has invalid dimension: X... 쿼리 벡터와 매핑된 dimension 불일치 쿼리 벡터 길이 확인 및 수정
knn vector field doesn't support this operation knn_vector 필드로 정렬/집계 시도 정렬이 필요하면 keyword 필드 분리 사용
unsupported_operation_exception knn 필드를 sort 또는 DSL 기능으로 잘못 참조 쿼리 구조 재검토 또는 field usage 변경

6. 사용 예시

PUT /products
{
  "settings": { "index.knn": true },
  "mappings": {
    "properties": {
      "features": {
        "type": "knn_vector",
        "dimension": 4,
        "method": {
          "name": "ivf",
          "engine": "faiss",
          "space_type": "l2",
          "parameters": { "nlist": 16 }
        }
      },
      "price": { "type": "float" },
      "category": { "type": "keyword" }
    }
  }
}

POST /products/_doc/1
{ "features": [1.0, 2.0, 3.0, 4.0], "price": 100, "category": "A" }
POST /products/_doc/2
{ "features": [1.1, 2.1, 3.1, 4.1], "price": 120, "category": "A" }
POST /products/_doc/3
{ "features": [10.0, 10.5, 11.0, 11.5], "price": 200, "category": "B" }

POST /products/_search
{
  "size": 2,
  "query": {
    "knn": {
      "features": {
        "vector": [1.05, 2.05, 3.05, 4.05],
        "k": 2,
        "filter": { "term": { "category": "A" } }
      }
    }
  }
}

dimension은 벡터 차원(예시에서는, dimension = 4)과 일치해야 하며, category: A 조건을 통해 A 그룹 내에서만 유사 문서를 검색합니다. 벡터가 가장 가까운 문서 1번과 2번이 반환됩니다.


참고자료

반응형