Share via


Créer une requête vectorielle dans Azure AI Search

Dans Recherche Azure AI, si vous avez un index vectoriel, cet article explique comment le faire :

Cet article utilise REST pour l’illustration. Pour obtenir des exemples de code dans d’autres langages, consultez les azure-search-vector-samples référentiel GitHub pour les solutions de bout en bout qui incluent des requêtes vectorielles.

Prérequis

Convertir une entrée de chaîne de requête en vecteur

Pour interroger un champ vectoriel, la requête elle-même doit être un vecteur.

Une approche pour convertir la chaîne de requête texte d'un utilisateur en sa représentation vectorielle consiste à appeler une bibliothèque d'intégration ou une API dans le code de votre application. Comme meilleure pratique, toujours utiliser les mêmes modèles d’incorporation utilisés pour générer des incorporations dans les documents sources. Vous trouverez des exemples de code montrant comment générer des incorporations dans le référentiel azure-search-vector-samples .

Une deuxième approche consiste à utiliser la vectorisation intégrée, actuellement en préversion publique, pour que la recherche Azure AI gère vos entrées et sorties de vectorisation de requête.

Voici un exemple d’API REST d’une chaîne de requête soumise à un déploiement d’un modèle d’intégration Azure OpenAI :

POST https://{{openai-service-name}}.openai.azure.com/openai/deployments/{{openai-deployment-name}}/embeddings?api-version={{openai-api-version}}
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "input": "what azure services support generative AI'"
}

La réponse attendue est 202 pour un appel réussi au modèle déployé.

Le champ « incorporation » dans le corps de la réponse est la représentation vectorielle de la chaîne de requête « entrée ». À des fins de test, vous copieriez la valeur du tableau « embedding » dans « vectorQueries.vector » dans une requête de requête, en utilisant la syntaxe présentée dans les sections suivantes.

La réponse réelle pour cet appel POST au modèle déployé comprend 1 536 intégrations, réduites ici uniquement aux premiers vecteurs pour plus de lisibilité.

{
    "object": "list",
    "data": [
        {
            "object": "embedding",
            "index": 0,
            "embedding": [
                -0.009171937,
                0.018715322,
                ...
                -0.0016804502
            ]
        }
    ],
    "model": "ada",
    "usage": {
        "prompt_tokens": 7,
        "total_tokens": 7
    }
}

Dans cette approche, votre code d'application est responsable de la connexion à un modèle, de la génération des intégrations et de la gestion de la réponse.

Demande de requête vectorielle

Cette section présente la structure de base d’une requête vectorielle. Vous pouvez utiliser le Portail Microsoft Azure, les API REST ou les SDK Azure pour formuler une requête vectorielle. Si vous effectuez une migration à partir de 2023-07-01-Preview, il existe des changements cassants. Pour plus d’informations, consultez Mise à niveau vers la dernière de l’API REST.

2023-11-01 est la version stable de l’API REST pour Rechercher POST. Cette version prend en charge :

  • vectorQueries est la construction de la recherche vectorielle.
  • kind défini sur vector spécifie que la requête est un tableau de vecteurs.
  • vector est une requête (représentation vectorielle du texte ou d’une image).
  • exhaustive (facultatif) appelle un KNN exhaustif au moment de la requête, même si le champ est indexé pour HNSW.

Dans l’exemple suivant, le vecteur est une représentation de cette chaîne : « quels services Azure prennent en charge la recherche en texte intégral ». La requête cible le champ contentVector. La requête retourne k résultats. Le vecteur réel a 1536 incorporations. Il est donc rogné dans cet exemple pour la lisibilité.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector",
            "k": 5
        }
    ]
}

Réponse à la requête vectorielle

Dans Recherche Azure AI, les réponses aux requêtes se composent de tous les champs retrievable par défaut. Toutefois, il est courant de limiter les résultats de recherche à un sous-ensemble de champs retrievable en les listant dans une instruction select .

Dans une requête vectorielle, réfléchissez bien à la nécessité de vecteur les champs dans une réponse. Les champs vectoriels ne sont pas lisibles par l'homme, donc si vous envoyez une réponse à une page Web, vous devez choisir des champs non vectoriels représentatifs du résultat. Par exemple, si la requête s'exécute sur contentVector, vous pouvez retourner content à la place.

Si vous souhaitez des champs vectoriels dans le résultat, voici un exemple de structure de réponse. contentVector est un tableau de chaînes d’incorporations, rogné ici pour la concision. Le score de recherche indique la pertinence. D'autres champs non vectoriels sont inclus pour le contexte.

{
    "@odata.count": 3,
    "value": [
        {
            "@search.score": 0.80025613,
            "title": "Azure Search",
            "category": "AI + Machine Learning",
            "contentVector": [
                -0.0018343845,
                0.017952163,
                0.0025753193,
                ...
            ]
        },
        {
            "@search.score": 0.78856903,
            "title": "Azure Application Insights",
            "category": "Management + Governance",
            "contentVector": [
                -0.016821077,
                0.0037742127,
                0.016136652,
                ...
            ]
        },
        {
            "@search.score": 0.78650564,
            "title": "Azure Media Services",
            "category": "Media",
            "contentVector": [
                -0.025449317,
                0.0038463024,
                -0.02488436,
                ...
            ]
        }
    ]
}

Points essentiels :

  • k détermine combien de résultats de voisins les plus proches sont renvoyés, dans ce cas, trois. Les requêtes vectorielles renvoient toujours des k résultats, en supposant qu'au moins des k documents existent, même s'il existe des documents peu similaires, car l'algorithme trouve les k voisins les plus proches du vecteur de requête.

  • Le @search.score est déterminé par l’algorithme de recherche vectorielle.

  • Les champs des résultats de recherche sont soit tous les retrievable champs, soit les select champs d'une clause. Lors de l’exécution d’une requête vectorielle, la correspondance est effectuée uniquement sur les données vectorielles. Toutefois, une réponse peut inclure n’importe quel champ retrievable d’un index. Puisqu'il n'existe aucune possibilité de décoder le résultat d'un champ vectoriel, l'inclusion de champs de texte non vectoriels est utile pour leurs valeurs lisibles par l'homme.

Requête vectorielle avec filtre

Une requête peut comprendre une requête vectorielle et une expression de filtre. Les filtres s'appliquent aux champs filterable non vectoriels, soit un champ de chaîne soit un champ numérique, et sont utiles pour inclure ou exclure des documents de recherche en fonction de critères de filtre. Bien qu’un champ vectoriel ne soit pas lui-même filtrable, des filtres peuvent être appliqués à d’autres champs dans le même index.

Vous pouvez appliquer des filtres en tant que critères d’exclusion avant que la requête s’exécute ou après l’exécution de la requête pour filtrer les résultats de la recherche. Pour une comparaison de chaque mode et des performances attendues en fonction de la taille de l'index, voir Filtres dans les requêtes vectorielles.

Conseil

Si vous n’avez pas de champs sources avec du texte ou des valeurs numériques, recherchez les métadonnées de document, telles que les propriétés LastModified ou CreatedBy, qui peuvent être utiles dans un filtre de métadonnées.

2023-11-01 est la version stable de cette API. Il comprend :

  • vectorFilterMode pour le préfiltre (valeur par défaut) ou les modes de filtrage postfilter.
  • filter fournit les critères.

Dans l’exemple suivant, le vecteur est une représentation de cette chaîne de requête : « ce que les services Azure prennent en charge la recherche en texte intégral ». La requête cible le champ contentVector. Le vecteur réel a 1536 incorporations. Il est donc rogné dans cet exemple pour la lisibilité.

Les critères de filtrage sont appliqués à un champ de texte filtrable (category dans cet exemple) avant que le moteur de recherche n'exécute la requête vectorielle.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "filter": "category eq 'Databases'",
    "vectorFilterMode": "preFilter",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector",
            "k": 5
        }
    ]
}

Champs de vecteurs multiples

Vous pouvez définir la propriété « vectorQueries.fields » sur plusieurs champs vectoriels. La requête vectorielle s'exécute sur chaque champ vectoriel que vous fournissez dans la liste fields. Lorsque vous interrogez plusieurs champs vectoriels, assurez-vous que chacun contient des intégrations du même modèle d'intégration et que la requête est également générée à partir du même modèle d'intégration.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2023-11-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector, titleVector",
            "k": 5
        }
    ]
}

Requêtes vectorielles multiples

La recherche vectorielle multi-requête envoie plusieurs requêtes sur plusieurs champs vectoriels dans votre index de recherche. Un exemple courant de cette requête est l’utilisation de modèles tels que CLIP pour une recherche vectorielle modale où le même modèle peut vectoriser le contenu d’image et de texte.

L’exemple de requête suivant recherche la similarité dans les deux myImageVector et myTextVector, mais envoie respectivement deux incorporations de requêtes différentes, chacune s’exécutant en parallèle. Cette requête produit un résultat marqué à l’aide de fusion de classement réciproque (RRF).

  • vectorQueries fournit un tableau de requêtes vectorielles.
  • vector contient les vecteurs d’image et les vecteurs de texte dans l’index de recherche. Chaque instance est une requête distincte.
  • fields spécifie le champ vecteur à cibler.
  • k correspond au nombre de correspondances voisines les plus proches à inclure dans les résultats.
{
    "count": true,
    "select": "title, content, category",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "fields": "myimagevector",
            "k": 5
        },
        {
            "kind": "vector"
            "vector": [
                -0.002222222,
                0.018708462,
                -0.013770515,
            . . .
            ],
            "fields": "mytextvector",
            "k": 5
        }
    ]
}

Les résultats de la recherche comprendront une combinaison de texte et d'images, à condition que votre index de recherche comprenne un champ pour le fichier image (un index de recherche ne stocke pas les images).

Requête avec vectorisation intégrée (aperçu)

Cette section présente une requête vectorielle qui appelle la nouvelle fonctionnalité intégrée d'évaluation de vectorisation qui convertit une requête texte en vecteur. Utilisez 2023-10-01-Preview API REST ou un package de sdk Azure bêta mis à jour.

La condition préalable est que l'index de recherche soit doté d'un vecteur configuré et assigné à un champ de vecteurs. Le vectoriseur fournit des informations de connexion à un modèle d’incorporation utilisé au moment de la requête.

Les requêtes fournissent des chaînes de texte au lieu de vecteurs :

  • kind doit être réglé sur text .
  • text doit contenir une chaîne de texte. Il est passé au vectoriseur affecté au champ vectoriel.
  • fields est le champ vectoriel à rechercher.

Voici un exemple simple de requête vectorisée au moment de l'interrogation. La chaîne de texte est vectorisée, puis utilisée pour interroger le champ descriptionVector.

POST https://{{search-service}}.search.windows.net/indexes/{{index}}/docs/search?api-version=2023-10-01-preview
{
    "select": "title, genre, description",
    "vectorQueries": [
        {
            "kind": "text",
            "text": "mystery novel set in London",
            "fields": "descriptionVector",
            "k": 5
        }
    ]
}

Voici une requête hybride à l’aide de vectorisation intégrée de requêtes de texte. Cette requête comprend plusieurs champs vectoriels de requête, plusieurs champs non vectoriels, un filtre et un classement sémantique. Là encore, les différences sont les kind de requête vectorielle et la chaîne text au lieu d’une vector.

Dans cet exemple, le moteur de recherche effectue trois appels de vectorisation aux vectoriseurs attribués à descriptionVector, synopsisVector et authorBioVector dans l'index. Les vecteurs résultants sont utilisés pour récupérer des documents sur leurs champs respectifs. Le moteur de recherche exécute également une recherche par mot clé sur la requête search, « mystère roman défini à Londres ».

POST https://{{search-service}}.search.windows.net/indexes/{{index}}/docs/search?api-version=2023-10-01-preview
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "search":"mystery novel set in London", 
    "searchFields":"description, synopsis", 
    "semanticConfiguration":"my-semantic-config", 
    "queryType":"semantic",
    "select": "title, author, synopsis",
    "filter": "genre eq 'mystery'",
    "vectorFilterMode": "postFilter",
    "vectorQueries": [
        {
            "kind": "text",
            "text": "mystery novel set in London",
            "fields": "descriptionVector, synopsisVector",
            "k": 5
        },
        {
            "kind": "text"
            "text": "living english author",
            "fields": "authorBioVector",
            "k": 5
        }
    ]
}

Les résultats marqués des quatre requêtes sont fusionnés à l’aide de classement RRF. Le classement sémantique secondaire est appelé sur les résultats de recherche fusionnés, mais sur le searchFields uniquement, ce qui améliore les résultats les plus sémantiquement alignés sur "search":"mystery novel set in London".

Remarque

Les vecteurs sont utilisés lors de l'indexation et de l'interrogation. Si vous n’avez pas besoin de segmentation et de vectorisation des données dans l’index, vous pouvez ignorer les étapes telles que la création d’un indexeur, d’un ensemble de compétences et d’une source de données. Dans ce scénario, le vectoriseur est utilisé uniquement au moment de la requête pour convertir une chaîne de texte en incorporation.

Nombre de résultats classés dans une réponse de requête vectorielle

Une requête vectorielle spécifie le paramètre k , qui détermine le nombre de correspondances retournées dans les résultats. Le moteur de recherche retourne toujours k nombre de correspondances. Si k est supérieur au nombre de documents dans l’index, le nombre de documents détermine alors la limite supérieure de ce qui peut être renvoyé.

Si vous connaissez la recherche en texte intégral, vous savez que vous obtenez zéro résultat si l’index ne contient pas de terme ou d’expression. Toutefois, dans la recherche vectorielle, l’opération de recherche identifie les voisins les plus proches et retourne toujours des résultats k même si les voisins les plus proches ne sont pas similaires. Par conséquent, il est possible d’obtenir des résultats pour les requêtes nonsensiques ou hors rubrique, en particulier si vous n’utilisez pas d’invites pour définir des limites. Les résultats moins pertinents ont un score de similarité moins bon, mais ils sont toujours les « plus proches » vecteurs s’il n’existe rien de plus proche. Par conséquent, une réponse sans résultats significatifs peut toujours renvoyer des résultats k, mais le score de similarité de chaque résultat est faible.

Une approche hybride qui inclut la recherche en texte intégral peut atténuer ce problème. Une autre atténuation consiste à définir un seuil minimal sur le score de recherche, mais uniquement si la requête est une requête vectorielle unique pure. Les requêtes hybrides ne sont pas propices aux seuils minimaux, car les plages RRF sont tellement plus petites et volatiles.

Les paramètres de requête affectant le nombre de résultats sont les suivants :

  • "k": n résultats pour les requêtes vectorielles uniquement
  • "top": n résultats pour les requêtes hybrides 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.

Algorithmes de classement utilisés dans une requête vectorielle

Le classement des résultats est calculé par les deux :

  • Métrique de similarité
  • Fusion réciproque des rangs (RRF) s'il y a plusieurs ensembles de résultats de recherche.

Métrique de similarité

Métrique de similarité spécifiée dans la section vectorSearch d’index pour une requête vectorielle uniquement. Les valeurs valides sont cosine, euclidean et dotProduct.

Les modèles d’incorporation Azure OpenAI utilisent la similarité cosinus. Par conséquent, si vous utilisez des modèles d’incorporation Azure OpenAI, cosine est la métrique recommandée. Les autres métriques de classement prises en charge incluent euclidean et dotProduct.

Utiliser RRF

Plusieurs ensembles sont créés si la requête cible plusieurs champs vectoriels, exécute plusieurs requêtes vectorielles en parallèle ou si la requête est un hybride de recherche vectorielle et de recherche en texte intégral, avec ou sans classement sémantique.

Lors de l'exécution d'une requête, une requête vectorielle ne peut cibler qu'un seul index vectoriel interne. Ainsi, pour plusieurs champs vectoriels et plusieurs requêtes vectorielles, le moteur de recherche génère plusieurs requêtes qui ciblent les index vectoriels respectifs de chaque champ. Le résultat est un ensemble de résultats classés pour chaque requête, qui sont fusionnés à l'aide de la méthode RRF. Pour plus d'informations, consultez Score de pertinence à l'aide de Reciprocal Rank Fusion (RRF).

Définir des seuils pour exclure les résultats de faible score (préversion)

Étant donné que la recherche voisine la plus proche retourne toujours les k voisins demandés, il est possible d’obtenir des correspondances de score faible sont incluses juste pour répondre aux exigences de nombre k.

À l’aide des API REST 2024-05-01-préversion, vous pouvez maintenant ajouter un paramètre de requête threshold pour exclure les résultats de recherche de faible score.

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

    { 
      "vectorQueries": [ 
        { 
          "kind": "vector", 
          "vector": [1.0, 2.0, 3.0], 
          "fields": "my-cosine-field", 
          "threshold": { 
            "kind": "vectorSimilarity", 
            "value": 0.8 
          } 
        }
      ]
    }

Le filtrage se produit avant la fusion des résultats des différents ensembles de rappels.

MaxTextSizeRecall pour la recherche hybride (préversion)

Ajoutez un objet de paramètre de requête hybridSearch pour spécifier le nombre maximal de documents rappelés à l’aide de requêtes de texte dans une recherche hybride (texte et vecteur). La valeur par défaut est 1 000 documents. Avec ce paramètre, vous pouvez augmenter ou diminuer le nombre de résultats retournés dans des requêtes hybrides.

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

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

Pondération de vecteurs (préversion)

Ajoutez un paramètre de requête weight pour spécifier la pondération relative de chaque vecteur inclus dans les opérations de recherche. Cette fonctionnalité est particulièrement utile dans les requêtes complexes où deux jeux de résultats distincts ou plus doivent être combinés, comme dans les requêtes de recherche hybride ou multi-vecteurs.

Les pondérations sont utilisées lors du calcul des scores de fusion de classement réciproque de chaque document. Le calcul consiste à multiplier la valeur weight par le score de classement du document dans son jeu de résultats respectif.

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

    { 
      "vectorQueries": [ 
        { 
          "kind": "vector", 
          "vector": [1.0, 2.0, 3.0], 
          "fields": "my_vector_field", 
          "k": 10, 
          "weight": 0.5 
        } 
      ], 
      "search": "hello world" 
    } 

Étapes suivantes

Dans une prochaine étape, examinez des exemples de code de requête vectorielle en Python, C# ou JavaScript.