Partager via


Démarrage rapide : Recherche vectorielle

Dans ce guide de démarrage rapide, vous utilisez la bibliothèque cliente Azure AI Search pour .NET pour créer, charger et interroger un index vectoriel. La bibliothèque de client .NET fournit une abstraction sur les API REST pour les opérations d’index.

Dans Azure AI Search, un index vectoriel a un schéma d’index qui définit des champs vectoriels et non vecteurs, une configuration de recherche vectorielle pour les algorithmes qui créent l’espace d’incorporation et les paramètres sur les définitions de champs vectoriels évaluées au moment de la requête. Index - Créer ou mettre à jour (API REST) crée l’index vectoriel.

Conseil / Astuce

Prérequis

Configurer l’accès

Avant de commencer, vérifiez que vous disposez des autorisations nécessaires pour accéder au contenu et aux opérations dans Azure AI Search. Ce guide de démarrage rapide utilise Microsoft Entra ID pour l’authentification et l’accès en fonction du rôle pour l’autorisation. Vous devez être un propriétaire ou un administrateur d'accès utilisateur pour attribuer des rôles. Si les rôles ne sont pas réalisables, utilisez plutôt l’authentification basée sur des clés.

Pour configurer l’accès en fonction du rôle recommandé :

  1. Activez l’accès en fonction du rôle pour votre service de recherche.

  2. Attribuez les rôles suivants à votre compte d’utilisateur.

    • Contributeur Service de Recherche

    • Contributeur de données d’index de la Recherche

    • Lecteur de données d’index de la Recherche

Obtenir un point de terminaison

Chaque service Azure AI Search a un endpoint, qui est une URL unique qui identifie et fournit un accès réseau au service. Dans une section ultérieure, vous spécifiez ce point de terminaison pour vous connecter à votre service de recherche par programmation.

Pour obtenir le point de terminaison :

  1. Connectez-vous au portail Azure et sélectionnez votre service de recherche.

  2. Dans le volet gauche, sélectionnez Vue d’ensemble.

  3. Notez le point de terminaison, qui doit ressembler à https://my-service.search.windows.net.

Configurer l’environnement

  1. Utilisez Git pour cloner l’exemple de référentiel.

    git clone https://github.com/Azure-Samples/azure-search-dotnet-samples
    
  2. Accédez au dossier de démarrage rapide et ouvrez-le dans Visual Studio Code.

    cd azure-search-dotnet-samples/quickstart-vector-search
    code .
    
  3. Dans VectorSearchCreatePopulateIndex/appsettings.json, remplacez la valeur d’espace réservé pour Endpoint par l’URL que vous avez obtenue dans Obtenir le point de terminaison.

  4. Répétez l’étape précédente pour VectorSearchExamples/appsettings.json.

  5. Pour l’authentification sans clé avec Microsoft Entra ID, connectez-vous à votre compte Azure. Si vous avez plusieurs abonnements, sélectionnez celui qui contient votre service Azure AI Search.

    az login
    

Exécuter le code

  1. Exécutez le premier projet pour créer et remplir l’index.

    cd VectorSearchCreatePopulateIndex
    dotnet run
    
  2. Dans VectorSearchExamples/Program.cs, décommentez les méthodes de requête que vous souhaitez exécuter.

  3. Exécutez le deuxième projet pour exécuter ces requêtes sur l’index.

    cd ..\VectorSearchExamples
    dotnet run
    

Output

La sortie du premier projet inclut la confirmation de la création d’index et les chargements de documents réussis.

Creating or updating index 'hotels-vector-quickstart'...
Index 'hotels-vector-quickstart' updated.

Key: 1, Succeeded: True
Key: 2, Succeeded: True
Key: 3, Succeeded: True
Key: 4, Succeeded: True
Key: 48, Succeeded: True
Key: 49, Succeeded: True
Key: 13, Succeeded: True

La sortie du deuxième projet affiche les résultats de recherche pour chaque méthode de requête activée. L’exemple suivant montre les résultats de recherche à vecteur unique.

Single Vector Search Results:
Score: 0.6605852, HotelId: 48, HotelName: Nordick's Valley Motel
Score: 0.6333684, HotelId: 13, HotelName: Luxury Lion Resort
Score: 0.605672, HotelId: 4, HotelName: Sublime Palace Hotel
Score: 0.6026341, HotelId: 49, HotelName: Swirling Currents Hotel
Score: 0.57902366, HotelId: 2, HotelName: Old Century Hotel

Comprendre le code

Remarque

Les extraits de code de cette section ont peut-être été modifiés pour la lisibilité. Pour obtenir un exemple de travail complet, consultez le code source.

Maintenant que vous avez exécuté le code, nous allons décomposer les étapes clés :

  1. Créer un index de vecteur
  2. Charger des documents dans l’index
  3. Interroger l’index

Créer un index de vecteur

Avant d’ajouter du contenu à Azure AI Search, vous devez créer un index pour définir la façon dont le contenu est stocké et structuré.

Le schéma d’index est organisé autour du contenu de l’hôtel. Les exemples de données se composent de descriptions vectorielles et non vectorielles d’hôtels fictifs. Le code suivant dans VectorSearchCreatePopulateIndex/Program.cs crée le schéma d’index, y compris le champ DescriptionVectorvectoriel.

static async Task CreateSearchIndex(string indexName, SearchIndexClient indexClient)
{
    var addressField = new ComplexField("Address");
    addressField.Fields.Add(new SearchableField("StreetAddress") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft });
    addressField.Fields.Add(new SearchableField("City") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });
    addressField.Fields.Add(new SearchableField("StateProvince") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });
    addressField.Fields.Add(new SearchableField("PostalCode") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });
    addressField.Fields.Add(new SearchableField("Country") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true });

    var allFields = new List<SearchField>()
    {
        new SimpleField("HotelId", SearchFieldDataType.String) { IsKey = true, IsFacetable = true, IsFilterable = true },
        new SearchableField("HotelName") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft },
        new SearchableField("Description") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft },
        new VectorSearchField("DescriptionVector", 1536, "my-vector-profile"),
        new SearchableField("Category") { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true },
        new SearchableField("Tags", collection: true) { AnalyzerName = LexicalAnalyzerName.EnMicrosoft, IsFacetable = true, IsFilterable = true },
        new SimpleField("ParkingIncluded", SearchFieldDataType.Boolean) { IsFacetable = true, IsFilterable = true },
        new SimpleField("LastRenovationDate", SearchFieldDataType.DateTimeOffset) { IsSortable = true },
        new SimpleField("Rating", SearchFieldDataType.Double) { IsFacetable = true, IsFilterable = true, IsSortable = true },
        addressField,
        new SimpleField("Location", SearchFieldDataType.GeographyPoint) { IsFilterable = true, IsSortable = true },
    };

    // Create the suggester configuration
    var suggester = new SearchSuggester("sg", new[] { "Address/City", "Address/Country" });

    // Create the semantic search
    var semanticSearch = new SemanticSearch()
    {
        Configurations =
        {
            new SemanticConfiguration(
                name: "semantic-config",
                prioritizedFields: new SemanticPrioritizedFields
                {
                    TitleField = new SemanticField("HotelName"),
                    KeywordsFields = { new SemanticField("Category") },
                    ContentFields = { new SemanticField("Description") }
                })
        }
    };

    // Add vector search configuration
    var vectorSearch = new VectorSearch();
    vectorSearch.Algorithms.Add(new HnswAlgorithmConfiguration(name: "my-hnsw-vector-config-1"));
    vectorSearch.Profiles.Add(new VectorSearchProfile(name: "my-vector-profile", algorithmConfigurationName: "my-hnsw-vector-config-1"));

    var definition = new SearchIndex(indexName)
    {
        Fields = allFields,
        Suggesters = { suggester },
        VectorSearch = vectorSearch,
        SemanticSearch = semanticSearch
    };

    // Create or update the index
    Console.WriteLine($"Creating or updating index '{indexName}'...");
    var result = await indexClient.CreateOrUpdateIndexAsync(definition);
    Console.WriteLine($"Index '{result.Value.Name}' updated.");
    Console.WriteLine();
}

Points clés :

  • Vous définissez un index en créant une liste de champs.

  • Cet index particulier prend en charge plusieurs fonctionnalités de recherche :

  • Le deuxième paramètre dans VectorSearchField détermine vectorSearchDimensions, qui doit correspondre à la taille de sortie de votre modèle d'intégration. Ce guide de démarrage rapide utilise 1 536 dimensions pour correspondre au text-embedding-ada-002 modèle.

  • La VectorSearch configuration définit l’algorithme De voisin le plus proche approximatif (ANN). Les algorithmes pris en charge incluent Hierarchical Navigable Small World (HNSW) et l’algorithme exhaustif des K plus proches voisins (KNN). Pour plus d’informations, consultez Pertinence dans la recherche vectorielle.

Charger des documents dans l’index

Les index nouvellement créés sont vides. Pour remplir un index et le rendre pouvant faire l’objet d’une recherche, vous devez charger des documents JSON conformes au schéma d’index.

Dans Azure AI Search, les documents servent d’entrées pour l’indexation et les sorties pour les requêtes. Par souci de simplicité, ce guide de démarrage rapide fournit des exemples de documents d’hôtel avec des vecteurs précomputés. Dans les scénarios de production, le contenu est souvent extrait de sources de données connectées et transformé en JSON à l’aide d’indexeurs.

Le code suivant charge les documents depuis HotelData.json vers votre service de recherche.

static async Task UploadDocs(SearchClient searchClient)
{
    var jsonPath = Path.Combine(Directory.GetCurrentDirectory(), "HotelData.json");

    // Read and parse hotel data
    var json = await File.ReadAllTextAsync(jsonPath);
    List<Hotel> hotels = new List<Hotel>();
    try
    {
        using var doc = JsonDocument.Parse(json);
        if (doc.RootElement.ValueKind != JsonValueKind.Array)
        {
            Console.WriteLine("HotelData.json root is not a JSON array.");
        }
        // Deserialize all hotel objects
        hotels = doc.RootElement.EnumerateArray()
            .Select(e => JsonSerializer.Deserialize<Hotel>(e.GetRawText()))
            .Where(h => h != null)
            .ToList();
    }
    catch (JsonException ex)
    {
        Console.WriteLine($"Failed to parse HotelData.json: {ex.Message}");
    }

    try
    {
        // Upload hotel documents to Azure Search
        var result = await searchClient.UploadDocumentsAsync(hotels);
        foreach (var r in result.Value.Results)
        {
            Console.WriteLine($"Key: {r.Key}, Succeeded: {r.Succeeded}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed to upload documents: " + ex);
    }
}

Votre code interagit avec un index de recherche spécifique hébergé dans votre service Azure AI Search via le SearchClient, qui est l’objet principal fourni par le package Azure.Search.Documents. Il SearchClient fournit l’accès aux opérations d’index, telles que :

  • Ingestion des données : UploadDocuments(), MergeDocuments(), DeleteDocuments()

  • Opérations de recherche : Search(), Autocomplete(), Suggest()

Interroger l’index

Les requêtes dans VectorSearchExamples démontrent différents modèles de recherche. L’exemple des requêtes vectorielles sont basés sur deux chaînes :

  • Chaîne de recherche en texte intégral : "historic hotel walk to restaurants and shopping"

  • Chaîne de requête vectorielle : "quintessential lodging near running trails, eateries, retail" (vectorisée en représentation mathématique)

La chaîne de requête vectorielle est sémantiquement similaire à la chaîne de recherche en texte intégral, mais elle inclut des termes qui n’existent pas dans l’index. Une recherche par mot clé uniquement pour la chaîne de requête vectorielle retourne zéro résultat. Toutefois, la recherche vectorielle recherche des correspondances pertinentes en fonction de la signification plutôt que des mots clés exacts.

Les exemples suivants commencent par une requête vectorielle de base et ajoutent progressivement des filtres, la recherche de mots clés et la reclassement sémantique.

La SearchSingleVector méthode illustre un scénario de base dans lequel vous souhaitez rechercher des descriptions de document qui correspondent étroitement à la chaîne de requête vectorielle. VectorizedQuery configure la recherche vectorielle :

  • KNearestNeighborsCount limite le nombre de résultats retournés en fonction de la similarité vectorielle.
  • Fields spécifie le champ vecteur à rechercher.
public static async Task SearchSingleVector(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> response = await searchClient.SearchAsync<Hotel>(
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" },
        });

    Console.WriteLine($"Single Vector Search Results:");
    await foreach (SearchResult<Hotel> result in response.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}, HotelId: {doc.HotelId}, HotelName: {doc.HotelName}");
    }
    Console.WriteLine();
}

Recherche à vecteur unique avec un filtre

Dans Azure AI Search, filters s’appliquent aux champs non-vecteurs d’un index. La SearchSingleVectorWithFilter méthode filtre sur le Tags champ pour filtrer les hôtels qui ne fournissent pas de wi-fi gratuit.

public static async Task SearchSingleVectorWithFilter(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithFilter = await searchClient.SearchAsync<Hotel>(
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Filter = "Tags/any(tag: tag eq 'free wifi')",
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" }
        });

    Console.WriteLine($"Single Vector Search With Filter Results:");
    await foreach (SearchResult<Hotel> result in responseWithFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}, HotelId: {doc.HotelId}, HotelName: {doc.HotelName}, Tags: {string.Join(String.Empty, doc.Tags)}");
    }
    Console.WriteLine();
}

Recherche à vecteur unique avec un filtre géographique

Vous pouvez spécifier un filtre géo-spatial pour limiter les résultats à une zone géographique spécifique. La SingleSearchWithGeoFilter méthode spécifie un point géographique (Washington D.C., à l’aide des coordonnées de longitude et de latitude) et renvoie des hôtels dans un rayon de 300 kilomètres. Par défaut, les filtres s’exécutent après la recherche vectorielle.

public static async Task SingleSearchWithGeoFilter(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithGeoFilter = await searchClient.SearchAsync<Hotel>(
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Filter = "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
            Select = { "HotelId", "HotelName", "Description", "Address", "Category", "Tags" },
            Facets = { "Address/StateProvince" },
        });

    Console.WriteLine($"Vector query with a geo filter:");
    await foreach (SearchResult<Hotel> result in responseWithGeoFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"HotelId: {doc.HotelId}");
        Console.WriteLine($"HotelName: {doc.HotelName}");
        Console.WriteLine($"Score: {result.Score}");
        Console.WriteLine($"City/State: {doc.Address.City}/{doc.Address.StateProvince}");
        Console.WriteLine($"Description: {doc.Description}");
        Console.WriteLine();
    }
    Console.WriteLine();
}

La recherche hybride combine des requêtes de texte intégral et de vecteur dans une seule requête. La SearchHybridVectorAndText méthode exécute les deux types de requêtes simultanément, puis utilise la fusion de classement réciproque (RRF) pour fusionner les résultats dans un classement unifié. RRF utilise l’inverse des classements de résultats de chaque jeu de résultats pour produire un classement fusionné. Notez que les scores de recherche hybride sont uniformément plus petits que les scores à requête unique.

public static async Task<SearchResults<Hotel>> SearchHybridVectorAndText(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithFilter = await searchClient.SearchAsync<Hotel>(
        "historic hotel walk to restaurants and shopping",
        new SearchOptions
        {
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" },
            Size = 5,
        });

    Console.WriteLine($"Hybrid search results:");
    await foreach (SearchResult<Hotel> result in responseWithFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}");
        Console.WriteLine($"HotelId: {doc.HotelId}");
        Console.WriteLine($"HotelName: {doc.HotelName}");
        Console.WriteLine($"Description: {doc.Description}");
        Console.WriteLine($"Category: {doc.Category}");
        Console.WriteLine($"Tags: {string.Join(String.Empty, doc.Tags)}");
        Console.WriteLine();
    }
    Console.WriteLine();
    return responseWithFilter;
}

La SearchHybridVectorAndSemantic méthode illustre le classement sémantique, qui reclasse les résultats en fonction de la compréhension du langage.

public static async Task SearchHybridVectorAndSemantic(SearchClient searchClient, ReadOnlyMemory<float> precalculatedVector)
{
    SearchResults<Hotel> responseWithFilter = await searchClient.SearchAsync<Hotel>(
        "historic hotel walk to restaurants and shopping",
        new SearchOptions
        {
            IncludeTotalCount = true,
            VectorSearch = new()
            {
                Queries = { new VectorizedQuery(precalculatedVector) { KNearestNeighborsCount = 5, Fields = { "DescriptionVector" } } }
            },
            Select = { "HotelId", "HotelName", "Description", "Category", "Tags" },
            SemanticSearch = new SemanticSearchOptions
            {
                SemanticConfigurationName = "semantic-config"
            },
            QueryType = SearchQueryType.Semantic,
            Size = 5
        });

    Console.WriteLine($"Hybrid search results:");
    await foreach (SearchResult<Hotel> result in responseWithFilter.GetResultsAsync())
    {
        Hotel doc = result.Document;
        Console.WriteLine($"Score: {result.Score}");
        Console.WriteLine($"HotelId: {doc.HotelId}");
        Console.WriteLine($"HotelName: {doc.HotelName}");
        Console.WriteLine($"Description: {doc.Description}");
        Console.WriteLine($"Category: {doc.Category}");
        Console.WriteLine();
    }
    Console.WriteLine();
}

Comparez ces résultats avec les résultats de recherche hybrides de la requête précédente. Sans reclassement sémantique, Sublime Palace Hotel se classe d’abord parce que la fusion de rang réciproque (RRF) combine le texte et les scores vectoriels pour produire un résultat fusionné. Après la reclassement sémantique, Swirling Currents Hotel se déplace vers la place supérieure.

Le ranker sémantique utilise des modèles de compréhension automatique pour évaluer la façon dont chaque résultat correspond à l’intention de la requête. La description de l'Hôtel Swirling Currents mentionne "walking access to shopping, dining, entertainment and the city center", qui s’aligne étroitement avec la requête de recherche "walk to restaurants and shopping". Cette correspondance sémantique pour les restaurants et commerces à proximité le place au-dessus du Sublime Palace Hotel, qui ne met pas en avant les commodités accessibles à pied dans sa description.

Points clés :

  • Dans une recherche hybride, vous pouvez intégrer la recherche vectorielle à la requête de texte intégral par mots-clés. Les filtres et le classement sémantique s’appliquent uniquement au contenu textuel, et non aux vecteurs.

  • Les résultats réels incluent plus de détails, notamment les textes de légendes sémantiques et les mises en surbrillance. Ce guide de démarrage rapide modifie les résultats afin d'améliorer la lisibilité. Pour obtenir la structure complète de la réponse, utilisez REST pour exécuter la requête.

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux de terminer un projet en supprimant les ressources dont vous n’avez plus besoin. Les ressources laissées actives peuvent vous coûter de l'argent.

Dans le portail Azure, sélectionnez All resources ou Resource groups dans le volet gauche pour rechercher et gérer les ressources. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer toutes les ressources à la fois.

Dans ce guide de démarrage rapide, vous utilisez la bibliothèque cliente Azure AI Search pour Java pour créer, charger et interroger un index vectoriel. La bibliothèque de client Java fournit une abstraction sur les API REST pour les opérations d’index.

Dans Azure AI Search, un index vectoriel a un schéma d’index qui définit des champs vectoriels et non vecteurs, une configuration de recherche vectorielle pour les algorithmes qui créent l’espace d’incorporation et les paramètres sur les définitions de champs vectoriels évaluées au moment de la requête. Index - Créer ou mettre à jour (API REST) crée l’index vectoriel.

Conseil / Astuce

Prérequis

Configurer l’accès

Avant de commencer, vérifiez que vous disposez des autorisations nécessaires pour accéder au contenu et aux opérations dans Azure AI Search. Ce guide de démarrage rapide utilise Microsoft Entra ID pour l’authentification et l’accès en fonction du rôle pour l’autorisation. Vous devez être un propriétaire ou un administrateur d'accès utilisateur pour attribuer des rôles. Si les rôles ne sont pas réalisables, utilisez plutôt l’authentification basée sur des clés.

Pour configurer l’accès en fonction du rôle recommandé :

  1. Activez l’accès en fonction du rôle pour votre service de recherche.

  2. Attribuez les rôles suivants à votre compte d’utilisateur.

    • Contributeur Service de Recherche

    • Contributeur de données d’index de la Recherche

    • Lecteur de données d’index de la Recherche

Obtenir un point de terminaison

Chaque service Azure AI Search a un endpoint, qui est une URL unique qui identifie et fournit un accès réseau au service. Dans une section ultérieure, vous spécifiez ce point de terminaison pour vous connecter à votre service de recherche par programmation.

Pour obtenir le point de terminaison :

  1. Connectez-vous au portail Azure et sélectionnez votre service de recherche.

  2. Dans le volet gauche, sélectionnez Vue d’ensemble.

  3. Notez le point de terminaison, qui doit ressembler à https://my-service.search.windows.net.

Configurer l’environnement

  1. Utilisez Git pour cloner l’exemple de référentiel.

    git clone https://github.com/Azure-Samples/azure-search-java-samples
    
  2. Accédez au dossier de démarrage rapide et ouvrez-le dans Visual Studio Code.

    cd azure-search-java-samples/quickstart-vector-search
    code .
    
  3. Dans src/main/resources/application.properties, remplacez la valeur d’espace réservé pour azure.search.endpoint par l’URL que vous avez obtenue dans Obtenir le point de terminaison.

  4. Installez les dépendances.

    mvn clean dependency:copy-dependencies
    

    Une fois la build terminée, vous devez voir un target/dependency dossier dans le répertoire du projet.

  5. Pour l’authentification sans clé avec Microsoft Entra ID, connectez-vous à votre compte Azure. Si vous avez plusieurs abonnements, sélectionnez celui qui contient votre service Azure AI Search.

    az login
    

Exécuter le code

  1. Créez un index vectoriel.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.CreateIndex"
    
  2. Chargez des documents qui contiennent des incorporations précomputées.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.UploadDocuments"
    
  3. Exécutez une requête de recherche vectorielle.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSingle"
    
  4. (Facultatif) Exécutez des variantes de requête supplémentaires.

    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSingleWithFilter"
    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSingleWithFilterGeo"
    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchHybrid"
    mvn compile exec:java "-Dexec.mainClass=com.example.search.SearchSemanticHybrid"
    

Output

La sortie de CreateIndex.java affiche le nom de l’index et la confirmation.

Using Azure Search endpoint: https://<search-service-name>.search.windows.net
Using Azure Search index: hotels-vector-quickstart
Creating index...
hotels-vector-quickstart created

La sortie de UploadDocuments.java affiche l'état de réussite de chaque document indexé.

Uploading documents...
Key: 1, Succeeded: true, ErrorMessage: none
Key: 2, Succeeded: true, ErrorMessage: none
Key: 3, Succeeded: true, ErrorMessage: none
Key: 4, Succeeded: true, ErrorMessage: none
Key: 48, Succeeded: true, ErrorMessage: none
Key: 49, Succeeded: true, ErrorMessage: none
Key: 13, Succeeded: true, ErrorMessage: none
Waiting for indexing... Current count: 0
All documents indexed successfully.

La sortie de SearchSingle.java montre les résultats de recherche vectorielle classés par score de similarité.

Single Vector search found 5
- HotelId: 48, HotelName: Nordick's Valley Motel, Tags: ["continental breakfast","air conditioning","free wifi"], Score 0.6605852
- HotelId: 13, HotelName: Luxury Lion Resort, Tags: ["bar","concierge","restaurant"], Score 0.6333684
- HotelId: 4, HotelName: Sublime Palace Hotel, Tags: ["concierge","view","air conditioning"], Score 0.605672
- HotelId: 49, HotelName: Swirling Currents Hotel, Tags: ["air conditioning","laundry service","24-hour front desk service"], Score 0.6026341
- HotelId: 2, HotelName: Old Century Hotel, Tags: ["pool","free wifi","air conditioning","concierge"], Score 0.57902366

Comprendre le code

Remarque

Les extraits de code de cette section ont peut-être été modifiés pour la lisibilité. Pour obtenir un exemple de travail complet, consultez le code source.

Maintenant que vous avez exécuté le code, nous allons décomposer les étapes clés :

  1. Créer un index de vecteur
  2. Charger des documents dans l’index
  3. Interroger l’index

Créer un index de vecteur

Avant d’ajouter du contenu à Azure AI Search, vous devez créer un index pour définir la façon dont le contenu est stocké et structuré.

Le schéma d’index est organisé autour du contenu de l’hôtel. Les exemples de données se composent de descriptions vectorielles et non vectorielles d’hôtels fictifs. Le code suivant dans CreateIndex.java crée le schéma d’index, y compris le champ DescriptionVectorvectoriel.

// Define fields
List<SearchField> fields = Arrays.asList(
    new SearchField("HotelId", SearchFieldDataType.STRING)
        .setKey(true)
        .setFilterable(true),
    new SearchField("HotelName", SearchFieldDataType.STRING)
        .setSortable(true)
        .setSearchable(true),
    new SearchField("Description", SearchFieldDataType.STRING)
        .setSearchable(true),
    new SearchField("DescriptionVector",
        SearchFieldDataType.collection(SearchFieldDataType.SINGLE))
        .setSearchable(true)
        .setVectorSearchDimensions(1536)
        .setVectorSearchProfileName("my-vector-profile"),
    new SearchField("Category", SearchFieldDataType.STRING)
        .setSortable(true)
        .setFilterable(true)
        .setFacetable(true)
        .setSearchable(true),
    new SearchField("Tags", SearchFieldDataType.collection(
        SearchFieldDataType.STRING))
        .setSearchable(true)
        .setFilterable(true)
        .setFacetable(true),
    // Additional fields: ParkingIncluded, LastRenovationDate, Rating, Address, Location
);

var searchIndex = new SearchIndex(indexName, fields);

// Define vector search configuration
var hnswParams = new HnswParameters()
    .setM(16)
    .setEfConstruction(200)
    .setEfSearch(128);
var hnsw = new HnswAlgorithmConfiguration("hnsw-vector-config");
hnsw.setParameters(hnswParams);

var vectorProfile = new VectorSearchProfile(
    "my-vector-profile",
    "hnsw-vector-config");
var vectorSearch = new VectorSearch()
    .setAlgorithms(Arrays.asList(hnsw))
    .setProfiles(Arrays.asList(vectorProfile));
searchIndex.setVectorSearch(vectorSearch);

// Define semantic configuration
var prioritizedFields = new SemanticPrioritizedFields()
    .setTitleField(new SemanticField("HotelName"))
    .setContentFields(Arrays.asList(new SemanticField("Description")))
    .setKeywordsFields(Arrays.asList(new SemanticField("Category")));
var semanticConfig = new SemanticConfiguration(
    "semantic-config",
    prioritizedFields);
var semanticSearch = new SemanticSearch()
    .setConfigurations(Arrays.asList(semanticConfig));
searchIndex.setSemanticSearch(semanticSearch);

// Define suggesters
var suggester = new SearchSuggester("sg", Arrays.asList("HotelName"));
searchIndex.setSuggesters(Arrays.asList(suggester));

// Create the search index
SearchIndex result = searchIndexClient.createOrUpdateIndex(searchIndex);

Points clés :

  • Vous définissez un index en créant une liste de champs.

  • Cet index particulier prend en charge plusieurs fonctionnalités de recherche :

  • La setVectorSearchDimensions() valeur doit correspondre à la taille de sortie de votre modèle d’incorporation. Ce guide de démarrage rapide utilise 1 536 dimensions pour correspondre au text-embedding-ada-002 modèle.

  • La VectorSearch configuration définit l’algorithme De voisin le plus proche approximatif (ANN). Les algorithmes pris en charge incluent Hierarchical Navigable Small World (HNSW) et l’algorithme exhaustif des K plus proches voisins (KNN). Pour plus d’informations, consultez Pertinence dans la recherche vectorielle.

Charger des documents dans l’index

Les index nouvellement créés sont vides. Pour remplir un index et le rendre pouvant faire l’objet d’une recherche, vous devez charger des documents JSON conformes au schéma d’index.

Dans Azure AI Search, les documents servent d’entrées pour l’indexation et les sorties pour les requêtes. Par souci de simplicité, ce guide de démarrage rapide fournit des exemples de documents d’hôtel avec des vecteurs précomputés. Dans les scénarios de production, le contenu est souvent extrait de sources de données connectées et transformé en JSON à l’aide d’indexeurs.

Le code suivant en UploadDocuments.java télécharge des documents dans votre service de recherche.

// Documents contain hotel data with 1536-dimension vectors for DescriptionVector
static final List<Map<String, Object>> DOCUMENTS = Arrays.asList(
    new HashMap<>() {{
        put("@search.action", "mergeOrUpload");
        put("HotelId", "1");
        put("HotelName", "Stay-Kay City Hotel");
        put("Description", "This classic hotel is fully-refurbished...");
        put("DescriptionVector", Arrays.asList(/* 1536 float values */));
        put("Category", "Boutique");
        put("Tags", Arrays.asList("view", "air conditioning", "concierge"));
        // Additional fields...
    }}
    // Additional hotel documents
);

// Upload documents to the index
IndexDocumentsResult result = searchClient.uploadDocuments(DOCUMENTS);
for (IndexingResult r : result.getResults()) {
    System.out.println("Key: %s, Succeeded: %s".formatted(r.getKey(), r.isSucceeded()));
}

Votre code interagit avec un index de recherche spécifique hébergé dans votre service Azure AI Search via le SearchClient, qui est l’objet principal fourni par le package azure-search-documents. Le SearchClient fournit l'accès à des opérations telles que :

  • Ingestion des données : uploadDocuments, mergeDocuments, deleteDocuments

  • Opérations de recherche : search, autocomplete, suggest

Interroger l’index

Les requêtes dans les fichiers de recherche illustrent différents modèles de recherche. L’exemple des requêtes vectorielles sont basés sur deux chaînes :

  • Chaîne de recherche en texte intégral : "historic hotel walk to restaurants and shopping"

  • Chaîne de requête vectorielle : "quintessential lodging near running trails, eateries, retail" (vectorisée en représentation mathématique)

La chaîne de requête vectorielle est sémantiquement similaire à la chaîne de recherche en texte intégral, mais elle inclut des termes qui n’existent pas dans l’index. Une recherche par mot clé uniquement pour la chaîne de requête vectorielle retourne zéro résultat. Toutefois, la recherche vectorielle recherche des correspondances pertinentes en fonction de la signification plutôt que des mots clés exacts.

Les exemples suivants commencent par une requête vectorielle de base et ajoutent progressivement des filtres, la recherche de mots clés et la reclassement sémantique.

SearchSingle.java illustre un scénario de base dans lequel vous souhaitez trouver des descriptions de document qui correspondent étroitement à la chaîne de requête vectorielle. VectorizedQuery configure la recherche vectorielle :

  • setKNearestNeighborsCount() limite le nombre de résultats retournés en fonction de la similarité vectorielle.
  • setFields() spécifie le champ vecteur à rechercher.
var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

var searchOptions = new SearchOptions()
    .setTop(7)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Description", "Category", "Tags")
    .setVectorSearchOptions(vectorSearchOptions);

var results = searchClient.search("*", searchOptions, Context.NONE);

for (SearchResult result : results) {
    SearchDocument document = result.getDocument(SearchDocument.class);
    System.out.println("HotelId: %s, HotelName: %s, Score: %s".formatted(
        document.get("HotelId"), document.get("HotelName"), result.getScore()));
}

Recherche à vecteur unique avec un filtre

Dans Azure AI Search, filters s’appliquent aux champs non-vecteurs d’un index. SearchSingleWithFilter.java filtres sur le Tags champ pour filtrer les hôtels qui ne fournissent pas de wi-fi gratuit.

var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

// Add filter for "free wifi" tag
var searchOptions = new SearchOptions()
    .setTop(7)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Description", "Category", "Tags")
    .setFilter("Tags/any(tag: tag eq 'free wifi')")
    .setVectorSearchOptions(vectorSearchOptions);

var results = searchClient.search("*", searchOptions, Context.NONE);

Recherche à vecteur unique avec un filtre géographique

Vous pouvez spécifier un filtre géo-spatial pour limiter les résultats à une zone géographique spécifique. SearchSingleWithGeoFilter.java spécifie un point géographique (Washington D.C., en utilisant les coordonnées de longitude et de latitude) et retourne des hôtels dans les 300 kilomètres. La méthode setFilterMode, appelée sur VectorSearchOptions, détermine quand le filtre s’exécute. Dans ce cas, POST_FILTER exécute le filtre après la recherche vectorielle.

var searchOptions = new SearchOptions()
    .setTop(5)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Category", "Description",
               "Address/City", "Address/StateProvince")
    .setFacets("Address/StateProvince")
    .setFilter("geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300")
    .setVectorSearchOptions(vectorSearchOptions);

La recherche hybride combine des requêtes de texte intégral et de vecteur dans une seule requête. SearchHybrid.java exécute les deux types de requêtes simultanément, puis utilise la fusion de classement réciproque (RRF) pour fusionner les résultats dans un classement unifié. RRF utilise l’inverse des classements de résultats de chaque jeu de résultats pour produire un classement fusionné. Notez que les scores de recherche hybride sont uniformément plus petits que les scores à requête unique.

var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

var searchOptions = new SearchOptions()
    .setTop(5)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Description", "Category", "Tags")
    .setVectorSearchOptions(vectorSearchOptions);

// Pass both text query and vector search options
var results = searchClient.search(
    "historic hotel walk to restaurants and shopping",
    searchOptions, Context.NONE);

SearchSemanticHybrid.java illustre le classement sémantique, qui reclasse les résultats en fonction de la compréhension du langage.

var vectorQuery = new VectorizedQuery(QueryVector.getVectorList())
    .setKNearestNeighborsCount(5)
    .setFields("DescriptionVector")
    .setExhaustive(true);

var vectorSearchOptions = new VectorSearchOptions()
    .setQueries(vectorQuery)
    .setFilterMode(VectorFilterMode.POST_FILTER);

SemanticSearchOptions semanticSearchOptions = new SemanticSearchOptions()
    .setSemanticConfigurationName("semantic-config");

var searchOptions = new SearchOptions()
    .setTop(5)
    .setIncludeTotalCount(true)
    .setSelect("HotelId", "HotelName", "Category", "Description")
    .setQueryType(QueryType.SEMANTIC)
    .setSemanticSearchOptions(semanticSearchOptions)
    .setVectorSearchOptions(vectorSearchOptions);

var results = searchClient.search(
    "historic hotel walk to restaurants and shopping",
    searchOptions, Context.NONE);

Comparez ces résultats avec les résultats de recherche hybrides de la requête précédente. Sans reclassement sémantique, Sublime Palace Hotel se classe d’abord parce que la fusion de rang réciproque (RRF) combine le texte et les scores vectoriels pour produire un résultat fusionné. Après la reclassement sémantique, Swirling Currents Hotel se déplace vers la place supérieure.

Le ranker sémantique utilise des modèles de compréhension automatique pour évaluer la façon dont chaque résultat correspond à l’intention de la requête. La description de l'Hôtel Swirling Currents mentionne "walking access to shopping, dining, entertainment and the city center", qui s’aligne étroitement avec la requête de recherche "walk to restaurants and shopping". Cette correspondance sémantique pour les restaurants et commerces à proximité le place au-dessus du Sublime Palace Hotel, qui ne met pas en avant les commodités accessibles à pied dans sa description.

Points clés :

  • Dans une recherche hybride, vous pouvez intégrer la recherche vectorielle à la requête de texte intégral par mots-clés. Les filtres et le classement sémantique s’appliquent uniquement au contenu textuel, et non aux vecteurs.

  • Les résultats réels incluent plus de détails, notamment les textes de légendes sémantiques et les mises en surbrillance. Ce guide de démarrage rapide modifie les résultats afin d'améliorer la lisibilité. Pour obtenir la structure complète de la réponse, utilisez REST pour exécuter la requête.

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux de terminer un projet en supprimant les ressources dont vous n’avez plus besoin. Les ressources laissées actives peuvent vous coûter de l'argent.

Dans le portail Azure, sélectionnez All resources ou Resource groups dans le volet gauche pour rechercher et gérer les ressources. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer toutes les ressources à la fois.

Sinon, exécutez la commande suivante pour supprimer l’index que vous avez créé dans ce guide de démarrage rapide.

mvn compile exec:java "-Dexec.mainClass=com.example.search.DeleteIndex"

Dans ce guide de démarrage rapide, vous utilisez la bibliothèque cliente Azure AI Search pour JavaScript pour créer, charger et interroger un index vectoriel. La bibliothèque cliente JavaScript fournit une abstraction sur les API REST pour les opérations d’index.

Dans Azure AI Search, un index vectoriel a un schéma d’index qui définit des champs vectoriels et non vecteurs, une configuration de recherche vectorielle pour les algorithmes qui créent l’espace d’incorporation et les paramètres sur les définitions de champs vectoriels évaluées au moment de la requête. Index - Créer ou mettre à jour (API REST) crée l’index vectoriel.

Conseil / Astuce

Prérequis

Configurer l’accès

Avant de commencer, vérifiez que vous disposez des autorisations nécessaires pour accéder au contenu et aux opérations dans Azure AI Search. Ce guide de démarrage rapide utilise Microsoft Entra ID pour l’authentification et l’accès en fonction du rôle pour l’autorisation. Vous devez être un propriétaire ou un administrateur d'accès utilisateur pour attribuer des rôles. Si les rôles ne sont pas réalisables, utilisez plutôt l’authentification basée sur des clés.

Pour configurer l’accès en fonction du rôle recommandé :

  1. Activez l’accès en fonction du rôle pour votre service de recherche.

  2. Attribuez les rôles suivants à votre compte d’utilisateur.

    • Contributeur Service de Recherche

    • Contributeur de données d’index de la Recherche

    • Lecteur de données d’index de la Recherche

Obtenir un point de terminaison

Chaque service Azure AI Search a un endpoint, qui est une URL unique qui identifie et fournit un accès réseau au service. Dans une section ultérieure, vous spécifiez ce point de terminaison pour vous connecter à votre service de recherche par programmation.

Pour obtenir le point de terminaison :

  1. Connectez-vous au portail Azure et sélectionnez votre service de recherche.

  2. Dans le volet gauche, sélectionnez Vue d’ensemble.

  3. Notez le point de terminaison, qui doit ressembler à https://my-service.search.windows.net.

Configurer l’environnement

  1. Utilisez Git pour cloner l’exemple de référentiel.

    git clone https://github.com/Azure-Samples/azure-search-javascript-samples
    
  2. Accédez au dossier de démarrage rapide et ouvrez-le dans Visual Studio Code.

    cd azure-search-javascript-samples/quickstart-vector-js
    code .
    
  3. Dans sample.env, remplacez la valeur d’espace réservé pour AZURE_SEARCH_ENDPOINT par l’URL que vous avez obtenue dans Obtenir le point de terminaison.

  4. Renommer sample.env en .env.

    mv sample.env .env
    
  5. Installez les dépendances.

    npm install
    

    Une fois l’installation terminée, vous devez voir un node_modules dossier dans le répertoire du projet.

  6. Pour l’authentification sans clé avec Microsoft Entra ID, connectez-vous à votre compte Azure. Si vous avez plusieurs abonnements, sélectionnez celui qui contient votre service Azure AI Search.

    az login
    

Exécuter le code

  1. Créez un index vectoriel.

    node -r dotenv/config src/createIndex.js
    
  2. Chargez des documents qui contiennent des incorporations précomputées.

    node -r dotenv/config src/uploadDocuments.js
    
  3. Exécutez une requête de recherche vectorielle.

    node -r dotenv/config src/searchSingle.js
    
  4. (Facultatif) Exécutez des variantes de requête supplémentaires.

    node -r dotenv/config src/searchSingleWithFilter.js
    node -r dotenv/config src/searchSingleWithFilterGeo.js
    node -r dotenv/config src/searchHybrid.js
    node -r dotenv/config src/searchSemanticHybrid.js
    

Output

La sortie de createIndex.js affiche le nom de l’index et la confirmation.

Using Azure Search endpoint: https://<search-service-name>.search.windows.net
Using Azure Search index: hotels-vector-quickstart
Creating index...
hotels-vector-quickstart created

La sortie de uploadDocuments.js affiche l'état de réussite de chaque document indexé.

Uploading documents...
Key: 1, Succeeded: true, ErrorMessage: none
Key: 2, Succeeded: true, ErrorMessage: none
Key: 3, Succeeded: true, ErrorMessage: none
Key: 4, Succeeded: true, ErrorMessage: none
Key: 48, Succeeded: true, ErrorMessage: none
Key: 49, Succeeded: true, ErrorMessage: none
Key: 13, Succeeded: true, ErrorMessage: none
Waiting for indexing... Current count: 0
All documents indexed successfully.

La sortie de searchSingle.js montre les résultats de recherche vectorielle classés par score de similarité.

Single Vector search found 5
- HotelId: 48, HotelName: Nordick's Valley Motel, Tags: ["continental breakfast","air conditioning","free wifi"], Score 0.6605852
- HotelId: 13, HotelName: Luxury Lion Resort, Tags: ["bar","concierge","restaurant"], Score 0.6333684
- HotelId: 4, HotelName: Sublime Palace Hotel, Tags: ["concierge","view","air conditioning"], Score 0.605672
- HotelId: 49, HotelName: Swirling Currents Hotel, Tags: ["air conditioning","laundry service","24-hour front desk service"], Score 0.6026341
- HotelId: 2, HotelName: Old Century Hotel, Tags: ["pool","free wifi","air conditioning","concierge"], Score 0.57902366

Comprendre le code

Remarque

Les extraits de code de cette section ont peut-être été modifiés pour la lisibilité. Pour obtenir un exemple de travail complet, consultez le code source.

Maintenant que vous avez exécuté le code, nous allons décomposer les étapes clés :

  1. Créer un index de vecteur
  2. Charger des documents dans l’index
  3. Interroger l’index

Créer un index de vecteur

Avant d’ajouter du contenu à Azure AI Search, vous devez créer un index pour définir la façon dont le contenu est stocké et structuré.

Le schéma d’index est organisé autour du contenu de l’hôtel. Les exemples de données se composent de descriptions vectorielles et non vectorielles d’hôtels fictifs. Le code suivant dans createIndex.js crée le schéma d’index, y compris le champ DescriptionVectorvectoriel.

const searchFields = [
    { name: "HotelId", type: "Edm.String", key: true, sortable: true, filterable: true, facetable: true },
    { name: "HotelName", type: "Edm.String", searchable: true, filterable: true },
    { name: "Description", type: "Edm.String", searchable: true },
    {
        name: "DescriptionVector",
        type: "Collection(Edm.Single)",
        searchable: true,
        vectorSearchDimensions: 1536,
        vectorSearchProfileName: "vector-profile"
    },
    { name: "Category", type: "Edm.String", filterable: true, facetable: true },
    { name: "Tags", type: "Collection(Edm.String)", filterable: true },
    // Additional fields: ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const vectorSearch = {
    profiles: [
        {
            name: "vector-profile",
            algorithmConfigurationName: "vector-search-algorithm"
        }
    ],
    algorithms: [
        {
            name: "vector-search-algorithm",
            kind: "hnsw",
            parameters: { m: 4, efConstruction: 400, efSearch: 1000, metric: "cosine" }
        }
    ]
};

const semanticSearch = {
    configurations: [
        {
            name: "semantic-config",
            prioritizedFields: {
                contentFields: [{ name: "Description" }],
                keywordsFields: [{ name: "Category" }],
                titleField: { name: "HotelName" }
            }
        }
    ]
};

const searchIndex = {
    name: indexName,
    fields: searchFields,
    vectorSearch: vectorSearch,
    semanticSearch: semanticSearch,
    suggesters: [{ name: "sg", searchMode: "analyzingInfixMatching", sourceFields: ["HotelName"] }]
};

const result = await indexClient.createOrUpdateIndex(searchIndex);

Points clés :

  • Vous définissez un index en créant une liste de champs.

  • Cet index particulier prend en charge plusieurs fonctionnalités de recherche :

  • La vectorSearchDimensions propriété doit correspondre à la taille de sortie de votre modèle d’incorporation. Ce guide de démarrage rapide utilise 1 536 dimensions pour correspondre au text-embedding-ada-002 modèle.

  • La vectorSearch configuration définit l’algorithme De voisin le plus proche approximatif (ANN). Les algorithmes pris en charge incluent Hierarchical Navigable Small World (HNSW) et l’algorithme exhaustif des K plus proches voisins (KNN). Pour plus d’informations, consultez Pertinence dans la recherche vectorielle.

Charger des documents dans l’index

Les index nouvellement créés sont vides. Pour remplir un index et le rendre pouvant faire l’objet d’une recherche, vous devez charger des documents JSON conformes au schéma d’index.

Dans Azure AI Search, les documents servent d’entrées pour l’indexation et les sorties pour les requêtes. Par souci de simplicité, ce guide de démarrage rapide fournit des exemples de documents d’hôtel avec des vecteurs précomputés. Dans les scénarios de production, le contenu est souvent extrait de sources de données connectées et transformé en JSON à l’aide d’indexeurs.

Le code suivant en uploadDocuments.js télécharge des documents dans votre service de recherche.

const DOCUMENTS = [
    // Array of hotel documents with embedded 1536-dimension vectors
    // Each document contains: HotelId, HotelName, Description, DescriptionVector,
    // Category, Tags, ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const searchClient = new SearchClient(searchEndpoint, indexName, credential);

const result = await searchClient.uploadDocuments(DOCUMENTS);
for (const r of result.results) {
    console.log(`Key: ${r.key}, Succeeded: ${r.succeeded}`);
}

Votre code interagit avec un index de recherche spécifique hébergé dans votre service Azure AI Search via le SearchClient, qui est l’objet principal fourni par le package @azure/search-documents. Il SearchClient fournit l’accès aux opérations d’index, telles que :

  • Ingestion des données : uploadDocuments, mergeDocuments, deleteDocuments

  • Opérations de recherche : search, autocomplete, suggest

Interroger l’index

Les requêtes dans les fichiers de recherche illustrent différents modèles de recherche. L’exemple des requêtes vectorielles sont basés sur deux chaînes :

  • Chaîne de recherche en texte intégral : "historic hotel walk to restaurants and shopping"

  • Chaîne de requête vectorielle : "quintessential lodging near running trails, eateries, retail" (vectorisée en représentation mathématique)

La chaîne de requête vectorielle est sémantiquement similaire à la chaîne de recherche en texte intégral, mais elle inclut des termes qui n’existent pas dans l’index. Une recherche par mot clé uniquement pour la chaîne de requête vectorielle retourne zéro résultat. Toutefois, la recherche vectorielle recherche des correspondances pertinentes en fonction de la signification plutôt que des mots clés exacts.

Les exemples suivants commencent par une requête vectorielle de base et ajoutent progressivement des filtres, la recherche de mots clés et la reclassement sémantique.

searchSingle.js illustre un scénario de base dans lequel vous souhaitez trouver des descriptions de document qui correspondent étroitement à la chaîne de requête vectorielle. L’objet vectorQuery configure la recherche vectorielle :

  • kNearestNeighborsCount limite le nombre de résultats retournés en fonction de la similarité vectorielle.
  • fields spécifie le champ vecteur à rechercher.
const vectorQuery = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"],
    includeTotalCount: true,
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results = await searchClient.search("*", searchOptions);

for await (const result of results.results) {
    const doc = result.document;
    console.log(`HotelId: ${doc.HotelId}, HotelName: ${doc.HotelName}, Score: ${result.score}`);
}

Recherche à vecteur unique avec un filtre

Dans Azure AI Search, filters s’appliquent aux champs non-vecteurs d’un index. searchSingleWithFilter.js filtres sur le Tags champ pour filtrer les hôtels qui ne fournissent pas de wi-fi gratuit.

const searchOptions = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"],
    includeTotalCount: true,
    filter: "Tags/any(tag: tag eq 'free wifi')", // Adding filter for "free wifi" tag
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results = await searchClient.search("*", searchOptions);

Recherche à vecteur unique avec un filtre géographique

Vous pouvez spécifier un filtre géo-spatial pour limiter les résultats à une zone géographique spécifique. searchSingleWithGeoFilter.js spécifie un point géographique (Washington D.C., en utilisant les coordonnées de longitude et de latitude) et retourne des hôtels dans les 300 kilomètres. La filterMode propriété détermine quand le filtre s’exécute. Dans ce cas, postFilter exécute le filtre après la recherche vectorielle.

const searchOptions = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description", "Address/City", "Address/StateProvince"],
    facets: ["Address/StateProvince"],
    filter: "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

La recherche hybride combine des requêtes de texte intégral et de vecteur dans une seule requête. searchHybrid.js exécute les deux types de requêtes simultanément, puis utilise la fusion de classement réciproque (RRF) pour fusionner les résultats dans un classement unifié. RRF utilise l’inverse des classements de résultats de chaque jeu de résultats pour produire un classement fusionné. Notez que les scores de recherche hybride sont uniformément plus petits que les scores à requête unique.

const vectorQuery = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"],
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

// Use search text for keyword search (hybrid search = vector + keyword)
const searchText = "historic hotel walk to restaurants and shopping";
const results = await searchClient.search(searchText, searchOptions);

searchSemanticHybrid.js illustre le classement sémantique, qui reclasse les résultats en fonction de la compréhension du langage.

const searchOptions = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description"],
    queryType: "semantic",
    semanticSearchOptions: {
        configurationName: "semantic-config"
    },
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const searchText = "historic hotel walk to restaurants and shopping";
const results = await searchClient.search(searchText, searchOptions);

for await (const result of results.results) {
    console.log(`Score: ${result.score}, Re-ranker Score: ${result.rerankerScore}`);
}

Comparez ces résultats avec les résultats de recherche hybrides de la requête précédente. Sans reclassement sémantique, Sublime Palace Hotel se classe d’abord parce que la fusion de rang réciproque (RRF) combine le texte et les scores vectoriels pour produire un résultat fusionné. Après la reclassement sémantique, Swirling Currents Hotel se déplace vers la place supérieure.

Le ranker sémantique utilise des modèles de compréhension automatique pour évaluer la façon dont chaque résultat correspond à l’intention de la requête. La description de l'Hôtel Swirling Currents mentionne "walking access to shopping, dining, entertainment and the city center", qui s’aligne étroitement avec la requête de recherche "walk to restaurants and shopping". Cette correspondance sémantique pour les restaurants et commerces à proximité le place au-dessus du Sublime Palace Hotel, qui ne met pas en avant les commodités accessibles à pied dans sa description.

Points clés :

  • Dans une recherche hybride, vous pouvez intégrer la recherche vectorielle à la requête de texte intégral par mots-clés. Les filtres et le classement sémantique s’appliquent uniquement au contenu textuel, et non aux vecteurs.

  • Les résultats réels incluent plus de détails, notamment les textes de légendes sémantiques et les mises en surbrillance. Ce guide de démarrage rapide modifie les résultats afin d'améliorer la lisibilité. Pour obtenir la structure complète de la réponse, utilisez REST pour exécuter la requête.

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux de terminer un projet en supprimant les ressources dont vous n’avez plus besoin. Les ressources laissées actives peuvent vous coûter de l'argent.

Dans le portail Azure, sélectionnez All resources ou Resource groups dans le volet gauche pour rechercher et gérer les ressources. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer toutes les ressources à la fois.

Sinon, exécutez la commande suivante pour supprimer l’index que vous avez créé dans ce guide de démarrage rapide.

node -r dotenv/config src/deleteIndex.js

Dans ce guide de démarrage rapide, vous utilisez la bibliothèque cliente Azure AI Search pour Python pour créer, charger et interroger un index vectoriel. La bibliothèque cliente Python fournit une abstraction sur les API REST pour les opérations d’index.

Dans Azure AI Search, un index vectoriel a un schéma d’index qui définit des champs vectoriels et non vecteurs, une configuration de recherche vectorielle pour les algorithmes qui créent l’espace d’incorporation et les paramètres sur les définitions de champs vectoriels évaluées au moment de la requête. Index - Créer ou mettre à jour (API REST) crée l’index vectoriel.

Conseil / Astuce

Prérequis

Configurer l’accès

Avant de commencer, vérifiez que vous disposez des autorisations nécessaires pour accéder au contenu et aux opérations dans Azure AI Search. Ce guide de démarrage rapide utilise Microsoft Entra ID pour l’authentification et l’accès en fonction du rôle pour l’autorisation. Vous devez être un propriétaire ou un administrateur d'accès utilisateur pour attribuer des rôles. Si les rôles ne sont pas réalisables, utilisez plutôt l’authentification basée sur des clés.

Pour configurer l’accès en fonction du rôle recommandé :

  1. Activez l’accès en fonction du rôle pour votre service de recherche.

  2. Attribuez les rôles suivants à votre compte d’utilisateur.

    • Contributeur Service de Recherche

    • Contributeur de données d’index de la Recherche

    • Lecteur de données d’index de la Recherche

Obtenir un point de terminaison

Chaque service Azure AI Search a un endpoint, qui est une URL unique qui identifie et fournit un accès réseau au service. Dans une section ultérieure, vous spécifiez ce point de terminaison pour vous connecter à votre service de recherche par programmation.

Pour obtenir le point de terminaison :

  1. Connectez-vous au portail Azure et sélectionnez votre service de recherche.

  2. Dans le volet gauche, sélectionnez Vue d’ensemble.

  3. Notez le point de terminaison, qui doit ressembler à https://my-service.search.windows.net.

Configurer l’environnement

  1. Utilisez Git pour cloner l’exemple de référentiel.

    git clone https://github.com/Azure-Samples/azure-search-python-samples
    
  2. Accédez au dossier de démarrage rapide et ouvrez-le dans Visual Studio Code.

    cd azure-search-python-samples/Quickstart-Vector-Search
    code .
    
  3. Dans sample.env, remplacez la valeur d’espace réservé pour AZURE_SEARCH_ENDPOINT par l’URL que vous avez obtenue dans Obtenir le point de terminaison.

  4. Renommer sample.env en .env.

    mv sample.env .env
    
  5. Ouvrez vector-search-quickstart.ipynb.

  6. Appuyez sur Ctrl+Maj+P, sélectionnez Bloc-notes : Sélectionner le noyau du bloc-notes, puis suivez les invites pour créer un environnement virtuel. Sélectionnez requirements.txt pour les dépendances.

    Une fois terminé, vous devez voir un .venv dossier dans le répertoire du projet.

  7. Pour l’authentification sans clé avec Microsoft Entra ID, connectez-vous à votre compte Azure. Si vous avez plusieurs abonnements, sélectionnez celui qui contient votre service Azure AI Search.

    az login
    

Exécuter le code

  1. Exécutez la Install packages and set variables cellule pour installer les packages requis et charger les variables d’environnement.

  2. Exécutez les cellules restantes séquentiellement pour créer un index vectoriel, charger des documents et exécuter différents types de requêtes vectorielles.

Output

Chaque cellule de code imprime sa sortie dans le bloc-notes. L’exemple suivant est la sortie de Single vector search, qui montre les résultats de recherche vectorielle classés par score de similarité.

Total results: 7
- HotelId: 48, HotelName: Nordick's Valley Motel, Category: Boutique
- HotelId: 13, HotelName: Luxury Lion Resort, Category: Luxury
- HotelId: 4, HotelName: Sublime Palace Hotel, Category: Boutique
- HotelId: 49, HotelName: Swirling Currents Hotel, Category: Suite
- HotelId: 2, HotelName: Old Century Hotel, Category: Boutique

Comprendre le code

Remarque

Les extraits de code de cette section ont peut-être été modifiés pour la lisibilité. Pour obtenir un exemple de travail complet, consultez le code source.

Maintenant que vous avez exécuté le code, nous allons décomposer les étapes clés :

  1. Créer un index de vecteur
  2. Charger des documents dans l’index
  3. Interroger l’index

Créer un index de vecteur

Avant d’ajouter du contenu à Azure AI Search, vous devez créer un index pour définir la façon dont le contenu est stocké et structuré.

Le schéma d’index est organisé autour du contenu de l’hôtel. Les exemples de données se composent de descriptions vectorielles et non vectorielles d’hôtels fictifs. La Create an index cellule du notebook crée le schéma d’index, y compris le champ DescriptionVectorvectoriel.

fields = [
    SimpleField(name="HotelId", type=SearchFieldDataType.String, key=True, filterable=True),
    SearchableField(name="HotelName", type=SearchFieldDataType.String, sortable=True),
    SearchableField(name="Description", type=SearchFieldDataType.String),
    SearchField(
        name="DescriptionVector",
        type=SearchFieldDataType.Collection(SearchFieldDataType.Single),
        searchable=True,
        vector_search_dimensions=1536,
        vector_search_profile_name="my-vector-profile"
    ),
    SearchableField(name="Category", type=SearchFieldDataType.String, sortable=True, filterable=True, facetable=True),
    SearchField(name="Tags", type=SearchFieldDataType.Collection(SearchFieldDataType.String), searchable=True, filterable=True, facetable=True),
    # Additional fields omitted for brevity
]

Points clés :

  • Vous définissez un index en créant une liste de champs. Chaque champ est créé à l’aide d’une méthode d’assistance qui définit le type de champ et ses paramètres.

  • Cet index particulier prend en charge plusieurs fonctionnalités de recherche :

  • La vector_search_dimensions propriété doit correspondre à la taille de sortie de votre modèle d’incorporation. Ce guide de démarrage rapide utilise 1 536 dimensions pour correspondre au text-embedding-ada-002 modèle.

  • La VectorSearch configuration définit l’algorithme De voisin le plus proche approximatif (ANN). Les algorithmes pris en charge incluent Hierarchical Navigable Small World (HNSW) et l’algorithme exhaustif des K plus proches voisins (KNN). Pour plus d’informations, consultez Pertinence dans la recherche vectorielle.

Charger des documents dans l’index

Les index nouvellement créés sont vides. Pour remplir un index et le rendre pouvant faire l’objet d’une recherche, vous devez charger des documents JSON conformes au schéma d’index.

Dans Azure AI Search, les documents servent d’entrées pour l’indexation et les sorties pour les requêtes. Par souci de simplicité, ce guide de démarrage rapide fournit des exemples de documents d’hôtel avec des vecteurs précomputés. Dans les scénarios de production, le contenu est souvent extrait de sources de données connectées et transformé en JSON à l’aide d’indexeurs.

Les cellules Create documents payload et Upload the documents chargent des documents dans l’index.

documents = [
    # List of hotel documents with embedded 1536-dimension vectors
    # Each document contains: HotelId, HotelName, Description, DescriptionVector,
    # Category, Tags, ParkingIncluded, LastRenovationDate, Rating, Address, Location
]

search_client = SearchClient(
    endpoint=search_endpoint,
    index_name=index_name,
    credential=credential
)

result = search_client.upload_documents(documents=documents)
for r in result:
    print(f"Key: {r.key}, Succeeded: {r.succeeded}, ErrorMessage: {r.error_message}")

Votre code interagit avec un index de recherche spécifique hébergé dans votre service Azure AI Search via le SearchClient, qui est l’objet principal fourni par le package azure-search-documents. Il SearchClient fournit l’accès aux opérations d’index, telles que :

  • Ingestion des données : upload_documents(), merge_documents(), delete_documents()

  • Opérations de recherche : search(), autocomplete(), suggest()

Interroger l’index

Les requêtes du bloc-notes illustrent différents modèles de recherche. L’exemple des requêtes vectorielles sont basés sur deux chaînes :

  • Chaîne de recherche en texte intégral : "historic hotel walk to restaurants and shopping"

  • Chaîne de requête vectorielle : "quintessential lodging near running trails, eateries, retail" (vectorisée en représentation mathématique)

La chaîne de requête vectorielle est sémantiquement similaire à la chaîne de recherche en texte intégral, mais elle inclut des termes qui n’existent pas dans l’index. Une recherche par mot clé uniquement pour la chaîne de requête vectorielle retourne zéro résultat. Toutefois, la recherche vectorielle recherche des correspondances pertinentes en fonction de la signification plutôt que des mots clés exacts.

Les exemples suivants commencent par une requête vectorielle de base et ajoutent progressivement des filtres, la recherche de mots clés et la reclassement sémantique.

La Single vector search cellule illustre un scénario de base dans lequel vous souhaitez rechercher des descriptions de document qui correspondent étroitement à la chaîne de requête vectorielle. VectorizedQuery configure la recherche vectorielle :

  • k_nearest_neighbors limite le nombre de résultats retournés en fonction de la similarité vectorielle.
  • fields spécifie le champ vecteur à rechercher.
vector_query = VectorizedQuery(
    vector=vector,
    k_nearest_neighbors=5,
    fields="DescriptionVector",
    kind="vector",
    exhaustive=True
)

results = search_client.search(
    vector_queries=[vector_query],
    select=["HotelId", "HotelName", "Description", "Category", "Tags"],
    top=5,
    include_total_count=True
)

Recherche à vecteur unique avec un filtre

Dans Azure AI Search, filters s’appliquent aux champs non-vecteurs d’un index. La Single vector search with filter cellule filtre sur le Tags champ pour filtrer les hôtels qui ne fournissent pas de wi-fi gratuit.

# vector_query omitted for brevity

results = search_client.search(
    vector_queries=[vector_query],
    filter="Tags/any(tag: tag eq 'free wifi')",
    select=["HotelId", "HotelName", "Description", "Category", "Tags"],
    top=7,
    include_total_count=True
)

Recherche à vecteur unique avec un filtre géographique

Vous pouvez spécifier un filtre géo-spatial pour limiter les résultats à une zone géographique spécifique. La Single vector search with geo filter cellule spécifie un point géographique (Washington D.C., à l’aide des coordonnées de longitude et de latitude) et fournit les hôtels dans un rayon de 300 kilomètres. Le vector_filter_mode paramètre détermine quand le filtre s’exécute. Dans ce cas, postFilter exécute le filtre après la recherche vectorielle.

# vector_query omitted for brevity

results = search_client.search(
    include_total_count=True,
    top=5,
    select=[
        "HotelId", "HotelName", "Category", "Description", "Address/City", "Address/StateProvince"
    ],
    facets=["Address/StateProvince"],
    filter="geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    vector_filter_mode="postFilter",
    vector_queries=[vector_query]
)

La recherche hybride combine des requêtes de texte intégral et de vecteur dans une seule requête. La Hybrid search cellule exécute les deux types de requêtes simultanément, puis utilise la fusion de classement réciproque (RRF) pour fusionner les résultats dans un classement unifié. RRF utilise l’inverse des classements de résultats de chaque jeu de résultats pour produire un classement fusionné. Notez que les scores de recherche hybride sont uniformément plus petits que les scores à requête unique.

# vector_query omitted for brevity

results = search_client.search(
    search_text="historic hotel walk to restaurants and shopping",
    vector_queries=[vector_query],
    select=["HotelId", "HotelName", "Description", "Category", "Tags"],
    top=5,
    include_total_count=True
)

La cellule illustre le Semantic hybrid searchclassement sémantique, qui reclasse les résultats en fonction de la compréhension du langage.

# vector_query omitted for brevity

results = search_client.search(
    search_text="historic hotel walk to restaurants and shopping",
    vector_queries=[vector_query],
    select=["HotelId", "HotelName", "Category", "Description"],
    query_type="semantic",
    semantic_configuration_name="my-semantic-config",
    top=5,
    include_total_count=True
)

Comparez ces résultats avec les résultats de recherche hybrides de la requête précédente. Sans reclassement sémantique, Sublime Palace Hotel se classe d’abord parce que la fusion de rang réciproque (RRF) combine le texte et les scores vectoriels pour produire un résultat fusionné. Après la reclassement sémantique, Swirling Currents Hotel se déplace vers la place supérieure.

Le ranker sémantique utilise des modèles de compréhension automatique pour évaluer la façon dont chaque résultat correspond à l’intention de la requête. La description de l'Hôtel Swirling Currents mentionne "walking access to shopping, dining, entertainment and the city center", qui s’aligne étroitement avec la requête de recherche "walk to restaurants and shopping". Cette correspondance sémantique pour les restaurants et commerces à proximité le place au-dessus du Sublime Palace Hotel, qui ne met pas en avant les commodités accessibles à pied dans sa description.

Points clés :

  • Dans une recherche hybride, vous pouvez intégrer la recherche vectorielle à la requête de texte intégral par mots-clés. Les filtres et le classement sémantique s’appliquent uniquement au contenu textuel, et non aux vecteurs.

  • Les résultats réels incluent plus de détails, notamment les textes de légendes sémantiques et les mises en surbrillance. Ce guide de démarrage rapide modifie les résultats afin d'améliorer la lisibilité. Pour obtenir la structure complète de la réponse, utilisez REST pour exécuter la requête.

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux de terminer un projet en supprimant les ressources dont vous n’avez plus besoin. Les ressources laissées actives peuvent vous coûter de l'argent.

Dans le portail Azure, sélectionnez All resources ou Resource groups dans le volet gauche pour rechercher et gérer les ressources. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer toutes les ressources à la fois.

Sinon, vous pouvez exécuter la cellule de code Clean up pour supprimer l’index que vous avez créé dans ce didacticiel rapide.

Dans ce guide de démarrage rapide, vous utilisez la bibliothèque cliente Azure AI Search pour JavaScript (compatible avec TypeScript) pour créer, charger et interroger un index vectoriel. La bibliothèque cliente JavaScript fournit une abstraction sur les API REST pour les opérations d’index.

Dans Azure AI Search, un index vectoriel a un schéma d’index qui définit des champs vectoriels et non vecteurs, une configuration de recherche vectorielle pour les algorithmes qui créent l’espace d’incorporation et les paramètres sur les définitions de champs vectoriels évaluées au moment de la requête. Index - Créer ou mettre à jour (API REST) crée l’index vectoriel.

Conseil / Astuce

Prérequis

Configurer l’accès

Avant de commencer, vérifiez que vous disposez des autorisations nécessaires pour accéder au contenu et aux opérations dans Azure AI Search. Ce guide de démarrage rapide utilise Microsoft Entra ID pour l’authentification et l’accès en fonction du rôle pour l’autorisation. Vous devez être un propriétaire ou un administrateur d'accès utilisateur pour attribuer des rôles. Si les rôles ne sont pas réalisables, utilisez plutôt l’authentification basée sur des clés.

Pour configurer l’accès en fonction du rôle recommandé :

  1. Activez l’accès en fonction du rôle pour votre service de recherche.

  2. Attribuez les rôles suivants à votre compte d’utilisateur.

    • Contributeur Service de Recherche

    • Contributeur de données d’index de la Recherche

    • Lecteur de données d’index de la Recherche

Obtenir un point de terminaison

Chaque service Azure AI Search a un endpoint, qui est une URL unique qui identifie et fournit un accès réseau au service. Dans une section ultérieure, vous spécifiez ce point de terminaison pour vous connecter à votre service de recherche par programmation.

Pour obtenir le point de terminaison :

  1. Connectez-vous au portail Azure et sélectionnez votre service de recherche.

  2. Dans le volet gauche, sélectionnez Vue d’ensemble.

  3. Notez le point de terminaison, qui doit ressembler à https://my-service.search.windows.net.

Configurer l’environnement

  1. Utilisez Git pour cloner l’exemple de référentiel.

    git clone https://github.com/Azure-Samples/azure-search-javascript-samples
    
  2. Accédez au dossier de démarrage rapide et ouvrez-le dans Visual Studio Code.

    cd azure-search-javascript-samples/quickstart-vector-ts
    code .
    
  3. Dans sample.env, remplacez la valeur d’espace réservé pour AZURE_SEARCH_ENDPOINT par l’URL que vous avez obtenue dans Obtenir le point de terminaison.

  4. Renommer sample.env en .env.

    mv sample.env .env
    
  5. Installez les dépendances.

    npm install
    

    Une fois l’installation terminée, vous devez voir un node_modules dossier dans le répertoire du projet.

  6. Générez les fichiers TypeScript.

    npm run build
    
  7. Pour l’authentification sans clé avec Microsoft Entra ID, connectez-vous à votre compte Azure. Si vous avez plusieurs abonnements, sélectionnez celui qui contient votre service Azure AI Search.

    az login
    

Exécuter le code

  1. Créez un index vectoriel.

    node -r dotenv/config dist/createIndex.js
    
  2. Chargez des documents qui contiennent des incorporations précomputées.

    node -r dotenv/config dist/uploadDocuments.js
    
  3. Exécutez une requête de recherche vectorielle.

    node -r dotenv/config dist/searchSingle.js
    
  4. (Facultatif) Exécutez des variantes de requête supplémentaires.

    node -r dotenv/config dist/searchSingleWithFilter.js
    node -r dotenv/config dist/searchSingleWithFilterGeo.js
    node -r dotenv/config dist/searchHybrid.js
    node -r dotenv/config dist/searchSemanticHybrid.js
    

    Remarque

    Ces commandes exécutent les fichiers .js du dossier dist car vous avez précédemment transpilé du TypeScript vers JavaScript avec npm run build.

Output

La sortie de createIndex.ts affiche le nom de l’index et la confirmation.

Using Azure Search endpoint: https://<search-service-name>.search.windows.net
Using index name: hotels-vector-quickstart
Creating index...
hotels-vector-quickstart created

La sortie de uploadDocuments.ts affiche l'état de réussite de chaque document indexé.

Uploading documents...
Key: 1, Succeeded: true, ErrorMessage: none
Key: 2, Succeeded: true, ErrorMessage: none
Key: 3, Succeeded: true, ErrorMessage: none
Key: 4, Succeeded: true, ErrorMessage: none
Key: 48, Succeeded: true, ErrorMessage: none
Key: 49, Succeeded: true, ErrorMessage: none
Key: 13, Succeeded: true, ErrorMessage: none
All documents indexed successfully.

La sortie de searchSingle.ts montre les résultats de recherche vectorielle classés par score de similarité.

Single Vector search found 5
- HotelId: 48, HotelName: Nordick's Valley Motel, Tags: ["continental breakfast","air conditioning","free wifi"], Score 0.6605852
- HotelId: 13, HotelName: Luxury Lion Resort, Tags: ["bar","concierge","restaurant"], Score 0.6333684
- HotelId: 4, HotelName: Sublime Palace Hotel, Tags: ["concierge","view","air conditioning"], Score 0.605672
- HotelId: 49, HotelName: Swirling Currents Hotel, Tags: ["air conditioning","laundry service","24-hour front desk service"], Score 0.6026341
- HotelId: 2, HotelName: Old Century Hotel, Tags: ["pool","free wifi","air conditioning","concierge"], Score 0.57902366

Comprendre le code

Remarque

Les extraits de code de cette section ont peut-être été modifiés pour la lisibilité. Pour obtenir un exemple de travail complet, consultez le code source.

Maintenant que vous avez exécuté le code, nous allons décomposer les étapes clés :

  1. Créer un index de vecteur
  2. Charger des documents dans l’index
  3. Interroger l’index

Créer un index de vecteur

Avant d’ajouter du contenu à Azure AI Search, vous devez créer un index pour définir la façon dont le contenu est stocké et structuré.

Le schéma d’index est organisé autour du contenu de l’hôtel. Les exemples de données se composent de descriptions vectorielles et non vectorielles d’hôtels fictifs. Le code suivant dans createIndex.ts crée le schéma d’index, y compris le champ DescriptionVectorvectoriel.

const searchFields: SearchField[] = [
    { name: "HotelId", type: "Edm.String", key: true, sortable: true, filterable: true, facetable: true },
    { name: "HotelName", type: "Edm.String", searchable: true, filterable: true },
    { name: "Description", type: "Edm.String", searchable: true },
    {
        name: "DescriptionVector",
        type: "Collection(Edm.Single)",
        searchable: true,
        vectorSearchDimensions: 1536,
        vectorSearchProfileName: "vector-profile"
    },
    { name: "Category", type: "Edm.String", filterable: true, facetable: true },
    { name: "Tags", type: "Collection(Edm.String)", filterable: true },
    // Additional fields: ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const vectorSearch: VectorSearch = {
    profiles: [
        {
            name: "vector-profile",
            algorithmConfigurationName: "vector-search-algorithm"
        }
    ],
    algorithms: [
        {
            name: "vector-search-algorithm",
            kind: "hnsw",
            parameters: { m: 4, efConstruction: 400, efSearch: 1000, metric: "cosine" }
        }
    ]
};

const semanticSearch: SemanticSearch = {
    configurations: [
        {
            name: "semantic-config",
            prioritizedFields: {
                contentFields: [{ name: "Description" }],
                keywordsFields: [{ name: "Category" }],
                titleField: { name: "HotelName" }
            }
        }
    ]
};

const searchIndex: SearchIndex = {
    name: indexName,
    fields: searchFields,
    vectorSearch: vectorSearch,
    semanticSearch: semanticSearch,
    suggesters: [{ name: "sg", searchMode: "analyzingInfixMatching", sourceFields: ["HotelName"] }]
};

const result = await indexClient.createOrUpdateIndex(searchIndex);

Points clés :

  • Vous définissez un index en créant une liste de champs.

  • Cet index particulier prend en charge plusieurs fonctionnalités de recherche :

  • La vectorSearchDimensions propriété doit correspondre à la taille de sortie de votre modèle d’incorporation. Ce guide de démarrage rapide utilise 1 536 dimensions pour correspondre au text-embedding-ada-002 modèle.

  • La vectorSearch configuration définit l’algorithme De voisin le plus proche approximatif (ANN). Les algorithmes pris en charge incluent Hierarchical Navigable Small World (HNSW) et l’algorithme exhaustif des K plus proches voisins (KNN). Pour plus d’informations, consultez Pertinence dans la recherche vectorielle.

Charger des documents dans l’index

Les index nouvellement créés sont vides. Pour remplir un index et le rendre pouvant faire l’objet d’une recherche, vous devez charger des documents JSON conformes au schéma d’index.

Dans Azure AI Search, les documents servent d’entrées pour l’indexation et les sorties pour les requêtes. Par souci de simplicité, ce guide de démarrage rapide fournit des exemples de documents d’hôtel avec des vecteurs précomputés. Dans les scénarios de production, le contenu est souvent extrait de sources de données connectées et transformé en JSON à l’aide d’indexeurs.

Le code suivant en uploadDocuments.ts télécharge des documents dans votre service de recherche.

const DOCUMENTS = [
    // Array of hotel documents with embedded 1536-dimension vectors
    // Each document contains: HotelId, HotelName, Description, DescriptionVector,
    // Category, Tags, ParkingIncluded, LastRenovationDate, Rating, Address, Location
];

const searchClient = new SearchClient(searchEndpoint, indexName, credential);

const result = await searchClient.uploadDocuments(DOCUMENTS);
for (const r of result.results) {
    console.log(`Key: ${r.key}, Succeeded: ${r.succeeded}`);
}

Votre code interagit avec un index de recherche spécifique hébergé dans votre service Azure AI Search via le SearchClient, qui est l’objet principal fourni par le package @azure/search-documents. Il SearchClient fournit l’accès aux opérations d’index, telles que :

  • Ingestion des données : uploadDocuments, mergeDocuments, deleteDocuments

  • Opérations de recherche : search, autocomplete, suggest

Interroger l’index

Les requêtes dans les fichiers de recherche illustrent différents modèles de recherche. L’exemple des requêtes vectorielles sont basés sur deux chaînes :

  • Chaîne de recherche en texte intégral : "historic hotel walk to restaurants and shopping"

  • Chaîne de requête vectorielle : "quintessential lodging near running trails, eateries, retail" (vectorisée en représentation mathématique)

La chaîne de requête vectorielle est sémantiquement similaire à la chaîne de recherche en texte intégral, mais elle inclut des termes qui n’existent pas dans l’index. Une recherche par mot clé uniquement pour la chaîne de requête vectorielle retourne zéro résultat. Toutefois, la recherche vectorielle recherche des correspondances pertinentes en fonction de la signification plutôt que des mots clés exacts.

Les exemples suivants commencent par une requête vectorielle de base et ajoutent progressivement des filtres, la recherche de mots clés et la reclassement sémantique.

searchSingle.ts illustre un scénario de base dans lequel vous souhaitez trouver des descriptions de document qui correspondent étroitement à la chaîne de requête vectorielle. L’objet VectorQuery configure la recherche vectorielle :

  • kNearestNeighborsCount limite le nombre de résultats retournés en fonction de la similarité vectorielle.
  • fields spécifie le champ vecteur à rechercher.
const vectorQuery: VectorQuery<HotelDocument> = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions: SearchOptions<HotelDocument> = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"] as const,
    includeTotalCount: true,
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results: SearchDocumentsResult<HotelDocument> = await searchClient.search("*", searchOptions);

for await (const result of results.results) {
    const doc = result.document;
    console.log(`HotelId: ${doc.HotelId}, HotelName: ${doc.HotelName}, Score: ${result.score}`);
}

Recherche à vecteur unique avec un filtre

Dans Azure AI Search, filters s’appliquent aux champs non-vecteurs d’un index. searchSingleWithFilter.ts filtres sur le Tags champ pour filtrer les hôtels qui ne fournissent pas de wi-fi gratuit.

const searchOptions: SearchOptions<HotelDocument> = {
    top: 7,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"] as const,
    includeTotalCount: true,
    filter: "Tags/any(tag: tag eq 'free wifi')", // Adding filter for "free wifi" tag
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const results: SearchDocumentsResult<HotelDocument> = await searchClient.search("*", searchOptions);

Recherche à vecteur unique avec un filtre géographique

Vous pouvez spécifier un filtre géo-spatial pour limiter les résultats à une zone géographique spécifique. searchSingleWithGeoFilter.ts spécifie un point géographique (Washington D.C., en utilisant les coordonnées de longitude et de latitude) et retourne des hôtels dans les 300 kilomètres. La filterMode propriété détermine quand le filtre s’exécute. Dans ce cas, postFilter exécute le filtre après la recherche vectorielle.

const searchOptions: SearchOptions<HotelDocument> = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description", "Address/City", "Address/StateProvince"] as const,
    facets: ["Address/StateProvince"],
    filter: "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

La recherche hybride combine des requêtes de texte intégral et de vecteur dans une seule requête. searchHybrid.ts exécute les deux types de requêtes simultanément, puis utilise la fusion de classement réciproque (RRF) pour fusionner les résultats dans un classement unifié. RRF utilise l’inverse des classements de résultats de chaque jeu de résultats pour produire un classement fusionné. Notez que les scores de recherche hybride sont uniformément plus petits que les scores à requête unique.

const vectorQuery: VectorQuery<HotelDocument> = {
    vector: vector,
    kNearestNeighborsCount: 5,
    fields: ["DescriptionVector"],
    kind: "vector",
    exhaustive: true
};

const searchOptions: SearchOptions<HotelDocument> = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Description", "Category", "Tags"] as const,
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

// Use search text for keyword search (hybrid search = vector + keyword)
const searchText = "historic hotel walk to restaurants and shopping";
const results: SearchDocumentsResult<HotelDocument> = await searchClient.search(searchText, searchOptions);

searchSemanticHybrid.ts illustre le classement sémantique, qui reclasse les résultats en fonction de la compréhension du langage.

const searchOptions: SearchOptions<HotelDocument> = {
    top: 5,
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Category", "Description"] as const,
    queryType: "semantic" as const,
    semanticSearchOptions: {
        configurationName: "semantic-config"
    },
    vectorSearchOptions: {
        queries: [vectorQuery],
        filterMode: "postFilter"
    }
};

const searchText = "historic hotel walk to restaurants and shopping";
const results: SearchDocumentsResult<HotelDocument> = await searchClient.search(searchText, searchOptions);

for await (const result of results.results) {
    console.log(`Score: ${result.score}, Re-ranker Score: ${result.rerankerScore}`);
}

Comparez ces résultats avec les résultats de recherche hybrides de la requête précédente. Sans reclassement sémantique, Sublime Palace Hotel se classe d’abord parce que la fusion de rang réciproque (RRF) combine le texte et les scores vectoriels pour produire un résultat fusionné. Après la reclassement sémantique, Swirling Currents Hotel se déplace vers la place supérieure.

Le ranker sémantique utilise des modèles de compréhension automatique pour évaluer la façon dont chaque résultat correspond à l’intention de la requête. La description de l'Hôtel Swirling Currents mentionne "walking access to shopping, dining, entertainment and the city center", qui s’aligne étroitement avec la requête de recherche "walk to restaurants and shopping". Cette correspondance sémantique pour les restaurants et commerces à proximité le place au-dessus du Sublime Palace Hotel, qui ne met pas en avant les commodités accessibles à pied dans sa description.

Points clés :

  • Dans une recherche hybride, vous pouvez intégrer la recherche vectorielle à la requête de texte intégral par mots-clés. Les filtres et le classement sémantique s’appliquent uniquement au contenu textuel, et non aux vecteurs.

  • Les résultats réels incluent plus de détails, notamment les textes de légendes sémantiques et les mises en surbrillance. Ce guide de démarrage rapide modifie les résultats afin d'améliorer la lisibilité. Pour obtenir la structure complète de la réponse, utilisez REST pour exécuter la requête.

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux de terminer un projet en supprimant les ressources dont vous n’avez plus besoin. Les ressources laissées actives peuvent vous coûter de l'argent.

Dans le portail Azure, sélectionnez All resources ou Resource groups dans le volet gauche pour rechercher et gérer les ressources. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer toutes les ressources à la fois.

Sinon, exécutez la commande suivante pour supprimer l’index que vous avez créé dans ce guide de démarrage rapide.

npm run build && node -r dotenv/config dist/deleteIndex.js

Dans ce guide de démarrage rapide, vous utilisez les API REST Azure AI Search pour créer, charger et interroger un index vectoriel.

Dans Azure AI Search, un index vectoriel a un schéma d’index qui définit des champs vectoriels et non vecteurs, une configuration de recherche vectorielle pour les algorithmes qui créent l’espace d’incorporation et les paramètres sur les définitions de champs vectoriels évaluées au moment de la requête. Index - Créer ou mettre à jour (API REST) crée l’index vectoriel.

Conseil / Astuce

Prérequis

Configurer l’accès

Avant de commencer, vérifiez que vous disposez des autorisations nécessaires pour accéder au contenu et aux opérations dans Azure AI Search. Ce guide de démarrage rapide utilise Microsoft Entra ID pour l’authentification et l’accès en fonction du rôle pour l’autorisation. Vous devez être un propriétaire ou un administrateur d'accès utilisateur pour attribuer des rôles. Si les rôles ne sont pas réalisables, utilisez plutôt l’authentification basée sur des clés.

Pour configurer l’accès en fonction du rôle recommandé :

  1. Activez l’accès en fonction du rôle pour votre service de recherche.

  2. Attribuez les rôles suivants à votre compte d’utilisateur.

    • Contributeur Service de Recherche

    • Contributeur de données d’index de la Recherche

    • Lecteur de données d’index de la Recherche

Obtenir un point de terminaison

Chaque service Azure AI Search a un endpoint, qui est une URL unique qui identifie et fournit un accès réseau au service. Dans une section ultérieure, vous spécifiez ce point de terminaison pour vous connecter à votre service de recherche par programmation.

Pour obtenir le point de terminaison :

  1. Connectez-vous au portail Azure et sélectionnez votre service de recherche.

  2. Dans le volet gauche, sélectionnez Vue d’ensemble.

  3. Notez le point de terminaison, qui doit ressembler à https://my-service.search.windows.net.

Configurer l’environnement

  1. Utilisez Git pour cloner l’exemple de référentiel.

    git clone https://github.com/Azure-Samples/azure-search-rest-samples
    
  2. Accédez au dossier de démarrage rapide et ouvrez-le dans Visual Studio Code.

    cd azure-search-rest-samples/Quickstart-vectors
    code .
    
  3. Dans az-search-quickstart-vectors.rest, remplacez la valeur d’espace réservé pour @baseUrl par l’URL que vous avez obtenue dans Obtenir le point de terminaison.

  4. Pour l’authentification sans clé avec Microsoft Entra ID, connectez-vous à votre compte Azure. Si vous avez plusieurs abonnements, sélectionnez celui qui contient votre service Azure AI Search.

    az login
    
  5. Pour l’authentification sans clé avec Microsoft Entra ID, générez un jeton d’accès.

    az account get-access-token --scope https://search.azure.com/.default --query accessToken -o tsv
    
  6. Remplacez la valeur de l’espace réservé par @token avec le jeton de l’étape précédente.

Exécuter le code

  1. Sous ### List existing indexes by name, sélectionnez Envoyer une demande pour vérifier votre connexion.

    Une réponse doit apparaître dans un volet adjacent. Si vous avez des index existants, ceux-ci sont répertoriés. Sinon, la liste est vide. Si le code HTTP est 200 OK, vous êtes prêt à continuer.

  2. Envoyez les requêtes restantes séquentiellement pour créer un index vectoriel, charger des documents et exécuter différents types de requêtes vectorielles.

Output

Chaque requête retourne des résultats JSON. L’exemple suivant est la sortie de la ### Run a single vector query requête, qui affiche les résultats de recherche vectorielle classés par score de similarité.

{
  "@odata.count": 5,
  "value": [
    {
      "@search.score": 0.6605852,
      "HotelId": "48",
      "HotelName": "Nordick's Valley Motel",
      "Description": "Only 90 miles (about 2 hours) from the nation's capital and nearby most everything the historic valley has to offer. Hiking? Wine Tasting? Exploring the caverns? It's all nearby and we have specially priced packages to help make our B&B your home base for fun while visiting the valley.",
      "Category": "Boutique",
      "Tags": [
        "continental breakfast",
        "air conditioning",
        "free wifi"
      ]
    },
    {
      "@search.score": 0.6333684,
      "HotelId": "13",
      "HotelName": "Luxury Lion Resort",
      "Description": "Unmatched Luxury. Visit our downtown hotel to indulge in luxury accommodations. Moments from the stadium and transportation hubs, we feature the best in convenience and comfort.",
      "Category": "Luxury",
      "Tags": [
        "bar",
        "concierge",
        "restaurant"
      ]
    },
    {
      "@search.score": 0.605672,
      "HotelId": "4",
      "HotelName": "Sublime Palace Hotel",
      "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
      "Category": "Boutique",
      "Tags": [
        "concierge",
        "view",
        "air conditioning"
      ]
    },
    {
      "@search.score": 0.6026341,
      "HotelId": "49",
      "HotelName": "Swirling Currents Hotel",
      "Description": "Spacious rooms, glamorous suites and residences, rooftop pool, walking access to shopping, dining, entertainment and the city center. Each room comes equipped with a microwave, a coffee maker and a minifridge. In-room entertainment includes complimentary W-Fi and flat-screen TVs.",
      "Category": "Suite",
      "Tags": [
        "air conditioning",
        "laundry service",
        "24-hour front desk service"
      ]
    },
    {
      "@search.score": 0.57902366,
      "HotelId": "2",
      "HotelName": "Old Century Hotel",
      "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
      "Category": "Boutique",
      "Tags": [
        "pool",
        "free wifi",
        "air conditioning",
        "concierge"
      ]
    }
  ]
}

Comprendre le code

Remarque

Les extraits de code de cette section ont peut-être été modifiés pour la lisibilité. Pour obtenir un exemple de travail complet, consultez le code source.

Maintenant que vous avez exécuté le code, nous allons décomposer les étapes clés :

  1. Créer un index de vecteur
  2. Charger des documents dans l’index
  3. Interroger l’index

Créer un index de vecteur

Avant d’ajouter du contenu à Azure AI Search, vous devez créer un index pour définir la façon dont le contenu est stocké et structuré. Ce guide de démarrage rapide appelle index - Créer (API REST) pour créer un index vectoriel nommé hotels-vector-quickstart et ses structures de données physiques sur votre service de recherche.

Le schéma d’index est organisé autour du contenu de l’hôtel. Les exemples de données se composent de descriptions vectorielles et non vectorielles d’hôtels fictifs. L’extrait suivant montre la structure clé de la ### Create a new index requête.

PUT {{baseUrl}}/indexes/hotels-vector-quickstart?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "name": "hotels-vector-quickstart",
    "fields": [
        { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true },
        { "name": "HotelName", "type": "Edm.String", "searchable": true },
        { "name": "Description", "type": "Edm.String", "searchable": true },
        {
            "name": "DescriptionVector",
            "type": "Collection(Edm.Single)",
            "searchable": true,
            "dimensions": 1536,
            "vectorSearchProfile": "my-vector-profile"
        },
        { "name": "Category", "type": "Edm.String", "filterable": true, "facetable": true },
        { "name": "Tags", "type": "Collection(Edm.String)", "filterable": true, "facetable": true }
        // Additional fields omitted for brevity
    ],
    "vectorSearch": {
        "algorithms": [
            { "name": "hnsw-vector-config", "kind": "hnsw" }
        ],
        "profiles": [
            { "name": "my-vector-profile", "algorithm": "hnsw-vector-config" }
        ]
    },
    "semantic": {
        "configurations": [
            {
                "name": "semantic-config",
                "prioritizedFields": {
                    "titleField": { "fieldName": "HotelName" },
                    "prioritizedContentFields": [{ "fieldName": "Description" }]
                }
            }
        ]
    }
}

Points clés :

  • Cet index particulier prend en charge plusieurs fonctionnalités de recherche :

  • La dimensions propriété doit correspondre à la taille de sortie de votre modèle d’incorporation. Ce guide de démarrage rapide utilise 1 536 dimensions pour correspondre au text-embedding-ada-002 modèle.

  • La vectorSearch section définit l’algorithme de voisin le plus proche approximatif (ANN). Les algorithmes pris en charge incluent Hierarchical Navigable Small World (HNSW) et l’algorithme exhaustif des K plus proches voisins (KNN). Pour plus d’informations, consultez Pertinence dans la recherche vectorielle.

Charger des documents dans l’index

Les index nouvellement créés sont vides. Pour remplir un index et le rendre pouvant faire l’objet d’une recherche, vous devez charger des documents JSON conformes au schéma d’index.

Dans Azure AI Search, les documents servent d’entrées pour l’indexation et les sorties pour les requêtes. Par souci de simplicité, ce guide de démarrage rapide fournit des exemples de documents d’hôtel en tant que JSON inline. Dans les scénarios de production, toutefois, le contenu est souvent extrait de sources de données connectées et transformé en JSON à l’aide d’indexeurs.

Ce guide de démarrage rapide appelle Documents - Index (API REST) pour ajouter des exemples de documents d’hôtel à votre index. L’extrait suivant montre la structure de la ### Upload 7 documents requête.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/index?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "value": [
        {
            "@search.action": "mergeOrUpload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is ideally located on the main commercial artery of the city...",
            "DescriptionVector": [-0.0347, 0.0289, ... ],  // 1536 floats
            "Category": "Boutique",
            "Tags": ["view", "air conditioning", "concierge"],
            "ParkingIncluded": false,
            "Rating": 3.60,
            "Address": { "City": "New York", "StateProvince": "NY" },
            "Location": { "type": "Point", "coordinates": [-73.975403, 40.760586] }
        }
        // Additional documents omitted for brevity
    ]
}

Points clés :

  • Chaque document du value tableau représente un hôtel et contient des champs qui correspondent au schéma d’index. Le @search.action paramètre spécifie l’opération à effectuer pour chaque document. Ce guide de démarrage rapide utilise mergeOrUpload, ce qui ajoute le document s’il n’existe pas ou met à jour le document s’il existe.

  • Les documents de la charge utile se composent de champs définis dans le schéma d’index.

Interroger l’index

Les requêtes dans l’exemple de fichier illustrent différents modèles de recherche. L’exemple des requêtes vectorielles sont basés sur deux chaînes :

  • Chaîne de recherche en texte intégral : "historic hotel walk to restaurants and shopping"

  • Chaîne de requête vectorielle : "quintessential lodging near running trails, eateries, retail" (vectorisée en représentation mathématique)

La chaîne de requête vectorielle est sémantiquement similaire à la chaîne de recherche en texte intégral, mais elle inclut des termes qui n’existent pas dans l’index. Une recherche par mot clé uniquement pour la chaîne de requête vectorielle retourne zéro résultat. Toutefois, la recherche vectorielle recherche des correspondances pertinentes en fonction de la signification plutôt que des mots clés exacts.

Les exemples suivants commencent par une requête vectorielle de base et ajoutent progressivement des filtres, la recherche de mots clés et la reclassement sémantique.

La ### Run a single vector query requête illustre un scénario de base dans lequel vous souhaitez trouver des descriptions de document qui correspondent étroitement à la chaîne de requête vectorielle. Le vectorQueries tableau configure la recherche vectorielle :

  • k limite le nombre de résultats retournés en fonction de la similarité vectorielle.
  • fields spécifie le champ vecteur à rechercher.
POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "select": "HotelId, HotelName, Description, Category, Tags",
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector of "quintessential lodging near running trails, eateries, retail"
            "k": 5,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Recherche à vecteur unique avec un filtre

Dans Azure AI Search, filters s’appliquent aux champs non-vecteurs d’un index. La requête ### Run a vector query with a filter applique un filtre sur le champ Tags afin d’exclure les hôtels qui ne proposent pas le Wi-Fi gratuit.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "select": "HotelId, HotelName, Description, Category, Tags",
    "filter": "Tags/any(tag: tag eq 'free wifi')",
    "vectorFilterMode": "postFilter",
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 7,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Recherche à vecteur unique avec un filtre géographique

Vous pouvez spécifier un filtre géo-spatial pour limiter les résultats à une zone géographique spécifique. La ### Run a vector query with a geo filter requête spécifie un point géographique (Washington D.C., en utilisant les coordonnées de longitude et de latitude) et retourne des hôtels dans un délai de 300 kilomètres. Le vectorFilterMode paramètre détermine quand le filtre s’exécute. Dans ce cas, postFilter exécute le filtre après la recherche vectorielle.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "select": "HotelId, HotelName, Address/City, Address/StateProvince, Description",
    "filter": "geo.distance(Location, geography'POINT(-77.03241 38.90166)') le 300",
    "vectorFilterMode": "postFilter",
    "top": 5,
    "facets": [ "Address/StateProvince"],
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 5,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

La recherche hybride combine des requêtes de texte intégral et de vecteur dans une seule requête. La ### Run a hybrid query requête exécute les deux types de requêtes simultanément, puis utilise la fusion de classement réciproque (RRF) pour fusionner les résultats dans un classement unifié. RRF utilise l’inverse des classements de résultats de chaque jeu de résultats pour produire un classement fusionné. Notez que les scores de recherche hybride sont uniformément plus petits que les scores à requête unique.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelId, HotelName, Category, Tags, Description",
    "top": 5,
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 5,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

La requête illustre le ### Run a hybrid query with semantic rerankingclassement sémantique, qui reclasse les résultats en fonction de la compréhension du langage.

POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "count": true,
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelId, HotelName, Category, Description",
    "queryType": "semantic",
    "semanticConfiguration": "semantic-config",
    "top": 5,
    "vectorQueries": [
        {
            "vector": [ ... ],  // 1536-dimensional vector
            "k": 7,
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true
        }
    ]
}

Comparez ces résultats avec les résultats de recherche hybrides de la requête précédente. Sans reclassement sémantique, Sublime Palace Hotel se classe d’abord parce que la fusion de rang réciproque (RRF) combine le texte et les scores vectoriels pour produire un résultat fusionné. Après la reclassement sémantique, Swirling Currents Hotel se déplace vers la place supérieure.

Le ranker sémantique utilise des modèles de compréhension automatique pour évaluer la façon dont chaque résultat correspond à l’intention de la requête. La description de l'Hôtel Swirling Currents mentionne "walking access to shopping, dining, entertainment and the city center", qui s’aligne étroitement avec la requête de recherche "walk to restaurants and shopping". Cette correspondance sémantique pour les restaurants et commerces à proximité le place au-dessus du Sublime Palace Hotel, qui ne met pas en avant les commodités accessibles à pied dans sa description.

Points clés :

  • Dans une recherche hybride, vous pouvez intégrer la recherche vectorielle à la requête de texte intégral par mots-clés. Les filtres et le classement sémantique s’appliquent uniquement au contenu textuel, et non aux vecteurs.

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux de terminer un projet en supprimant les ressources dont vous n’avez plus besoin. Les ressources laissées actives peuvent vous coûter de l'argent.

Dans le portail Azure, sélectionnez All resources ou Resource groups dans le volet gauche pour rechercher et gérer les ressources. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer toutes les ressources à la fois.

Sinon, vous pouvez envoyer la demande de suppression de l’index ### Delete an index que vous avez créé dans ce guide de démarrage rapide.