Indeksowanie i wektory zapytań w usłudze Azure Cosmos DB for NoSQL w języku Java
Przed użyciem indeksowania wektorów i wyszukiwania należy najpierw włączyć tę funkcję. W tym artykule opisano następujące kroki:
- Włączanie wyszukiwania wektorowego w usłudze Azure Cosmos DB dla noSQL
- Konfigurowanie kontenera usługi Azure Cosmos DB na potrzeby wyszukiwania wektorów
- Zasady osadzania wektorów tworzenia
- Dodawanie indeksów wektorów do zasad indeksowania kontenerów
- Tworzenie kontenera z indeksami wektorów i zasad osadzania wektorów
- Wykonywanie wyszukiwania wektorowego na przechowywanych danych
W tym przewodniku przedstawiono proces tworzenia danych wektorowych, indeksowania danych, a następnie wykonywania zapytań dotyczących danych w kontenerze.
Wymagania wstępne
- Istniejące konto usługi Azure Cosmos DB for NoSQL.
- Jeśli nie masz subskrypcji platformy Azure, wypróbuj bezpłatnie usługę Azure Cosmos DB dla noSQL.
- Jeśli masz istniejącą subskrypcję platformy Azure, utwórz nowe konto usługi Azure Cosmos DB for NoSQL.
- Najnowsza wersja zestawu Java SDK usługi Azure Cosmos DB.
Włączanie funkcji
Wyszukiwanie wektorowe dla usługi Azure Cosmos DB dla NoSQL wymaga włączenia funkcji. Wykonaj poniższe kroki, aby się zarejestrować:
- Przejdź do strony zasobów usługi Azure Cosmos DB for NoSQL.
- Wybierz okienko "Funkcje" w elemencie menu "Ustawienia".
- Wybierz pozycję "Wyszukiwanie wektorowe w usłudze Azure Cosmos DB for NoSQL".
- Przeczytaj opis funkcji, aby potwierdzić, że chcesz ją włączyć.
- Wybierz pozycję "Włącz", aby włączyć wyszukiwanie wektorów w usłudze Azure Cosmos DB dla noSQL.
Napiwek
Możesz też użyć interfejsu wiersza polecenia platformy Azure, aby zaktualizować możliwości konta w celu obsługi wyszukiwania wektorów NoSQL.
az cosmosdb update \
--resource-group <resource-group-name> \
--name <account-name> \
--capabilities EnableNoSQLVectorSearch
Uwaga
Żądanie rejestracji zostanie automatycznie zatwierdzone; jednak może upłynąć 15 minut.
Opis kroków związanych z wyszukiwaniem wektorowym
W poniższych krokach założono, że wiesz, jak skonfigurować konto NoSQL usługi Cosmos DB i utworzyć bazę danych. Funkcja wyszukiwania wektorowego nie jest obecnie obsługiwana w istniejących kontenerach, dlatego należy utworzyć nowy kontener i określić zasady osadzania wektora na poziomie kontenera oraz zasady indeksowania wektorów w czasie tworzenia kontenera.
Przyjrzyjmy się przykładowi tworzenia bazy danych dla internetowej księgarni i przechowujesz tytuł, autor, ISBN i opis dla każdej książki. Definiujemy również dwie właściwości, które mają zawierać osadzanie wektorów. Pierwsza to właściwość "contentVector", która zawiera osadzanie tekstu wygenerowane na podstawie zawartości tekstowej książki (na przykład łączenie właściwości "title" "author" "isbn" i "description" przed utworzeniem osadzania). Drugi to "coverImageVector", który jest generowany na podstawie obrazów okładki książki.
- Twórz i przechowuj wektorowe osadzania dla pól, na których chcesz przeprowadzić wyszukiwanie wektorów.
- Określ ścieżki osadzania wektorów w zasadach osadzania wektorów.
- Uwzględnij wszystkie żądane indeksy wektorów w zasadach indeksowania dla kontenera.
W kolejnych sekcjach tego artykułu rozważymy poniższą strukturę elementów przechowywanych w naszym kontenerze:
{
"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]
}
Najpierw utwórz CosmosContainerProperties
obiekt.
CosmosContainerProperties collectionDefinition = new CosmosContainerProperties(UUID.randomUUID().toString(), "Partition_Key_Def");
Tworzenie zasad osadzania wektorów dla kontenera
Następnie należy zdefiniować zasady wektora kontenera. Te zasady zawierają informacje używane do informowania aparatu zapytań usługi Azure Cosmos DB o sposobie obsługi właściwości wektorów w funkcjach systemu VectorDistance. Informuje to również zasady indeksowania wektorów o niezbędnych informacjach, jeśli chcesz je określić. Następujące informacje znajdują się w zasadach zawartych wektorów:
- "path": ścieżka właściwości zawierająca wektory
- "datatype": typ elementów wektora (wartość domyślna Float32)
- "dimensions": długość każdego wektora w ścieżce (domyślnie 1536)
- "distanceFunction": metryka używana do obliczania odległości/podobieństwa (domyślna cosinus)
W naszym przykładzie ze szczegółami książki zasady wektorów mogą wyglądać jak przykładowy kod JSON:
// 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);
Tworzenie indeksu wektorowego w zasadach indeksowania
Po podjęciu decyzji o ścieżkach osadzania wektorów należy dodać indeksy wektorów do zasad indeksowania. Obecnie funkcja wyszukiwania wektorowego dla usługi Azure Cosmos DB for NoSQL jest obsługiwana tylko w nowych kontenerach, więc należy zastosować zasady wektorów w czasie tworzenia kontenera i nie można jej później modyfikować. W tym przykładzie zasady indeksowania będą wyglądać mniej więcej tak:
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);
Na koniec utwórz kontener za pomocą zasad indeksu kontenera i zasad indeksu wektora.
database.createContainer(collectionDefinition).block();
Ważne
Ścieżka wektorowa dodana do sekcji "excludedPaths" zasad indeksowania w celu zapewnienia zoptymalizowanej wydajności wstawiania. Dodanie ścieżki wektora do "excludedPaths" spowoduje wyższe obciążenie jednostek RU i opóźnienie dla wstawiania wektorów.
Uruchamianie zapytania wyszukiwania podobieństwa wektorów
Po utworzeniu kontenera z żądanymi zasadami wektorów i wstawieniu danych wektorowych do kontenera można przeprowadzić wyszukiwanie wektorów przy użyciu funkcji systemowej Vector Distance w zapytaniu. Załóżmy, że chcesz wyszukać książki dotyczące przepisów spożywczych, patrząc na opis, musisz najpierw uzyskać osadzanie tekstu zapytania. W takim przypadku możesz wygenerować osadzanie dla tekstu zapytania — "przepis na żywność". Po osadzeniu zapytania wyszukiwania można go użyć w funkcji VectorDistance w zapytaniu wyszukiwania wektorowego i pobrać wszystkie elementy podobne do zapytania, jak pokazano poniżej:
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])
To zapytanie pobiera tytuły książki wraz z wynikami podobieństwa w odniesieniu do zapytania. Oto przykład w języku 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()));
}