Partager via


Tutoriel : Vectoriser à partir d’une disposition de document structurée

Azure AI Search peut extraire et indexer à la fois le texte et les images à partir de documents PDF stockés dans le stockage Blob Azure. Ce tutoriel vous montre comment créer un pipeline d’indexation modal qui segmente les données en fonction de la structure de document et utilise des incorporations modales pour vectoriser du texte et des images à partir du même document. Les images rognées sont stockées dans une base de connaissances, et le texte et le contenu visuel sont vectorisés et ingérés dans un index pouvant faire l’objet d’une recherche. La segmentation est basée sur le modèle de disposition d'Azure Document Intelligence dans les outils Foundry qui reconnaît la structure du document.

Dans ce tutoriel, vous utilisez :

  • Document PDF de 36 pages qui combine du contenu visuel enrichi, tel que des graphiques, des infographies et des pages numérisées, avec du texte traditionnel.

  • Un indexeur et un ensemble de compétences pour créer un pipeline d’indexation qui inclut l’enrichissement par IA par le biais de compétences.

  • Compétence de disposition du document pour extraire du texte et des images normalisées avec ses locationMetadata à partir de différents documents, tels que les numéros de page ou les régions englobantes.

  • La fonctionnalité d’incorporations multimodales Azure Vision pour vectoriser du texte et des images.

  • Index de recherche configuré pour stocker du texte extrait et du contenu d’image. Certains contenus sont vectorisés pour la recherche de similarité basée sur des vecteurs.

Prerequisites

  • Ressource Microsoft Foundry. Cette ressource permet d’accéder à la fois au modèle d’incorporation modale Azure Vision et au modèle de disposition Azure Document Intelligence utilisé par les compétences de ce didacticiel. Vous devez utiliser une ressource Foundry pour accéder à ces ressources par ensemble de compétences.

  • Recherche Azure AI. Configurez votre service de recherche pour le contrôle d’accès en fonction du rôle et une identité managée. Votre service doit se trouver sur le niveau De base ou supérieur. Ce tutoriel n’est pas pris en charge sur le niveau Gratuit.

  • Stockage Azure, utilisé pour stocker des exemples de données et pour créer une base de connaissances.

  • Visual Studio Code avec un client REST.

Limitations

Préparer des données

Les instructions suivantes s’appliquent au Stockage Azure qui fournit les exemples de données et héberge également la base de connaissances. Une identité de service de recherche a besoin d’un accès en lecture au Stockage Azure pour récupérer les exemples de données, et elle a besoin d’un accès en écriture pour créer la base de connaissances. Le service de recherche crée le conteneur pour les images recadrées pendant le traitement des compétences, en utilisant le nom que vous fournissez dans une variable d’environnement.

  1. Téléchargez l’exemple de pdf suivant : sustainable-ai-pdf

  2. Dans Stockage Azure, créez un conteneur nommé durable-ai-pdf.

  3. Chargez l’exemple de fichier de données.

  4. Créez des attributions de rôles et spécifiez une identité managée dans une chaîne de connexion :

    1. Attribuez le rôle Storage Blob Data Reader pour la récupération des données par l’indexeur. Attribuez Storage Blob Data Contributor et Storage Table Data Contributor pour créer et charger la base de connaissances. Vous pouvez utiliser une identité managée affectée par le système ou une identité managée affectée par l’utilisateur pour votre attribution de rôle de service de recherche.

    2. Pour les connexions effectuées à l’aide d’une identité managée affectée par le système, obtenez une chaîne de connexion qui contient un ResourceId, sans clé de compte ni mot de passe. ResourceId doit inclure l’ID d’abonnement du compte de stockage, le groupe de ressources du compte de stockage et le nom du compte de stockage. La chaîne de connexion est similaire à l’exemple suivant :

      "credentials" : { 
          "connectionString" : "ResourceId=/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/MY-DEMO-RESOURCE-GROUP/providers/Microsoft.Storage/storageAccounts/MY-DEMO-STORAGE-ACCOUNT/;" 
      }
      
    3. Pour les connexions effectuées à l’aide d’une identité managée affectée par l’utilisateur, obtenez une chaîne de connexion qui contient un ResourceId, sans clé de compte ni mot de passe. ResourceId doit inclure l’ID d’abonnement du compte de stockage, le groupe de ressources du compte de stockage et le nom du compte de stockage. Fournissez une identité à l’aide de la syntaxe indiquée dans l’exemple suivant. Définissez userAssignedIdentity sur l’identité managée affectée par l’utilisateur. La chaîne de connexion est similaire à l’exemple suivant :

      "credentials" : { 
          "connectionString" : "ResourceId=/subscriptions/00000000-0000-0000-0000-00000000/resourceGroups/MY-DEMO-RESOURCE-GROUP/providers/Microsoft.Storage/storageAccounts/MY-DEMO-STORAGE-ACCOUNT/;" 
      },
      "identity" : { 
          "@odata.type": "#Microsoft.Azure.Search.DataUserAssignedIdentity",
          "userAssignedIdentity" : "/subscriptions/00000000-0000-0000-0000-00000000/resourcegroups/MY-DEMO-RESOURCE-GROUP/providers/Microsoft.ManagedIdentity/userAssignedIdentities/MY-DEMO-USER-MANAGED-IDENTITY" 
      }
      

Préparer des modèles

Ce tutoriel suppose que vous disposez d’une ressource Foundry existante à travers laquelle la compétence appelle le modèle d'intégration Azure Vision multimodal 4.0. Le service de recherche se connecte au modèle pendant le traitement de l’ensemble de compétences à l’aide de son identité managée. Cette section fournit des conseils et des liens pour l’attribution de rôles pour l’accès autorisé.

La même attribution de rôle est également utilisée pour accéder au modèle de disposition Azure Document Intelligence via une ressource Foundry.

  1. Connectez-vous au portail Azure (et non au portail Foundry) et recherchez la ressource Foundry. Assurez-vous qu’elle se trouve dans une région qui fournit l’API modale 4.0 et le modèle de disposition Azure Document Intelligence.

  2. Sélectionnez Contrôle d’accès (IAM) .

  3. Sélectionnez Ajouter , puis Ajouter une attribution de rôle.

  4. Recherchez Cognitive Services User puis sélectionnez-le.

  5. Choisissez Identité managée , puis attribuez votre identité managée de service de recherche.

Configurer votre fichier REST

Pour ce tutoriel, votre connexion de client REST locale à Azure AI Search nécessite un point de terminaison et une clé API. Vous pouvez obtenir ces valeurs à partir du Portail Azure. Pour obtenir d’autres méthodes de connexion, consultez Se connecter à un service de recherche.

Pour les connexions authentifiées qui se produisent pendant le traitement de l’indexeur et de l’ensemble de compétences, le service de recherche utilise les attributions de rôles que vous avez définies précédemment.

  1. Démarrez Visual Studio Code et créez un fichier.

  2. Fournissez des valeurs pour les variables utilisées dans la requête. Pour @storageConnection, assurez-vous que votre chaîne de connexion n’a pas de points-virgules ou de guillemets de fin. Pour @imageProjectionContainer, fournissez un nom de conteneur unique dans le stockage d’objets blob. Azure AI Search crée ce conteneur pour vous pendant le traitement des compétences.

    @searchUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @searchApiKey = PUT-YOUR-ADMIN-API-KEY-HERE
    @storageConnection = PUT-YOUR-STORAGE-CONNECTION-STRING-HERE
    @cognitiveServicesUrl = PUT-YOUR-AZURE-AI-FOUNDARY-ENDPOINT-HERE
    @modelVersion = 2023-04-15
    @imageProjectionContainer=sustainable-ai-pdf-images
    
  3. Enregistrez le fichier en utilisant une extension de fichier .rest ou .http. Pour obtenir de l’aide sur le client REST, consultez Démarrage rapide : Recherche en texte intégral à l’aide de REST.

Pour obtenir le point de terminaison Azure AI Search et la clé API :

  1. Connectez-vous au Portail Azure, accédez à la page Vue d’ensemble du service de recherche et copiez l’URL. Voici un exemple de point de terminaison : https://mydemo.search.windows.net.

  2. Sous Paramètres>Clés, copiez une clé d’administration. Les clés d’administration sont utilisées pour ajouter, modifier et supprimer des objets. Il existe deux clés d’administration interchangeables. Copiez l’une ou l’autre.

    Capture d’écran de l’URL et des clés API dans le portail Azure.

Créer une source de données

Créer une source de données (REST) permet de créer une connexion à la source de données qui spécifie les données à indexer.

### Create a data source using system-assigned managed identities
POST {{searchUrl}}/datasources?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}

  {
    "name": "doc-intelligence-multimodal-embedding-ds",
    "description": "A data source to store multimodal documents",
    "type": "azureblob",
    "subtype": null,
    "credentials":{
      "connectionString":"{{storageConnection}}"
    },
    "container": {
      "name": "sustainable-ai-pdf",
      "query": null
    },
    "dataChangeDetectionPolicy": null,
    "dataDeletionDetectionPolicy": null,
    "encryptionKey": null,
    "identity": null
  }

Envoyez la demande. La réponse doit ressembler à ce qui suit :

HTTP/1.1 201 Created
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
Location: https://<YOUR-SEARCH-SERVICE-NAME>.search.windows-int.net:443/datasources('doc-extraction-multimodal-embedding-ds')?api-version=2025-11-01-preview -Preview
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: 4eb8bcc3-27b5-44af-834e-295ed078e8ed
elapsed-time: 346
Date: Sat, 26 Apr 2025 21:25:24 GMT
Connection: close

{
  "name": "doc-extraction-multimodal-embedding-ds",
  "description": null,
  "type": "azureblob",
  "subtype": null,
  "indexerPermissionOptions": [],
  "credentials": {
    "connectionString": null
  },
  "container": {
    "name": "sustainable-ai-pdf",
    "query": null
  },
  "dataChangeDetectionPolicy": null,
  "dataDeletionDetectionPolicy": null,
  "encryptionKey": null,
  "identity": null
}

Création d'un index

Créer un index (REST) permet de créer un index de recherche sur votre service de recherche. Un index spécifie tous les paramètres et leurs attributs.

Pour un JSON imbriqué, les champs d’index doivent être identiques aux champs sources. Actuellement, Azure AI Search ne prend pas en charge les mappages de champs vers json imbriqués. Par conséquent, les noms de champs et les types de données doivent correspondre complètement. L’index suivant s’aligne sur les éléments JSON dans le contenu brut.

### Create an index
POST {{searchUrl}}/indexes?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}

{
    "name": "doc-intelligence-multimodal-embedding-index",
    "fields": [
        {
            "name": "content_id",
            "type": "Edm.String",
            "retrievable": true,
            "key": true,
            "analyzer": "keyword"
        },
        {
            "name": "text_document_id",
            "type": "Edm.String",
            "searchable": false,
            "filterable": true,
            "retrievable": true,
            "stored": true,
            "sortable": false,
            "facetable": false
        },          
        {
            "name": "document_title",
            "type": "Edm.String",
            "searchable": true
        },
        {
            "name": "image_document_id",
            "type": "Edm.String",
            "filterable": true,
            "retrievable": true
        },
        {
            "name": "content_text",
            "type": "Edm.String",
            "searchable": true,
            "retrievable": true
        },
        {
            "name": "content_embedding",
            "type": "Collection(Edm.Single)",
            "dimensions": 1024,
            "searchable": true,
            "retrievable": true,
            "vectorSearchProfile": "hnsw"
        },
        {
            "name": "content_path",
            "type": "Edm.String",
            "searchable": false,
            "retrievable": true
        },
        {
            "name": "offset",
            "type": "Edm.String",
            "searchable": false,
            "retrievable": true
        },
        {
            "name": "location_metadata",
            "type": "Edm.ComplexType",
            "fields": [
                {
                "name": "page_number",
                "type": "Edm.Int32",
                "searchable": false,
                "retrievable": true
                },
                {
                "name": "bounding_polygons",
                "type": "Edm.String",
                "searchable": false,
                "retrievable": true,
                "filterable": false,
                "sortable": false,
                "facetable": false
                }
            ]
        }         
    ],
    "vectorSearch": {
        "profiles": [
            {
                "name": "hnsw",
                "algorithm": "defaulthnsw",
                "vectorizer": "demo-vectorizer"
            }
        ],
        "algorithms": [
            {
                "name": "defaulthnsw",
                "kind": "hnsw",
                "hnswParameters": {
                    "m": 4,
                    "efConstruction": 400,
                    "metric": "cosine"
                }
            }
        ],
        "vectorizers": [
            {
                "name": "demo-vectorizer",
                "kind": "aiServicesVision",
                "aiServicesVisionParameters": {
                    "resourceUri": "{{cognitiveServicesUrl}}",
                    "authIdentity": null,
                    "modelVersion": "{{modelVersion}}"
                }
            }
        ]     
    },
    "semantic": {
        "defaultConfiguration": "semanticconfig",
        "configurations": [
            {
                "name": "semanticconfig",
                "prioritizedFields": {
                    "titleField": {
                        "fieldName": "document_title"
                    },
                    "prioritizedContentFields": [
                    ],
                    "prioritizedKeywordsFields": []
                }
            }
        ]
    }
}

Points clés :

  • Les incorporations de texte et d’images sont stockées dans le content_embedding champ et doivent être configurées avec des dimensions appropriées, telles que 1024 et un profil de recherche vectorielle.

  • location_metadata capture les métadonnées de polygone englobant et de numéro de page pour chaque bloc de texte et image normalisée, ce qui permet une recherche spatiale précise ou des superpositions d’interface utilisateur.

  • Pour plus d’informations sur la recherche vectorielle, consultez Vectors in Azure AI Search.

  • Pour plus d’informations sur le classement sémantique, consultez Classement sémantique dans Recherche IA Azure.

Créer un ensemble de compétences

Créer un ensemble de compétences (REST) crée un ensemble de compétences sur votre service de recherche. Un ensemble de compétences définit les opérations qui segmentent et incorporent du contenu avant l’indexation. Cet ensemble de compétences utilise la compétence Disposition du document pour extraire du texte et des images, en préservant les métadonnées d’emplacement qui sont utiles pour les citations dans les applications RAG. Il utilise la compétence d’incorporations multimodales Azure Vision pour vectoriser le contenu d'images et de texte.

### Create a skillset
POST {{searchUrl}}/skillsets?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}

{
  "name": "doc-intelligence-multimodal-embedding-skillset",
  "description": "A sample skillset for multimodal using multimodal embedding",
  "skills": [
    {
      "@odata.type": "#Microsoft.Skills.Util.DocumentIntelligenceLayoutSkill",
      "name": "document-layout-skill",
      "description": "Azure Document Intelligence skill for document cracking",
      "context": "/document",
      "outputMode": "oneToMany",
      "outputFormat": "text",
      "extractionOptions": ["images", "locationMetadata"],
      "chunkingProperties": {     
          "unit": "characters",
          "maximumLength": 2000, 
          "overlapLength": 200
      },
      "inputs": [
        {
          "name": "file_data",
          "source": "/document/file_data"
        }
      ],
      "outputs": [
        { 
          "name": "text_sections", 
          "targetName": "text_sections" 
        }, 
        { 
          "name": "normalized_images", 
          "targetName": "normalized_images" 
        } 
      ]
    },
    { 
      "@odata.type": "#Microsoft.Skills.Vision.VectorizeSkill", 
      "name": "text-embedding-skill",
      "description": "Vision Vectorization skill for text",
      "context": "/document/text_sections/*", 
      "modelVersion": "2023-04-15", 
      "inputs": [ 
        { 
          "name": "text", 
          "source": "/document/text_sections/*/content" 
        } 
      ], 
      "outputs": [ 
        { 
          "name": "vector",
          "targetName": "text_vector"
        } 
      ] 
    },    
    { 
      "@odata.type": "#Microsoft.Skills.Vision.VectorizeSkill", 
      "name": "image-embedding-skill",
      "description": "Vision Vectorization skill for images",
      "context": "/document/normalized_images/*", 
      "modelVersion": "2023-04-15", 
      "inputs": [ 
        { 
          "name": "image", 
          "source": "/document/normalized_images/*" 
        } 
      ], 
      "outputs": [ 
        { 
          "name": "vector",
          "targetName": "image_vector"
        } 
      ] 
    },
    {
      "@odata.type": "#Microsoft.Skills.Util.ShaperSkill",
      "name": "shaper-skill",
      "context": "/document/normalized_images/*",
      "inputs": [
        {
          "name": "normalized_images",
          "source": "/document/normalized_images/*",
          "inputs": []
        },
        {
          "name": "imagePath",
          "source": "='my_container_name/'+$(/document/normalized_images/*/imagePath)",
          "inputs": []
        }
      ],
      "outputs": [
        {
          "name": "output",
          "targetName": "new_normalized_images"
        }
      ]
    }      
  ], 
   "indexProjections": {
      "selectors": [
        {
          "targetIndexName": "doc-intelligence-multimodal-embedding-index",
          "parentKeyFieldName": "text_document_id",
          "sourceContext": "/document/text_sections/*",
          "mappings": [    
            {
            "name": "content_embedding",
            "source": "/document/text_sections/*/text_vector"
            },                      
            {
              "name": "content_text",
              "source": "/document/text_sections/*/content"
            },
            {
              "name": "location_metadata",
              "source": "/document/text_sections/*/locationMetadata"
            },                
            {
              "name": "document_title",
              "source": "/document/document_title"
            }   
          ]
        },        
        {
          "targetIndexName": "{{index}}",
          "parentKeyFieldName": "image_document_id",
          "sourceContext": "/document/normalized_images/*",
          "mappings": [    
            {
            "name": "content_embedding",
            "source": "/document/normalized_images/*/image_vector"
            },                                           
            {
              "name": "content_path",
              "source": "/document/normalized_images/*/new_normalized_images/imagePath"
            },                    
            {
              "name": "document_title",
              "source": "/document/document_title"
            },
            {
              "name": "location_metadata",
              "source": "/document/normalized_images/*/locationMetadata"
            }             
          ]
        }
      ],
      "parameters": {
        "projectionMode": "skipIndexingParentDocuments"
      }
  },
  "cognitiveServices": {
    "@odata.type": "#Microsoft.Azure.Search.AIServicesByIdentity",
    "subdomainUrl": "{{cognitiveServicesUrl}}",
    "identity": null
  },
  "knowledgeStore": {
    "storageConnectionString": "",
    "identity": null,
    "projections": [
      {
        "files": [
          {
            "storageContainer": "{{imageProjectionContainer}}",
            "source": "/document/normalized_images/*"
          }
        ]
      }
    ]
  }
}

Cet ensemble de compétences extrait du texte et des images, vectorise les deux et forme les métadonnées d’image pour la projection dans l’index.

Points clés :

  • Le content_text champ est rempli avec du texte extrait et segmenté à l’aide de la compétence Disposition du document

  • content_path contient le chemin relatif du fichier image dans le conteneur de projection d’images désigné. Ce champ est généré uniquement pour les images extraites de documents lorsque extractOption est défini sur ["images", "locationMetadata"] ou ["images"], et peut être mappé à partir du document enrichi depuis le champ source /document/normalized_images/*/imagePath.

  • La compétence d’intégration multimodale Azure Vision permet l’intégration de données textuelles et visuelles à l’aide du même type de compétence, différenciée selon l'entrée (texte ou image). Pour plus d’informations, consultez la compétence d’incorporations modales Azure Vision.

Créer et exécuter un indexeur

Créer un indexeur permet de créer un indexeur sur votre service de recherche. Un indexeur se connecte à la source de données, charge des données, exécute un ensemble de compétences et indexe les données enrichies.

### Create and run an indexer
POST {{searchUrl}}/indexers?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}

{
  "dataSourceName": "doc-intelligence-multimodal-embedding-ds",
  "targetIndexName": "doc-intelligence-multimodal-embedding-index",
  "skillsetName": "doc-intelligence-multimodal-embedding-skillset",
  "parameters": {
    "maxFailedItems": -1,
    "maxFailedItemsPerBatch": 0,
    "batchSize": 1,
    "configuration": {
      "allowSkillsetToReadFileData": true
    }
  },
  "fieldMappings": [
    {
      "sourceFieldName": "metadata_storage_name",
      "targetFieldName": "document_title"
    }
  ],
  "outputFieldMappings": []
}

Exécuter des requêtes

Vous pouvez démarrer la recherche dès que le premier document est chargé.

### Query the index
POST {{searchUrl}}/indexes/doc-intelligence-multimodal-embedding-index/docs/search?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}
  
  {
    "search": "*",
    "count": true
  }

Envoyez la demande. Il s’agit d’une requête de recherche en texte intégral non spécifiée qui retourne tous les champs marqués comme récupérables dans l’index, ainsi qu’un nombre de documents. La réponse doit ressembler à ce qui suit :

{
  "@odata.count": 100,
  "@search.nextPageParameters": {
    "search": "*",
    "count": true,
    "skip": 50
  },
  "value": [
  ],
  "@odata.nextLink": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/indexes/doc-intelligence-multimodal-embedding-index/docs/search?api-version=2025-11-01-preview "
}

100 documents sont retournés dans la réponse.

Pour les filtres, vous pouvez également utiliser des opérateurs logiques (and, or, not) et des opérateurs de comparaison (eq, ne, gt, lt, ge, le). Les comparaisons de chaînes sont sensibles à la casse. Pour plus d’informations et d’exemples, consultez Exemples de requêtes de recherche simples.

Note

Le $filter paramètre fonctionne uniquement sur les champs marqués filtrables lors de la création de l’index.

### Query for only images
POST {{searchUrl}}/indexes/doc-intelligence-multimodal-embedding-index/docs/search?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}
  
  {
    "search": "*",
    "count": true,
    "filter": "image_document_id ne null"
  }
### Query for text or images with content related to energy, returning the id, parent document, and text (only populated for text chunks), and the content path where the image is saved in the knowledge store (only populated for images)
POST {{searchUrl}}/indexes/doc-intelligence-multimodal-embedding-index/docs/search?api-version=2025-11-01-preview   HTTP/1.1
  Content-Type: application/json
  api-key: {{searchApiKey}}
  
  {
    "search": "energy",
    "count": true,
    "select": "content_id, document_title, content_text, content_path"
  }

Réinitialiser et réexécuter

Les indexeurs peuvent être réinitialisés pour effacer l’historique d’exécution, ce qui permet une réexécution complète. Les requêtes POST suivantes servent à la réinitialisation, suivie d'une nouvelle exécution.

### Reset the indexer
POST {{searchUrl}}/indexers/doc-intelligence-multimodal-embedding-indexer/reset?api-version=2025-11-01-preview   HTTP/1.1
  api-key: {{searchApiKey}}
### Run the indexer
POST {{searchUrl}}/indexers/doc-intelligence-multimodal-embedding-indexer/run?api-version=2025-11-01-preview   HTTP/1.1
  api-key: {{searchApiKey}}
### Check indexer status 
GET {{searchUrl}}/indexers/doc-intelligence-multimodal-embedding-indexer/status?api-version=2025-11-01-preview   HTTP/1.1
  api-key: {{searchApiKey}}

Nettoyer les ressources

Lorsque vous travaillez dans votre propre abonnement, il est judicieux à la fin d’un projet de supprimer les ressources dont vous n’avez plus besoin. Les ressources qui restent actives peuvent vous coûter de l’argent. Vous pouvez supprimer des ressources individuellement ou supprimer le groupe de ressources pour supprimer l’ensemble des ressources.

Vous pouvez utiliser le portail Azure pour supprimer les index, les indexeurs et les sources de données.

Voir aussi

Maintenant que vous connaissez un exemple d’implémentation d’un scénario d’indexation modale, consultez :