Déployer un modèle dans une API web ASP.NET Core

Découvrez comment alimenter un modèle Machine Learning ML.NET préentraîné sur le web avec une API web ASP.NET Core. L’alimentation d’un modèle sur une API web permet d’effectuer des prédictions par le biais de méthodes HTTP standard.

Prérequis

Créer un projet d’API web ASP.NET Core

  1. Démarrez Visual Studio 2022 et sélectionnez Créer un projet.

  2. Dans la boîte de dialogue Créer un projet :

    • Entrez Web API dans la zone de recherche.
    • Sélectionnez le modèle API web ASP.NET Core, puis Suivant.
  3. Dans la boîte de dialogue Configurer votre projet :

    • Nommez votre projet SentimentAnalysisWebAPI.
    • Sélectionnez Suivant.
  4. Dans la boîte de dialogue Informations supplémentaires :

    • Décochez la case N’utilisez pas d’instructions de niveau supérieur.
    • Sélectionnez Create (Créer).
  5. Installez les packages NuGet suivants :

    Pour plus d’informations sur l’installation de packages NuGet dans Visual Studio, consultez le guide Installer et utiliser un package NuGet dans Visual Studio.

Ajouter un modèle au projet d’API web ASP.NET Core

  1. Copiez votre modèle prédéfini dans votre répertoire de projet SentimentAnalysisWebAPI.

  2. Configurez votre projet pour copier votre fichier de modèle dans le répertoire de sortie. Dans l’Explorateur de solutions :

    • Cliquez avec le bouton de droite sur le fichier zip et sélectionnez Propriétés.
    • Sous Avancé, remplacez la valeur Copier dans le répertoire de sortie par Copier si plus récent.

Créer des modèles de données

Vous devez créer des classes pour définir le schéma de l’entrée et de la sortie de votre modèle.

Notes

Les propriétés de vos classes de schéma d’entrée et de sortie dépendent des colonnes de jeux de données utilisées pour effectuer l'apprentissage de votre modèle ainsi que de la tâche Machine Learning (régression, classification, etc.).

Dans votre fichier Program.cs :

  1. Ajoutez les instructions using suivantes :

    using Microsoft.ML.Data;
    using Microsoft.Extensions.ML;
    
  2. En bas du fichier, ajoutez les classes suivantes :

    Entrée de modèle

    Pour ce modèle, l’entrée contient une propriété SentimentText unique qui est une chaîne qui représente un commentaire utilisateur.

    public class ModelInput
    {
        public string SentimentText;
    }
    

    Sortie du modèle

    Une fois que le modèle a évalué l’entrée, il génère une prédiction avec trois propriétés : Sentiment, Probability et Score. Dans ce cas, le Sentiment est le sentiment prédit du commentaire de l’utilisateur et Probability et Score sont des mesures fiables pour la prédiction.

    public class ModelOutput
    {
        [ColumnName("PredictedLabel")]
        public bool Sentiment { get; set; }
    
        public float Probability { get; set; }
    
        public float Score { get; set; }
    }
    

Inscrire PredictionEnginePool pour l’utiliser dans l’application

Pour effectuer une prédiction unique, vous devez créer un PredictionEngine. PredictionEngine n’est pas thread-safe. En outre, vous devez créer une instance de celui-ci partout où il est nécessaire dans votre application. À mesure que votre application croît, ce processus peut devenir non gérable. Pour améliorer les performances et la sécurité des threads, utilisez une combinaison d’injection de dépendances et du service PredictionEnginePool, qui crée un ObjectPool d’objets PredictionEngine à utiliser dans votre application.

Le lien suivant fournit plus d’informations si vous souhaitez en savoir plus sur Injection de dépendances dans ASP.NET Core.

Ajoutez le code suivant à votre fichier Program.cs :

builder.Services.AddPredictionEnginePool<ModelInput, ModelOutput>()
    .FromFile(modelName: "SentimentAnalysisModel", filePath: "sentiment_model.zip", watchForChanges: true);

À haut niveau, ce code initialise automatiquement les objets et services pour une utilisation ultérieure à la demande de l’application, ce qui évite d’avoir à le faire manuellement.

Les modèles Machine Learning ne sont pas statiques. À mesure que de nouvelles données de formation deviennent disponibles, le modèle est réentraîné et redéployé. Pour obtenir la dernière version du modèle dans votre application, vous pouvez redémarrer ou redéployer votre application. Toutefois, cela entraîne un temps d’arrêt de l’application. Le service PredictionEnginePool fournit un mécanisme pour recharger un modèle mis à jour sans redémarrer ou redéployer votre application.

Définissez le paramètre watchForChanges sur true et PredictionEnginePool démarre un FileSystemWatcher qui écoute les notifications de modification du système de fichiers et déclenche des événements en cas de modification du fichier. Cela invite le PredictionEnginePool à recharger automatiquement le modèle.

Le modèle est identifié par le paramètre modelName afin que plusieurs modèles par application puissent être rechargés en cas de modification.

Conseil

Vous pouvez également utiliser la méthode FromUri lors de l’utilisation de modèles stockés à distance. Au lieu de surveiller les événements de modification de fichiers, FromUri interroge l’emplacement distant pour les modifications. L’intervalle d’interrogation est de 5 minutes par défaut. Vous pouvez augmenter ou diminuer l’intervalle d’interrogation en fonction des exigences de votre application. Dans l’exemple de code ci-dessous, le PredictionEnginePool sonde le modèle stocké au niveau de l’URI spécifié chaque minute.

services.AddPredictionEnginePool<SentimentData, SentimentPrediction>()
  .FromUri(
      modelName: "SentimentAnalysisModel",
      uri:"https://github.com/dotnet/samples/raw/main/machine-learning/models/sentimentanalysis/sentiment_model.zip",
      period: TimeSpan.FromMinutes(1));

Point de terminaison de prédiction du mappage

Pour traiter les requêtes HTTP entrantes, créez un point de terminaison.

Remplacez le point de terminaison / par ce qui suit :

var predictionHandler =
    async (PredictionEnginePool<ModelInput, ModelOutput> predictionEnginePool, ModelInput input) =>
        await Task.FromResult(predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", input));

app.MapPost("/predict", predictionHandler);

Le point de terminaison /predict accepte les requêtes HTTP POST et utilise le pool de moteurs de prédiction pour retourner une prédiction à l’aide de l’entrée fournie.

Une fois terminé, votre fichier Program.cs doit ressembler à ce qui suit :

using Microsoft.ML.Data;
using Microsoft.Extensions.ML;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddPredictionEnginePool<ModelInput, ModelOutput>()
    .FromFile(modelName: "SentimentAnalysisModel", filePath: "sentiment_model.zip", watchForChanges: true);

var app = builder.Build();

var predictionHandler =
    async (PredictionEnginePool<ModelInput, ModelOutput> predictionEnginePool, ModelInput input) =>
        await Task.FromResult(predictionEnginePool.Predict(modelName: "SentimentAnalysisModel", input));

app.MapPost("/predict", predictionHandler);

app.Run();

public class ModelInput
{
    public string SentimentText;
}

public class ModelOutput
{
    [ColumnName("PredictedLabel")]
    public bool Sentiment { get; set; }

    public float Probability { get; set; }

    public float Score { get; set; }
}

Tester l’API web localement

Maintenant que tout est configuré, il est temps de tester l’application.

  1. Exécutez l’application.

  2. Ouvrez PowerShell et entrez le code suivant, où PORT est le port d’écoute de votre application.

    Invoke-RestMethod "https://localhost:<PORT>/predict" -Method Post -Body (@{SentimentText="This was a very bad steak"} | ConvertTo-Json) -ContentType "application/json"
    

    En cas de réussite, la sortie devrait se présenter ainsi :

    sentiment probability score
    --------- ----------- -----
    False         0.5     0
    

Félicitations ! Vous avez réussi à alimenter votre modèle de façon à effectuer des prédictions sur Internet à l’aide d’une API web ASP.NET Core.

Étapes suivantes