벡터 임베딩으로 검색

이 페이지에서는 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])
});
Go
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

type CoffeeBean struct {
	Name           string             `firestore:"name,omitempty"`
	Description    string             `firestore:"description,omitempty"`
	EmbeddingField firestore.Vector32 `firestore:"embedding_field,omitempty"`
	Color          string             `firestore:"color,omitempty"`
}

func storeVectors(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	// Vector can be represented by Vector32 or Vector64
	doc := CoffeeBean{
		Name:           "Kahawa coffee beans",
		Description:    "Information about the Kahawa coffee beans.",
		EmbeddingField: []float32{1.0, 2.0, 3.0},
		Color:          "red",
	}
	ref := client.Collection("coffee-beans").NewDoc()
	if _, err = ref.Set(ctx, doc); err != nil {
		fmt.Fprintf(w, "failed to upsert: %v", err)
		return err
	}

	return nil
}
자바
import com.google.cloud.firestore.CollectionReference;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.FieldValue;
import com.google.cloud.firestore.VectorQuery;

CollectionReference coll = firestore.collection("coffee-beans");

Map<String, Object> docData = new HashMap<>();
docData.put("name", "Kahawa coffee beans");
docData.put("description", "Information about the Kahawa coffee beans.");
docData.put("embedding_field", FieldValue.vector(new double[] {1.0, 2.0, 3.0}));

ApiFuture<DocumentReference> future = coll.add(docData);
DocumentReference documentReference = future.get();

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,
  });
}
Go
  // Not yet supported in the Go client library
자바
  // Not yet supported in the Java client library

벡터 색인 만들기 및 관리

벡터 임베딩으로 최근접 이웃 검색을 수행하려면 먼저 해당하는 색인을 만들어야 합니다 다음 예시는 Google Cloud CLI를 사용하여 벡터 색인을 만들고 관리하는 방법을 보여줍니다. 벡터 색인은 Firebase CLI 및 Terraform으로 관리할 수도 있습니다.

벡터 색인 만들기

벡터 색인을 만들기 전에 Google Cloud CLI의 최신 버전으로 업그레이드합니다.

gcloud components update

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

gcloud
gcloud 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": "{}"}

다음 예시에서는 vector-field 필드의 벡터 색인과 color 필드의 오름차순 색인을 포함하는 복합 색인을 만듭니다. 이러한 유형의 색인을 사용하여 최근접 이웃 검색을 수행하기 전에 데이터를 사전 필터링할 수 있습니다.

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

모든 벡터 색인 나열

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

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

벡터 색인 삭제

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

각 항목의 의미는 다음과 같습니다.

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

벡터 색인 설명

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

각 항목의 의미는 다음과 같습니다.

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

최근접 이웃 쿼리 수행

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

다음 예시에서는 쿼리 벡터의 최근접 이웃 10개를 찾습니다.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

# Requires a single-field vector index
vector_query = 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 a single-field vector index
const vectorQuery: VectorQuery = coll.findNearest({
  vectorField: 'embedding_field',
  queryVector: [3.0, 1.0, 2.0],
  limit: 10,
  distanceMeasure: 'EUCLIDEAN'
});

const vectorQuerySnapshot: VectorQuerySnapshot = await vectorQuery.get();
Go
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchBasic(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		5,
		// More info: https://firebase.google.com/docs/firestore/vector-search#vector_distances
		firestore.DistanceMeasureEuclidean,
		nil)

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
자바
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN);

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

벡터 거리

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

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

거리 측정 선택

모든 벡터 임베딩이 정규화되었는지 여부에 따라 거리 측정을 찾는 데 사용할 거리 측정을 결정할 수 있습니다. 정규화된 벡터 임베딩의 크기(길이)는 정확히 1.0입니다.

또한 모델이 어떤 거리 측정으로 학습되었는지 알고 있다면 해당 거리 측정을 사용하여 벡터 임베딩 간의 거리를 계산할 수 있습니다.

정규화된 데이터

모든 벡터 임베딩이 정규화된 데이터 세트가 있다면, 세 거리 측정 모두 동일한 시맨틱 검색 결과를 제공합니다. 기본적으로 각 거리 측정은 서로 다른 값을 반환하지만 해당 값은 동일한 방식으로 정렬됩니다. 임베딩이 정규화될 때는 일반적으로 DOT_PRODUCT가 가장 계산 효율적이지만 대부분의 경우 그 차이는 무시할 수 있을 정도입니다. 하지만 애플리케이션이 성능에 매우 민감한 경우 DOT_PRODUCT가 성능 조정에 도움이 될 수 있습니다.

비정규화된 데이터

벡터 임베딩이 정규화되지 않은 데이터 세트가 있는 경우 내적에서 거리를 측정하지 않기 때문에 DOT_PRODUCT를 거리 측정으로 사용하는 것은 수학적으로 올바르지 않습니다. 임베딩이 생성된 방법과 원하는 검색 유형에 따라 COSINE 또는 EUCLIDEAN 거리 측정에서 다른 거리 측정보다 주관적으로 더 나은 검색 결과를 생성할 수 있습니다. 사용 사례에 가장 적합한 방식을 결정하려면 COSINE 또는 EUCLIDEAN를 실험해야 할 수 있습니다.

데이터가 정규화되었는지 또는 비정규화되었는지 확실하지 않음

데이터가 정규화되었는지 여부가 확실하지 않고 DOT_PRODUCT를 사용하려는 경우 대신 COSINE를 사용하는 것이 좋습니다. COSINE은 정규화가 내장된 DOT_PRODUCT와 같습니다. COSINE을 사용하여 측정한 거리의 범위는 0~2입니다. 결과가 0에 가까우면 벡터가 매우 유사하다는 것을 나타냅니다.

문서 사전 필터링

최근접 이웃을 찾기 전에 문서를 사전 필터링하려면 유사성 검색을 다른 쿼리 연산자와 결합할 수 있습니다. andor 복합 필터가 지원됩니다. 지원되는 필드 필터에 대한 자세한 내용은 쿼리 연산자를 참조하세요.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

# Similarity search with pre-filter
# Requires a composite vector index
vector_query = 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({
      vectorField: "embedding_field",
      queryVector: [3.0, 1.0, 2.0],
      limit: 5,
      distanceMeasure: "EUCLIDEAN",
    });

const vectorQueryResults = await preFilteredVectorQuery.get();
Go
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchPrefilter(w io.Writer, projectID string) error {
	ctx := context.Background()

	// Create client
	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Similarity search with pre-filter
	// Requires a composite vector index
	vectorQuery := collection.Where("color", "==", "red").
		FindNearest("embedding_field",
			[]float32{3.0, 1.0, 2.0},
			5,
			// More info: https://firebase.google.com/docs/firestore/vector-search#vector_distances
			firestore.DistanceMeasureEuclidean,
			nil)

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
자바
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery preFilteredVectorQuery = coll
        .whereEqualTo("color", "red")
        .findNearest(
                "embedding_field",
                new double[] {3.0, 1.0, 2.0},
                /* limit */ 10,
                VectorQuery.DistanceMeasure.EUCLIDEAN);

ApiFuture<VectorQuerySnapshot> future = preFilteredVectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

계산된 벡터 거리 검색하기

다음 예시와 같이 FindNearest 쿼리에 distance_result_field 출력 속성 이름을 할당하여 계산된 벡터 거리를 검색할 수 있습니다.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([3.0, 1.0, 2.0]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}, Distance: {doc.get('vector_distance')}")
Node.js
const vectorQuery: VectorQuery = coll.findNearest(
    {
      vectorField: 'embedding_field',
      queryVector: [3.0, 1.0, 2.0],
      limit: 10,
      distanceMeasure: 'EUCLIDEAN',
      distanceResultField: 'vector_distance'
    });

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

snapshot.forEach((doc) => {
  console.log(doc.id, ' Distance: ', doc.get('vector_distance'));
});
Go
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchDistanceResultField(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		10,
		firestore.DistanceMeasureEuclidean,
		&firestore.FindNearestOptions{
			DistanceResultField: "vector_distance",
		})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintf(w, "%v, Distance: %v\n", doc.Data()["name"], doc.Data()["vector_distance"])
	}
	return nil
}
자바
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder().setDistanceResultField("vector_distance").build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId() + " Distance: " + document.get("vector_distance"));
}

필드 마스크를 사용하여 distanceResultField와 함께 문서 필드의 하위 집합을 반환하려면 다음 예시와 같이 필드 마스크에 distanceResultField 값도 포함해야 합니다.

Python
vector_query = collection.select(["color", "vector_distance"]).find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([3.0, 1.0, 2.0]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_result_field="vector_distance",
)
Node.js
const vectorQuery: VectorQuery = coll
    .select('name', 'description', 'vector_distance')
    .findNearest({
      vectorField: 'embedding_field',
      queryVector: [3.0, 1.0, 2.0],
      limit: 10,
      distanceMeasure: 'EUCLIDEAN',
      distanceResultField: 'vector_distance'
    });
Go
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchDistanceResultFieldMasked(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.Select("color", "vector_distance").
		FindNearest("embedding_field",
			[]float32{3.0, 1.0, 2.0},
			10,
			firestore.DistanceMeasureEuclidean,
			&firestore.FindNearestOptions{
				DistanceResultField: "vector_distance",
			})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintf(w, "%v, Distance: %v\n", doc.Data()["color"], doc.Data()["vector_distance"])
	}
	return nil
}
자바
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll
        .select("name", "description", "vector_distance")
        .findNearest(
          "embedding_field",
          new double[] {3.0, 1.0, 2.0},
          /* limit */ 10,
          VectorQuery.DistanceMeasure.EUCLIDEAN,
          VectorQueryOptions.newBuilder()
            .setDistanceResultField("vector_distance")
            .build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId() + " Distance: " + document.get("vector_distance"));
}

거리 기준점 지정

기준점 내의 문서만 반환하는 유사성 기준점을 지정할 수 있습니다. 기준점 필드의 동작은 선택한 거리 측정에 따라 다릅니다.

  • EUCLIDEANCOSINE 거리는 거리가 지정된 기준점 이하인 문서로 기준점을 제한합니다. 이러한 거리 측정은 벡터가 더 유사해질수록 감소합니다.
  • DOT_PRODUCT 거리는 거리가 지정된 기준점 이상인 문서로 기준점을 제한합니다. 내적 거리는 벡터가 더 유사해질수록 증가합니다.

다음 예시는 EUCLIDEAN 거리 측정항목을 사용하여 최대 4.5단위 거리에 있는 가장 가까운 문서를 최대 10개 반환하도록 거리 기준점을 지정하는 방법을 보여줍니다.

Python
from google.cloud.firestore_v1.base_vector_query import DistanceMeasure
from google.cloud.firestore_v1.vector import Vector

collection = db.collection("coffee-beans")

vector_query = collection.find_nearest(
    vector_field="embedding_field",
    query_vector=Vector([3.0, 1.0, 2.0]),
    distance_measure=DistanceMeasure.EUCLIDEAN,
    limit=10,
    distance_threshold=4.5,
)

docs = vector_query.stream()

for doc in docs:
    print(f"{doc.id}")
Node.js
const vectorQuery: VectorQuery = coll.findNearest({
  vectorField: 'embedding_field',
  queryVector: [3.0, 1.0, 2.0],
  limit: 10,
  distanceMeasure: 'EUCLIDEAN',
  distanceThreshold: 4.5
});

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

snapshot.forEach((doc) => {
  console.log(doc.id);
});
Go
import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/firestore"
)

func vectorSearchDistanceThreshold(w io.Writer, projectID string) error {
	ctx := context.Background()

	client, err := firestore.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("firestore.NewClient: %w", err)
	}
	defer client.Close()

	collection := client.Collection("coffee-beans")

	// Requires a vector index
	// https://firebase.google.com/docs/firestore/vector-search#create_and_manage_vector_indexes
	vectorQuery := collection.FindNearest("embedding_field",
		[]float32{3.0, 1.0, 2.0},
		10,
		firestore.DistanceMeasureEuclidean,
		&firestore.FindNearestOptions{
			DistanceThreshold: firestore.Ptr[float64](4.5),
		})

	docs, err := vectorQuery.Documents(ctx).GetAll()
	if err != nil {
		fmt.Fprintf(w, "failed to get vector query results: %v", err)
		return err
	}

	for _, doc := range docs {
		fmt.Fprintln(w, doc.Data()["name"])
	}
	return nil
}
자바
import com.google.cloud.firestore.VectorQuery;
import com.google.cloud.firestore.VectorQueryOptions;
import com.google.cloud.firestore.VectorQuerySnapshot;

VectorQuery vectorQuery = coll.findNearest(
        "embedding_field",
        new double[] {3.0, 1.0, 2.0},
        /* limit */ 10,
        VectorQuery.DistanceMeasure.EUCLIDEAN,
        VectorQueryOptions.newBuilder()
          .setDistanceThreshold(4.5)
          .build());

ApiFuture<VectorQuerySnapshot> future = vectorQuery.get();
VectorQuerySnapshot vectorQuerySnapshot = future.get();

for (DocumentSnapshot document : vectorQuerySnapshot.getDocuments()) {
    System.out.println(document.getId());
}

제한사항

벡터 임베딩으로 작업할 때 다음 제한사항에 유의하세요.

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

다음 단계