Démarrage rapide : Bibliothèque de client Personalizer

Important

À compter du 20 septembre 2023, vous ne pourrez pas créer de ressources Personalizer. Le service Personalizer est mis hors service le 1er octobre 2026.

Prise en main des bibliothèques de client Azure AI Personalizer pour configurer une boucle d’apprentissage de base. Une boucle d’apprentissage est un système de décisions et de commentaires : une application demande un classement de décision au service, puis utilise le choix le mieux classé et calcule un score de récompense à partir du résultat. Il retourne le score de récompense au service. Au fil du temps, Personalizer utilise des algorithmes d’IA pour prendre de meilleures décisions selon un contexte donné. Procédez comme suit pour configurer un exemple d’application.

Exemple de scénario

Dans ce guide de démarrage rapide, un détaillant en ligne souhaite augmenter son chiffre d’affaires en affichant des produits pertinents et personnalisés pour chaque client sur son site web. Dans la page principale, il existe une section « Produit proposé » qui affiche un produit de repas préparé aux clients potentiels. Ce détaillant aimerait déterminer comment montrer le bon produit au bon client afin de maximiser la probabilité d’achat.

Le service Personalizer résout ce problème de manière automatisée, évolutive et adaptable à l’aide de l’apprentissage par renforcement. Vous apprendrez à créer des actions et leurs caractéristiques, des caractéristiques contextuelles et des scores de récompense. Vous allez utiliser la bibliothèque cliente Personalizer pour effectuer des appels aux API Classement et Récompense.

Documentation de référence | Code source de la bibliothèque | Package (NuGet) | Exemples de code .NET

Prérequis

  • Abonnement Azure - En créer un gratuitement
  • Version actuelle de .NET Core
  • Une fois que vous avez votre abonnement Azure, créez une ressource Personalizer dans le portail Azure pour obtenir votre clé et votre point de terminaison. À la fin du déploiement, sélectionnez Accéder à la ressource.
    • Vous avez besoin de la clé et du point de terminaison de la ressource que vous créez pour connecter votre application à l’API Personalizer. Vous collerez votre clé et votre point de terminaison dans le code ci-dessous plus loin dans le guide de démarrage rapide.
    • Vous pouvez utiliser le niveau tarifaire Gratuit (F0) pour tester le service, puis passer par la suite à un niveau payant pour la production.

Configuration du modèle

Changer la fréquence de mise à jour du modèle

Dans le portail Azure, accédez à la page Configuration de votre ressource Personalizer et passez la fréquence de mise à jour du modèle à 30 secondes. Ainsi, l’apprentissage du modèle est effectué rapidement, ce qui vous permet de voir comment l’action recommandée change pour chaque itération.

Change model update frequency

Modifier le temps d’attente de la récompense

Dans le portail Azure, accédez à la page Configuration de votre ressource Personalizer et passez le temps d’attente de la récompense à 10 minutes. Cela détermine combien de temps le modèle doit attendre avant de recevoir des commentaires de récompense de la recommandation qui a été envoyée. L’apprentissage ne peut avoir lieu tant que le temps d’attente de la récompense n’est pas écoulé.

Change reward wait time

Créer une application C#

Créez une application .NET Core dans votre éditeur ou IDE favori.

Dans une fenêtre de console (par exemple cmd, PowerShell ou Bash), utilisez la commande dotnet new pour créer une application console avec le nom personalizer-quickstart. Cette commande crée un projet C# « Hello World » simple avec un seul fichier source : Program.cs.

dotnet new console -n personalizer-quickstart

Déplacez vos répertoires vers le dossier d’application nouvellement créé. Générez ensuite l’application avec :

dotnet build

La sortie de génération ne doit contenir aucun avertissement ni erreur.

...
Build succeeded.
 0 Warning(s)
 0 Error(s)
...

Installer la bibliothèque de client

Dans le répertoire de l’application, installez la bibliothèque de client Personalizer pour .NET avec la commande suivante :

dotnet add package Microsoft.Azure.CognitiveServices.Personalizer --version 1.0.0

Conseil

Si vous utilisez l’IDE Visual Studio, la bibliothèque de client est disponible sous forme de package NuGet téléchargeable.

Bloc de code 1 : générer des exemples de données

Personalizer est destiné à s’exécuter sur des applications qui reçoivent et interprètent des données en temps réel. Dans ce guide de démarrage rapide, vous allez utiliser un exemple de code pour générer des actions imaginaires de clients sur le site web d’un commerce. Le bloc de code suivant définit trois méthodes clés : GetActions, GetContext et GetRewardScore.

  • GetActions retourne une liste des choix que le site web du commerce doit classer. Dans cet exemple, les actions sont des produits alimentaires. Chaque choix d’action comporte des détails (caractéristiques) qui peuvent avoir une incidence sur le comportement ultérieur de l’utilisateur. Les actions sont utilisées comme entrée pour l’API Rank

  • GetContext retourne une visite de client simulée. Elle sélectionne des détails aléatoires (des caractéristiques de contexte) comme le client présent et l’heure de la visite. En général, le contexte représente l’état actuel de votre application, système, environnement ou utilisateur. L’objet de contexte est utilisé comme entrée pour l’API Rank.

    Les fonctionnalités de contexte de ce guide de démarrage rapide sont très simples. Toutefois, dans un système de production réel, la conception de vos caractéristiques et l’évaluation de leur efficacité sont importantes. Pour obtenir des conseils, reportez-vous à la documentation liée.

  • GetRewardScore retourne un score compris entre zéro et un qui représente le succès d’une interaction client. Elle utilise une logique simple pour déterminer comment différents contextes répondent à différents choix d’action. Par exemple, un certain utilisateur donnera toujours un 1,0 pour les produits végétariens et végétaliens, et un 0,0 pour les autres produits. Dans un scénario réel, Personalizer apprend les préférences utilisateur des données envoyées dans les appels d’API Rank et Reward. Vous ne les définissez pas explicitement comme dans l’exemple de code.

    Dans un système de production réel, le score de récompense doit être conçu pour s’aligner sur vos objectifs métier et vos indicateurs de performance clés. Pour déterminer la façon de calculer la métrique de récompense, il faudra peut-être s’adonner à quelques expérimentations.

    Dans le code ci-dessous, les préférences et les réponses des utilisateurs aux actions sont codées en dur sous la forme d’une série d’instructions conditionnelles, et un texte explicatif est inclus dans le code à des fins de démonstration.

  1. Trouvez votre clé et votre point de terminaison.

    Important

    Accédez au portail Azure. Si la ressource Personalizer que vous avez créée dans la section Prérequis a été déployée, cliquez sur le bouton Accéder à la ressource sous Étapes suivantes. La clé et le point de terminaison se trouvent dans la page Clé et point de terminaison de la ressource, sous Gestion des ressources.

    N’oubliez pas de supprimer la clé de votre code une fois que vous avez terminé, et ne la postez jamais publiquement. Pour la production, envisagez d’utiliser une méthode de stockage et d’accès sécurisée pour vos informations d’identification. Par exemple, Azure Key Vault.

  2. Ouvrez Program.cs dans un éditeur de texte ou un environnement de développement intégré et collez le code suivant.

    using Microsoft.Azure.CognitiveServices.Personalizer;
    using Microsoft.Azure.CognitiveServices.Personalizer.Models;
    
    class Program
    {
        private static readonly string ApiKey = "REPLACE_WITH_YOUR_PERSONALIZER_KEY";
        private static readonly string ServiceEndpoint = "REPLACE_WITH_YOUR_ENDPOINT_URL";
    
        static PersonalizerClient InitializePersonalizerClient(string url)
        {
            PersonalizerClient client = new PersonalizerClient(
                new ApiKeyServiceClientCredentials(ApiKey))
            { Endpoint = url };
    
            return client;
        }
    
        static Dictionary<string, ActionFeatures> actions = new Dictionary<string, ActionFeatures>
        {
        {"pasta", new ActionFeatures(
                        new BrandInfo(company: "pasta_inc"),
                        new ItemAttributes(
                            quantity: 1,
                            category: "Italian",
                            price: 12),
                        new DietaryAttributes(
                            vegan: false,
                            lowCarb: false,
                            highProtein: false,
                            vegetarian: false,
                            lowFat: true,
                            lowSodium: true))},
        {"bbq", new ActionFeatures(
                        new BrandInfo(company: "ambisco"),
                        new ItemAttributes(
                            quantity: 2,
                            category: "bbq",
                            price: 20),
                        new DietaryAttributes(
                            vegan: false,
                            lowCarb: true,
                            highProtein: true,
                            vegetarian: false,
                            lowFat: false,
                            lowSodium: false))},
        {"bao", new ActionFeatures(
                        new BrandInfo(company: "bao_and_co"),
                        new ItemAttributes(
                            quantity: 4,
                            category: "Chinese",
                            price: 8),
                        new DietaryAttributes(
                            vegan: false,
                            lowCarb: true,
                            highProtein: true,
                            vegetarian: false,
                            lowFat: true,
                            lowSodium: false))},
        {"hummus", new ActionFeatures(
                        new BrandInfo(company: "garbanzo_inc"),
                        new ItemAttributes(
                            quantity: 1,
                            category: "Breakfast",
                            price: 5),
                        new DietaryAttributes(
                            vegan: true,
                            lowCarb: false,
                            highProtein: true,
                            vegetarian: true,
                            lowFat: false,
                            lowSodium: false))},
        {"veg_platter", new ActionFeatures(
                        new BrandInfo(company: "farm_fresh"),
                        new ItemAttributes(
                            quantity: 1,
                            category: "produce",
                            price: 7),
                        new DietaryAttributes(
                            vegan: true,
                            lowCarb: true,
                            highProtein: false,
                            vegetarian: true,
                            lowFat: true,
                            lowSodium: true ))},
    };
    
        static IList<RankableAction> GetActions()
        {
            IList<RankableAction> rankableActions = new List<RankableAction>();
            foreach (var action in actions)
            {
                rankableActions.Add(new RankableAction
                {
                    Id = action.Key,
                    Features = new List<object>() { action.Value }
                });
            }
    
            return rankableActions;
        }
    
        public class BrandInfo
        {
            public string Company { get; set; }
            public BrandInfo(string company)
            {
                Company = company;
            }
        }
    
        public class ItemAttributes
        {
            public int Quantity { get; set; }
            public string Category { get; set; }
            public double Price { get; set; }
            public ItemAttributes(int quantity, string category, double price)
            {
                Quantity = quantity;
                Category = category;
                Price = price;
            }
        }
    
        public class DietaryAttributes
        {
            public bool Vegan { get; set; }
            public bool LowCarb { get; set; }
            public bool HighProtein { get; set; }
            public bool Vegetarian { get; set; }
            public bool LowFat { get; set; }
            public bool LowSodium { get; set; }
            public DietaryAttributes(bool vegan, bool lowCarb, bool highProtein, bool vegetarian, bool lowFat, bool lowSodium)
            {
                Vegan = vegan;
                LowCarb = lowCarb;
                HighProtein = highProtein;
                Vegetarian = vegetarian;
                LowFat = lowFat;
                LowSodium = lowSodium;
    
            }
        }
    
        public class ActionFeatures
        {
            public BrandInfo BrandInfo { get; set; }
            public ItemAttributes ItemAttributes { get; set; }
            public DietaryAttributes DietaryAttributes { get; set; }
            public ActionFeatures(BrandInfo brandInfo, ItemAttributes itemAttributes, DietaryAttributes dietaryAttributes)
            {
                BrandInfo = brandInfo;
                ItemAttributes = itemAttributes;
                DietaryAttributes = dietaryAttributes;
            }
        }
    
        public static Context GetContext()
        {
            return new Context(
                    user: GetRandomUser(),
                    timeOfDay: GetRandomTimeOfDay(),
                    location: GetRandomLocation(),
                    appType: GetRandomAppType());
        }
    
        static string[] timesOfDay = new string[] { "morning", "afternoon", "evening" };
    
        static string[] locations = new string[] { "west", "east", "midwest" };
    
        static string[] appTypes = new string[] { "edge", "safari", "edge_mobile", "mobile_app" };
    
        static IList<UserProfile> users = new List<UserProfile>
    {
        new UserProfile(
            name: "Bill",
            dietaryPreferences: new Dictionary<string, bool> { { "low_carb", true } },
            avgOrderPrice: "0-20"),
        new UserProfile(
            name: "Satya",
            dietaryPreferences: new Dictionary<string, bool> { { "low_sodium", true} },
            avgOrderPrice: "201+"),
        new UserProfile(
            name: "Amy",
            dietaryPreferences: new Dictionary<string, bool> { { "vegan", true }, { "vegetarian", true } },
            avgOrderPrice: "21-50")
    };
    
        static string GetRandomTimeOfDay()
        {
            var random = new Random();
            var timeOfDayIndex = random.Next(timesOfDay.Length);
            Console.WriteLine($"TimeOfDay: {timesOfDay[timeOfDayIndex]}");
            return timesOfDay[timeOfDayIndex];
        }
    
        static string GetRandomLocation()
        {
            var random = new Random();
            var locationIndex = random.Next(locations.Length);
            Console.WriteLine($"Location: {locations[locationIndex]}");
            return locations[locationIndex];
        }
    
        static string GetRandomAppType()
        {
            var random = new Random();
            var appIndex = random.Next(appTypes.Length);
            Console.WriteLine($"AppType: {appTypes[appIndex]}");
            return appTypes[appIndex];
        }
    
        static UserProfile GetRandomUser()
        {
            var random = new Random();
            var userIndex = random.Next(users.Count);
            Console.WriteLine($"\nUser: {users[userIndex].Name}");
            return users[userIndex];
        }
    
        public class UserProfile
        {
            // Mark name as non serializable so that it is not part of the context features
            [NonSerialized()]
            public string Name;
            public Dictionary<string, bool> DietaryPreferences { get; set; }
            public string AvgOrderPrice { get; set; }
    
            public UserProfile(string name, Dictionary<string, bool> dietaryPreferences, string avgOrderPrice)
            {
                Name = name;
                DietaryPreferences = dietaryPreferences;
                AvgOrderPrice = avgOrderPrice;
            }
        }
    
        public class Context
        {
            public UserProfile User { get; set; }
            public string TimeOfDay { get; set; }
            public string Location { get; set; }
            public string AppType { get; set; }
    
            public Context(UserProfile user, string timeOfDay, string location, string appType)
            {
                User = user;
                TimeOfDay = timeOfDay;
                Location = location;
                AppType = appType;
            }
        }
        public static float GetRewardScore(Context context, string actionId)
        {
            float rewardScore = 0.0f;
            string userName = context.User.Name;
            ActionFeatures actionFeatures = actions[actionId];
            if (userName.Equals("Bill"))
            {
                if (actionFeatures.ItemAttributes.Price < 10 && !context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill likes to be economical when he's not in the midwest visiting his friend Warren. He bought {actionId} because it was below a price of $10.");
                }
                else if (actionFeatures.DietaryAttributes.LowCarb && context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill is visiting his friend Warren in the midwest. There he's willing to spend more on food as long as it's low carb, so Bill bought {actionId}.");
                }
                else if (actionFeatures.ItemAttributes.Price >= 10 && !context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill didn't buy {actionId} because the price was too high when not visting his friend Warren in the midwest.");
                }
                else if (actionFeatures.DietaryAttributes.LowCarb && context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill didn't buy {actionId} because it's not low-carb, and he's in the midwest visitng his friend Warren.");
                }
            }
            else if (userName.Equals("Satya"))
            {
                if (actionFeatures.DietaryAttributes.LowSodium)
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nSatya is health conscious, so he bought {actionId} since it's low in sodium.");
                }
                else
                {
                    Console.WriteLine($"\nSatya did not buy {actionId} because it's not low sodium.");
                }
            }
            else if (userName.Equals("Amy"))
            {
                if (actionFeatures.DietaryAttributes.Vegan || actionFeatures.DietaryAttributes.Vegetarian)
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nAmy likes to eat plant-based foods, so she bought {actionId} because it's vegan or vegetarian friendly.");
                }
                else
                {
                    Console.WriteLine($"\nAmy did not buy {actionId} because it's not vegan or vegetarian.");
                }
            }
            return rewardScore;
        }
        // ...
    
  3. Collez votre clé et votre point de terminaison dans le code à l’endroit indiqué. Votre point de terminaison présente la forme https://<your_resource_name>.cognitiveservices.azure.com/.

    Important

    N’oubliez pas de supprimer la clé de votre code une fois que vous avez terminé, et ne la postez jamais publiquement. Pour la production, utilisez un moyen sécurisé de stocker et d’accéder à vos informations d’identification comme Azure Key Vault. Pour plus d’informations, consultez l’article sur la sécurité d’Azure AI services.

Bloc de code 2 : itérer la boucle d’apprentissage

Le bloc de code suivant définit la méthode principale et ferme le script. Il exécute une itération de boucle d’apprentissage, dans laquelle il génère un contexte (y compris un client), demande un classement des actions dans ce contexte à l’aide de l’API Rank, calcule le score de récompense et transmet ce score au service Personalizer à l’aide de l’API Reward. Il imprime les informations pertinentes sur la console à chaque étape.

Dans cet exemple, chaque appel de classement est effectué pour déterminer quel produit doit être affiché dans la section « Produit proposé ». Ensuite, l’appel Reward indique si le produit proposé a été acheté par l’utilisateur. Les récompenses sont associées à leurs décisions par le biais d’une valeur EventId commune.

    static void Main(string[] args)
    {
        int iteration = 1;
        bool runLoop = true;

        // Get the actions list to choose from personalizer with their features.
        IList<RankableAction> actions = GetActions();

        // Initialize Personalizer client.
        PersonalizerClient client = InitializePersonalizerClient(ServiceEndpoint);

        do
        {
            Console.WriteLine("\nIteration: " + iteration++);

            // Get context information.
            Context context = GetContext();

            // Create current context from user specified data.
            IList<object> currentContext = new List<object>() {
            context
        };

            // Generate an ID to associate with the request.
            string eventId = Guid.NewGuid().ToString();

            // Rank the actions
            var request = new RankRequest(actions: actions, contextFeatures: currentContext, eventId: eventId);
            RankResponse response = client.Rank(request);

            Console.WriteLine($"\nPersonalizer service thinks {context.User.Name} would like to have: {response.RewardActionId}.");

            float reward = GetRewardScore(context, response.RewardActionId);

            // Send the reward for the action based on user response.
            client.Reward(response.EventId, new RewardRequest(reward));

            Console.WriteLine("\nPress q to break, any other key to continue:");
            runLoop = !(GetKey() == "Q");

        } while (runLoop);
    }

        private static string GetKey()
    {
        return Console.ReadKey().Key.ToString().Last().ToString().ToUpper();
    }

}

Exécuter le programme

Exécutez l’application avec la commande dotnet run dotnet à partir de votre répertoire d’application.

dotnet run

Lors de la première itération, Personalizer recommande une action aléatoire, car il n’a pas encore été entraîné. Vous pouvez éventuellement exécuter d’autres itérations. Après environ 10 minutes, le service commence à présenter des améliorations dans ses recommandations.

The quickstart program asks a couple of questions to gather user preferences, known as features, then provides the top action.

Générer de nombreux événements pour l’analyse (facultatif)

Vous pouvez facilement générer par exemple 5 000 événements à partir de ce scénario de démarrage rapide, ce qui est suffisant pour avoir de l’expérience avec le mode Apprenti et le mode En ligne, en exécutant des évaluations hors connexion et en créant des évaluations de fonctionnalités. Remplacez la méthode principale ci-dessus par :

    static void Main(string[] args)
    {
    int iteration = 1;
    int runLoop = 0;

    // Get the actions list to choose from personalizer with their features.
    IList<RankableAction> actions = GetActions();

    // Initialize Personalizer client.
    PersonalizerClient client = InitializePersonalizerClient(ServiceEndpoint);

    do
    {
        Console.WriteLine("\nIteration: " + iteration++);

        // Get context information.
        Context context = GetContext();

        // Create current context from user specified data.
        IList<object> currentContext = new List<object>() {
            context
        };

        // Generate an ID to associate with the request.
        string eventId = Guid.NewGuid().ToString();

        // Rank the actions
        var request = new RankRequest(actions: actions, contextFeatures: currentContext, eventId: eventId);
        RankResponse response = client.Rank(request);

        Console.WriteLine($"\nPersonalizer service thinks {context.User.Name} would like to have: {response.RewardActionId}.");

        float reward = GetRewardScore(context, response.RewardActionId);

        // Send the reward for the action based on user response.
        client.Reward(response.EventId, new RewardRequest(reward));

        runLoop = runLoop + 1;

    } while (runLoop < 1000);
}

Le code source associé à ce démarrage rapide est disponible sur GitHub.

Documentation de référence |Code source de la bibliothèque | Package (npm) | Exemples de code de démarrage rapide

Prérequis

  • Abonnement Azure - En créer un gratuitement
  • Installez Node.js et npm (vérifié avec Node.js v14.16.0 et npm 6.14.11).
  • Une fois que vous avez votre abonnement Azure, créez une ressource Personalizer dans le portail Azure pour obtenir votre clé et votre point de terminaison. À la fin du déploiement, sélectionnez Accéder à la ressource.
    • Vous avez besoin de la clé et du point de terminaison de la ressource que vous créez pour connecter votre application à l’API Personalizer. Vous collerez votre clé et votre point de terminaison dans le code ci-dessous plus loin dans le guide de démarrage rapide.
    • Vous pouvez utiliser le niveau tarifaire Gratuit (F0) pour tester le service, puis passer par la suite à un niveau payant pour la production.

Configuration du modèle

Changer la fréquence de mise à jour du modèle

Dans le portail Azure, accédez à la page Configuration de votre ressource Personalizer et passez la fréquence de mise à jour du modèle à 30 secondes. Ainsi, l’apprentissage du modèle est effectué rapidement, ce qui vous permet de voir comment l’action recommandée change pour chaque itération.

Change model update frequency

Modifier le temps d’attente de la récompense

Dans le portail Azure, accédez à la page Configuration de votre ressource Personalizer et passez le temps d’attente de la récompense à 10 minutes. Cela détermine combien de temps le modèle doit attendre avant de recevoir des commentaires de récompense de la recommandation qui a été envoyée. L’apprentissage ne peut avoir lieu tant que le temps d’attente de la récompense n’est pas écoulé.

Change reward wait time

Création d’une application Node.js

Dans une fenêtre de console (telle que cmd, PowerShell ou bash), créez un répertoire pour votre application et accédez-y.

mkdir myapp && cd myapp

Exécutez la commande npm init -y pour créer un fichier package.json.

npm init -y

Créez un script Node.js dans l’éditeur ou l’environnement de développement intégré de votre choix, nommé personalizer-quickstart.js, puis créez des variables pour le point de terminaison et la clé d’abonnement de votre ressource.

Installer la bibliothèque de client

Installez la bibliothèque de client Personalizer pour Node.js avec la commande suivante :

npm install @azure/cognitiveservices-personalizer --save

Installez les packages npm restants pour ce guide de démarrage rapide :

npm install @azure/ms-rest-azure-js @azure/ms-rest-js readline-sync uuid --save

Bloc de code 1 : générer des exemples de données

Personalizer est destiné à s’exécuter sur des applications qui reçoivent et interprètent des données en temps réel. Dans ce guide de démarrage rapide, vous allez utiliser un exemple de code pour générer des actions imaginaires de clients sur le site web d’un commerce. Le bloc de code suivant définit trois méthodes clés : getActionsList, getContextFeaturesList et getReward.

  • getActionsList retourne une liste des choix que le site web du commerce doit classer. Dans cet exemple, les actions sont des produits alimentaires. Chaque choix d’action comporte des détails (caractéristiques) qui peuvent avoir une incidence sur le comportement ultérieur de l’utilisateur. Les actions sont utilisées comme entrée pour l’API Rank

  • getContextFeaturesList retourne une visite de client simulée. Elle sélectionne des détails aléatoires (des caractéristiques de contexte) comme le client présent et l’heure de la visite. En général, le contexte représente l’état actuel de votre application, système, environnement ou utilisateur. L’objet de contexte est utilisé comme entrée pour l’API Rank.

    Les fonctionnalités de contexte de ce guide de démarrage rapide sont très simples. Toutefois, dans un système de production réel, la conception de vos caractéristiques et l’évaluation de leur efficacité sont importantes. Pour obtenir des conseils, reportez-vous à la documentation liée.

  • getReward invite l’utilisateur à évaluer la recommandation du service comme succès ou échec. Cela retourne un score compris entre zéro et un qui représente le succès d’une interaction client. Dans un scénario réel, Personalizer apprend les préférences des utilisateurs à partir d’interactions client en temps réel.

    Dans un système de production réel, le score de récompense doit être conçu pour s’aligner sur vos objectifs métier et vos indicateurs de performance clés. Pour déterminer la façon de calculer la métrique de récompense, il faudra peut-être s’adonner à quelques expérimentations.

Ouvrez personalizer-quickstart.js dans un éditeur de texte ou un environnement de développement intégré, et collez le code ci-dessous.

const uuidv1 = require('uuid/v1');
const Personalizer = require('@azure/cognitiveservices-personalizer');
const CognitiveServicesCredentials = require('@azure/ms-rest-azure-js').CognitiveServicesCredentials;
const readline = require('readline-sync');

function getReward() {
  const answer = readline.question("\nIs this correct (y/n)\n");
  if (answer.toLowerCase() === 'y') {
    console.log("\nGreat| Enjoy your food.");
    return 1;
  }
  console.log("\nYou didn't like the recommended food choice.");
  return 0;
}

function getContextFeaturesList() {
  const timeOfDayFeatures = ['morning', 'afternoon', 'evening', 'night'];
  const tasteFeatures = ['salty', 'sweet'];

  let answer = readline.question("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n");
  let selection = parseInt(answer);
  const timeOfDay = selection >= 1 && selection <= 4 ? timeOfDayFeatures[selection - 1] : timeOfDayFeatures[0];

  answer = readline.question("\nWhat type of food would you prefer (enter number)? 1. salty 2. sweet\n");
  selection = parseInt(answer);
  const taste = selection >= 1 && selection <= 2 ? tasteFeatures[selection - 1] : tasteFeatures[0];

  console.log("Selected features:\n");
  console.log("Time of day: " + timeOfDay + "\n");
  console.log("Taste: " + taste + "\n");

  return [
    {
      "time": timeOfDay
    },
    {
      "taste": taste
    }
  ];
}

function getExcludedActionsList() {
  return [
    "juice"
  ];
}

function getActionsList() {
  return [
    {
      "id": "pasta",
      "features": [
        {
          "taste": "salty",
          "spiceLevel": "medium"
        },
        {
          "nutritionLevel": 5,
          "cuisine": "italian"
        }
      ]
    },
    {
      "id": "ice cream",
      "features": [
        {
          "taste": "sweet",
          "spiceLevel": "none"
        },
        {
          "nutritionalLevel": 2
        }
      ]
    },
    {
      "id": "juice",
      "features": [
        {
          "taste": "sweet",
          "spiceLevel": "none"
        },
        {
          "nutritionLevel": 5
        },
        {
          "drink": true
        }
      ]
    },
    {
      "id": "salad",
      "features": [
        {
          "taste": "salty",
          "spiceLevel": "low"
        },
        {
          "nutritionLevel": 8
        }
      ]
    }
  ];
}

Bloc de code 2 : itérer la boucle d’apprentissage

Le bloc de code suivant définit la méthode principale et ferme le script. Il exécute une itération de boucle d’apprentissage dans laquelle il demande à l’utilisateur ses préférences sur la ligne de commande, puis envoie ces informations à Personalizer qui sélectionnera la meilleure action. L’action sélectionnée est présentée à l’utilisateur, qui effectue un choix à l’aide de la ligne de commande. Ensuite, il envoie un score de récompense au service Personalizer pour signaler la performance du service dans sa sélection.

La boucle d’apprentissage Personalizer est un cycle d’appels aux API Rank et Reward. Dans ce guide de démarrage rapide, chaque appel Rank en vue de personnaliser le contenu est suivi d’un appel Reward qui indique à Personalizer l’efficacité du service.

  1. Ajoutez le code ci-dessous pour personalizer-quickstart.js.

  2. Trouvez votre clé et votre point de terminaison. Votre point de terminaison présente la forme https://<your_resource_name>.cognitiveservices.azure.com/.

    Important

    Accédez au portail Azure. Si la ressource Personalizer que vous avez créée dans la section Prérequis a été déployée, cliquez sur le bouton Accéder à la ressource sous Étapes suivantes. La clé et le point de terminaison se trouvent dans la page Clé et point de terminaison de la ressource, sous Gestion des ressources.

    N’oubliez pas de supprimer la clé de votre code une fois que vous avez terminé, et ne la postez jamais publiquement. Pour la production, envisagez d’utiliser une méthode de stockage et d’accès sécurisée pour vos informations d’identification. Par exemple, Azure Key Vault.

  3. Collez votre clé et votre point de terminaison dans le code à l’endroit indiqué.

    Important

    N’oubliez pas de supprimer la clé de votre code une fois que vous avez terminé, et ne la postez jamais publiquement. Pour la production, utilisez un moyen sécurisé de stocker et d’accéder à vos informations d’identification comme Azure Key Vault. Pour plus d’informations sur la sécurité, consultez l’article sur la sécurité d’Azure AI services.

    async function main() {
    
        // The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
        const serviceKey = "PASTE_YOUR_PERSONALIZER_SUBSCRIPTION_KEY_HERE";
      
        // The endpoint specific to your personalization service instance; 
        // e.g. https://<your-resource-name>.cognitiveservices.azure.com
        const baseUri = "PASTE_YOUR_PERSONALIZER_ENDPOINT_HERE";
      
        const credentials = new CognitiveServicesCredentials(serviceKey);
      
        // Initialize Personalization client.
        const personalizerClient = new Personalizer.PersonalizerClient(credentials, baseUri);
      
      
        let runLoop = true;
      
        do {
      
          let rankRequest = {}
      
          // Generate an ID to associate with the request.
          rankRequest.eventId = uuidv1();
      
          // Get context information from the user.
          rankRequest.contextFeatures = getContextFeaturesList();
      
          // Get the actions list to choose from personalization with their features.
          rankRequest.actions = getActionsList();
      
          // Exclude an action for personalization ranking. This action will be held at its current position.
          rankRequest.excludedActions = getExcludedActionsList();
      
          rankRequest.deferActivation = false;
      
          // Rank the actions
          const rankResponse = await personalizerClient.rank(rankRequest);
      
          console.log("\nPersonalization service thinks you would like to have:\n")
          console.log(rankResponse.rewardActionId);
      
          // Display top choice to user, user agrees or disagrees with top choice
          const reward = getReward();
      
          console.log("\nPersonalization service ranked the actions with the probabilities as below:\n");
          for (let i = 0; i < rankResponse.ranking.length; i++) {
            console.log(JSON.stringify(rankResponse.ranking[i]) + "\n");
          }
      
          // Send the reward for the action based on user response.
      
          const rewardRequest = {
            value: reward
          }
      
          await personalizerClient.events.reward(rankRequest.eventId, rewardRequest);
      
          runLoop = continueLoop();
      
        } while (runLoop);
      }
      
      function continueLoop() {
        const answer = readline.question("\nPress q to break, any other key to continue.\n")
        if (answer.toLowerCase() === 'q') {
          return false;
        }
        return true;
      }
    
    main()
    .then(result => console.log("done"))
    .catch(err=> console.log(err));
    

Exécuter le programme

Exécutez l’application avec la commande Node.js à partir du répertoire de votre application.

node personalizer-quickstart.js

Itérez avec quelques boucles d’apprentissage. Après environ 10 minutes, le service commence à présenter des améliorations dans ses recommandations.

Le code source associé à ce démarrage rapide est disponible sur GitHub.

Documentation de référence | Code source de la bibliothèque | Package (pypi) | Exemples de code de démarrage rapide

Prérequis

  • Abonnement Azure - En créer un gratuitement
  • Python 3.x
  • Une fois que votre abonnement Azure est configuré, créer une ressource Personalizer sur le portail Azure et obtenez votre clé et votre point de terminaison. À la fin du déploiement, sélectionnez Accéder à la ressource.
    • Vous aurez besoin de la clé et du point de terminaison de la ressource créée pour connecter votre application à l'API Personalizer, que vous collerez dans le code de démarrage rapide ci-dessous.
    • Vous pouvez utiliser le niveau tarifaire Gratuit (F0) pour tester le service, puis passer à un niveau payant pour la production plus tard.

Configuration du modèle

Changer la fréquence de mise à jour du modèle

Dans le portail Azure, accédez à la page Configuration de votre ressource Personalizer et passez la fréquence de mise à jour du modèle à 30 secondes. Ainsi, l’apprentissage du modèle est effectué rapidement, ce qui vous permet de voir comment l’action recommandée change pour chaque itération.

Change model update frequency

Modifier le temps d’attente de la récompense

Dans le portail Azure, accédez à la page Configuration de votre ressource Personalizer et passez le temps d’attente de la récompense à 10 minutes. Cela détermine combien de temps le modèle doit attendre avant de recevoir des commentaires de récompense de la recommandation qui a été envoyée. L’apprentissage ne peut avoir lieu tant que le temps d’attente de la récompense n’est pas écoulé.

Change reward wait time

Créer une application Python

Créez un fichier d’application Python nommé personalizer_quickstart.py.

Installer la bibliothèque de client

Installez la bibliothèque de client Personalizer avec pip :

pip install azure-cognitiveservices-personalizer

Bloc de code 1 : générer des exemples de données

Personalizer est destiné à s’exécuter sur des applications qui reçoivent et interprètent des données en temps réel. Pour ce guide de démarrage rapide, vous allez utiliser un exemple de code pour générer des actions imaginaires de clients sur le site web d’un commerce. Le bloc de code suivant définit trois fonctions clés : get_actions, get_context et get_reward_score.

  • get_actions retourne une liste des choix que le site web du commerce doit classer. Dans cet exemple, les actions sont des produits alimentaires. Chaque choix d’action comporte des détails (caractéristiques) qui peuvent avoir une incidence sur le comportement ultérieur de l’utilisateur. Les actions sont utilisées comme entrée pour l’API Rank

  • get_context retourne une visite de client simulée. Elle sélectionne des détails aléatoires (des caractéristiques de contexte) comme le client présent et l’heure de la visite. En général, le contexte représente l’état actuel de votre application, système, environnement ou utilisateur. L’objet de contexte est utilisé comme entrée pour l’API Rank.

    Les fonctionnalités de contexte de ce guide de démarrage rapide sont très simples. Toutefois, dans un système de production réel, la conception de vos caractéristiques et l’évaluation de leur efficacité sont primordiales. Pour obtenir des conseils, reportez-vous à la documentation liée.

  • get_reward_score retourne un score compris entre zéro et un qui représente le succès d’une interaction client. Elle utilise une logique simple pour déterminer comment différents contextes répondront à différents choix d’action. Par exemple, un certain utilisateur donnera toujours un 1,0 pour les produits végétariens et végétaliens, et un 0,0 pour les autres produits. Dans un scénario réel, Personalizer apprend les préférences utilisateur des données envoyées dans les appels d’API Rank et Reward. Vous ne les définissez pas explicitement comme dans l’exemple de code.

    Dans un système de production réel, le score de récompense doit être conçu pour s’aligner sur vos objectifs métier et vos indicateurs de performance clés. Pour déterminer la façon de calculer la métrique de récompense, il faudra peut-être s’adonner à quelques expérimentations.

    Dans le code ci-dessous, les préférences et les réponses des utilisateurs aux actions sont codées en dur sous la forme d’une série d’instructions conditionnelles, et un texte explicatif est inclus dans le code à des fins de démonstration.

Suivez ces étapes pour définir le script Personalizer.

  1. Trouvez votre clé et votre point de terminaison.

    Important

    Accédez au portail Azure. Si la ressource Personalizer que vous avez créée dans la section Prérequis a été déployée, cliquez sur le bouton Accéder à la ressource sous Étapes suivantes. La clé et le point de terminaison se trouvent dans la page Clé et point de terminaison de la ressource, sous Gestion des ressources.

    N’oubliez pas de supprimer la clé de votre code une fois que vous avez terminé, et ne la postez jamais publiquement. Pour la production, envisagez d’utiliser une méthode de stockage et d’accès sécurisée pour vos informations d’identification. Par exemple, Azure Key Vault.

  2. Ouvrez personalizer-quickstart.py dans un éditeur de texte ou un environnement de développement intégré, et collez le code ci-dessous.

  3. Collez votre clé et votre point de terminaison dans le code à l’endroit indiqué. Votre point de terminaison présente la forme https://<your_resource_name>.cognitiveservices.azure.com/.

    Important

    N’oubliez pas de supprimer la clé de votre code une fois que vous avez terminé, et ne la postez jamais publiquement. Pour la production, utilisez un moyen sécurisé de stocker et d’accéder à vos informations d’identification, comme Azure Key Vault. Pour plus d’informations, consultez la sécurité d’Azure AI services.

from azure.cognitiveservices.personalizer import PersonalizerClient
from azure.cognitiveservices.personalizer.models import RankableAction, RewardRequest, RankRequest
from msrest.authentication import CognitiveServicesCredentials

import datetime, json, os, time, uuid, random

key = "paste_your_personalizer_key_here"
endpoint = "paste_your_personalizer_endpoint_here"

# Instantiate a Personalizer client
client = PersonalizerClient(endpoint, CognitiveServicesCredentials(key))

actions_and_features = {
    'pasta': {
        'brand_info': {
            'company':'pasta_inc'
        }, 
        'attributes': {
            'qty':1, 'cuisine':'italian',
            'price':12
        },
        'dietary_attributes': {
            'vegan': False,
            'low_carb': False,
            'high_protein': False,
            'vegetarian': False,
            'low_fat': True,
            'low_sodium': True
        }
    },
    'bbq': {
        'brand_info' : {
            'company': 'ambisco'
        },
        'attributes': {
            'qty': 2,
            'category': 'bbq',
            'price': 20
        }, 
        'dietary_attributes': {
            'vegan': False,
            'low_carb': True,
            'high_protein': True,
            'vegetarian': False,
            'low_fat': False,
            'low_sodium': False
        }
    },
    'bao': {
        'brand_info': {
            'company': 'bao_and_co'
        },
        'attributes': {
            'qty': 4,
            'category': 'chinese',
            'price': 8
        }, 
        'dietary_attributes': {
            'vegan': False,
            'low_carb': True,
            'high_protein': True,
            'vegetarian': False,
            'low_fat': True,
            'low_sodium': False
        }
    },
    'hummus': {
        'brand_info' : { 
            'company': 'garbanzo_inc'
        },
        'attributes' : {
            'qty': 1,
            'category': 'breakfast',
            'price': 5
        }, 
        'dietary_attributes': {
            'vegan': True, 
            'low_carb': False,
            'high_protein': True,
            'vegetarian': True,
            'low_fat': False, 
            'low_sodium': False
        }
    },
    'veg_platter': {
        'brand_info': {
            'company': 'farm_fresh'
        }, 
        'attributes': {
            'qty': 1,
            'category': 'produce', 
            'price': 7
        },
        'dietary_attributes': {
            'vegan': True,
            'low_carb': True,
            'high_protein': False,
            'vegetarian': True,
            'low_fat': True,
            'low_sodium': True
        }
    }
}

def get_actions():
    res = []
    for action_id, feat in actions_and_features.items():
        action = RankableAction(id=action_id, features=[feat])
        res.append(action)
    return res

user_profiles = {
    'Bill': {
        'dietary_preferences': 'low_carb', 
        'avg_order_price': '0-20',
        'browser_type': 'edge'
    },
    'Satya': {
        'dietary_preferences': 'low_sodium',
        'avg_order_price': '201+',
        'browser_type': 'safari'
    },
    'Amy': {
        'dietary_preferences': {
            'vegan', 'vegetarian'
        },
        'avg_order_price': '21-50',
        'browser_type': 'edge'},
    }

def get_context(user):
    location_context = {'location': random.choice(['west', 'east', 'midwest'])}
    time_of_day = {'time_of_day': random.choice(['morning', 'afternoon', 'evening'])}
    app_type = {'application_type': random.choice(['edge', 'safari', 'edge_mobile', 'mobile_app'])}
    res = [user_profiles[user], location_context, time_of_day, app_type]
    return res

def get_random_users(k = 5):
    return random.choices(list(user_profiles.keys()), k=k)


def get_reward_score(user, actionid, context):
    reward_score = 0.0
    action = actions_and_features[actionid]
    
    if user == 'Bill':
        if action['attributes']['price'] < 10 and (context[1]['location'] !=  "midwest"):
            reward_score = 1.0
            print("Bill likes to be economical when he's not in the midwest visiting his friend Warren. He bought", actionid, "because it was below a price of $10.")
        elif (action['dietary_attributes']['low_carb'] == True) and (context[1]['location'] ==  "midwest"):
            reward_score = 1.0
            print("Bill is visiting his friend Warren in the midwest. There he's willing to spend more on food as long as it's low carb, so Bill bought" + actionid + ".")
            
        elif (action['attributes']['price'] >= 10) and (context[1]['location'] != "midwest"):
            print("Bill didn't buy", actionid, "because the price was too high when not visting his friend Warren in the midwest.")
            
        elif (action['dietary_attributes']['low_carb'] == False) and (context[1]['location'] ==  "midwest"):
            print("Bill didn't buy", actionid, "because it's not low-carb, and he's in the midwest visitng his friend Warren.")
             
    elif user == 'Satya':
        if action['dietary_attributes']['low_sodium'] == True:
            reward_score = 1.0
            print("Satya is health conscious, so he bought", actionid,"since it's low in sodium.")
        else:
            print("Satya did not buy", actionid, "because it's not low sodium.")   
            
    elif user == 'Amy':
        if (action['dietary_attributes']['vegan'] == True) or (action['dietary_attributes']['vegetarian'] == True):
            reward_score = 1.0
            print("Amy likes to eat plant-based foods, so she bought", actionid, "because it's vegan or vegetarian friendly.")       
        else:
            print("Amy did not buy", actionid, "because it's not vegan or vegetarian.")
                
    return reward_score
    # ...

Bloc de code 2 : itérer la boucle d’apprentissage

Le bloc de code suivant définit la fonction run_personalizer_cycle et l’appelle dans une boucle de commentaires d’utilisateur simple. Il exécute une itération de boucle d’apprentissage, dans laquelle il génère un contexte (y compris un client), demande un classement des actions dans ce contexte à l’aide de l’API Rank, calcule le score de récompense et transmet ce score au service Personalizer à l’aide de l’API Reward. Il imprime les informations pertinentes sur la console à chaque étape.

Dans cet exemple, chaque appel de classement est effectué pour déterminer quel produit doit être affiché dans la section « Produit proposé ». Ensuite, l’appel Reward indique si le produit proposé a été acheté par l’utilisateur. Les récompenses sont associées à leurs décisions par le biais d’une valeur EventId commune.

def run_personalizer_cycle():
    actions = get_actions()
    user_list = get_random_users()
    for user in user_list:
        print("------------")
        print("User:", user, "\n")
        context = get_context(user)
        print("Context:", context, "\n")
        
        rank_request = RankRequest(actions=actions, context_features=context)
        response = client.rank(rank_request=rank_request)
        print("Rank API response:", response, "\n")
        
        eventid = response.event_id
        actionid = response.reward_action_id
        print("Personalizer recommended action", actionid, "and it was shown as the featured product.\n")
        
        reward_score = get_reward_score(user, actionid, context)
        client.events.reward(event_id=eventid, value=reward_score)     
        print("\nA reward score of", reward_score , "was sent to Personalizer.")
        print("------------\n")

continue_loop = True
while continue_loop:
    run_personalizer_cycle()
    
    br = input("Press Q to exit, or any other key to run another loop: ")
    if(br.lower()=='q'):
        continue_loop = False

Exécuter le programme

Une fois que tout le code ci-dessus est inclus dans votre fichier Python, vous pouvez l’exécuter à partir du répertoire de votre application.

python personalizer-quickstart.py

Lors de la première itération, Personalizer recommande une action aléatoire, car il n’a pas encore été entraîné. Vous pouvez éventuellement exécuter d’autres itérations. Après environ 10 minutes, le service commence à présenter des améliorations dans ses recommandations.

The quickstart program asks a couple of questions to gather user preferences, known as features, then provides the top action.

Générer de nombreux événements pour l’analyse (facultatif)

Vous pouvez facilement générer par exemple 5 000 événements à partir de ce scénario de démarrage rapide, ce qui est suffisant pour avoir de l’expérience avec le mode Apprenti ou le mode En ligne, en exécutant des évaluations hors connexion et en créant des évaluations de fonctionnalités. Remplacez la boucle while du bloc de code ci-dessus par le code suivant.

for i in range(0,1000):
    run_personalizer_cycle()

Le code source associé à ce démarrage rapide est disponible sur GitHub.

Télécharger le modèle entraîné

Si vous souhaitez télécharger un modèle Personalizer qui a été entraîné sur 5 000 événements à partir de l’exemple ci-dessus, consultez le référentiel d’exemples Personalizer et téléchargez le fichier Personalizer_QuickStart_Model.zip. Accédez ensuite à votre ressource Personalizer dans le portail Azure, puis à la page Installation et à l’onglet Importation/exportation, et importez le fichier.

Nettoyer les ressources

Pour nettoyer votre abonnement Azure AI services, vous pouvez supprimer la ressource ou le groupe de ressources, ce qui supprime également toutes les ressources associées.

Étapes suivantes