Partager 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.

Vous pouvez également utiliser Explorateur de recherche dans le Portail Azure si vous configurer un vectoriseur qui convertit des chaînes en incorporations.

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 et des API REST plus récentes en préversion ou un package bêta du kit de développement logiciel (SDK) Azure 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. Vérifiez la définition d’index d’une spécification des vectoriseurs.

Capture d’écran d’un paramètre du vectoriseur dans un index de recherche.

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=2024-05-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=2024-05-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)

La recherche voisine la plus proche retournant toujours les k voisins demandés, il est possible d’obtenir de nombreuses correspondances de score faible pour répondre aux exigences de nombre k sur les résultats de la recherche.

À l’aide des API REST 2024-05-01-préversion, vous pouvez à présent ajouter un paramètre de requête threshold pour exclure des résultats de recherche à faible score, en fonction d’un score minimal. Le filtrage se produit avant la fusion des résultats des différents ensembles de rappels.

Dans cet exemple, toutes les correspondances dont le score est inférieur à 0,8 sont exclues des résultats de recherche vectorielle, même si le nombre de résultats passe en dessous k.

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 
          } 
        }
      ]
    }

MaxTextSizeRecall pour la recherche hybride (préversion)

Les requêtes vectorielles sont souvent utilisées dans des constructions hybrides qui incluent des champs non vecteurs. Si vous découvrez que les résultats du classement BM25 sont sur ou sous-représentés dans les résultats d’une requête hybride, vous pouvez définir maxTextRecallSize pour augmenter ou diminuer les résultats du classement BM25 fournis pour le classement hybride.

Vous ne pouvez définir cette propriété que dans les requêtes hybrides qui incluent à la fois les composants « search » et « vectorQueries ».

Pour plus d’informations, consultez Set maxTextRecallSize – Créer une requête hybride.

Pondération de vecteurs (préversion)

Ajoutez un paramètre de requête weight pour spécifier le poids relatif de chaque requête vectorielle incluse dans les opérations de recherche. Cette valeur est utilisée lors de la combinaison des résultats de plusieurs listes de classement produites par deux requêtes vectorielles ou plus dans la même requête, ou à partir de la partie vectorielle d’une requête hybride.

La valeur par défaut est 1,0 et la valeur doit être un nombre positif supérieur à zéro.

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.

L’exemple suivant est une requête hybride avec deux chaînes de requête vectorielle et une chaîne de caractères. Les pondérations sont affectées aux requêtes vectorielles. La première requête est 0,5 ou la moitié de la pondération, ce qui réduit son importance dans la requête. La deuxième requête vectorielle est deux fois plus importante.

Les requêtes de texte n’ont aucun paramètre de pondération, mais vous pouvez augmenter ou diminuer leur importance en définissant 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_first_vector_field", 
          "k": 10, 
          "weight": 0.5 
        },
        { 
          "kind": "vector", 
          "vector": [4.0, 5.0, 6.0], 
          "fields": "my_second_vector_field", 
          "k": 10, 
          "weight": 2.0
        } 
      ], 
      "search": "hello world" 
    } 

Étapes suivantes

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