Partager via


Créer une requête hybride dans Recherche Azure AI

La recherche hybride combine les requêtes textuelles (mots clés) et vectorielles en une seule requête de recherche. Toutes les sous-requêtes de la requête s’exécutent en parallèle. Les résultats sont fusionnés et réorganisés par nouveaux scores de recherche, à l’aide de la fusion de classement réciproque (RRF) pour retourner un jeu de résultats unifié. Dans de nombreux cas, selon les tests de référence, les requêtes hybrides avec un classement sémantique retournent les résultats les plus pertinents.

Dans cet article, découvrez comment :

  • Configurer une requête de base
  • Formuler des requêtes hybrides avec davantage de paramètres et de filtres
  • Améliorer la pertinence à l’aide du classement sémantique ou de la pondération vectorielle
  • Optimiser le comportement des requêtes en contrôlant les entrées textuelles et vectorielles

Remarque

La nouveauté de la préversion 2024-09-01-preview consiste à pouvoir cibler des filtres uniquement sur les sous-requêtes vectorielles d’une requête hybride. Cela vous donne plus de précision sur la façon dont les filtres sont appliqués. Pour plus d’informations, consultez les aspects relatifs au ciblage des filtres sur des sous-requêtes vectorielles dans cet article.

Prérequis

Choisir une API ou un outil

  • L’Explorateur de recherche dans le portail Azure (prend en charge à la fois la syntaxe de recherche d’API stable et celle en préversion) dispose d’une vue JSON qui vous permet de coller une requête hybride.

  • La version stable 2024-07-01 ou une version d’API récente en préversion si vous utilisez des fonctionnalités en préversion telles que maxTextRecallSize et countAndFacetMode(preview).

    Pour des raisons de lisibilité, nous utilisons des exemples REST afin d’expliquer le fonctionnement des API. Vous pouvez utiliser un client REST tel que Visual Studio Code avec l’extension REST pour créer des requêtes hybrides. Pour plus d’informations, consultez Démarrage rapide : Recherche vectorielle à l’aide des API REST.

  • Packages stables ou en version bêta des kits Azure SDK (consultez les journaux des modifications pour la prise en charge des fonctionnalités du kit SDK).

Configurer une requête hybride dans l’Explorateur de recherche

  1. Dans l’Explorateur de recherche, vérifiez que la version de l’API est 2024-07-01 ou une version d’API plus récente en préversion.

  2. Sous Affichage, sélectionnez Vue JSON pour pouvoir coller une requête vectorielle.

  3. Remplacez le modèle de requête par défaut par une requête hybride, en utilisant notamment l’exemple « Run a hybrid query » (Exécuter une requête hybride), qui commence à la ligne 539 du Guide de démarrage rapide sur les vecteurs. Par souci de concision, le vecteur est tronqué dans cet article.

    Une requête hybride a une requête de texte spécifiée dans search et une requête vectorielle spécifiée sous vectorQueries.vector.

    La requête textuelle et la requête vectorielle peuvent être équivalentes ou divergentes, mais il est courant qu’elles partagent la même intention.

    {
        "count": true,
        "search": "historic hotel walk to restaurants and shopping",
        "select": "HotelId, HotelName, Category, Tags, Description",
        "top": 7,
        "vectorQueries": [
            {
                "vector": [0.01944167, 0.0040178085, -0.007816401 ... <remaining values omitted> ], 
                "k": 7,
                "fields": "DescriptionVector",
                "kind": "vector",
                "exhaustive": true
            }
        ]
    }
    
  4. Sélectionnez Rechercher.

Conseil

Les résultats de la recherche sont plus faciles à lire si vous masquez les vecteurs. Dans Options de requête, activez Masquer les valeurs vectorielles dans les résultats de la recherche.

Demande de requête hybride (API REST)

Une requête hybride combine la recherche en texte et la recherche vectorielle, où le paramètre search prend une chaîne de requête et vectorQueries.vector prend la requête vectorielle. Le moteur de recherche exécute des requêtes de texte intégral et de vecteur en parallèle. L’union de toutes les correspondances est évaluée pour la pertinence à l’aide de la fusion de classement réciproque (RRF) et un jeu de résultats unique est retourné dans la réponse.

Les résultats sont renvoyés en texte clair, y compris les vecteurs dans les champs marqués comme retrievable. Étant donné que les vecteurs numériques ne sont pas utiles dans les résultats de recherche, choisissez d’autres champs dans l’index en tant que proxy pour la correspondance vectorielle. Par exemple, si un index a des champs « descriptionVector » et « descriptionText », la requête peut correspondre à « descriptionVector », mais le résultat de la recherche peut afficher « descriptionText ». Utilisez le paramètre select pour spécifier uniquement les champs lisibles par l’homme dans les résultats.

L’exemple suivant illustre une configuration de requête hybride.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true,
            "k": 10
        },
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true,
            "k": 10
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Address/City",
    "top": 10
}

Points essentiels :

  • La chaîne de recherche vectorielle est spécifiée par le biais de la propriété vectorQueries.vector. La requête s’exécute sur le champ « DescriptionVector ». Définissez kind sur « vector » pour indiquer le type de requête. Si vous le souhaitez, définissez la valeur exhaustive sur true pour interroger le contenu complet du champ vectoriel.

  • La recherche par mot clé est spécifiée par le biais de la propriété search. Elle s’exécute en parallèle avec la requête vectorielle.

  • k détermine le nombre de correspondances du plus proche voisin retournées par la requête vectorielle et fournies au ranker RRF.

  • top détermine le nombre de correspondances retournées dans la réponse. Dans cet exemple, la réponse comprend dix résultats, en supposant qu’il y ait au moins dix correspondances dans les résultats fusionnés.

Recherche hybride avec filtre

Cet exemple ajoute un filtre, qui est appliqué aux champs non vectoriels filterable de l’index de recherche.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "k": 10
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "vectorFilterMode": "postFilter",
    "filter": "ParkingIncluded",
    "top": "10"
}

Points essentiels :

  • Les filtres sont appliqués au contenu des champs filtrables. Dans cet exemple, le champ ParkingIncluded est une valeur booléenne et elle est marquée comme filterable dans le schéma de l’index.

  • Dans les requêtes hybrides, les filtres peuvent être appliqués avant l’exécution de la requête afin de réduire la surface de requête, ou après l’exécution de la requête afin de réduire les résultats. "preFilter" est la valeur par défaut. Pour utiliser postFilter, définissez le mode de traitement de filtre comme illustré dans cet exemple.

  • Lorsque vous postfiltrez des résultats de requête, le nombre de résultats peut être inférieur à top-n.

Recherche hybride avec des filtres ciblant les sous-requêtes vectorielles (préversion)

À l’aide de la préversion 2024-09-01-preview, vous pouvez remplacer un filtre global sur la requête de recherche en appliquant un filtre secondaire qui cible uniquement les sous-requêtes vectorielles d’une requête hybride.

Cette fonctionnalité fournit un contrôle affiné, car elle permet de vérifier que les filtres influencent uniquement les résultats de la recherche vectorielle, sans affecter les résultats de la recherche basée sur des mots clés.

Le filtre ciblé remplace entièrement le filtre global, notamment les filtres utilisés pour le filtrage de sécurité ou la recherche géospatiale. Dans les cas où des filtres globaux sont nécessaires, par exemple le filtrage de sécurité, vous devez inclure explicitement ces filtres dans le filtre de premier niveau ainsi que dans chaque filtre de niveau vectoriel pour garantir l’application cohérente de la sécurité et des autres contraintes.

Pour appliquer des filtres vectoriels ciblés :

Voici un exemple de requête hybride qui ajoute un remplacement de filtre. Le filtre global « Rating gt 3 » est remplacé à l’exécution par filterOvrride.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-09-01=preview

{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "exhaustive": true,
            "filterOverride": "Address/City eq 'Seattle'",
            "k": 10
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Address/City, Rating",
    "filter": "Rating gt 3"
    "debug": "vector",
    "top": 10
}

En supposant que vous avez activé le classeur sémantique et que votre définition d’index inclut une configuration sémantique, vous pouvez formuler une requête qui inclut la recherche vectorielle, ainsi que la recherche par mot clé avec un classement sémantique sur le jeu de résultats fusionné. Si vous le souhaitez, vous pouvez ajouter des légendes et des réponses.

Chaque fois que vous utilisez le classement sémantique avec des vecteurs, assurez-vous que k est défini sur 50. Le classeur sémantique utilise jusqu’à 50 correspondances comme entrée. En indiquant moins de 50, on prive les modèles de classement sémantique des entrées nécessaires.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "k": 50
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Tags",
    "queryType": "semantic",
    "semanticConfiguration": "my-semantic-config",
    "captions": "extractive",
    "answers": "extractive",
    "top": "50"
}

Points essentiels :

  • Le classeur sémantique accepte jusqu’à 50 résultats de la réponse fusionnée.

  • « queryType » et « semanticConfiguration » sont obligatoires.

  • « captions » et « answers » sont facultatifs. Les valeurs sont extraites du texte détaillé dans les résultats. Une réponse est retournée uniquement si les résultats incluent du contenu ayant les caractéristiques d’une réponse à la requête.

Recherche hybride sémantique avec filtre

Voici la dernière requête de la collection. Il s’agit de la même requête hybride sémantique que l’exemple précédent, mais avec un filtre.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "vectorQueries": [
        {
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "DescriptionVector",
            "kind": "vector",
            "k": 50
        }
    ],
    "search": "historic hotel walk to restaurants and shopping",
    "select": "HotelName, Description, Tags",
    "queryType": "semantic",
    "semanticConfiguration": "my-semantic-config",
    "captions": "extractive",
    "answers": "extractive",
    "filter": "ParkingIsIncluded'",
    "vectorFilterMode": "postFilter",
    "top": "50"
}

Points essentiels :

  • Le mode de filtre peut affecter le nombre de résultats accessibles au reranker sémantique. En guise de meilleure pratique, il est judicieux de donner au ranker sémantique le nombre maximal de documents (50). Si les préfiltres ou les postfiltres sont trop sélectifs, vous risquez de sous-servir le ranker sémantique en lui donnant moins de 50 documents avec lesquels travailler.

  • Le préfiltrage est appliqué avant l’exécution de la requête. Si le préfiltre réduit la zone de recherche à 100 documents, la requête vectorielle s’exécute sur le champ « DescriptionVector » pour ces 100 documents, et retourne les k=50 meilleures correspondances. Ces 50 documents correspondants passent ensuite à RRF pour les résultats fusionnés, puis au ranker sémantique.

  • Le postfiltre est appliqué après l’exécution de la requête. Si k=50 renvoie 50 correspondances du côté de la requête vectorielle, suivie d'un post-filtre appliqué aux 50 correspondances, vos résultats sont réduits du nombre de documents qui répondent aux critères de filtre. Cela vous laisse moins de 50 documents à transmettre au classificateur sémantique. Gardez cela à l'esprit si vous utilisez le classement sémantique. Le classeur sémantique fonctionne mieux s’il a 50 documents comme entrée.

Définir maxTextRecallSize et countAndFacetMode (préversion)

Cette section explique comment ajuster les entrées d’une requête hybride en contrôlant la quantité de résultats classés BM25 qui circulent jusqu’au modèle de classement hybride. Le contrôle de l’entrée classée BM25 vous offre davantage d’options pour le réglage de la pertinence dans les scénarios hybrides.

Nous vous recommandons la préversion de l’API REST 2024-05-01-preview.

Conseil

Une autre option à prendre en compte est une technique supplémentaire ou de remplacement, à savoir la pondération vectorielle, qui augmente l’importance des requêtes vectorielles dans la requête.

  1. Utilisez Search – POST ou Search – GET dans 2024-05-01-preview pour spécifier ces paramètres.

  2. Ajoutez un objet de paramètre de requête hybridSearch pour définir le nombre maximal de documents rappelés parmi les résultats classés BM25 d’une requête hybride. Elle contient deux propriétés :

    • maxTextRecallSize spécifie le nombre de résultats classés BM25 à fournir au classeur de fusion de classement réciproque (RRF) utilisé dans les requêtes hybrides. La valeur par défaut est 1000. La valeur maximale est 10 000.

    • countAndFacetMode indique le nombre de résultats classés BM25 (et de facettes si vous les utilisez). La valeur par défaut est tous les documents qui correspondent à la requête. Si vous le souhaitez, vous pouvez définir maxTextRecallSize comme étendue de « count ».

  3. Réduisez maxTextRecallSize si la recherche de similarité vectorielle fournit généralement de meilleures performances que le côté texte de la requête hybride.

  4. Augmentez maxTextRecallSize si vous avez un index volumineux et que le paramètre par défaut ne capture pas un nombre suffisant de résultats. Avec un jeu de résultats classé BM25 plus grand, vous pouvez également définir top, skip et next pour récupérer des parties de ces résultats.

Les exemples REST suivants montrent deux cas d’usage pour définir maxTextRecallSize.

Le premier exemple réduit maxTextRecallSize à 100, limitant le côté texte de la requête hybride à seulement 100 documents. Il définit également countAndFacetMode de façon à inclure uniquement ces résultats à partir de maxTextRecallSize.

POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-05-01-Preview 

    { 
      "vectorQueries": [ 
        { 
          "kind": "vector", 
          "vector": [1.0, 2.0, 3.0], 
          "fields": "my_vector_field", 
          "k": 10 
        } 
      ], 
      "search": "hello world", 
      "hybridSearch": { 
        "maxTextRecallSize": 100, 
        "countAndFacetMode": "countRetrievableResults" 
      } 
    } 

Le deuxième exemple augmente maxTextRecallSize à 5000. Il utilise également top, skip et next pour extraire les résultats à partir de jeux de résultats volumineux. Dans ce cas, la requête extrait les résultats classés BM25 de la position 1500 à la position 2000 en tant que contribution de requête texte au jeu de résultats composite RRF.

POST https://[service-name].search.windows.net/indexes/[index-name]/docs/search?api-version=2024-05-01-Preview 

    { 
      "vectorQueries": [ 
        { 
          "kind": "vector", 
          "vector": [1.0, 2.0, 3.0], 
          "fields": "my_vector_field", 
          "k": 10 
        } 
      ], 
      "search": "hello world",
      "top": 500,
      "skip": 1500,
      "next": 500,
      "hybridSearch": { 
        "maxTextRecallSize": 5000, 
        "countAndFacetMode": "countRetrievableResults" 
      } 
    } 

Configurer une réponse à une requête

Lorsque vous configurez la requête hybride, réfléchissez à la structure de réponse. La réponse est un ensemble de lignes aplati. Les paramètres de la requête déterminent les champs contenus dans chaque ligne et le nombre de lignes dans la réponse. Le moteur de recherche classe les documents correspondants et renvoie les résultats les plus pertinents.

Champs dans une réponse

Les résultats de la recherche sont composés de champs retrievable à partir de votre index de recherche. Le résultat est soit :

  • Tous les champs retrievable (une API REST par défaut).
  • Champs explicitement répertoriés dans un paramètre « select » sur la requête.

Les exemples de cet article utilisent une instruction « select » pour spécifier des champs de texte (non vecteur) dans la réponse.

Remarque

Les vecteurs ne sont pas inversés en texte lisible par l’homme. Évitez donc de les renvoyer dans la réponse. Au lieu de cela, choisissez des champs non vectoriels représentatifs du document de recherche. Par exemple, si la requête cible un champ « DescriptionVector », la réponse renvoie un champ texte équivalent si vous en avez un (« Description »).

Nombre de résultats

Une requête peut correspondre à un nombre quelconque de documents, autant que tous si les critères de recherche sont faibles (par exemple , « search=* » pour une requête Null). Étant donné qu’il est rarement pratique de retourner des résultats non liés, vous devez spécifier un maximum pour la réponse globale :

  • "top": n résultats pour les requêtes par mot clé uniquement (aucun vecteur)
  • "k": n résultats pour les requêtes vectorielles uniquement
  • "top": n résultats pour les requêtes hybrides (avec ou sans sémantique) qui incluent un paramètre « recherche »

« k » et « top » sont facultatifs. Non spécifié, le nombre par défaut de résultats dans une réponse est 50. Vous pouvez définir « haut » et « ignorer » sur la page par le biais de résultats supplémentaires ou modifier la valeur par défaut.

Remarque

Si vous utilisez la recherche hybride dans l’API 2024-05-01-preview, vous pouvez contrôler le nombre de résultats de la requête par mot clé à l’aide de maxTextRecallSize. Combinez-le avec un paramètre pour « k » pour contrôler la représentation à partir de chaque sous-système de recherche (mot clé et vecteur).

Résultats du classeur sémantique

Remarque

Le ranker sémantique peut prendre jusqu’à 50 résultats.

Si vous utilisez le classeur sémantique dans l’API 2024-05-01-preview, la meilleure pratique consiste à définir « k » et « maxTextRecallSize » pour obtenir un total d’au moins 50. Vous pouvez ensuite restreindre les résultats retournés à l’utilisateur avec le paramètre « top ».

Si vous utilisez le classeur sémantique dans des API antérieures, procédez de la manière suivante :

  • si vous effectuez une recherche par mot-clé uniquement (aucun vecteur), définissez la valeur « top » sur 50
  • si vous effectuez une recherche hybride, définissez "k" sur 50, afin de vous assurer que le classeur sémantique reçoive au moins 50 résultats.

Classement

Plusieurs jeux sont créés pour les requêtes hybrides, avec ou sans le nouveau classement sémantique facultative. Le classement des résultats est calculé par fusion de classement réciproque (RRF).

Dans cette section, comparez les réponses entre la recherche vectorielle unique et la recherche hybride simple pour obtenir le meilleur résultat. Les différents algorithmes de classement, dans ce cas-ci la métrique de similarité de HNSW et la RRF, produisent des scores ayant différentes magnitudes. Ce comportement est inhérent au produit. Les scores RRF peuvent sembler assez faibles, même avec une correspondance de similarité élevée. Les bas scores sont une caractéristique de l’algorithme RRF. Dans une requête hybride avec RRF, la réciproque des documents classés est davantage incluse dans les résultats, étant donné le score relativement plus faible des documents classés de la RRF, par opposition à la recherche vectorielle pure.

Recherche vectorielle unique :@search.score pour des résultats classés par similarité cosinus (fonction de distance de similarité de vecteur par défaut).

{
    "@search.score": 0.8399121,
    "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.",
    "Category": "Luxury",
    "Address": {
    "City": "Arlington"
    }
}

Recherche hybride : @search.score pour les résultats hybrides classés à l’aide de la fusion de classement réciproque.

{
    "@search.score": 0.032786883413791656,
    "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.",
    "Category": "Luxury",
    "Address": {
    "City": "Arlington"
    }
}

Étapes suivantes

À l’étape suivante, nous vous recommandons d’évaluer le code de démonstration pour Python, C#, ou Javascript.