벡터 임베딩으로 검색

이 페이지에서는 Cloud Firestore를 사용하여 다음 기법을 사용하여 K-최근접 이웃(KNN) 벡터 검색을 수행하는 방법을 보여줍니다.

  • 벡터 값 저장
  • KNN 벡터 색인 만들기 및 관리
  • 지원되는 벡터 거리 함수 중 하나를 사용하여 K-최근접 이웃(KNN) 쿼리 수행

벡터 임베딩 저장

Cloud Firestore 데이터에서 텍스트 임베딩과 같은 벡터 값을 만들고 Cloud Firestore 문서에 저장할 수 있습니다.

벡터 임베딩을 사용한 쓰기 작업

다음 예시는 Cloud Firestore 문서에 벡터 임베딩을 저장하는 방법을 보여줍니다.

Python
from google.cloud import firestore
from google.cloud.firestore_v1.vector import Vector

firestore_client = firestore.Client()
collection = firestore_client.collection("coffee-beans")
doc = {
  "name": "Kahawa coffee beans",
  "description": "Information about the Kahawa coffee beans.",
  "embedding_field": Vector([1.0 , 2.0, 3.0])
}

collection.add(doc)
    
Node.js
import {
  Firestore,
  FieldValue,
} from "@google-cloud/firestore";

const db = new Firestore();
const coll = db.collection('coffee-beans');
await coll.add({
  name: "Kahawa coffee beans",
  description: "Information about the Kahawa coffee beans.",
  embedding_field: FieldValue.vector([1.0 , 2.0, 3.0])
});
    

Cloud 함수로 벡터 임베딩 계산

문서가 업데이트 또는 생성될 때마다 벡터 임베딩을 계산하고 저장하기 위해 Cloud 함수를 설정할 수 있습니다.

Python
@functions_framework.cloud_event
def store_embedding(cloud_event) -> None:
  """Triggers by a change to a Firestore document.
  """
  firestore_payload = firestore.DocumentEventData()
  payload = firestore_payload._pb.ParseFromString(cloud_event.data)

  collection_id, doc_id = from_payload(payload)
  # Call a function to calculate the embedding
  embedding = calculate_embedding(payload)
  # Update the document
  doc = firestore_client.collection(collection_id).document(doc_id)
  doc.set({"embedding_field": embedding}, merge=True)
    
Node.js
/**
 * A vector embedding will be computed from the
 * value of the `content` field. The vector value
 * will be stored in the `embedding` field. The
 * field names `content` and `embedding` are arbitrary
 * field names chosen for this example.
 */
async function storeEmbedding(event: FirestoreEvent<any>): Promise<void> {
  // Get the previous value of the document's `content` field.
  const previousDocumentSnapshot = event.data.before as QueryDocumentSnapshot;
  const previousContent = previousDocumentSnapshot.get("content");

  // Get the current value of the document's `content` field.
  const currentDocumentSnapshot = event.data.after as QueryDocumentSnapshot;
  const currentContent = currentDocumentSnapshot.get("content");

  // Don't update the embedding if the content field did not change
  if (previousContent === currentContent) {
    return;
  }

  // Call a function to calculate the embedding for the value
  // of the `content` field.
  const embeddingVector = calculateEmbedding(currentContent);

  // Update the `embedding` field on the document.
  await currentDocumentSnapshot.ref.update({
    embedding: embeddingVector,
  });
}
    

벡터 색인 만들기 및 관리

벡터 임베딩으로 최근접 이웃 검색을 수행하려면 먼저 해당하는 색인을 만들어야 합니다 다음 예시는 벡터 색인을 만들고 관리하는 방법을 보여줍니다.

단일 필드 벡터 색인 만들기

단일 필드 벡터 색인을 만들려면 gcloud alpha firestore indexes composite create를 사용합니다.

gcloud
gcloud alpha firestore indexes composite create \
--collection-group=collection-group \
--query-scope=COLLECTION \
--field-config field-path=vector-field,vector-config='vector-configuration' \
--database=database-id
    

각 매개변수는 다음과 같습니다.

  • collection-group은 컬렉션 그룹의 ID입니다.
  • vector-field는 벡터 임베딩이 포함된 필드의 이름입니다.
  • database-id는 데이터베이스의 ID입니다.
  • vector-configuration에는 벡터 dimension과 색인 유형이 포함됩니다. dimension은 최대 2048까지의 정수입니다. 색인 유형은 flat이어야 합니다. 색인 구성의 형식을 다음과 같이 지정합니다. {"dimension":"DIMENSION", "flat": "{}"}

복합 벡터 색인 만들기

다음 예시에서는 color 필드에 대한 복합 벡터 색인과 벡터 임베딩 필드를 만듭니다.

gcloud
gcloud alpha firestore indexes composite create \
--collection-group=collection-group \
--query-scope=COLLECTION \
--field-config=order=ASCENDING,field-path="color" \
--field-config field-path=field,vector-config='{"dimension":"1024", "flat": "{}"}' \
--database=database-id
    

모든 벡터 색인 나열

gcloud
gcloud alpha firestore indexes composite list --database=database-id

database-id를 데이터베이스 ID로 바꿉니다.

벡터 색인 삭제

gcloud
gcloud alpha firestore indexes composite delete index-id --database=database-id
    

각 매개변수는 다음과 같습니다.

  • index-id는 삭제할 색인의 ID입니다. indexes composite list를 사용하여 색인 ID를 검색합니다.
  • database-id는 데이터베이스의 ID입니다.

벡터 색인 설명

gcloud
gcloud alpha firestore indexes composite describe index-id --database=database-id
    

각 매개변수는 다음과 같습니다.

  • index-id는 설명할 색인의 ID입니다. indexes composite list를 사용하여 색인 ID를 검색합니다.
  • database-id는 데이터베이스의 ID입니다.

최근접 이웃 쿼리 수행

유사성 검색을 수행하여 벡터 임베딩의 최근접 이웃을 찾을 수 있습니다. 유사성 검색에는 벡터 색인이 필요합니다. 색인이 없으면 Cloud Firestore에서 gcloud CLI를 사용하여 만들 색인을 제안합니다.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure

collection = collection("coffee-beans")

# Requires vector index
collection.find_nearest(
   vector_field="embedding_field",
   query_vector=Vector([3.0, 1.0, 2.0]),
   distance_measure=DistanceMeasure.EUCLIDEAN,
   limit=5)
    
Node.js
import {
  Firestore,
  FieldValue,
  VectorQuery,
  VectorQuerySnapshot,
} from "@google-cloud/firestore";

// Requires single-field vector index
const vectorQuery: VectorQuery = coll.findNearest('embedding_field', FieldValue.vector([3.0, 1.0, 2.0]), {
  limit: 5,
  distanceMeasure: 'EUCLIDEAN'
});

const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
    

벡터 거리

최근접 이웃 쿼리는 벡터 거리에 대한 다음 옵션을 지원합니다.

  • EUCLIDEAN: 벡터 간의 EUCLIDEAN 거리를 측정합니다. 자세한 내용은 유클리드를 참조하세요.
  • COSINE: 벡터 크기를 기반으로 하지 않는 유사성을 측정할 수 있도록 벡터 사이의 각도를 기준으로 벡터를 비교합니다. COSINE 거리 대신 DOT_PRODUCT를 단위 정규화된 벡터와 함께 사용하는 것이 좋습니다. 이는 수학적으로 동일하며 성능이 더 우수합니다. 자세한 내용은 코사인 유사성을 참조하세요.
  • DOT_PRODUCT: COSINE과 유사하지만 벡터의 크기에 영향을 받습니다. 자세한 내용은 내적을 참조하세요.

데이터 사전 필터링

최근접 이웃을 찾기 전에 데이터를 사전 필터링하려면 불일치 필터를 제외한 다른 필터와의 유사성 검색을 결합할 수 있습니다. andor 복합 필터가 지원됩니다. 필드 필터의 경우 다음과 같은 필터가 지원됩니다.

  • == 같음
  • in
  • array_contains
  • array_contains_any
Python
# Similarity search with pre-filter
# Requires composite vector index
collection.where("color", "==", "red").find_nearest(
   vector_field="embedding_field",
   query_vector=Vector([3.0, 1.0, 2.0]),
   distance_measure=DistanceMeasure.EUCLIDEAN,
   limit=5)
    
Node.js
// Similarity search with pre-filter
// Requires composite vector index
const preFilteredVectorQuery: VectorQuery = coll
  .where("color", "==", "red")
  .findNearest("embedding_field", FieldValue.vector([3.0, 1.0, 2.0]), {
    limit: 5,
    distanceMeasure: "EUCLIDEAN",
  });

vectorQueryResults = await preFilteredVectorQuery.get();
    

제한사항

벡터 임베딩을 사용할 때는 다음 제한사항에 유의하세요.

  • 지원되는 최대 임베딩 차원은 2048입니다. 더 큰 색인을 저장하려면 차원 축소를 사용합니다.
  • 최근접 이웃 쿼리에서 반환할 최대 문서 수는 1,000개입니다.
  • 벡터 검색은 실시간 스냅샷 리스너를 지원하지 않습니다.
  • 불일치 필터를 사용하여 데이터를 사전 필터링할 수 없습니다.
  • Python 및 Node.js 클라이언트 라이브러리만 벡터 검색을 지원합니다.

다음 단계