Mettre en forme les résultats de recherche ou modifier la composition des résultats de recherche dans la Recherche Azure AI
Cet article explique la composition des résultats de recherche et la manière de les mettre en forme pour qu’ils s’adaptent à vos scénarios. Les résultats de recherche sont retournés dans une réponse à la requête. La forme de la réponse est déterminée par les paramètres de la requête elle-même. Ces paramètres sont les suivants :
- Nombre de correspondances trouvées dans l’index (
count
) - Nombre de correspondances retournées dans la réponse (50 par défaut, configurable par
top
) ou par page (skip
ettop
) - Score de recherche pour chaque résultat, utilisé pour le classement (
@search.score
) - Champs inclus dans les résultats de la recherche (
select
) - Logique de tri (
orderby
) - Mise en surbrillance des termes dans un résultat, en mettant en correspondance la totalité ou une partie du terme dans le corps
- Éléments facultatifs du classeur sémantique (
answers
en haut,captions
pour chaque correspondance)
Les résultats de la recherche peuvent inclure des champs de niveau supérieur, mais la plus grande partie de la réponse consiste à faire correspondre des documents dans un tableau.
Clients et API pour définir la réponse à la requête
Vous pouvez utiliser les clients suivants pour configurer une réponse à une requête :
- Explorateur de recherche dans le Portail Azure, à l’aide d’une vue JSON qui permet de spécifier tous les paramètres pris en charge
- Documents – POST (API REST)
- Méthode SearchClient.Search (Kit de développement logiciel (SDK) pour .NET)
- Méthode SearchClient.Search (Kit de développement logiciel (SDK) pour Python)
- Méthode SearchClient.Search (Kit de développement logiciel (SDK) pour JavaScript)
- Méthode SearchClient.Search (Kit de développement logiciel (SDK) pour Java)
Composition des résultats
Les résultats sont principalement présentés sous forme de tableaux, composés de champs comprenant tous les champs retrievable
ou limités aux seuls champs spécifiés dans le paramètre select
. Les lignes sont les documents correspondants, généralement classés par ordre de pertinence, sauf si votre logique de requête exclut le classement par pertinence.
Vous pouvez choisir les champs qui se trouvent dans les résultats de la recherche. Bien qu’un document de recherche puisse avoir un grand nombre de champs, en général, seuls quelques-uns sont nécessaires pour représenter chaque document dans les résultats. Sur une demande de requête, ajoutez select=<field list>
pour spécifier les champs retrievable
qui doivent apparaître dans la réponse.
Choisissez les champs qui distinguent et différencient les documents, en fournissant suffisamment d’informations pour inviter l’utilisateur à cliquer sur le document. Sur un site d’e-commerce, il peut s’agir d’un nom de produit, d’une description, d’une couleur, d’une taille, d’un prix et d’une évaluation. Pour l’exemple intégré hotels-sample-index, il peut s’agir des champs « select » dans l’exemple suivant :
POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
"search": "sandy beaches",
"select": "HotelId, HotelName, Description, Rating, Address/City",
"count": true
}
Conseils en cas de résultats inattendus
Parfois, la sortie de requête n’est pas ce que vous attendez à voir. Par exemple, vous constaterez peut-être que certains résultats semblent être des doublons, ou qu’un résultat qui devrait apparaître près du haut est positionné plus bas dans les résultats. Quand les résultats de requête sont inattendus, vous pouvez essayer ces modifications de requête pour voir si les résultats s’améliorent :
Remplacez
searchMode=any
(valeur par défaut) parsearchMode=all
pour exiger des correspondances sur tous les critères plutôt que sur un seul d’entre eux. Cela s’applique particulièrement quand des opérateurs booléens sont inclus dans la requête.Expérimentez différents analyseurs lexicaux ou analyseurs personnalisés pour déterminer s’ils modifient le résultat de la requête. L’analyseur par défaut fractionne les mots avec des tirets et réduit les mots aux formes racines, ce qui améliore généralement la robustesse d’une réponse de requête. Toutefois, si vous devez conserver les tirets ou si des chaînes incluent des caractères spéciaux, vous devrez peut-être configurer des analyseurs personnalisés pour vous assurer que l’index contient des jetons au format approprié. Pour plus d’informations, consultez Recherche de termes partiels et modèles avec des caractères spéciaux (traits d’union, caractères génériques, expressions régulières, modèles).
Comptage des correspondances
Le paramètre count
retourne le nombre de documents dans l’index considérés comme correspondant à la requête. Pour retourner le nombre, ajoutez count=true
à la demande de requête. Aucune valeur maximale n’est imposée par le service de recherche. En fonction de la requête et du contenu de vos documents, le nombre peut être aussi élevé que le nombre de documents dans l’index.
Le nombre est précis quand l’index est stable. Si le système ajoute, met à jour ou supprime activement des documents, le comptage est approximatif et exclut les documents qui ne sont pas entièrement indexés.
Le nombre ne sera pas affecté par la maintenance de routine ou d’autres charges de travail sur le service de recherche. Toutefois, si vous disposez de plusieurs partitions et d’un seul réplica, des fluctuations à court terme peuvent se produire concernant le nombre de documents (plusieurs minutes) à mesure que les partitions sont redémarrées.
Conseil
Pour vérifier les opérations d’indexation, vous pouvez confirmer que l’index contient le nombre de documents attendu en ajoutant count=true
à une requête de recherche search=*
vide. Le résultat correspond au nombre total de documents dans votre index.
Quand vous testez la syntaxe de requête, count=true
peut rapidement déterminer si vos modifications retournent des résultats supérieurs ou inférieurs, ce qui peut être utile.
Nombre de résultats dans la réponse
La Recherche Azure AI utilise la pagination côté serveur pour éviter que les requêtes ne récupèrent trop de documents à la fois. Les paramètres de requête qui déterminent le nombre de résultats dans une réponse sont top
et skip
.
top
correspond au nombre de résultats de recherche dans une page.
skip
est un intervalle de top
, et indique au moteur de recherche le nombre de résultats à ignorer avant d’obtenir la série suivante.
La taille de page par défaut est de 50, tandis que la taille de page maximale est de 1000. Si vous spécifiez une valeur supérieure à 1000 et qu’il y a plus de 1000 résultats dans votre index, seuls les 1000 premiers résultats sont retournés. Si le nombre de résultats dépasse la taille de la page, la réponse inclut des informations pour récupérer la page de résultats suivante. Par exemple :
"@odata.nextLink": "https://contoso-search-eastus.search.windows.net/indexes/realestate-us-sample-index/docs/search?api-version=2024-07-01"
Les meilleures correspondances sont déterminées par le score de recherche, en supposant que la requête est une recherche en texte intégral ou sémantique. Dans le cas contraire, les premières correspondances sont classées dans un ordre arbitraire pour les requêtes avec correspondance exacte (où l’uniforme @search.score=1.0
indique un classement arbitraire).
Définissez top
pour remplacer la valeur par défaut de 50. Dans les API de préversion plus récentes, si vous utilisez une requête hybride, vous pouvez spécifier maxTextRecallSize pour retourner jusqu’à 10 000 documents.
Pour contrôler la pagination de tous les documents retournés dans un jeu de résultats, utilisez top
et skip
ensemble. Cette requête retourne le premier jeu de 15 documents correspondants ainsi qu’un décompte du nombre total de correspondances.
POST https://contoso-search-eastus.search.windows.net/indexes/realestate-us-sample-index/docs/search?api-version=2024-07-01
{
"search": "condos with a view",
"count": true,
"top": 15,
"skip": 0
}
Cette requête retourne la deuxième série, en sautant les 15 premières pour obtenir les 15 suivantes (16 à 30) :
POST https://contoso-search-eastus.search.windows.net/indexes/realestate-us-sample-index/docs/search?api-version=2024-07-01
{
"search": "condos with a view",
"count": true,
"top": 15,
"skip": 15
}
Il n’est pas garanti que les résultats des requêtes paginées soient stables si l’index sous-jacent est modifié. La pagination modifie la valeur de skip
pour chaque page, mais chaque requête est indépendante et opère sur l’affichage actuel des données telles qu’elles existent dans l’index au moment de la requête. En d’autres termes, il n’y a aucune mise en cache ni capture instantanée des résultats, comme c’est le cas dans une base de données à usage général.
Voici un exemple de la façon dont vous pouvez obtenir des doublons. Imaginons un index avec quatre documents :
{ "id": "1", "rating": 5 }
{ "id": "2", "rating": 3 }
{ "id": "3", "rating": 2 }
{ "id": "4", "rating": 1 }
Supposons à présent que vous souhaitiez que les résultats soient retournés par deux, classés par évaluation. Vous exécuterez cette requête pour obtenir la première page des résultats, $top=2&$skip=0&$orderby=rating desc
, et vous obtenez les résultats suivants :
{ "id": "1", "rating": 5 }
{ "id": "2", "rating": 3 }
Sur le service, supposez qu’un cinquième document est ajouté à l’index entre les appels de requête : { "id": "5", "rating": 4 }
. Peu de temps après, vous exécutez une requête pour extraire la deuxième page, $top=2&$skip=2&$orderby=rating desc
, et vous obtenez ces résultats :
{ "id": "2", "rating": 3 }
{ "id": "3", "rating": 2 }
Notez que le document 2 est extrait 2 fois. Cela est dû au fait que le nouveau document 5 a une plus grande valeur d’évaluation. Il est donc trié avant le document 2 et atterrit sur la première page. Bien que ce comportement puisse être inattendu, c’est généralement ainsi qu’un moteur de recherche se comporte.
Parcourir un grand nombre de résultats
Une autre technique de pagination consiste à utiliser un ordre de tri et un filtre de plage comme solution de contournement pour skip
.
Dans cette solution de contournement, un tri et un filtre sont appliqués à un champ d’ID de document ou à un autre champ qui est unique pour chaque document. Le champ unique doit avoir une attribution filterable
et sortable
dans l’index de recherche.
Envoyez une requête pour obtenir une page complète de résultats triés.
POST /indexes/good-books/docs/search?api-version=2024-07-01 { "search": "divine secrets", "top": 50, "orderby": "id asc" }
Choisissez le dernier résultat renvoyé par la requête de recherche. L’exemple de résultat indiqué ici a seulement la valeur ID.
{ "id": "50" }
Utilisez cette valeur ID dans une requête de plage pour récupérer la page suivante des résultats. Ce champ ID doit avoir des valeurs uniques, sinon la pagination peut contenir des résultats en double.
POST /indexes/good-books/docs/search?api-version=2024-07-01 { "search": "divine secrets", "top": 50, "orderby": "id asc", "filter": "id ge 50" }
La pagination se termine quand la requête renvoie zéro résultat.
Remarque
Les attributs filterable
et sortable
peuvent uniquement être activés lorsqu’un champ est ajouté pour la première fois à un index (ils ne peuvent pas être activés pour un champ existant).
Classement des résultats
Dans une requête de recherche en texte intégral, les résultats peuvent être classés selon :
- un score de recherche
- un score de reclassement sémantique
- un ordre de tri sur un champ
sortable
Vous pouvez également améliorer toutes les correspondances trouvées dans des champs spécifiques en ajoutant un profil de score.
Trier par score de recherche
Pour les requêtes de recherche en texte intégral, les résultats sont automatiquement classés par un score de recherche à l’aide d’un algorithme BM25, calculé en fonction de la fréquence des termes, de la longueur du document et de la longueur moyenne du document.
Sur les services plus anciens, la plage @search.score
est soit non délimitée, soit comprise entre 0 et 1,00 (non inclus).
Pour les deux algorithmes, un @search.score
égal à 1,00 indique un jeu de résultats non notés ou non classés. Le score de 1,0 est uniforme pour tous les résultats. Des résultats sans score se produisent quand le formulaire de requête est une recherche approximative, des requêtes Regex ou de caractères génériques, ou une recherche vide (search=*
). Si vous devez imposer une structure de classement sur des résultats sans score, vous pouvez utiliser une expression orderby
pour atteindre cet objectif.
Trier avec le reclassement sémantique
Si vous utilisez le classeur sémantique, le @search.rerankerScore
détermine l’ordre de tri de vos résultats.
L’intervalle @search.rerankerScore
est compris entre 1 et 4,00, où un score plus élevé indique une correspondance sémantique plus forte.
Ordonner avec orderby
Si un tri cohérent est une exigence de l’application, vous pouvez définir une expression orderby
sur un champ. Seuls les champs qui sont indexés en tant que « triables » peuvent être utilisés pour trier les résultats.
Les champs couramment utilisés dans orderby
incluent les champs d’évaluation, de date et d’emplacement. Le filtrage par emplacement nécessite que l’expression de filtre appelle la geo.distance()
fonction , en plus du nom de champ.
Les champs numériques (Edm.Double
, Edm.Int32
, Edm.Int64
) sont triés dans l’ordre numérique (par exemple, 1, 2, 10, 11, 20).
Les champs de type chaîne (Edm.String
, Edm.ComplexType
sous-champs) sont triés selon l'ordre ASCII ou l'ordre Unicode, en fonction de la langue.
Le contenu numérique des champs de chaîne est trié par ordre alphabétique (1, 10, 11, 2, 20).
Les chaînes majuscules sont triées avant la minuscule (APPLE, Apple, BANANA, Banana, Apple, apple, banana). Vous pouvez affecter une normalisation de texte pour prétraiter le texte avant le tri pour modifier ce comportement. L’utilisation du générateur de jetons en minuscules sur un champ n’a pas d’effet sur le comportement de tri, car la Recherche Azure AI effectue le tri sur une copie non analysée du champ.
Les chaînes qui commencent par des signes diacritiques apparaissent en dernier (Äpfel, Öffnen, Üben).
Améliorer la pertinence avec un profil de score
Une autre approche qui favorise la cohérence consiste à utiliser un profil de score personnalisé. Les profils de scoring vous permettent de mieux contrôler le classement des éléments dans les résultats de recherche, avec la possibilité d’augmenter le nombre de correspondances trouvées dans des champs spécifiques. La logique de score supplémentaire peut aider à surmonter les différences mineures entre les réplicas, car les scores de recherche pour chaque document sont plus éloignés les uns des autres. Nous vous recommandons d’utiliser l’algorithme de classement pour cette approche.
Mise en surbrillance des correspondances
La mise en surbrillance des correspondances fait référence à la mise en forme de texte (par exemple, caractères gras ou surlignage jaune) appliquée au terme correspondant dans un résultat, ce qui facilite le repérage de l’occurrence. La mise en surbrillance est utile pour des champs de contenu longs, comme un champ de description, où la correspondance n’est pas immédiatement évidente.
Notez que la mise en surbrillance est appliquée à des termes individuels. Il n’existe pas de fonctionnalité de mise en évidence pour le contenu d’un champ entier. Si vous souhaitez mettre en surbrillance toute une expression, vous devez fournir les termes correspondants (ou l’expression correspondante) dans une chaîne de requête entre guillemets. Cette technique est décrite plus loin dans cette section.
Des instructions pour la mise en surbrillance des correspondances sont fournies dans la demande de requête. Les requêtes qui déclenchent une extension de requête dans le moteur, telles que les recherches floues ou par caractères génériques, offrent une prise en charge limitée de la mise en surbrillance des correspondances.
Conditions de mise en surbrillance des correspondances
- Les champs doivent être de type
Edm.String
ouCollection(Edm.String)
- Les champs doivent être attribués à
searchable
Spécifier la mise en évidence dans la requête
Pour retourner des termes mis en évidence, vous devez inclure le paramètre « highlight » dans la requête. Le paramètre est défini sur une liste de champs délimités par des virgules.
Par défaut, le format de marquage est <em>
, mais vous pouvez remplacer la balise à l’aide de paramètres highlightPreTag
et highlightPostTag
. Votre code client gère la réponse (par exemple, en appliquant une police en gras ou un arrière-plan jaune).
POST /indexes/good-books/docs/search?api-version=2024-07-01
{
"search": "divine secrets",
"highlight": "title, original_title",
"highlightPreTag": "<b>",
"highlightPostTag": "</b>"
}
Par défaut, la Recherche Azure AI renvoie jusqu’à cinq éléments en surbrillance par champ. Vous pouvez ajuster ce nombre en ajoutant un tiret suivi d’un entier. Par exemple, "highlight": "description-10"
retourne jusqu’à 10 termes mis en surbrillance sur le contenu correspondant dans le champ de description.
Résultats mis en évidence
Lorsque la mise en surbrillance est ajoutée à la requête, la réponse inclut un @search.highlights
pour chaque résultat afin que votre code d’application puisse cibler cette structure. La liste des champs spécifiés pour la « mise en évidence » est incluse dans la réponse.
Dans une recherche par mot clé, chaque terme est analysé séparément. Une requête portant sur « divine secrets » retourne les correspondances sur tout document contenant l’un ou l’autre terme.
Mise en évidence de recherche de mot clé
Dans un champ mis en évidence, la mise en forme est appliquée aux termes entiers. Par exemple, sur une correspondance par rapport à « The Divine Secrets of the Ya-Ya Sisterhood », la mise en forme est appliquée séparément à tous les termes, même s’ils sont consécutifs.
"@odata.count": 39,
"value": [
{
"@search.score": 19.593246,
"@search.highlights": {
"original_title": [
"<em>Divine</em> <em>Secrets</em> of the Ya-Ya Sisterhood"
],
"title": [
"<em>Divine</em> <em>Secrets</em> of the Ya-Ya Sisterhood"
]
},
"original_title": "Divine Secrets of the Ya-Ya Sisterhood",
"title": "Divine Secrets of the Ya-Ya Sisterhood"
},
{
"@search.score": 12.779835,
"@search.highlights": {
"original_title": [
"<em>Divine</em> Madness"
],
"title": [
"<em>Divine</em> Madness (Cherub, #5)"
]
},
"original_title": "Divine Madness",
"title": "Divine Madness (Cherub, #5)"
},
{
"@search.score": 12.62534,
"@search.highlights": {
"original_title": [
"Grave <em>Secrets</em>"
],
"title": [
"Grave <em>Secrets</em> (Temperance Brennan, #5)"
]
},
"original_title": "Grave Secrets",
"title": "Grave Secrets (Temperance Brennan, #5)"
}
]
Mise en évidence de recherche d’expression
La mise en forme des termes entiers s’applique même à une recherche d’expression, où plusieurs termes sont placés entre guillemets. L’exemple suivant est la même requête, sauf que « divine search » est soumis en tant qu’expression entre guillemets (certains clients REST exigent la mise en échappement des guillemets intérieurs avec une barre oblique inverse \"
) :
POST /indexes/good-books/docs/search?api-version=2024-07-01
{
"search": "\"divine secrets\"",
"select": "title,original_title",
"highlight": "title",
"highlightPreTag": "<b>",
"highlightPostTag": "</b>",
"count": true
}
Comme le critère a maintenant les deux termes, une seule correspondance est trouvée dans l’index de recherche. La réponse à la requête précédente ressemble à ceci :
{
"@odata.count": 1,
"value": [
{
"@search.score": 19.593246,
"@search.highlights": {
"title": [
"<b>Divine</b> <b>Secrets</b> of the Ya-Ya Sisterhood"
]
},
"original_title": "Divine Secrets of the Ya-Ya Sisterhood",
"title": "Divine Secrets of the Ya-Ya Sisterhood"
}
]
}
Mise en évidence d’expression sur des services plus anciens
Les services de recherche qui ont été créés avant le 15 juillet 2020 implémentent une expérience de mise en évidence différente pour les requêtes d’expressions.
Pour les exemples suivants, imaginez une chaîne de requête incluant l’expression « super bowl » entre guillemets. Avant juillet 2020, tous les termes d’expression étaient mis en surbrillance :
"@search.highlights": {
"sentence": [
"The <em>super</em> <em>bowl</em> is <em>super</em> awesome with a <em>bowl</em> of chips"
]
Pour les services de recherche créés après juillet 2020, seules les phrases correspondant à la requête complète sont renvoyées dans @search.highlights
:
"@search.highlights": {
"sentence": [
"The <em>super</em> <em>bowl</em> is super awesome with a bowl of chips"
]
Étapes suivantes
Pour générer rapidement une page de recherche pour votre client, envisagez les options suivantes :
Créer une application de démo, dans le Portail Azure, crée une page HTML avec une barre de recherche, une navigation à facettes et une zone de miniatures si vous avez des images.
Le tutoriel Ajouter la recherche sur une application ASP.NET Core (MVC) contient un exemple de code permettant de générer un client fonctionnel.
Ajouter une recherche aux applications web est un tutoriel C# et un exemple de code qui utilise les bibliothèques JavaScript React pour l’expérience utilisateur. L’application est déployée à l’aide d’Azure Static Web Apps et implémente la pagination.