Créer un index vectoriel

Dans la Recherche Azure AI, un magasin de vecteurs a un schéma d’index qui définit des champs vectoriels et non vectoriels, une configuration vectorielle pour les algorithmes qui créent et compressent l’espace d’incorporation et les paramètres sur les définitions de champ vectoriel utilisées dans les demandes de requête.

L’API Créer ou mettre à jour un index crée le magasin de vecteurs. Procédez comme suit pour indexer les données vectorielles :

  • Définir un schéma avec des algorithmes vectoriels et une compression facultative
  • Ajouter des définitions de champs vectoriels
  • Charger des données prévectorisées en tant qu’étape distincte ou utiliser la vectorisation intégrée pour la segmentation et l’encodage des données pendant l’indexation

Cet article explique le flux de travail et utilise REST à des fins d’illustration. Une fois que vous avez compris le flux de travail de base, poursuivez avec les exemples de code du SDK Azure dans le dépôt azure-search-vector-samples pour obtenir des conseils sur l’utilisation de ces fonctionnalités dans le code de test et de production.

Conseil

Utilisez le Portail Azure pour créer un index vectoriel et essayer la segmentation et la vectorisation des données intégrées.

Prérequis

  • La Recherche Azure AI, dans n’importe quelle région et sur n’importe quel niveau. La plupart des services existants prennent en charge la recherche vectorielle. Pour les services créés avant janvier 2019, il existe un petit sous-ensemble qui ne peut pas créer d’index vectoriel. Dans ce cas, un nouveau service doit être créé. Si vous utilisez la vectorisation intégrée (ensembles de compétences qui appellent Azure AI), la Recherche Azure AI doit se trouver dans la même région qu’Azure OpenAI ou Azure AI services.

  • Des incorporations de vecteurs préexistantes, ou utilisez la vectorisation intégrée, où les modèles d’incorporation sont appelés à partir du pipeline d’indexation.

  • Vous devez connaître la limite de dimensions du modèle utilisé pour créer les incorporations. Les valeurs valides sont comprises entre 2 et 3 072 dimensions. Dans Azure OpenAI, pour text-embedding-ada-002, la longueur du vecteur numérique est 1536. Pour text-embedding-3-small ou text-embedding-3-large, la longueur du vecteur est de 3072.

  • Vous devez également connaître les métriques de similarité prises en charge. Pour Azure OpenAI, la similarité est calculée à l’aide de cosine.

  • Vous devez être familiarisé avec la création d'un index. Le schéma doit inclure un champ pour la clé de document, d’autres champs que vous souhaitez rechercher ou filtrer, ainsi que d’autres configurations pour les comportements nécessaires lors de l’indexation et des requêtes.

Préparer des documents pour l’indexation

Avant l’indexation, vous devez assembler un document qui comprend des champs de données vectorielles et non vectorielles. La structure du document doit être conforme au schéma de l'index.

Vérifiez que vos documents sont les suivants :

  1. Fournissez un champ ou une propriété de métadonnées qui identifie de manière unique chaque document. Tous les index de recherche nécessitent une clé de document. Pour répondre aux exigences de clé de document, un document source doit avoir un champ ou une propriété qui peut l’identifier de manière unique dans l’index. Ce champ source doit être mappé à un champ d’index de type Edm.String et key=true dans l’index de recherche.

  2. Fournir des données vectorielles (un tableau de nombres à virgule flottante en simple précision) dans les champs source.

    Les champs vectoriels contiennent un tableau généré par des modèles d’incorporation, une incorporation par champ, où le champ est un champ de niveau supérieur (qui ne fait pas partie d’un type imbriqué ou complexe). Pour l’intégration la plus simple, nous recommandons les modèles d’intégration dans Azure OpenAI, tels que text-embedding-ada-002 pour les documents textuels ou l’API REST Recherche d’images pour les images.

    Si vous pouvez prendre une dépendance vis-à-vis des indexeurs et des ensembles de compétences, envisagez d’utiliser la vectorisation intégrée qui encode des images et du contenu alphanumérique pendant l’indexation. Vos définitions de champ sont destinées aux champs vectoriels, mais les données sources peuvent être du texte ou des images, avec des tableaux de vecteurs créés lors de l’indexation.

  3. Fournissez d’autres champs avec du contenu alphanumérique lisible par l’homme pour la réponse à la requête et pour les scénarios de requête hybrides qui incluent la recherche en texte intégral ou le classement sémantique dans la même requête.

Votre index de recherche doit inclure des champs et du contenu pour tous les scénarios de requête que vous souhaitez prendre en charge. Supposons que vous souhaitez rechercher ou filtrer les noms de produits, les versions, les métadonnées ou les adresses. Dans ce cas, la recherche de similarité n’est pas particulièrement utile. La recherche par mot clé, la recherche géographique ou les filtres seraient un meilleur choix. Un index de recherche qui comprend une collection complète de données vectorielles et non vectorielles offre une flexibilité maximale pour la construction des requêtes et la composition de la réponse.

Un bref exemple d’une charge utile de documents qui comprend des champs vectoriels et non vectoriels est présenté dans la section charge des données vectorielles de cet article.

Ajouter une configuration de recherche vectorielle

Une configuration vectorielle spécifie les paramètres utilisés lors de l’indexation pour créer les informations sur les « plus proches voisins » parmi les nœuds du vecteur :

  • Hierarchical Navigable Small Worlds (HNSW)
  • Exhaustive KNN

Si vous choisissez HNSW sur un champ, vous pouvez opter pour un KNN exhaustif au moment de la requête. Mais l’autre direction ne fonctionne pas : si vous choisissez exhaustive, vous ne pouvez pas demander ultérieurement la recherche HNSW, car les structures de données supplémentaires qui activent la recherche approximative n’existent pas.

Une configuration vectorielle spécifie également des méthodes de quantification pour réduire la taille du vecteur :

  • Scalaire
  • Binaire (disponible uniquement dans les versions 2024-07-01 et ultérieures des packages SDK Azure)

Pour obtenir des instructions sur la migration vers la dernière version, consultez Mettre à jour l’API REST.

2024-07-01 est en disponibilité générale. Elle prend en charge une configuration vectorielle ayant :

  • vectorSearch.algorithms prennent en charge HNSW et KNN exhaustif.
  • vectorSearch.compressions prennent en charge la quantification scalaire et binaire, le suréchantillonnage et le reclassement avec des vecteurs d’origine.
  • vectorSearch.profiles fournissent plusieurs combinaisons de configurations des algorithmes et de la compression.

Veillez à avoir une stratégie pour vectoriser votre contenu. Nous vous recommandons la vectorisation intégrée et les vectoriseurs au moment de la requête pour l’encodage intégré.

  1. Utilisez l’API Créer ou mettre à jour l’index pour créer l’index.

  2. Ajoutez une section vectorSearch dans l’index qui spécifie les algorithmes de recherche utilisés pour créer l’espace d’incorporation.

     "vectorSearch": {
         "compressions": [
             {
                 "name": "scalar-quantization",
                 "kind": "scalarQuantization",
                 "rerankWithOriginalVectors": true,
                 "defaultOversampling": 10.0,
                     "scalarQuantizationParameters": {
                         "quantizedDataType": "int8"
                     }
             },
             {
                 "name": "binary-quantization",
                 "kind": "binaryQuantization",
                 "rerankWithOriginalVectors": true,
                 "defaultOversampling": 10.0,
             }
         ],
         "algorithms": [
             {
                 "name": "hnsw-1",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 4,
                     "efConstruction": 400,
                     "efSearch": 500,
                     "metric": "cosine"
                 }
             },
             {
                 "name": "hnsw-2",
                 "kind": "hnsw",
                 "hnswParameters": {
                     "m": 8,
                     "efConstruction": 800,
                     "efSearch": 800,
                     "metric": "hamming"
                 }
             },
             {
                 "name": "eknn",
                 "kind": "exhaustiveKnn",
                 "exhaustiveKnnParameters": {
                     "metric": "euclidean"
                 }
             }
    
         ],
         "profiles": [
           {
             "name": "vector-profile-hnsw-scalar",
             "compression": "scalar-quantization",
             "algorithm": "hnsw-1"
           }
         ]
     }
    

    Points essentiels :

    • Les noms de chaque configuration de compression, d’algorithme et de profil doivent être uniques pour son type dans l’index.

    • vectorSearch.compressions.kind peut avoir la valeur scalarQuantization ou binaryQuantization.

    • vectorSearch.compressions.rerankWithOriginalVectors utilise les vecteurs originaux non compressés pour recalculer la similarité et reclasser les meilleurs résultats renvoyés par la requête de recherche initiale. Les vecteurs non compressés existent dans l'index de recherche même si stored sont faux. Cette propriété est facultative. La valeur par défaut est true.

    • vectorSearch.compressions.defaultOversampling considère un ensemble plus large de résultats potentiels pour compenser la réduction des informations résultant de la quantification. La formule des résultats potentiels consiste en le k dans la requête, avec un multiplicateur de suréchantillonnage. Par exemple, si la requête spécifie un k de 5 et que le suréchantillonnage est de 20, alors la requête demande effectivement 100 documents à utiliser dans le reclassement, en utilisant le vecteur non compressé d'origine à cette fin. Seuls les résultats k les mieux classés sont renvoyés. Cette propriété est facultative. La valeur par défaut est 4.

    • vectorSearch.compressions.scalarQuantizationParameters.quantizedDataType doit être défini sur int8. Il s’agit du seul type de données primitif pris en charge pour le moment. Cette propriété est facultative. La valeur par défaut est int8.

    • vectorSearch.algorithms.kind sont "hnsw" ou "exhaustiveKnn". Il s’agit des algorithmes des plus proches voisins approximatifs (ANN) utilisés pour organiser le contenu vectoriel pendant l’indexation.

    • vectorSearch.algorithms.m est le nombre de liens bidirectionnels. La valeur par défaut est 4. La fourchette est comprise entre 4 et 10. Les valeurs inférieures doivent retourner moins de bruit dans les résultats.

    • vectorSearch.algorithms.efConstruction est le nombre de plus proches voisins utilisés lors de l’indexation. La valeur par défaut est 400. La plage est comprise entre 100 et 1,000.

    • "vectorSearch.algorithms.fSearch est le nombre de plus proches voisins utilisés lors de la recherche. La valeur par défaut est 500. La plage est comprise entre 100 et 1,000.

    • vectorSearch.algorithms.metric doit être « cosinus » si vous utilisez Azure OpenAI, sinon utilisez la métrique de similarité associée au modèle d’incorporation que vous utilisez. Les valeurs prises en charge sont cosine, dotProduct, euclidean, hamming (utilisé pour l’indexation des données binaires).

    • vectorSearch.profiles ajouter une couche d’abstraction pour accueillir des définitions plus riches. Un profil est défini dans vectorSearch, puis référencé par nom sur chaque champ vectoriel. Il s’agit d’une combinaison de configurations de compression et d’algorithme. Il s’agit de la propriété que vous affectez à un champ vectoriel, qui détermine les champs algorithme et compression.

Ajouter un champ vectoriel à la collection de champs

La collection de champs doit inclure un champ pour la clé de document, les champs vectoriels et tous les autres champs dont vous avez besoin pour les scénarios de recherche hybride.

Les champs vectoriels sont caractérisés par leur type de données, une propriété dimensions basée sur le modèle d’incorporation utilisé pour générer les vecteurs et un profil vectoriel.

2024-07-01 est en disponibilité générale.

  1. Utilisez l’index Créer ou mettre à jour pour créer l’index.

  2. Définissez un champ vectoriel avec les attributs suivants. Vous pouvez stocker un incorporation généré par champ. Pour chaque champ vectoriel :

    • type doit être un type de données vectorielle. Collection(Edm.Single) est le plus courant pour les modèles d’incorporation.
    • dimensions retourne le nombre de dimensions dans le modèle d’incorporation. Pour text-embedding-ada-002, c'est 1536.
    • vectorSearchProfile est le nom d’un profil défini ailleurs dans l’index.
    • searchable doit être true.
    • retrievable peut avoir la valeur « true » ou « false ». True retourne les vecteurs bruts (1536 d’entre eux) sous forme de texte brut et consomme de l’espace de stockage. Définissez la valeur true si vous transmettez un résultat vectoriel à une application en aval.
    • stored peut avoir la valeur « true » ou « false ». Il détermine si une copie supplémentaire de vecteurs est stockée pour la récupération. Pour plus d’informations, consultez Réduire la taille des vecteurs.
    • filterable, facetable, sortable doit être false.
  3. Si vous souhaitez appeler le préfiltrage ou le post-filtrage sur la requête vectorielle , ajoutez des champs non vectoriels filtrables à la collection, tels que « titre » avec filterable défini sur true.

  4. Ajoutez d’autres champs qui définissent la substance et la structure du contenu textuel que vous indexez. Au minimum, vous avez besoin d'une clé de document.

    Vous devez également ajouter des champs utiles à la requête ou à la réponse. L’exemple suivant montre des champs vectoriels pour le titre et le contenu (« titleVector », « contentVector ») équivalents aux vecteurs. Il fournit également des champs pour le contenu textuel équivalent (« titre », « contenu ») utile pour le tri, le filtrage et la lecture dans un résultat de recherche.

    L'exemple suivant montre la collection de champs :

    PUT https://my-search-service.search.windows.net/indexes/my-index?api-version=2024-07-01&allowIndexDowntime=true
    Content-Type: application/json
    api-key: {{admin-api-key}}
    {
        "name": "{{index-name}}",
        "fields": [
            {
                "name": "id",
                "type": "Edm.String",
                "key": true,
                "filterable": true
            },
            {
                "name": "title",
                "type": "Edm.String",
                "searchable": true,
                "filterable": true,
                "sortable": true,
                "retrievable": true
            },
            {
                "name": "titleVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": true,
                "stored": true,
                "dimensions": 1536,
                "vectorSearchProfile": "vector-profile-1"
            },
            {
                "name": "content",
                "type": "Edm.String",
                "searchable": true,
                "retrievable": true
            },
            {
                "name": "contentVector",
                "type": "Collection(Edm.Single)",
                "searchable": true,
                "retrievable": false,
                "stored": false,
                "dimensions": 1536,
                "vectorSearchProfile": "vector-profile-1"
            }
        ],
        "vectorSearch": {
            "algorithms": [
                {
                    "name": "hnsw-1",
                    "kind": "hnsw",
                    "hnswParameters": {
                        "m": 4,
                        "efConstruction": 400,
                        "efSearch": 500,
                        "metric": "cosine"
                    }
                }
            ],
            "profiles": [
                {
                    "name": "vector-profile-1",
                    "algorithm": "hnsw-1"
                }
            ]
        }
    }
    

Charger des données vectorielles pour l’indexation

Le contenu que vous fournissez pour l'indexation doit être conforme au schéma de l'index et inclure une chaîne de valeur unique pour la clé du document. Les données prévectorisées sont chargées dans un ou plusieurs champs vectoriels, qui peuvent coexister avec d’autres champs contenant du contenu alphanumérique.

Vous pouvez utiliser méthodologies push ou pull pour l’ingestion de données.

Utilisez Documents – Index pour charger des données vectorielles et non vectorielles dans un index. Les API d’envoi (push) pour l’indexation sont identiques dans toutes les versions stables et préliminaires. Utilisez l’une des API suivantes pour charger des documents :

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

{
    "value": [
        {
            "id": "1",
            "title": "Azure App Service",
            "content": "Azure App Service is a fully managed platform for building, deploying, and scaling web apps. You can host web apps, mobile app backends, and RESTful APIs. It supports a variety of programming languages and frameworks, such as .NET, Java, Node.js, Python, and PHP. The service offers built-in auto-scaling and load balancing capabilities. It also provides integration with other Azure services, such as Azure DevOps, GitHub, and Bitbucket.",
            "category": "Web",
            "titleVector": [
                -0.02250031754374504,
                 . . . 
                        ],
            "contentVector": [
                -0.024740582332015038,
                 . . .
            ],
            "@search.action": "upload"
        },
        {
            "id": "2",
            "title": "Azure Functions",
            "content": "Azure Functions is a serverless compute service that enables you to run code on-demand without having to manage infrastructure. It allows you to build and deploy event-driven applications that automatically scale with your workload. Functions support various languages, including C#, F#, Node.js, Python, and Java. It offers a variety of triggers and bindings to integrate with other Azure services and external services. You only pay for the compute time you consume.",
            "category": "Compute",
            "titleVector": [
                -0.020159931853413582,
                . . .
            ],
            "contentVector": [
                -0.02780858241021633,
                 . . .
            ],
            "@search.action": "upload"
        }
        . . .
    ]
}

Vérifiez le contenu vectoriel de votre index

À des fins de validation, vous pouvez interroger l’index à l’aide de l’Explorateur de recherche sur le Portail Azure ou d’un appel d’API REST. Étant donné qu’Azure AI Search ne peut pas convertir un vecteur en texte lisible par l’homme, essayez de renvoyer des champs du même document qui fournissent des preuves de la correspondance. Par exemple, si la requête vectorielle cible le champ « titleVector », vous pouvez sélectionner « titre » pour les résultats de la recherche.

Les champs doivent être attribués comme « récupérables » pour être inclus dans les résultats.

  • Passez en revue les index dans Gestion de la recherche>Index pour afficher toutes les tailles d’index et la taille de l’index vectoriel. Une taille d’index vectoriel positif indique que des vecteurs sont présents.

  • Utilisez l’Explorateur de recherche pour interroger un index. L’Explorateur de recherche a deux vues : la vue Requête (par défaut) et la vue JSON.

    • Définissez Options de requête>Masquer les valeurs de vecteur dans les résultats de la recherche pour obtenir des résultats plus lisibles.

    • Utilisez la vue JSON pour les requêtes vectorielles. Vous pouvez coller une définition JSON de la requête vectorielle que vous souhaitez exécuter, ou utiliser la conversion de texte en vecteur ou d’image en vecteur intégrée si votre index a une affectation de vectoriseur. Pour plus d’informations sur la recherche d’images, consultez Démarrage rapide : Rechercher des images dans l’Explorateur de recherche.

    • Utilisez la vue Requête par défaut pour une confirmation rapide que l’index contient des vecteurs. L’affichage de requête est destiné à la recherche en texte intégral. Bien que vous ne puissiez pas l’utiliser pour les requêtes vectorielles, vous pouvez envoyer une recherche vide (search=*) pour rechercher du contenu. Le contenu de tous les champs, y compris les champs vectoriels, est retourné sous forme de texte brut.

    • Pour plus d’informations, consultez Créer une requête vectorielle.

Mettre à jour un magasin vectoriel

Pour mettre à jour un magasin vectoriel, modifiez le schéma et, si nécessaire, rechargez les documents pour remplir de nouveaux champs. Les API pour les mises à jour de schéma incluent Create or Update Index (REST), CreateOrUpdateIndex dans le SDK Azure pour .NET, create_or_update_index dans le SDK Azure pour Python et des méthodes similaires dans d’autres SDK Azure.

L’aide standard pour la mise à jour d’un index est disponible dans Mettre à jour ou régénérer un index.

Les points clés sont les suivants :

  • La suppression et la régénération sont souvent requises pour les mises à jour et la suppression de champs existants.

  • Toutefois, vous pouvez mettre à jour un schéma existant avec les modifications suivantes, sans aucune régénération requise :

    • Ajouter de nouveaux champs à une collection de champs.
    • Ajouter de nouvelles configurations vectorielles (affectées à de nouveaux champs, mais pas à des champs existants déjà vectorisés).
    • Modifier « retrievable » (les valeurs sont true ou false) sur un champ existant. Les champs vectoriels doivent pouvoir faire l’objet d’une recherche et être récupérables. Toutefois, si vous souhaitez désactiver l’accès à un champ vectoriel dans des situations où la suppression et la régénération ne sont pas réalisables, vous pouvez définir retrievable sur false.

Étapes suivantes

À l’étape suivante, nous vous recommandons d' données de vecteur de requête dans un index de recherche.

Les exemples de code du dépôt azure-search-vector illustrent des workflows de bout en bout qui incluent la définition de schéma, la vectorisation, l’indexation et les requêtes.

Le code de démonstration est disponible en Python, C# et JavaScript.