Bu sayfada, aşağıdaki teknikleri kullanarak K en yakın komşu (KNN) vektör aramaları yapmak için Cloud Firestore aracını nasıl kullanacağınız gösterilmektedir:
- Vektör değerlerini depolama
- KNN vektör dizinleri oluşturma ve yönetme
- Desteklenen vektör mesafe ölçümlerinden birini kullanarak en yakın k komşu (KNN) sorgusu oluşturma
Başlamadan önce
Yerleştirmeleri Cloud Firestore ürününde depolamadan önce vektör yerleştirmeleri oluşturmanız gerekir. Cloud Firestore, yerleştirmeleri oluşturmaz. Vektör değerleri (ör. Cloud Firestore verilerinizden metin yerleştirmeleri) oluşturmak için Agent Platform gibi bir hizmet kullanabilirsiniz. Ardından bu yerleştirmeleri tekrar Cloud Firestore dokümanlarında depolayabilirsiniz.
Yerleştirmeler hakkında daha fazla bilgi edinmek için Yerleştirme nedir? başlıklı makaleyi inceleyin.
Agent Platform ile metin yerleştirmeleri almayı öğrenmek için Metin yerleştirmeleri alma başlıklı makaleyi inceleyin.
Vektör yerleştirmelerini depolama
Aşağıdaki örneklerde, vektör yerleştirmelerin Cloud Firestore içinde nasıl depolanacağı gösterilmektedir.
Vektör yerleştirme ile yazma işlemi
Aşağıdaki örnekte, bir vektör yerleştirmenin Cloud Firestore dokümanında nasıl depolanacağı gösterilmektedir:
Python
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
Java
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 Functions işleviyle vektör yerleştirmeleri hesaplama
Bir doküman güncellendiğinde veya oluşturulduğunda vektör yerleştirmeleri hesaplayıp depolamak için bir Cloud Functions işlevi oluşturabilirsiniz:
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
Java
// Not yet supported in the Java client library
Vektör dizinleri oluşturma ve yönetme
Vektör yerleştirmelerinizle en yakın komşu araması yapabilmek için ilgili bir dizin oluşturmanız gerekir. Aşağıdaki örneklerde, Google Cloud CLI ve konsol ile vektör dizinlerinin nasıl oluşturulacağı ve yönetileceği gösterilmektedir. Vektör dizinlerini Firebase CLI ve Terraform ile de yönetebilirsiniz.
Vektör dizini oluşturma
Google Cloud konsolu
Google Cloud Console'dan manuel olarak yeni bir dizin oluşturmak için:
- Google Cloud Console'da Veritabanları sayfasına gidin.
- Veritabanları listesinden gerekli veritabanını seçin.
- Gezinme menüsünde Dizinler'i, ardından Manuel sekmesini tıklayın.
- Create Index'i (Dizin Oluştur) tıklayın.
Vektör aramaları için bir vektör alanını dizine eklemek istiyorsanız Vektör dizini oluştur'u seçin.
-
Koleksiyon kimliği girin. Bir vektör alanı yolu ve vektör yerleştirme boyutlarının sayısını girin. Dizine eklemek istediğiniz diğer alanların adlarını ve her alan için bir dizin modu ekleyin.
Save Index'i (Dizini Kaydet) tıklayın.
Yeni dizininiz manuel dizinler listesinde görünür ve Cloud Firestore, dizininizi oluşturmaya başlar. Dizininiz oluşturulduğunda dizinin yanında yeşil bir onay işareti görürsünüz.
gcloud
Vektör dizini oluşturmadan önce Google Cloud CLI aracını en yeni sürüme yükseltin:
gcloud components update
Vektör dizini oluşturmak için gcloud firestore indexes composite create ifadesini kullanın:
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
Bu örnekte:
- collection-group, koleksiyon grubunun kimliğidir.
- vector-field, vektör yerleştirmeyi içeren alanın adıdır.
- database-id, veritabanının kimliğidir.
- vector-configuration,
dimensionvektörünü ve dizin türünü içerir.dimension, 2048'e kadar bir tam sayıdır. Dizin türüflatolmalıdır. Dizin yapılandırmasını şu şekilde biçimlendirin:{"dimension":"DIMENSION", "flat": "{}"}.
Aşağıdaki örnekte, vector-field alanı için vektör dizini ve color alanı için artan dizin içeren bir bileşik dizin oluşturulmaktadır. En yakın komşu aramasından önce verileri önceden filtrelemek için bu dizin türünü kullanabilirsiniz.
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
Tüm vektör dizinlerini listeleme
Google Cloud konsolu
- Google Cloud Console'da Veritabanları sayfasına gidin.
- Veritabanları listesinden gerekli veritabanını seçin.
-
Gezinme menüsünde Dizinler'i, ardından Manuel sekmesini tıklayın.
Dizinler tablosunda, veritabanındaki tüm dizinler listelenir. Vektör dizinleri, simgesi olan bir vektör alanı içerir.
gcloud
Tüm dizinleri listelemek ve dizin kimliklerini almak için:
gcloud firestore indexes composite list --database=database-id
database-id yerine veritabanının kimliğini yazın.
Dizinle ilgili daha fazla ayrıntı görüntülemek için dizin kimliğini kullanabilirsiniz:
gcloud firestore indexes composite describe index-id --database=database-id
Bu örnekte:
- index-id, açıklanacak dizinin kimliğidir.
- database-id, veritabanının kimliğidir.
Vektör dizinini silme
Google Cloud konsolu
- Google Cloud Console'da Veritabanları sayfasına gidin.
- Veritabanları listesinden gerekli veritabanını seçin.
-
Gezinme menüsünde Dizinler'i, ardından Manuel sekmesini tıklayın.
- Manuel dizinlerinizin listesinde, silmek istediğiniz dizin için Diğer düğmesini tıklayın. Sil'i tıklayın.
- Uyarıda Dizini Sil'i tıklayarak bu dizini silmek istediğinizi onaylayın.
gcloud
gcloud firestore indexes composite delete index-id --database=database-id
Bu örnekte:
- index-id, silinecek dizinin kimliğidir.
Dizin kimliğini almak için
indexes composite listkomutunu kullanın. - database-id, veritabanının kimliğidir.
En yakın komşu sorgusu yapma
Bir vektör yerleştirmenin en yakın komşularını bulmak için benzerlik araması yapabilirsiniz. Benzerlik aramaları için vektör dizinleri gerekir. Dizin yoksa Cloud Firestore, gcloud CLI kullanarak oluşturulacak bir dizin önerir.
Aşağıdaki örnekte, sorgu vektörünün en yakın 10 komşusu bulunur.
Python
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
Java
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();
Vektör mesafeleri
En yakın komşu sorguları, vektör mesafesi için aşağıdaki seçenekleri destekler:
EUCLIDEAN: Vektörler arasındakiEUCLIDEANmesafeyi ölçer. Daha fazla bilgi için Öklid başlıklı makaleyi inceleyin.COSINE: Vektörleri aralarındaki açıya göre karşılaştırır. Bu sayede, vektörlerin büyüklüğüne bağlı olmayan benzerliği ölçebilirsiniz. COSINE mesafesi yerine birim normalleştirilmiş vektörlerleDOT_PRODUCTkullanmanızı öneririz. Bu, matematiksel olarak eşdeğerdir ve daha iyi performans sağlar. Daha fazla bilgi için Kosinüs benzerliği başlıklı makaleyi inceleyin.DOT_PRODUCT:COSINEile benzerdir ancak vektörlerin büyüklüğünden etkilenir. Daha fazla bilgi edinmek için Nokta çarpımı başlıklı makaleyi inceleyin.
Mesafe ölçüsünü seçme
Tüm vektör yerleştirmelerinizin normalleştirilip normalleştirilmediğine bağlı olarak, mesafe ölçümünü bulmak için hangi mesafe ölçümünü kullanacağınızı belirleyebilirsiniz. Normalleştirilmiş bir vektör yerleştirmenin büyüklüğü (uzunluğu) tam olarak 1,0'dir.
Ayrıca, modelinizin hangi mesafe ölçümüyle eğitildiğini biliyorsanız vektör yerleştirmeleriniz arasındaki mesafeyi hesaplamak için bu mesafe ölçümünü kullanın.
Normalleştirilmiş veriler
Tüm vektör yerleştirmelerin normalleştirildiği bir veri kümeniz varsa üç mesafe ölçümü de aynı semantik arama sonuçlarını verir. Özetle, her mesafe ölçümü farklı bir değer döndürse de bu değerler aynı şekilde sıralanır. Yerleştirmeler normalleştirildiğinde genellikle en verimli hesaplama yöntemi DOT_PRODUCT olur ancak çoğu durumda fark önemsizdir. Ancak uygulamanız performansa karşı çok hassassa DOT_PRODUCT, performans ayarı konusunda yardımcı olabilir.
Normalleştirilmemiş veriler
Vektör yerleştirmelerinin normalleştirilmediği bir veri kümeniz varsa nokta çarpımı mesafeyi ölçmediği için mesafe ölçüsü olarak DOT_PRODUCT kullanmak matematiksel olarak doğru değildir. Yerleştirmelerin nasıl oluşturulduğuna ve tercih edilen arama türüne bağlı olarak, COSINE veya EUCLIDEAN mesafe ölçümü, diğer mesafe ölçümlerine göre öznel olarak daha iyi arama sonuçları üretir.
Kullanım alanınız için en iyi seçeneği belirlemek amacıyla COSINE veya EUCLIDEAN ile deneme yapmanız gerekebilir.
Verilerin normalleştirilip normalleştirilmediğinden emin değilseniz
Verilerinizin normalleştirilip normalleştirilmediğinden emin değilseniz ve DOT_PRODUCT kullanmak istiyorsanız bunun yerine COSINE kullanmanızı öneririz.
COSINE, normalleştirme özelliği eklenmiş DOT_PRODUCT gibidir.
COSINE kullanılarak ölçülen mesafe 0 ile 2 arasında değişir. 0 değerine yakın bir sonuç, vektörlerin çok benzer olduğunu gösterir.
Belgeleri önceden filtreleme
En yakın komşuları bulmadan önce dokümanları önceden filtrelemek için benzerlik aramasını diğer sorgu operatörleriyle birleştirebilirsiniz. and ve or bileşik filtreleri desteklenir. Desteklenen alan filtreleri hakkında daha fazla bilgi için Sorgu operatörleri başlıklı makaleyi inceleyin.
Python
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
Java
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();
Hesaplanan vektör mesafesini alma
Hesaplanan vektör mesafesini, aşağıdaki örnekte gösterildiği gibi FindNearest sorgusuna bir distance_result_field çıkış özelliği adı atayarak alabilirsiniz:
Python
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
Java
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 ile birlikte belge alanlarının bir alt kümesini döndürmek için alan maskesi kullanmak istiyorsanız aşağıdaki örnekte gösterildiği gibi alan maskesine distanceResultField değerini de eklemeniz gerekir:
Python
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
Java
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")); }
Mesafe eşiği belirtme
Yalnızca eşik dahilindeki dokümanları döndüren bir benzerlik eşiği belirtebilirsiniz. Eşik alanının davranışı, seçtiğiniz mesafe ölçüsüne bağlıdır:
EUCLIDEANveCOSINEmesafeleri, eşiği mesafenin belirtilen eşikten küçük veya eşit olduğu belgelerle sınırlar. Vektörler birbirine benzedikçe bu mesafe ölçümleri azalır.DOT_PRODUCTdistance, eşiği, mesafenin belirtilen eşikten büyük veya eşit olduğu dokümanlarla sınırlar. Vektörler birbirine daha çok benzedikçe iç çarpım uzaklıkları artar.
Aşağıdaki örnekte, EUCLIDEAN mesafe metriğini kullanarak en fazla 4, 5 birim uzaklıktaki en yakın 10 belgeyi döndürmek için mesafe eşiğinin nasıl belirtileceği gösterilmektedir:
Python
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
Java
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()); }
Sınırlamalar
Vektör yerleştirmeleriyle çalışırken aşağıdaki sınırlamalara dikkat edin:
- Desteklenen maksimum yerleştirme boyutu 2048'dir. Daha büyük dizinleri depolamak için boyut azaltma özelliğini kullanın.
- En yakın komşu sorgusundan döndürülecek maksimum belge sayısı 1.000'dir (yalnızca Standard sürüm sınırlaması).
- Vektör araması, gerçek zamanlı anlık görüntü dinleyicilerini desteklemez.
- Yalnızca Python, Node.js, Go ve Java istemci kitaplıkları vektör aramayı destekler.
Sırada ne var?
- Cloud Firestore için en iyi uygulamalar hakkında bilgi edinin.
- Geniş ölçekte okuma ve yazma işlemlerini anlama