Dela via


Index- och frågevektorer i Azure Cosmos DB för NoSQL i Java

Innan du använder vektorindexering och sökning måste du först aktivera funktionen. Den här artikeln beskriver följande steg:

  1. Aktivera vektorsökning i Azure Cosmos DB för NoSQL-funktionen
  2. Konfigurera Azure Cosmos DB-containern för vektorsökning
  3. Redigeringsvektor för inbäddningsprincip
  4. Lägga till vektorindex i containerindexeringsprincipen
  5. Skapa en container med vektorindex och inbäddningsprincip för vektorer
  6. Utföra en vektorsökning på lagrade data

Den här guiden går igenom processen med att skapa vektordata, indexera data och sedan köra frågor mot data i en container.

Förutsättningar

Aktivera funktionen

Vektorsökning för Azure Cosmos DB för NoSQL kräver funktionsaktivering. Följ stegen nedan för att registrera dig:

  1. Gå till resurssidan för Azure Cosmos DB for NoSQL.
  2. Välj fönstret "Funktioner" under menyalternativet "Inställningar".
  3. Välj "Vector Search in Azure Cosmos DB for NoSQL" (Vektorsökning i Azure Cosmos DB för NoSQL).
  4. Läs beskrivningen av funktionen för att bekräfta att du vill aktivera den.
  5. Välj "Aktivera" för att aktivera vektorsökning i Azure Cosmos DB för NoSQL.

Dricks

Du kan också använda Azure CLI för att uppdatera funktionerna i ditt konto för att stödja NoSQL-vektorsökning.

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

Kommentar

Registreringsbegäran godkänns automatiskt. Det kan dock ta 15 minuter att börja gälla.

Följande steg förutsätter att du vet hur du konfigurerar ett Cosmos DB NoSQL-konto och skapar en databas. Vektorsökningsfunktionen stöds för närvarande inte på befintliga containrar, så du måste skapa en ny container och ange inbäddningsprincipen för vektor på containernivå och vektorindexeringsprincipen när containern skapas.

Låt oss ta ett exempel på hur du skapar en databas för en internetbaserad bokhandel och du lagrar Title, Author, ISBN och Description för varje bok. Vi definierar också två egenskaper som ska innehålla inbäddningar av vektorer. Den första är egenskapen "contentVector", som innehåller textbäddningar som genereras från textinnehållet i boken (till exempel att sammanfoga egenskaperna "title" "author" "isbn" och "description" innan du skapar inbäddningen). Den andra är "coverImageVector", som genereras från bilder av bokens omslag.

  1. Skapa och lagra vektorinbäddningar för de fält där du vill utföra vektorsökning.
  2. Ange vektorbäddningssökvägarna i inbäddningsprincipen för vektorer.
  3. Inkludera önskade vektorindex i indexeringsprincipen för containern.

För efterföljande avsnitt i den här artikeln överväger vi strukturen nedan för de objekt som lagras i containern:

{
  "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] 
} 

CosmosContainerProperties Skapa först objektet.

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

Skapa en vektorinbäddningsprincip för din container

Därefter måste du definiera en containervektorprincip. Den här principen innehåller information som används för att informera Azure Cosmos DB-frågemotorn om hur vektoregenskaper i VectorDistance-systemfunktionerna ska hanteras. Detta informerar också vektorindexeringsprincipen om nödvändig information, om du väljer att ange en. Följande information ingår i policyn för inneslutna vektorer:

  • "path": Egenskapssökvägen som innehåller vektorer
  • "datatype": Typen av element i vektorn (standard float32)
  • "dimensions": Längden på varje vektor i sökvägen (standard 1536)
  • "distanceFunction": Måttet som används för att beräkna avstånd/likhet (standard cosiné)

I vårt exempel med bokinformation kan vektorprincipen se ut som JSON-exemplet:

// 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);

Skapa ett vektorindex i indexeringsprincipen

När vektorbäddningsvägarna har bestämts måste vektorindex läggas till i indexeringsprincipen. För närvarande stöds vektorsökningsfunktionen för Azure Cosmos DB for NoSQL endast på nya containrar, så du måste tillämpa vektorprincipen när containern skapas och den kan inte ändras senare. I det här exemplet skulle indexeringsprincipen se ut ungefär så här:

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);

Skapa slutligen containern med containerindexprincipen och vektorindexprincipen.

database.createContainer(collectionDefinition).block();

Viktigt!

Vektorsökvägen har lagts till i avsnittet "excludedPaths" i indexeringsprincipen för att säkerställa optimerad prestanda för infogning. Om du inte lägger till vektorsökvägen till "excludedPaths" resulterar det i högre RU-laddning och svarstid för vektorinfogningar.

Köra vektorlikhetssökningsfråga

När du har skapat en container med önskad vektorprincip och infogat vektordata i containern kan du utföra en vektorsökning med hjälp av systemfunktionen Vektoravstånd i en fråga. Anta att du vill söka efter böcker om matrecept genom att titta på beskrivningen. Du måste först hämta inbäddningarna för frågetexten. I det här fallet kanske du vill generera inbäddningar för frågetexten – "matrecept". När du har bäddat in för sökfrågan kan du använda den i funktionen VectorDistance i vektorsökningsfrågan och hämta alla objekt som liknar din fråga som du ser här:

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])   

Den här frågan hämtar boktitlarna tillsammans med likhetspoäng med avseende på din fråga. Här är ett exempel i Java:

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()));
  }