Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Użyj wyszukiwania wektorów w Azure Cosmos DB z biblioteką klienta Java. Wydajne przechowywanie danych wektorów i wykonywanie zapytań w aplikacjach.
W tym przewodniku szybkiego startu użyto przykładowego hotelowego zestawu danych zawartego w pliku JSON z wektorami z modelu text-embedding-3-small. Zestaw danych zawiera nazwy hoteli, lokalizacje, opisy i osadzanie wektorów.
Znajdź przykładowy kod z aprowizowaniem zasobów w GitHub.
Wymagania wstępne
Subskrypcja Azure
- Jeśli nie masz subskrypcji Azure, utwórz konto free
Istniejący dostęp do płaszczyzny danych zasobów Azure Cosmos DB
- Jeśli nie masz zasobu, utwórz zasób nowy zasób
- Zapora skonfigurowana do zezwalania na dostęp do adresu IP klienta
- Przypisane role kontroli dostępu opartej na rolach (RBAC):
- Wbudowany współautor danych w usłudze Cosmos DB (płaszczyzna danych)
- Identyfikator roli:
00000000-0000-0000-0000-000000000002
-
- Skonfigurowano domenę niestandardową
- Przypisano rolę kontroli dostępu opartej na rolach (RBAC):
- Użytkownik usług Cognitive Services OpenAI
- Identyfikator roli:
5e0bd9bd-7b93-4f28-af87-19fc36ad61bd
-
text-embedding-3-smallwdrożony model
Tworzenie pliku danych z wektorami
Utwórz nowy katalog danych dla pliku danych hoteli:
mkdir dataPobierz plik danych raw z wektorami do katalogu
data:curl -o data/HotelsData_toCosmosDB_Vector.json https://raw.githubusercontent.com/Azure-Samples/cosmos-db-vector-samples/refs/heads/main/data/HotelsData_toCosmosDB_Vector.json
Tworzenie projektu Java
Utwórz nowy katalog równorzędny dla projektu na tym samym poziomie co katalog danych i otwórz go w Visual Studio Code:
mkdir vector-search-quickstart cd vector-search-quickstart code .pom.xmlUtwórz plik w katalogu głównym projektu przy użyciu konfiguracji narzędzia Maven:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example.cosmos.samples</groupId> <artifactId>nosql-vector-search-sample</artifactId> <version>1.0.0</version> <name>Azure Cosmos DB NoSQL Vector Search - Java</name> <properties> <maven.compiler.release>21</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Azure Cosmos DB SDK (NoSQL API) --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-cosmos</artifactId> <version>4.69.0</version> </dependency> <!-- Azure Identity (DefaultAzureCredential) --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.18.1</version> </dependency> <!-- Azure OpenAI (embeddings) --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-ai-openai</artifactId> <version>1.0.0-beta.16</version> </dependency> <!-- Jackson (JSON serialization) --> <dependency> <groupId>tools.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>3.0.3</version> </dependency> <!-- Suppress noisy SDK logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>2.0.17</version> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.5.0</version> <configuration> <mainClass>com.example.cosmos.vectorsearch.VectorSearch</mainClass> </configuration> </plugin> </plugins> </build> </project>Kluczowe zależności:
- azure-identity — biblioteka uwierzytelniania Azure dla połączeń bez hasła (tożsamości zarządzanej)
- azure-cosmos — biblioteka klienta Azure Cosmos DB dla operacji bazy danych
- azure-ai-openai — SDK platformy Azure OpenAI do generowania wektorów osadzania
- slf4j-nop — pomija głośne rejestrowanie zestawu SDK w czasie wykonywania
Utwórz strukturę katalogu źródłowego:
mkdir -p src/main/java/com/example/cosmos/vectorsearch.envUtwórz plik w katalogu głównym projektu dla zmiennych środowiskowych:# Azure OpenAI Embedding Settings AZURE_OPENAI_EMBEDDING_MODEL=text-embedding-3-small AZURE_OPENAI_EMBEDDING_API_VERSION=2024-08-01-preview AZURE_OPENAI_EMBEDDING_ENDPOINT= # Cosmos DB configuration AZURE_COSMOSDB_ENDPOINT= # Data file DATA_FILE_WITH_VECTORS=../data/HotelsData_toCosmosDB_Vector.json FIELD_TO_EMBED=Description EMBEDDED_FIELD=DescriptionVector EMBEDDING_DIMENSIONS=1536 # Vector search algorithm: diskann or quantizedflat VECTOR_ALGORITHM=diskannZastąp wartości znaczników zastępczych w pliku
.envwłasnymi informacjami:-
AZURE_OPENAI_EMBEDDING_ENDPOINT: Adres URL punktu końcowego zasobu Azure OpenAI -
AZURE_COSMOSDB_ENDPOINT: Adres URL punktu końcowego Azure Cosmos DB
Uwaga / Notatka
Przykład Java używa
System.getenv()do odczytywania zmiennych środowiskowych. Należy wyeksportować te zmienne w sesji powłoki lub użyćazd env get-values, aby je ustawić. Plik.envsłuży jako szablon odwołania — nie jest ładowany automatycznie przez aplikację.-
Omówienie schematu dokumentu
Przed utworzeniem aplikacji dowiedz się, jak wektory są przechowywane w dokumentach Azure Cosmos DB. Każdy dokument hotelowy zawiera:
-
Pola standardowe:
HotelId,HotelName,Description,Category, itp. -
Pole wektorowe:
DescriptionVector— tablica 1536 liczb zmiennoprzecinkowych reprezentujących semantyczne znaczenie opisu hotelu
Oto uproszczony przykład struktury dokumentów hotelowych:
{
"HotelId": "1",
"HotelName": "Stay-Kay City Hotel",
"Description": "This classic hotel is fully-refurbished...",
"Rating": 3.6,
"DescriptionVector": [
-0.04886505,
-0.02030743,
0.01763356,
...
// 1536 dimensions total
]
}
Najważniejsze kwestie dotyczące przechowywania osadzania:
- Tablice wektorowe są przechowywane jako standardowe tablice JSON w dokumentach
-
Zasady wektorów definiują ścieżkę (), typ danych (
/DescriptionVectorfloat32), wymiary (1536) i funkcję odległości (cosinus) - Zasady indeksowania tworzą indeks wektorowy w polu wektora w celu wydajnego wyszukiwania podobieństwa
- Pole wektorowe powinno zostać wykluczone ze standardowego indeksowania w celu zoptymalizowania wydajności wstawiania
Te zasady są definiowane w szablonach Bicep dla metryk odległości dla tego przykładowego projektu. Aby uzyskać więcej informacji na temat polityk wektorowych i indeksowania, zobacz Wyszukiwanie wektorowe w Azure Cosmos DB.
Tworzenie plików kodu na potrzeby wyszukiwania wektorowego
Utwórz dwa pliki źródłowe Java w katalogu src/main/java/com/example/cosmos/vectorsearch:
touch src/main/java/com/example/cosmos/vectorsearch/VectorSearch.java
touch src/main/java/com/example/cosmos/vectorsearch/Utils.java
Tworzenie kodu na potrzeby wyszukiwania wektorów
Wklej następujący kod do VectorSearch.java pliku.
package com.example.cosmos.vectorsearch;
import com.azure.ai.openai.OpenAIClient;
import com.azure.ai.openai.models.EmbeddingItem;
import com.azure.ai.openai.models.EmbeddingsOptions;
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.models.CosmosQueryRequestOptions;
import com.azure.cosmos.models.SqlParameter;
import com.azure.cosmos.models.SqlQuerySpec;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Azure Cosmos DB NoSQL vector search sample — Java port of nosql-vector-search-typescript.
*
* Demonstrates:
* - Passwordless authentication with DefaultAzureCredential
* - Bulk insert of hotel data with pre-computed embeddings
* - Vector similarity search using VectorDistance() SQL function
* - DiskANN and QuantizedFlat algorithm selection via environment variable
*/
public final class VectorSearch {
private static final String SAMPLE_QUERY =
"quintessential lodging near running trails, eateries, retail";
private static final Set<String> VALID_ALGORITHMS = Set.of("diskann", "quantizedflat");
private static final Map<String, String> ALGORITHM_CONTAINERS = Map.of(
"diskann", "hotels_diskann",
"quantizedflat", "hotels_quantizedflat"
);
private static final Map<String, String> ALGORITHM_DISPLAY = Map.of(
"diskann", "DiskANN",
"quantizedflat", "QuantizedFlat"
);
public static void main(String[] args) {
try {
new VectorSearch().run();
} catch (Exception e) {
System.err.println("App failed: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
private void run() throws Exception {
// ── Configuration ───────────────────────────────────────────────
var algorithm = Utils.envOrDefault("VECTOR_ALGORITHM", "diskann").trim().toLowerCase();
var dbName = Utils.envOrDefault("AZURE_COSMOSDB_DATABASENAME", "Hotels");
var dataFile = Utils.requireEnv("DATA_FILE_WITH_VECTORS");
var embeddedField = Utils.requireEnv("EMBEDDED_FIELD");
var deployment = Utils.requireEnv("AZURE_OPENAI_EMBEDDING_MODEL");
var distanceFunction = Utils.envOrDefault("VECTOR_DISTANCE_FUNCTION", "cosine");
if (!VALID_ALGORITHMS.contains(algorithm)) {
throw new IllegalArgumentException(
"Invalid algorithm '" + algorithm + "'. Must be one of: " +
String.join(", ", VALID_ALGORITHMS));
}
var containerName = ALGORITHM_CONTAINERS.get(algorithm);
var algorithmDisplay = ALGORITHM_DISPLAY.get(algorithm);
// ── Clients ─────────────────────────────────────────────────────
OpenAIClient aiClient = Utils.createOpenAIClient();
CosmosClient dbClient = Utils.createCosmosClient();
try {
var database = dbClient.getDatabase(dbName);
System.out.println("Connected to database: " + dbName);
CosmosContainer container = database.getContainer(containerName);
System.out.println("Connected to container: " + containerName);
System.out.println("\n[Algorithm] Vector Search Algorithm: " + algorithmDisplay);
System.out.println("[Distance] Distance Function: " + distanceFunction);
// Verify container exists
container.read();
// ── Load & Insert Data ──────────────────────────────────────
var dataPath = Path.of(dataFile);
var data = Utils.readJsonFile(dataPath);
Utils.insertData(container, data);
// ── Generate Query Embedding ────────────────────────────────
var embeddingOptions = new EmbeddingsOptions(List.of(SAMPLE_QUERY));
var embeddingResult = aiClient.getEmbeddings(deployment, embeddingOptions);
List<Float> embedding = embeddingResult.getData().get(0).getEmbedding();
// Convert Float list to List<Double> for Cosmos DB parameter binding
var embeddingDoubles = new ArrayList<Double>(embedding.size());
for (var f : embedding) {
embeddingDoubles.add(f.doubleValue());
}
// ── Build & Execute Vector Search Query ─────────────────────
var safeField = Utils.validateFieldName(embeddedField);
var queryText = "SELECT TOP 5 c.HotelName, c.Description, c.Rating, " +
"VectorDistance(c." + safeField + ", @embedding) AS SimilarityScore " +
"FROM c " +
"ORDER BY VectorDistance(c." + safeField + ", @embedding)";
System.out.println("\n--- Executing Vector Search Query ---");
System.out.println("Query: " + queryText);
System.out.println("Parameters: @embedding (vector with " + embeddingDoubles.size() + " dimensions)");
System.out.println("--------------------------------------\n");
var sqlQuery = new SqlQuerySpec(
queryText,
List.of(new SqlParameter("@embedding", embeddingDoubles))
);
var queryOptions = new CosmosQueryRequestOptions();
@SuppressWarnings("unchecked")
var resultPages = container.queryItems(sqlQuery, queryOptions, Map.class);
var results = new ArrayList<Map<String, Object>>();
var requestCharge = 0.0;
for (var page : resultPages.iterableByPage()) {
requestCharge += page.getRequestCharge();
for (var item : page.getResults()) {
@SuppressWarnings("unchecked")
var typedItem = (Map<String, Object>) item;
results.add(typedItem);
}
}
Utils.printSearchResults(results, requestCharge);
} finally {
dbClient.close();
}
}
}
Ten kod:
- Konfiguruje algorytm wektora
DiskANNlubquantizedFlatz zmiennej środowiskowejVECTOR_ALGORITHM. - Nawiązuje połączenie z Azure OpenAI i Azure Cosmos DB poprzez uwierzytelnianie bezhasłowe.
- Ładuje wstępnie wektoryzowane dane hotelowe z pliku JSON.
- Wstawia dane do odpowiedniego kontenera.
- Generuje osadzanie dla zapytania w języku naturalnym (
quintessential lodging near running trails, eateries, retail). - Wykonuje zapytanie SQL,
VectorDistanceaby pobrać 5 najbardziej semantycznie podobnych hoteli sklasyfikowanych według wyniku podobieństwa. - Obsługuje błędy brakujących klientów, wybór nieprawidłowego algorytmu i nieistniejące kontenery/bazy danych.
Omówienie kodu: Generowanie osadzania za pomocą Azure OpenAI
Kod tworzy osadzanie dla tekstu zapytania:
EmbeddingsOptions options = new EmbeddingsOptions(
List.of(queryText) // Array of description strings to embed
);
Embeddings embeddings = openAIClient.getEmbeddings(model, options);
List<Float> queryVector = embeddings.getData().get(0).getEmbedding();
To wywołanie Azure OpenAI SDK konwertuje tekst, taki jak "kwintesencjonalne zakwaterowanie w pobliżu tras biegowych", na wektor o wymiarze 1536, który oddaje jego znaczenie semantyczne. Aby uzyskać więcej informacji na temat generowania wektorów osadzających, zobacz dokumentację wektorów osadzających Azure OpenAI.
Opis kodu: Przechowywanie wektorów w Azure Cosmos DB
Wszystkie dokumenty z tablicami wektorowymi są wstawiane na dużą skalę przy użyciu executeBulkOperations metody w pliku Utils.insertData(). Każdy dokument jest mapowany na zbiorczą operację tworzenia przy użyciu PartitionKeyBuilder dla wartości klucza partycji każdego dokumentu. Narzędzie śledzi wstawione, pominięte i nieudane liczby wraz z całkowitym użyciem jednostek RU.
Spowoduje to wstawienie dokumentów hotelowych, w tym wstępnie wygenerowanych DescriptionVector tablic do kontenera. Możesz bezpiecznie przekazać wszystkie dane dokumentu, a biblioteka klienta obsługuje przetwarzanie wsadowe oraz ponowne próby.
Opis kodu: Uruchamianie wyszukiwania podobieństwa wektorów
Kod wykonuje wyszukiwanie wektorów przy użyciu VectorDistance funkcji :
String queryText = String.format(
"SELECT TOP 5 c.HotelName, c.Description, c.Rating, " +
"VectorDistance(c.%s, @embedding) AS SimilarityScore " +
"FROM c ORDER BY VectorDistance(c.%s, @embedding)",
embeddedField, embeddedField
);
SqlQuerySpec querySpec = new SqlQuerySpec(queryText,
new SqlParameter("@embedding", queryVector));
CosmosPagedIterable<ObjectNode> results = container.queryItems(
querySpec, new CosmosQueryRequestOptions(), ObjectNode.class);
Ten kod tworzy sparametryzowane zapytanie SQL, które używa funkcji VectorDistance do porównywania wektora osadzania zapytania (@embedding) względem pola wektora składowanego każdego dokumentu (DescriptionVector), zwracając 5 najlepszych hoteli z ich nazwą i wynikiem podobieństwa, uporządkowanym z najbardziej podobnych do najmniej podobnych. Osadzenie zapytania jest przekazywane jako parametr, aby uniknąć injekcji i pochodzi z wcześniejszego wywołania osadzania Azure OpenAI.
Co zwraca to zapytanie:
- 5 najbardziej podobnych hoteli w oparciu o odległość wektora
- Właściwości hoteli:
HotelName,Description,Rating -
SimilarityScore: wartość liczbowa wskazująca, jak podobny jest każdy hotel do zapytania - Wyniki uporządkowane z najbardziej podobnych do najmniej podobnych
Aby uzyskać więcej informacji na VectorDistance temat funkcji, zobacz dokumentację vectorDistance.
Tworzenie funkcji narzędziowych
Wklej następujący kod do Utils.javapliku :
package com.example.cosmos.vectorsearch;
import com.azure.ai.openai.OpenAIClientBuilder;
import com.azure.ai.openai.OpenAIClient;
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.models.CosmosBulkOperations;
import com.azure.cosmos.models.CosmosItemOperation;
import com.azure.cosmos.models.PartitionKey;
import com.azure.cosmos.models.PartitionKeyBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;
import tools.jackson.databind.json.JsonMapper;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Shared utilities for Azure Cosmos DB NoSQL vector search sample.
* Provides authentication, bulk insert, field validation, and result formatting.
*/
public final class Utils {
private static final JsonMapper JSON_MAPPER = JsonMapper.builder().build();
private Utils() {
// utility class
}
// ── Authentication ──────────────────────────────────────────────────
/**
* Create an Azure OpenAI client using DefaultAzureCredential (passwordless).
*/
public static OpenAIClient createOpenAIClient() {
var endpoint = requireEnv("AZURE_OPENAI_EMBEDDING_ENDPOINT");
var credential = new DefaultAzureCredentialBuilder().build();
return new OpenAIClientBuilder()
.endpoint(endpoint)
.credential(credential)
.buildClient();
}
/**
* Create a Cosmos DB client using DefaultAzureCredential (passwordless).
*/
public static CosmosClient createCosmosClient() {
var endpoint = requireEnv("AZURE_COSMOSDB_ENDPOINT");
var credential = new DefaultAzureCredentialBuilder().build();
return new CosmosClientBuilder()
.endpoint(endpoint)
.credential(credential)
.buildClient();
}
// ── Data Loading ────────────────────────────────────────────────────
/**
* Read a JSON array file and return its contents as a list of maps.
*/
@SuppressWarnings("unchecked")
public static List<Map<String, Object>> readJsonFile(Path filePath) throws IOException {
System.out.println("Reading JSON file from " + filePath);
var bytes = Files.readAllBytes(filePath);
return JSON_MAPPER.readValue(bytes, List.class);
}
// ── Bulk Insert ─────────────────────────────────────────────────────
/**
* Insert documents into a Cosmos DB container using bulk operations.
* Skips insert if the container already contains data.
*
* @return summary with counts and RU charge
*/
public static BulkInsertResult insertData(CosmosContainer container,
List<Map<String, Object>> data) {
// Check existing document count
var existingCount = getDocumentCount(container);
if (existingCount > 0) {
System.out.println("Container already has " + existingCount + " documents. Skipping insert.");
return new BulkInsertResult(0, 0, 0, (int) existingCount, 0.0);
}
System.out.println("Inserting " + data.size() + " items using bulk operations...");
// Build bulk create operations
var operations = new ArrayList<CosmosItemOperation>();
for (var item : data) {
// Cosmos DB requires an "id" field — map HotelId to id
var doc = new java.util.HashMap<>(item);
var hotelId = String.valueOf(doc.get("HotelId"));
doc.put("id", hotelId);
operations.add(CosmosBulkOperations.getCreateItemOperation(doc,
new PartitionKeyBuilder().add(hotelId).build()));
}
var inserted = 0;
var failed = 0;
var skipped = 0;
var totalRUs = 0.0;
var startTime = System.currentTimeMillis();
System.out.println("Starting bulk insert (" + operations.size() + " items)...");
var responses = container.executeBulkOperations(operations);
for (var response : responses) {
var statusCode = response.getResponse().getStatusCode();
totalRUs += response.getResponse().getRequestCharge();
if (statusCode >= 200 && statusCode < 300) {
inserted++;
} else if (statusCode == 409) {
skipped++;
} else {
failed++;
}
}
var durationSec = (System.currentTimeMillis() - startTime) / 1000.0;
System.out.printf("Bulk insert completed in %.2fs%n", durationSec);
System.out.printf("%nInsert Request Charge: %.2f RUs%n%n", totalRUs);
return new BulkInsertResult(data.size(), inserted, failed, skipped, totalRUs);
}
private static long getDocumentCount(CosmosContainer container) {
var result = container.queryItems(
"SELECT VALUE COUNT(1) FROM c",
new com.azure.cosmos.models.CosmosQueryRequestOptions(),
Long.class
);
for (var count : result) {
return count;
}
return 0;
}
// ── Field Name Validation ───────────────────────────────────────────
/**
* Validates a field name to prevent NoSQL injection when building queries
* with string interpolation.
*
* @param fieldName the field name to validate
* @return the validated field name
* @throws IllegalArgumentException if the field name contains unsafe characters
*/
public static String validateFieldName(String fieldName) {
if (!fieldName.matches("^[A-Za-z_][A-Za-z0-9_]*$")) {
throw new IllegalArgumentException(
"Invalid field name: \"" + fieldName + "\". " +
"Field names must start with a letter or underscore " +
"and contain only letters, numbers, and underscores.");
}
return fieldName;
}
// ── Output Formatting ───────────────────────────────────────────────
/**
* Print search results in a consistent tabular format.
*/
public static void printSearchResults(List<Map<String, Object>> results, double requestCharge) {
System.out.println("\n--- Search Results ---");
if (results == null || results.isEmpty()) {
System.out.println("No results found.");
return;
}
for (var i = 0; i < results.size(); i++) {
var r = results.get(i);
var name = r.get("HotelName");
var score = r.get("SimilarityScore");
System.out.printf("%d. %s, Score: %.4f%n", i + 1, name, ((Number) score).doubleValue());
}
System.out.printf("%nVector Search Request Charge: %.2f RUs%n%n", requestCharge);
}
// ── Environment Helpers ─────────────────────────────────────────────
public static String requireEnv(String key) {
var value = System.getenv(key);
if (value == null || value.isBlank()) {
throw new IllegalStateException("Required environment variable not set: " + key);
}
return value;
}
public static String envOrDefault(String key, String defaultValue) {
var value = System.getenv(key);
return (value != null && !value.isBlank()) ? value : defaultValue;
}
// ── Result Record ───────────────────────────────────────────────────
public record BulkInsertResult(int total, int inserted, int failed, int skipped, double requestCharge) {}
}
Ta klasa narzędzi udostępnia następujące kluczowe funkcje:
-
createOpenAIClient/createCosmosClient: Tworzenie klientów dla Azure OpenAI i Azure Cosmos DB przy użyciu uwierzytelniania bez hasła za pośrednictwem opcji DefaultAzureCredential. Włącz kontrolę dostępu opartą na rolach dla obu zasobów i zaloguj się do Azure CLI -
insertData: Wstawia dane w partiach do kontenera Azure Cosmos DB przy użyciu operacji zbiorczych i śledzi liczby wstawionych, pominiętych i nieudanych operacji wraz z całkowitym użyciem jednostek RU. -
printSearchResults: Wyświetla wyniki wyszukiwania wektorowego, w tym wynik i nazwę hotelu -
validateFieldName: Sprawdza, czy nazwa pola istnieje w danych, aby zapobiec iniekcji
Uwierzytelnianie przy użyciu Azure CLI
Zaloguj się do Azure CLI przed uruchomieniem aplikacji, aby aplikacja mogła bezpiecznie uzyskiwać dostęp do Azure zasobów.
az login
Kod używa lokalnego uwierzytelniania dewelopera do uzyskiwania dostępu do Azure Cosmos DB i Azure OpenAI za pomocą createOpenAIClient i createCosmosClient z Utils.java. Te funkcje bazują na DefaultAzureCredential z azure-identity który prowadzi uporządkowany łańcuch dostawców poświadczeń i rozpoznaje Azure CLI poświadczenia na potrzeby programowania lokalnego. Dowiedz się więcej o tym, jak uwierzytelniać aplikacje Java do usług Azure przy użyciu biblioteki Azure Identity.
Kompilowanie i uruchamianie aplikacji
Skompiluj i uruchom aplikację za pomocą narzędzia Maven:
Linux/macOS:
VECTOR_ALGORITHM=diskann mvn compile exec:java
Windows:
set VECTOR_ALGORITHM=diskann && mvn compile exec:java
Rejestrowanie i dane wyjściowe aplikacji pokazują:
- Stan wstawiania danych
- Tworzenie indeksu wektorowego
- Wyniki wyszukiwania z nazwami hoteli i wynikami podobieństwa
Connected to database: Hotels
Connected to container: hotels_diskann
📊 Vector Search Algorithm: DiskANN
📏 Distance Function: cosine
Reading JSON file from ../data/HotelsData_toCosmosDB_Vector.json
Inserting 50 items using bulk operations...
Starting bulk insert (50 items)...
Bulk insert completed in 3.41s
Insert Request Charge: 6805.25 RUs
--- Executing Vector Search Query ---
Query: SELECT TOP 5 c.HotelName, c.Description, c.Rating, VectorDistance(c.DescriptionVector, @embedding) AS SimilarityScore FROM c ORDER BY VectorDistance(c.DescriptionVector, @embedding)
Parameters: @embedding (vector with 1536 dimensions)
--------------------------------------
--- Search Results ---
1. Royal Cottage Resort, Score: 0.4991
2. Country Comfort Inn, Score: 0.4786
3. Nordick's Valley Motel, Score: 0.4635
4. Economy Universe Motel, Score: 0.4461
5. Roach Motel, Score: 0.4388
Vector Search Request Charge: 5.33 RUs
Metryki odległości
Azure Cosmos DB obsługuje trzy funkcje odległości dla podobieństwa wektorów:
| Funkcja odległości | Zakres wyników | Interpretacja | Najlepsze dla |
|---|---|---|---|
| Cosinus (ustawienie domyślne) | Od 0.0 do 1.0 | Wyższe wyniki (bliżej 1,0) wskazują na większe podobieństwo | Ogólne podobieństwo tekstu, osadzenia Azure OpenAI (używane w tym szybkim starcie) |
| Euklidesan (L2) | Od 0,0 do ∞ | Dolna = bardziej podobna | Dane przestrzenne, gdy wielkość ma znaczenie |
| Kropka produktu | -∞ do +∞ | Wyższe = bardziej podobne | Gdy wielkości wektorów są znormalizowane |
Funkcja distance jest ustawiana w zasadach osadzania wektorów podczas tworzenia kontenera. Jest to dostępne w infrastrukturze w przykładowym repozytorium. Jest on definiowany jako część definicji kontenera.
{
name: 'hotels_diskann'
partitionKeyPaths: [
'/HotelId'
]
indexingPolicy: {
indexingMode: 'consistent'
automatic: true
includedPaths: [
{
path: '/*'
}
]
excludedPaths: [
{
path: '/_etag/?'
}
{
path: '/DescriptionVector/*'
}
]
vectorIndexes: [
{
path: '/DescriptionVector'
type: 'diskANN'
}
]
}
vectorEmbeddingPolicy: {
vectorEmbeddings: [
{
path: '/DescriptionVector'
dataType: 'float32'
dimensions: 1536
distanceFunction: 'cosine'
}
]
}
}
Ten kod Bicep definiuje konfigurację kontenera Azure Cosmos DB do przechowywania dokumentów hotelowych z funkcjami wyszukiwania wektorowego.
| Majątek | Opis |
|---|---|
partitionKeyPaths |
Partycjonuje dokumenty z użyciem HotelId dla rozproszonego przechowywania. |
indexingPolicy |
Konfiguruje automatyczne indeksowanie wszystkich właściwości dokumentu (/*) oprócz pola systemowego _etag i tablicy DescriptionVector w celu zoptymalizowania wydajności zapisu. Pola wektorowe nie wymagają indeksowania standardowego, ponieważ zamiast tego używają wyspecjalizowanej vectorIndexes konfiguracji. |
vectorIndexes |
Tworzy indeks DiskANN lub quantizedFlat na /DescriptionVector ścieżce w celu efektywnego wyszukiwania podobieństwa. |
vectorEmbeddingPolicy |
Definiuje cechy pola wektorowego: float32 typ danych o wymiarach 1536 (pasujących text-embedding-3-small do danych wyjściowych modelu) i cosinus jako funkcja odległości do mierzenia podobieństwa między wektorami podczas zapytań. |
Interpretowanie wyników podobieństwa
W przykładowych wynikach przy użyciu podobieństwa cosinus:
- 0.4991 (Royal Cottage Resort) - Najwyższa podobieństwo, najlepsze dopasowanie do "zakwaterowania w pobliżu tras biegowych, restauracji, handlu detalicznego"
- 0.4388 (Roach Motel) - Niższe podobieństwo, nadal istotne, ale mniej zgodne
- Wyniki bliżej 1,0 wskazują na silniejsze podobieństwo semantyczne
- Wyniki zbliżone do 0 wskazują na niewielkie podobieństwo
Ważna
- Wartości wyników bezwzględnych zależą od modelu osadzania i danych
- Skup się na względnym rankingu , a nie na progach bezwzględnych
- Embeddingi Azure OpenAI najlepiej współpracują z podobieństwem cosinusowym.
Aby uzyskać szczegółowe informacje na temat funkcji odległości, zobacz Co to są funkcje odległości?
Wyświetlanie danych i zarządzanie nimi w Visual Studio Code
Wybierz rozszerzenie Cosmos DB w Visual Studio Code, aby nawiązać połączenie z kontem Azure Cosmos DB.
Wyświetl dane i indeksy w bazie danych Hotels.
Uprzątnij zasoby
Jeśli nie potrzebujesz już interfejsu API dla konta NoSQL, możesz usunąć odpowiednią grupę zasobów.