Compétence API web personnalisée dans un pipeline d’enrichissement de Recherche Azure AI

La compétence API web personnalisée vous permet d’étendre l’enrichissement par IA en appelant un point de terminaison d’API web qui fournit des opérations personnalisées. Tout comme les compétences intégrées, une compétence API web personnalisée a des entrées et des sorties. Selon les entrées, votre API web reçoit une charge utile JSON pendant l’exécution de l’indexeur et génère une charge utile JSON en réponse, ainsi qu’un code d’état de réussite. La réponse est censée avoir les sorties spécifiées par votre compétence personnalisée. Toute autre réponse est considérée comme une erreur et aucun enrichissement n’est effectué. La structure des charges utiles JSON est décrite plus bas dans ce document.

La compétence API web personnalisée est également utilisée dans l’implémentation de la fonctionnalité Azure OpenAI sur vos données. Si Azure OpenAI est configuré pour l’accès en fonction du rôle et que vous recevez des appels 403 Forbidden lors de la création de l’index vectoriel, vérifiez que Recherche Azure AI dispose d’une identité affectée par le système et s’exécute en tant que service approuvé sur Azure OpenAI.

Remarque

L’indexeur réessaie deux fois pour certains codes d’état HTTP standard retournés par l’API web. Ces codes d’état HTTP sont les suivants :

  • 502 Bad Gateway
  • 503 Service Unavailable
  • 429 Too Many Requests

@odata.type

Microsoft.Skills.Custom.WebApiSkill

Paramètres de la compétence

Les paramètres respectent la casse.

Nom du paramètre Description
uri URI de l’API web à laquelle la charge utile JSON est envoyée. Seul le schéma d’URI https est autorisé.
authResourceId (Facultatif) Chaîne qui, si elle est définie, indique que cette compétence doit utiliser une identité managée sur la connexion à la fonction ou à l’application qui héberge le code. Cette propriété prend un ID d’application (client) ou l’inscription de l’application dans Microsoft Entra ID, dans un format pris en charge : api://<appId>. Cette valeur est utilisée pour étendre le jeton d’authentification récupéré par l’indexeur et est envoyée avec la demande d’API de compétence web personnalisée à la fonction ou à l’application. La définition de cette propriété nécessite que votre service de recherche soit configuré pour une identité managée et que votre application de fonction Azure soit configurée pour une connexion Microsoft Entra. Pour utiliser ce paramètre, appelez l’API avec api-version=2023-10-01-Preview.
httpMethod Méthode à utiliser pour envoyer la charge utile. Les méthodes autorisées sont PUT ou POST
httpHeaders Collection de paires clé-valeur où les clés représentent les noms d’en-tête et les valeurs représentent les valeurs d’en-tête envoyées à votre API web avec la charge utile. Les en-têtes suivants sont interdits dans cette collection : Accept, Accept-Charset, Accept-Encoding, Content-Length, Content-Type, Cookie, Host, TE, Upgrade, Via.
timeout (Facultatif) Si spécifié, indique le délai d’expiration pour le client http qui effectue l’appel d’API. Il doit être formaté en tant que valeur « dayTimeDuration » XSD (un sous-ensemble limité d'une valeur de durée ISO 8601 ). Par exemple, PT60S pour 60 secondes. S’il n’est pas défini, une valeur par défaut de 30 secondes est choisie. Le délai d’expiration peut être défini sur 230 secondes maximum et 1 seconde minimum.
batchSize (Facultatif) Indique le nombre « d’enregistrements de données » (voir la structure de charge utile JSON ci-dessous) envoyés par appel d’API. S’il n’est pas défini, une valeur par défaut de 1000 est choisie. Nous vous recommandons d’utiliser ce paramètre pour avoir un compromis entre le débit d’indexation et la charge sur votre API.
degreeOfParallelism (Facultatif) Lorsqu’il est spécifié, indique le nombre d’appels que l’indexeur effectue en parallèle au point de terminaison que vous fournissez. Vous pouvez réduire cette valeur si votre point de terminaison échoue en raison de la pression ou l’augmenter s’il peut gérer la charge. S’il n’est pas défini, une valeur par défaut de 5 secondes est utilisée. Le degreeOfParallelism peut avoir une valeur maximale de 10 et un minimum de 1.

Entrées de la compétence

Il n’y a pas d’entrée prédéfinie pour cette compétence. Les entrées sont n’importe quel champ existant ou n’importe quel nœud de l’arborescence d’enrichissement que vous souhaitez transmettre à votre compétence personnalisée.

Sorties de la compétence

Il n’y a pas de sortie prédéfinie pour cette compétence. Veillez à définir un mappage de champ de sortie dans l’indexeur si la sortie de la compétence doit être envoyée à un champ de l’index de recherche.

Exemple de définition

{
  "@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
  "description": "A custom skill that can identify positions of different phrases in the source text",
  "uri": "https://contoso.count-things.com",
  "batchSize": 4,
  "context": "/document",
  "inputs": [
    {
      "name": "text",
      "source": "/document/content"
    },
    {
      "name": "language",
      "source": "/document/languageCode"
    },
    {
      "name": "phraseList",
      "source": "/document/keyphrases"
    }
  ],
  "outputs": [
    {
      "name": "hitPositions"
    }
  ]
}

Exemple de structure JSON d’entrée

Cette structure JSON représente la charge utile envoyée à votre API web. Elle suit toujours ces contraintes :

  • L’entité de niveau supérieur est appelée values et est un tableau d’objets. Le nombre de ces objets équivaut à batchSize au maximum.

  • Chaque objet dans le tableau values a :

    • Une propriété recordId constituant une chaîne unique, utilisée pour identifier cet enregistrement.

    • Une propriété data constituant un objet JSON. Les champs de la propriété data correspondent aux « noms » spécifiés dans la section inputs de la définition de compétence. Les valeurs de ces champs proviennent de la source de ces champs (qui peuvent provenir d’un champ du document ou éventuellement une autre compétence).

{
    "values": [
      {
        "recordId": "0",
        "data":
           {
             "text": "Este es un contrato en Inglés",
             "language": "es",
             "phraseList": ["Este", "Inglés"]
           }
      },
      {
        "recordId": "1",
        "data":
           {
             "text": "Hello world",
             "language": "en",
             "phraseList": ["Hi"]
           }
      },
      {
        "recordId": "2",
        "data":
           {
             "text": "Hello world, Hi world",
             "language": "en",
             "phraseList": ["world"]
           }
      },
      {
        "recordId": "3",
        "data":
           {
             "text": "Test",
             "language": "es",
             "phraseList": []
           }
      }
    ]
}

Exemple de structure JSON de sortie

« output » correspond à la réponse renvoyée par votre API web. L’API web doit retourner uniquement une charge utile JSON (vérifiée en examinant l’en-tête de réponse Content-Type) et doit satisfaire les contraintes suivantes :

  • Il doit y avoir une entité de niveau supérieur appelée values qui doit être un tableau d’objets.

  • Le nombre d’objets dans le tableau doit être le même que le nombre d’objets envoyés à l’API web.

  • Chaque objet doit avoir :

    • Une propriété recordId.

    • Une propriété data, qui est un objet dans lequel les champs sont des enrichissements correspondant aux « noms » dans output et dont la valeur est considérée comme l’enrichissement.

    • Une propriété errors, tableau listant toutes les erreurs rencontrées et qui est ajouté à l’historique d’exécution de l’indexeur. Cette propriété est obligatoire, mais peut avoir une valeur null.

    • Une propriété warnings, tableau listant tous les avertissements rencontrés et qui est ajouté à l’historique d’exécution de l’indexeur. Cette propriété est obligatoire, mais peut avoir une valeur null.

  • L’ordre des objets dans les values indiquées dans la demande ou la réponse n’a pas d’importance. Toutefois, comme le recordId est utilisé pour la corrélation, tous les enregistrements dans la réponse contenant un recordId absent de la demande d’origine envoyée à l’API web sont ignorés.

{
    "values": [
        {
            "recordId": "3",
            "data": {
            },
            "errors": [
              {
                "message" : "'phraseList' should not be null or empty"
              }
            ],
            "warnings": null
        },
        {
            "recordId": "2",
            "data": {
                "hitPositions": [6, 16]
            },
            "errors": null,
            "warnings": null
        },
        {
            "recordId": "0",
            "data": {
                "hitPositions": [0, 23]
            },
            "errors": null,
            "warnings": null
        },
        {
            "recordId": "1",
            "data": {
                "hitPositions": []
            },
            "errors": null,
            "warnings": [
              {
                "message": "No occurrences of 'Hi' were found in the input text"
              }
            ]
        },
    ]
}

Cas d’erreur

En plus de la non-disponibilité de votre API web ou de l’envoi de codes d’état non réussis, les cas suivants sont considérés comme erronés :

  • Si l’API web retourne un code d’état de réussite, mais que la réponse indique que ce n’est pas application/json, la réponse est considérée comme non valide et aucun enrichissement n’est effectué.

  • S’il existe des enregistrements non valides (par exemple, absence ou duplication de recordId) dans le tableau values de réponses, aucun enrichissement n’est effectué pour les enregistrements non valides. Il est important d’adhérer au contrat de compétences de l’API web lors du développement de compétences personnalisées. Vous pouvez vous référer à cet exemple fourni dans le dépôt Power Skill qui suit le contrat prévu.

Quand l’API web n’est pas disponible ou retourne une erreur HTTP, une erreur amicale avec tous les détails disponibles sur l’erreur HTTP est ajoutée à l’historique d’exécution de l’indexeur.

Voir aussi