Java'da NoSQL için Azure Cosmos DB'de dizin ve sorgu vektörleri

Bu makalede vektör verileri oluşturma, verilerin dizinini oluşturma ve ardından kapsayıcıdaki verileri sorgulama açıklanmaktadır.

Vektör dizin oluşturma ve arama özelliğini kullanmadan önce NoSQL için Azure Cosmos DB'de vektör aramasını etkinleştirmeniz gerekir. Azure Cosmos DB kapsayıcısını vektör araması için ayarladıktan sonra bir vektör ekleme ilkesi oluşturursunuz. Ardından, kapsayıcı dizin oluşturma ilkesine vektör dizinleri eklersiniz. Ardından vektör dizinleri ve vektör ekleme ilkesi içeren bir kapsayıcı oluşturursunuz. Son olarak, depolanan veriler üzerinde vektör araması yaparsınız.

Prerequisites

Özelliği etkinleştirme

NoSQL için Azure Cosmos DB'de vektör aramasını etkinleştirmek için şu adımları izleyin:

  1. NoSQL için Azure Cosmos DB kaynak sayfanıza gidin.
  2. Sol bölmedeki Ayarlar'ın altında Özellikler'i seçin.
  3. Vektör Arama için NoSQL API'yi seçin.
  4. Özelliği etkinleştirmek istediğinizi onaylamak için özelliğin açıklamasını okuyun.
  5. NoSQL için Azure Cosmos DB'de vektör aramasını açmak için Etkinleştir'i seçin.

Tip

Alternatif olarak, Hesabınızın özelliklerini NoSQL için Azure Cosmos DB vektör aramasını destekleyecek şekilde güncelleştirmek için Azure CLI'yi kullanın.

az cosmosdb update \
     --resource-group <resource-group-name> \
     --name <account-name> \
     --capabilities EnableNoSQLVectorSearch

Kayıt isteği otomatik olarak onaylanır, ancak geçerlilik kazanması 15 dakika sürebilir.

Aşağıdaki adımlarda , NoSQL için Azure Cosmos DB hesabı ayarlamayı ve veritabanı oluşturmayı bildiğiniz varsayılır. Vektör arama özelliği şu anda mevcut kapsayıcılarda desteklenmiyor. Yeni bir kapsayıcı oluşturmanız gerekir. Kapsayıcıyı oluşturduğunuzda, kapsayıcı düzeyinde vektör ekleme ilkesini ve vektör dizin oluşturma ilkesini belirtirsiniz.

Şimdi İnternet tabanlı bir kitapçı için veritabanı oluşturma örneği ele alalım. Her kitap için başlık, yazar, ISBN ve açıklama bilgilerini depolamak istiyorsunuz. Vektör eklemelerini içerecek şekilde aşağıdaki iki özelliği de tanımlamanız gerekir:

  • özelliği, contentVector kitabın metin içeriğinden oluşturulan metin eklemelerini içerir. Örneğin, ekleme oluşturmadan önce title, author, isbn ve description özelliklerini birleştirirsiniz.
  • Özellik coverImageVector , kitabın kapağındaki görüntülerden oluşturulur.

Vektör araması yapmak için şunları yaparsınız:

  1. Vektör araması yapmak istediğiniz alanlar için vektör eklemeleri oluşturun ve depolayın.
  2. Vektör ekleme ilkesinde vektör ekleme yollarını belirtin.
  3. Kapsayıcı için dizin oluşturma ilkesine istediğiniz vektör dizinlerini ekleyin.

Bu makalenin sonraki bölümleri için kapsayıcınızda depolanan öğeler için aşağıdaki yapıyı göz önünde bulundurun:

{
  "title": "book-title", 
  "author": "book-author", 
  "isbn": "book-isbn", 
  "description": "book-description", 
  "contentVector": [2, -1, 4, 3, 5, -2, 5, -7, 3, 1], 
  "coverImageVector": [0.33, -0.52, 0.45, -0.67, 0.89, -0.34, 0.86, -0.78] 
} 

İlk olarak nesnesini oluşturun CosmosContainerProperties .

CosmosContainerProperties collectionDefinition = new CosmosContainerProperties(UUID.randomUUID().toString(), "Partition_Key_Def");

Kapsayıcınız için vektör ekleme ilkesi oluşturma

Şimdi bir kapsayıcı vektör ilkesi tanımlamanız gerekir. Bu ilke, Sistem işlevlerindeki vektör özelliklerinin nasıl işleneceğini Azure Cosmos DB sorgu altyapısına VectorDistance bildiren bilgiler sağlar. Bu ilke, bir tane belirtmeyi seçerseniz vektör dizin oluşturma ilkesine de gerekli bilgileri sağlar.

Kapsayıcı vektör ilkesine aşağıdaki bilgiler dahildir:

Parametre Description
path Vektörleri içeren özellik yolu.
datatype Vektör öğelerinin türü. Varsayılan değer: Float32.
dimensions Yoldaki her vektörün uzunluğu. Varsayılan değer: 1536.
distanceFunction Uzaklığı/benzerliği hesaplamak için kullanılan ölçüm. Varsayılan değer: Cosine.

Kitap ayrıntıları içeren örnekte vektör ilkesi aşağıdaki örneğe benzer olabilir:

// Creating vector embedding policy
CosmosVectorEmbeddingPolicy cosmosVectorEmbeddingPolicy = new CosmosVectorEmbeddingPolicy();

CosmosVectorEmbedding embedding1 = new CosmosVectorEmbedding();
embedding1.setPath("/coverImageVector");
embedding1.setDataType(CosmosVectorDataType.FLOAT32);
embedding1.setDimensions(8L);
embedding1.setDistanceFunction(CosmosVectorDistanceFunction.COSINE);

CosmosVectorEmbedding embedding2 = new CosmosVectorEmbedding();
embedding2.setPath("/contentVector");
embedding2.setDataType(CosmosVectorDataType.FLOAT32);
embedding2.setDimensions(10L);
embedding2.setDistanceFunction(CosmosVectorDistanceFunction.DOT_PRODUCT);

cosmosVectorEmbeddingPolicy.setCosmosVectorEmbeddings(Arrays.asList(embedding1, embedding2, embedding3));

collectionDefinition.setVectorEmbeddingPolicy(cosmosVectorEmbeddingPolicy);

Dizin oluşturma ilkesinde vektör dizini oluşturma

Vektör ekleme yollarına karar verdikten sonra dizin oluşturma ilkesine vektör dizinleri eklemeniz gerekir. Şu anda NoSQL için Azure Cosmos DB vektör arama özelliği yalnızca yeni kapsayıcılarda desteklenmektedir. Kapsayıcıyı oluşturduğunuzda vektör ilkesini uygularsınız. İlkeyi daha sonra değiştiremezsiniz. Dizin oluşturma ilkesi aşağıdaki örneğe benzer:

IndexingPolicy indexingPolicy = new IndexingPolicy();
indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT);
ExcludedPath excludedPath1 = new ExcludedPath("/coverImageVector/*");
ExcludedPath excludedPath2 = new ExcludedPath("/contentVector/*");
indexingPolicy.setExcludedPaths(ImmutableList.of(excludedPath1, excludedPath2));

IncludedPath includedPath1 = new IncludedPath("/*");
indexingPolicy.setIncludedPaths(Collections.singletonList(includedPath1));

// Creating vector indexes
CosmosVectorIndexSpec cosmosVectorIndexSpec1 = new CosmosVectorIndexSpec();
cosmosVectorIndexSpec1.setPath("/coverImageVector");
cosmosVectorIndexSpec1.setType(CosmosVectorIndexType.QUANTIZED_FLAT.toString());

CosmosVectorIndexSpec cosmosVectorIndexSpec2 = new CosmosVectorIndexSpec();
cosmosVectorIndexSpec2.setPath("/contentVector");
cosmosVectorIndexSpec2.setType(CosmosVectorIndexType.DISK_ANN.toString());

indexingPolicy.setVectorIndexes(Arrays.asList(cosmosVectorIndexSpec1, cosmosVectorIndexSpec2, cosmosVectorIndexSpec3));

collectionDefinition.setIndexingPolicy(indexingPolicy);

Son olarak, kapsayıcıyı, kapsayıcı indeks politikası ve vektör indeks politikası ile oluşturun.

database.createContainer(collectionDefinition).block();

Important

Vektör yolu, ekleme için iyileştirilmiş performans sağlamak amacıyla dizin oluşturma ilkesinin excludedPaths bölümüne eklenir. Vektör yolunun excludedPaths eklenmemesi, istek birimi ücretinin artmasına ve vektör eklemeleri için gecikme yaşanmasına neden olur.

Vektör benzerliği arama sorgusu çalıştırma

İstediğiniz vektör ilkesine sahip bir kapsayıcı oluşturduktan ve kapsayıcıya vektör verileri ekledikten sonra, vektör araması yapmak için sorgudaki VectorDistance sistem işlevini kullanın.

Açıklamaya bakarak yemek tarifleriyle ilgili kitaplar aramak istediğinizi varsayalım. Öncelikle sorgu metninizin embedding'lerini almanız gerekir. Bu durumda, sorgu metni food recipeiçin eklemeler oluşturmak isteyebilirsiniz. Arama sorgunuz için ekleme işlemini yaptıktan sonra, sorgunuza benzer tüm öğeleri almak için bunu vektör arama sorgusundaki işlevde kullanabilirsiniz VectorDistance :

SELECT TOP 10 c.title, VectorDistance(c.contentVector, [1,2,3,4,5,6,7,8,9,10]) AS SimilarityScore   
FROM c  
ORDER BY VectorDistance(c.contentVector, [1,2,3,4,5,6,7,8,9,10])   

Bu sorgu, kitap başlıklarını ve sorgunuzla ilgili benzerlik puanlarını alır. Java'da bir örnek aşağıda verilmişti:

float[] embedding = new float[10];
for (int i = 0; i < 10; i++) {
    array[i] = i + 1;
}
ArrayList<SqlParameter> paramList = new ArrayList<SqlParameter>();
  paramList.add(new SqlParameter("@embedding", embedding));
  SqlQuerySpec querySpec = new SqlQuerySpec("SELECT c.title, VectorDistance(c.contentVector,@embedding) AS SimilarityScore  FROM c ORDER BY VectorDistance(c.contentVector,@embedding)", paramList);
  CosmosPagedIterable<Family> filteredFamilies = container.queryItems(querySpec, new CosmosQueryRequestOptions(), Family.class);

  if (filteredFamilies.iterator().hasNext()) {
      Family family = filteredFamilies.iterator().next();
      logger.info(String.format("First query result: Family with (/id, partition key) = (%s,%s)",family.getId(),family.getLastName()));
  }