벡터 유사도 검색

벡터 검색은 쿼리 벡터와 가장 유사한 벡터를 가진 객체를 반환합니다. 텍스트를 쿼리로 주면 그 텍스트의 벡터를 만들어 근처의 객체를 찾고, 이미지·객체 ID·원시 벡터로도 검색할 수 있어요. 의미 기반 검색의 핵심입니다.

입력 형태에 따라 Near Text, Near Object, Near Vector, Near Image 연산자를 골라 쓰면 됩니다.

출처: 공식문서

텍스트로 검색

Near Text 연산자로 입력 텍스트와 가장 가까운 벡터를 가진 객체를 찾습니다.

from weaviate.classes.query import MetadataQuery

jeopardy = client.collections.use("JeopardyQuestion")
response = jeopardy.query.near_text(
    query="animals in movies",
    limit=2,
    return_metadata=MetadataQuery(distance=True)
)
for o in response.objects:
    print(o.properties)
    print(o.metadata.distance)

기존 객체로 검색

객체 ID를 알고 있으면 Near Object 연산자로 그 객체와 비슷한 객체를 찾습니다.

uuid = jeopardy.query.fetch_objects(limit=1).objects[0].uuid

response = jeopardy.query.near_object(
    near_object=uuid,  # 객체 UUID (예: "56b9449e-65db-5df4-887b-0a4773f52aa7")
    limit=2,
    return_metadata=MetadataQuery(distance=True)
)

벡터로 검색

입력 벡터가 있다면 Near Vector 연산자로 유사한 벡터를 가진 객체를 찾습니다.

response = jeopardy.query.fetch_objects(limit=1, include_vector=True)
query_vector = response.objects[0].vector["default"]

response = jeopardy.query.near_vector(
    near_vector=query_vector,  # 쿼리 벡터
    limit=2,
    return_metadata=MetadataQuery(distance=True)
)

Named vectors

named vectors가 있는 컬렉션은 target vector 필드로 어떤 named 벡터를 검색할지 지정해야 해요.

reviews = client.collections.use("WineReviewNV")
response = reviews.query.near_text(
    query="a sweet German white wine",
    limit=2,
    target_vector="title_country",  # named vector 컬렉션의 target 벡터 지정
    return_metadata=MetadataQuery(distance=True)
)

유사도 임계값 설정

검색 벡터와 대상 벡터 사이의 유사도 임계값을 정하려면 최대 distance(또는 certainty)를 지정합니다.

response = jeopardy.query.near_text(
    query="animals in movies",
    distance=0.25,  # 최대 허용 distance
    return_metadata=MetadataQuery(distance=True)
)

참고 사항:

  • distance 값은 사용하는 벡터화 모델을 포함한 여러 요인에 따라 달라지므로, 데이터로 실험해 직접 찾아야 해요.
  • certaintycosine distance에서만 사용 가능합니다.
  • 가장 유사하지 않은 객체를 찾으려면 nearVector 검색에 음의 cosine distance를 사용하세요.

limit & offset

limit으로 반환할 최대 객체 수를 정하고, 선택적으로 offset으로 페이지네이션합니다.

response = jeopardy.query.near_text(
    query="animals in movies",
    limit=2,  # 2개 반환
    offset=1,  # 1개 건너뜀
    return_metadata=MetadataQuery(distance=True)
)

결과 그룹 제한 (autocut)

쿼리와 비슷한 거리의 그룹만 반환하려면 autocut 필터로 그룹 수를 정합니다.

response = jeopardy.query.near_text(
    query="animals in movies",
    auto_limit=1,  # 가까운 그룹 수
    return_metadata=MetadataQuery(distance=True)
)

그룹핑(Group by)

프로퍼티나 크로스 레퍼런스로 결과를 그룹핑합니다. 그룹핑하려면 쿼리에 Near Text, Near Object 같은 Near 검색 연산자가 포함돼야 해요.

from weaviate.classes.query import GroupBy

group_by = GroupBy(
    prop="round",
    objects_per_group=2,
    number_of_groups=2,
)
response = jeopardy.query.near_text(
    query="animals in movies",
    limit=10,
    return_metadata=MetadataQuery(distance=True),
    group_by=group_by
)

필터 적용

더 구체적인 결과를 위해 filter로 검색을 좁힙니다.

from weaviate.classes.query import Filter

response = jeopardy.query.near_text(
    query="animals in movies",
    filters=Filter.by_property("round").equal("Double Jeopardy!"),
    limit=2,
    return_metadata=MetadataQuery(distance=True),
)

다양성 선택 (MMR)

표준 벡터 검색은 쿼리에 가장 가까운 매치를 반환하는데, 종종 거의 중복인 결과 클러스터가 됩니다. **MMR(Maximal Marginal Relevance)**은 관련성과 다양성의 균형을 맞춰 재순위화해요. 각 선택 결과가 결과 집합에 새로운 것을 더해야 합니다.

어떤 벡터 검색 쿼리든 diversity_selection 파라미터를 추가하면 됩니다.

동작 방식

  1. Weaviate가 일반 벡터 검색으로 후보 집합을 가져옵니다(쿼리 limit가 크기).
  2. 가장 관련성 높은 후보를 먼저 선택합니다.
  3. 남은 각 후보에 대해 쿼리 유사도와 (이미 선택된 결과와의 최대 유사도)를 balance로 가중해 MMR 점수를 계산합니다.
  4. MMR 점수가 가장 높은 후보를 다음으로 선택합니다.
  5. Diversity.mmr(limit)에 도달할 때까지 3~4를 반복합니다.

파라미터

파라미터 타입 설명
limit int MMR 재순위화 후 반환할 결과 수. 최소 1, 쿼리 최상위 limit(후보 집합 크기) 이하여야 함. 빠뜨리거나 범위 밖이면 오류.
balance float 관련성-다양성 트레이드오프 (0.0~1.0). 0.0=순수 다양성, 0.5=균형, 1.0=순수 관련성(표준 검색과 동일).

중요한 노트:

  • 결과 정렬: 쿼리 유사도가 아닌 MMR 점수 순서. 첫 결과가 가장 관련성 높지만, 이후 결과는 다양성 때문에 쿼리 유사도가 낮을 수 있어요.
  • 재인덱싱 불필요: MMR은 쿼리 시점에 적용돼요. 스키마 변경 없이 기존 컬렉션에 사용 가능합니다.
  • 지원 쿼리: near_text, near_vector, near_object, near_image, near_media. 하이브리드 검색은 v1.38.6부터 지원.
  • 미지원: 멀티벡터 컬렉션. 오류로 거부됩니다.

:::tip 후보 집합을 크게(상위 limit 높게) 잡을수록 MMR이 고를 결과가 많아져 다양성이 좋아지지만 계산이 약간 늘어납니다. 시작점은 후보 limit을 MMR limit의 2~4배로 잡아보세요. :::

페이지네이션

다양성 선택은 offset의 의미를 바꿔요. offset은 페이지가 아니라 후보 윈도우를 옮기므로, 반환 객체 수가 아니라 쿼리 최상위 limit만큼 전진해야 합니다. Weaviate는 offsetlimit의 관계를 검증하지 않아, 잘못되면 오류·경고 없이 페이지 간에 객체가 반복되거나 아예 반환되지 않는 증상만 나타납니다.

두 가지 limit이 있는 구조예요.

  • 쿼리 최상위 limit = 다양화될 후보 윈도우
  • 다양성 limit = 페이지 크기(반환되는 객체 수)

각 페이지는 관련성 정렬 결과의 [offset, offset + limit) 슬라이스에서 가져오므로, offset쿼리 limit만큼 전진해야 합니다. (예: 쿼리 limit 10, 다양성 limit 3일 때 반환 수 기준 3씩 전진하면 [0:10], [3:13], [6:16]을 읽어 객체가 반복·누락됩니다.)

Boost로 부드럽게 순위 조정

벡터 검색 쿼리도 v1.38부터 선택적으로 boost 인자를 받아요. 매칭 문서를 제거하지 않고 위로 끌어올립니다. 최신성, 인기도, 소프트 필터 신호로 결과를 치우칠 때 유용합니다.

지원 조건 타입과 곡선·블렌딩·깊이 조절은 Boost를 참고하세요.

더 알아보기 (Learn more)