Início Rápido: Biblioteca de clientes do Personalizador

Importante

A partir de 20 de setembro de 2023, você não poderá criar novos recursos do Personalizador. O serviço Personalizador está sendo desativado no dia 1º de outubro de 2026.

Introdução às bibliotecas do cliente do Personalizador do Azure para configurar um loop de aprendizado básico. Um loop de aprendizado é um sistema de decisões e comentários: um aplicativo solicita uma classificação de decisão do serviço, depois usa a escolha mais bem classificada e calcula uma pontuação de recompensa a partir do resultado. Ele retorna a pontuação da recompensa para o serviço. Com o tempo, o Personalizador utiliza algoritmos de inteligência artificial para tomar melhores decisões em qualquer contexto. Siga as etapas a seguir para configurar um aplicativo de exemplo.

Cenário de exemplo

Neste início rápido, um supermercado varejista de eletrônicos quer aumentar a receita, mostrando produtos relevantes e personalizados para cada cliente em seu site. Na página principal, há uma seção "Produto em Destaque" que exibe um produto de refeição pronta para possíveis clientes. O varejista de eletrônicos gostaria de determinar como mostrar o produto certo para o cliente certo, a fim de maximizar a probabilidade de uma compra.

O serviço Personalizador resolve esse problema de forma automatizada, escalonável e adaptável utilizando aprendizado por reforço. Você aprenderá como criar ações e seus recursos, recursos de contexto e pontuações de recompensa. Você usará a biblioteca de clientes do Personalizador para fazer chamadas às APIs de classificação e recompensa.

Documentação de referência | Código-fonte da biblioteca | Pacote (NuGet) | Exemplo de código .NET

Pré-requisitos

  • Assinatura do Azure – Criar uma gratuitamente
  • A versão atual do .NET Core.
  • Depois de obter a assinatura do Azure, criar um recurso do Personalizador no portal do Azure para obter a chave e o ponto de extremidade. Após a implantação, selecione Ir para recurso.
    • Você precisará da chave e do ponto de extremidade do recurso que você criar para conectar o seu aplicativo à API do Personalizador. Cole a chave e o ponto de extremidade no código abaixo mais adiante no guia de início rápido.
    • Use o tipo de preço gratuito (F0) para experimentar o serviço e atualizar mais tarde para um nível pago para produção.

Configuração do modelo

Alterar a frequência de atualização do modelo

No portal do Azure, vá para a página Configuração do recurso Personalizador e altere a Frequência de atualização do modelo para 30 segundos. Essa curta duração treinará o modelo rapidamente, permitindo que você veja como a ação recomendada é alterada a cada iteração.

Change model update frequency

Alterar o tempo de espera da recompensa

No portal do Azure, acesse a página Configuração do recurso Personalizador e altere o Tempo de espera da recompensa para 10 minutos. Isso determina quanto tempo o modelo esperará após o envio de uma recomendação para receber os comentários de recompensa dessa recomendação. O treinamento não ocorrerá até que tenha passado o tempo de espera da recompensa.

Change reward wait time

Criar um aplicativo em C#

Crie um novo aplicativo .NET Core em seu IDE ou editor preferido.

Em uma janela de console (como cmd, PowerShell ou Bash), use o comando dotnet new para criar um novo aplicativo do console com o nome personalizer-quickstart. Esse comando cria um projeto simples em C# do tipo "Olá, Mundo" com um arquivo de origem único: Program.cs.

dotnet new console -n personalizer-quickstart

Altere o diretório para a pasta do aplicativo recém-criado. Em seguida, compile o aplicativo com:

dotnet build

A saída de compilação não deve conter nenhum aviso ou erro.

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

Instalar a biblioteca de clientes

Dentro do diretório do aplicativo, instale a biblioteca de clientes do Personalizador para .NET com o seguinte comando:

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

Dica

Se você estiver usando o IDE do Visual Studio, a biblioteca de clientes estará disponível como um pacote baixável do NuGet.

Bloco de códigos 1: gerar dados de exemplo

O Personalizador destina-se a ser executado em aplicativos que recebem e interpretam dados em tempo real. Neste início rápido, você usará um código de exemplo para gerar as ações imaginárias do cliente em um site de supermercado. O bloco de códigos a seguir define três métodos principais: GetActions , GetContext e GetRewardScore.

  • GetActions retorna uma lista de opções que o site de supermercado precisa classificar. Neste exemplo, as ações são produtos alimentícios. Cada escolha de ação tem detalhes (recursos) que podem afetar o comportamento do usuário mais tarde. As ações são utilizadas como entrada para a API de Classificação

  • GetContext retorna uma visita simulada do cliente. Ele seleciona detalhes aleatórios (recursos de contexto), como qual cliente está presente e a que hora do dia a visita está ocorrendo. Em geral, um contexto representa o estado atual do seu aplicativo, sistema, ambiente ou usuário. O objeto de contexto é usado como entrada para a API de Classificação.

    Neste início rápido, os recursos do contexto são simplistas. Entretanto, em um sistema de produção real, é importante projetar seus recursos e avaliar sua eficácia. Consulte a documentação vinculada para obter as diretrizes.

  • O GetRewardScore retorna uma pontuação entre 0 e 1 que representa o êxito de uma interação com o cliente. Ela usa uma lógica simples para determinar como diferentes contextos respondem a diferentes opções de ação. Por exemplo, um determinado usuário sempre dará um 1,0 para produtos vegetarianos e veganos e um 0,0 para outros produtos. Em um cenário real, o Personalizador aprenderá as preferências do usuário com base nos dados enviados em chamadas à API de classificação e recompensa. Você não as definirá explicitamente como no código de exemplo.

    Em um sistema de produção real, a pontuação de recompensa deve ser projetada para se alinhar aos objetivos de negócios e KPIs. Determinar como calcular a métrica de recompensa pode exigir alguma experiência.

    No código abaixo, as preferências e as respostas dos usuários às ações são embutidas em código como uma série de instruções condicionais, e o texto explicativo é incluído no código para fins demonstrativos.

  1. Encontre sua chave e ponto de extremidade.

    Importante

    Acesse o portal do Azure. Se o recurso do Personalizador que você criou na seção Pré-requisitos tiver sido implantado com êxito, clique no botão Acessar o Recurso em Próximas Etapas. Encontre a chave e o ponto de extremidade na página da chave e do ponto de extremidade do recurso, em gerenciamento de recursos.

    Lembre-se de remover a chave do seu código quando terminar e nunca poste-a publicamente. Para produção, considere o uso de uma maneira segura de armazenar e acessar suas credenciais. Por exemplo, o Azure Key Vault.

  2. Abra o Program.cs em um editor de texto ou IDE e cole o código a seguir.

    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. Cole a chave e o ponto de extremidade no código onde indicado. Seu ponto de extremidade tem a forma https://<your_resource_name>.cognitiveservices.azure.com/.

    Importante

    Lembre-se de remover a chave do seu código quando terminar e nunca poste-a publicamente. Para produção, use uma maneira segura de armazenar e acessar suas credenciais, como o Azure Key Vault. Consulte o artigo sobre segurança do serviços de IA do Azure para obter mais informações.

Bloco de códigos 2: iterar o loop de aprendizado

O próximo bloco de códigos define o método principal e fecha o script. Ele executa uma iteração no loop de aprendizado, na qual gera um contexto (incluindo um cliente), solicita uma classificação de ações nesse contexto usando a API de Classificação, calcula a pontuação da recompensa e passa essa pontuação de volta para o serviço Personalizador usando a API de Recompensa. Ele imprime informações relevantes para o console em cada etapa.

Neste exemplo, cada chamada de Classificação é feita para determinar qual produto deve ser exibido na seção "Produto em Destaque". Em seguida, a chamada de Recompensa indica se o produto em destaque foi ou não comprado pelo usuário. As recompensas são associadas às suas decisões através de um valor EventId comum.

    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();
    }

}

Execute o programa

Execute o aplicativo em seu próprio diretório com o comando dotnet run de dotnet.

dotnet run

Na primeira iteração, o Personalizador recomendará uma ação aleatória, porque ainda não fez nenhum treinamento. Opcionalmente, você pode executar mais iterações. Após cerca de 10 minutos, o serviço começará a mostrar melhorias nas suas recomendações.

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

Gerar muitos eventos para análise (opcional)

Você pode gerar facilmente, digamos, 5.000 eventos a partir desse cenário de início rápido, o que é suficiente para obter experiência usando o modo Aprendiz e o modo Online, executando avaliações offline e criando avaliações de recursos. Substitua o método principal acima por:

    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);
}

O código-fonte para este início rápido está disponível no GitHub.

Documentação de referência |Código-fonte da biblioteca | Pacote (npm) | Exemplos de código de Início Rápido

Pré-requisitos

  • Assinatura do Azure – Criar uma gratuitamente
  • Instale o Node.js e o NPM (verificado com o Node.js v14.16.0 e o npm 6.14.11).
  • Depois de obter a assinatura do Azure, criar um recurso do Personalizador no portal do Azure para obter a chave e o ponto de extremidade. Após a implantação, selecione Ir para recurso.
    • Você precisará da chave e do ponto de extremidade do recurso que você criar para conectar o seu aplicativo à API do Personalizador. Cole a chave e o ponto de extremidade no código abaixo mais adiante no guia de início rápido.
    • Use o tipo de preço gratuito (F0) para experimentar o serviço e atualizar mais tarde para um nível pago para produção.

Configuração do modelo

Alterar a frequência de atualização do modelo

No portal do Azure, vá para a página Configuração do recurso Personalizador e altere a Frequência de atualização do modelo para 30 segundos. Essa curta duração treinará o modelo rapidamente, permitindo que você veja como a ação recomendada é alterada a cada iteração.

Change model update frequency

Alterar o tempo de espera da recompensa

No portal do Azure, acesse a página Configuração do recurso Personalizador e altere o Tempo de espera da recompensa para 10 minutos. Isso determina quanto tempo o modelo esperará após o envio de uma recomendação para receber os comentários de recompensa dessa recomendação. O treinamento não ocorrerá até que tenha passado o tempo de espera da recompensa.

Change reward wait time

Criar um novo aplicativo do Node.js

Em uma janela de console (como cmd, PowerShell ou Bash), crie um novo diretório para seu aplicativo e navegue até ele.

mkdir myapp && cd myapp

Execute o comando npm init -y para criar um arquivo package.json.

npm init -y

Crie um novo script Node.js no seu editor ou IDE preferido chamado personalizer-quickstart.js e crie variáveis para o ponto de extremidade e a chave de assinatura do seu recurso.

Instalar a biblioteca de clientes

Instale a biblioteca de clientes do Personalizador para Node.js com o seguinte comando:

npm install @azure/cognitiveservices-personalizer --save

Instale os pacotes npm restantes para este início rápido:

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

Bloco de códigos 1: gerar dados de exemplo

O Personalizador destina-se a ser executado em aplicativos que recebem e interpretam dados em tempo real. Neste início rápido, você usará um código de exemplo para gerar as ações imaginárias do cliente em um site de supermercado. O bloco de códigos a seguir define três métodos principais: getActionsList , getContextFeaturesList e getReward.

  • getActionsList retorna uma lista de opções que o site de supermercado precisa classificar. Neste exemplo, as ações são produtos alimentícios. Cada escolha de ação tem detalhes (recursos) que podem afetar o comportamento do usuário mais tarde. As ações são utilizadas como entrada para a API de Classificação

  • getContextFeaturesList retorna uma visita simulada do cliente. Ele seleciona detalhes aleatórios (recursos de contexto), como qual cliente está presente e a que hora do dia a visita está ocorrendo. Em geral, um contexto representa o estado atual do seu aplicativo, sistema, ambiente ou usuário. O objeto de contexto é usado como entrada para a API de Classificação.

    Neste início rápido, os recursos do contexto são simplistas. Entretanto, em um sistema de produção real, é importante projetar seus recursos e avaliar sua eficácia. Consulte a documentação vinculada para obter as diretrizes.

  • getReward solicita que o usuário pontue a recomendação do serviço como um êxito ou falha. Ele retorna uma pontuação entre 0 e 1 que representa o êxito de uma interação com o cliente. Em um cenário real, o Personalizador aprenderá as preferências do usuário a partir das interações com o cliente em tempo real.

    Em um sistema de produção real, a pontuação de recompensa deve ser projetada para se alinhar aos objetivos de negócios e KPIs. Determinar como calcular a métrica de recompensa pode exigir alguma experiência.

Abra o personalizer-quickstart.js em um editor de texto ou IDE e cole no código abaixo.

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
        }
      ]
    }
  ];
}

Bloco de códigos 2: iterar o loop de aprendizado

O próximo bloco de códigos define o método principal e fecha o script. Ele executa uma iteração de loop de aprendizado, na qual solicita ao usuário suas preferências na linha de comando e envia essas informações ao Personalizador para selecionar a melhor ação. Ele apresenta a ação selecionada ao usuário, que faz uma escolha usando a linha de comando. Em seguida, ele envia uma pontuação de recompensa para o serviço Personalizador para sinalizar o quão bem o serviço se saiu em sua seleção.

O loop de aprendizado do Personalizador é um ciclo de chamadas de Classificação e Recompensa. Neste início rápido, cada chamada de Classificação, para personalizar o conteúdo, é seguida por uma chamada de Recompensa para informar ao Personalizador o nível de desempenho do serviço.

  1. Adicione o código abaixo ao personalizer-quickstart.js.

  2. Encontre sua chave e ponto de extremidade. Seu ponto de extremidade tem a forma https://<your_resource_name>.cognitiveservices.azure.com/.

    Importante

    Acesse o portal do Azure. Se o recurso do Personalizador que você criou na seção Pré-requisitos tiver sido implantado com êxito, clique no botão Acessar o Recurso em Próximas Etapas. Encontre a chave e o ponto de extremidade na página da chave e do ponto de extremidade do recurso, em gerenciamento de recursos.

    Lembre-se de remover a chave do seu código quando terminar e nunca poste-a publicamente. Para produção, considere o uso de uma maneira segura de armazenar e acessar suas credenciais. Por exemplo, o Azure Key Vault.

  3. Cole a chave e o ponto de extremidade no código onde indicado.

    Importante

    Lembre-se de remover a chave do seu código quando terminar e nunca poste-a publicamente. Para produção, use uma maneira segura de armazenar e acessar suas credenciais, como o Azure Key Vault. Para saber mais sobre segurança, consulte o artigo sobre segurança dos serviços de IA do Azure.

    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));
    

Execute o programa

Execute o aplicativo com o comando Node.js a partir do diretório do aplicativo.

node personalizer-quickstart.js

Iterar através de alguns loops de aprendizagem. Após cerca de 10 minutos, o serviço começará a mostrar melhorias nas suas recomendações.

O código-fonte para este início rápido está disponível no GitHub.

Documentação de referência | Código-fonte da biblioteca | Pacote (pypi) | Exemplos de código de Início Rápido

Pré-requisitos

  • Assinatura do Azure – Criar uma gratuitamente
  • Python 3.x
  • Depois que sua assinatura do Azure estiver configurada, crie um recurso do Personalizador no portal do Azure para obter a chave e o ponto de extremidade. Após a implantação, selecione Ir para recurso.
    • Você precisará da chave e do ponto de extremidade do recurso criado para conectar o aplicativo à API do Personalizador, que você colará no código do guia de início rápido abaixo.
    • Você pode usar o tipo de preço gratuito (F0) para experimentar o serviço e atualizar para um nível pago de produção mais tarde.

Configuração do modelo

Alterar a frequência de atualização do modelo

No portal do Azure, vá para a página Configuração do recurso Personalizador e altere a Frequência de atualização do modelo para 30 segundos. Essa curta duração treinará o modelo rapidamente, permitindo que você veja como a ação recomendada é alterada a cada iteração.

Change model update frequency

Alterar o tempo de espera da recompensa

No portal do Azure, acesse a página Configuração do recurso Personalizador e altere o Tempo de espera da recompensa para 10 minutos. Isso determina quanto tempo o modelo esperará após o envio de uma recomendação para receber os comentários de recompensa dessa recomendação. O treinamento não ocorrerá até que tenha passado o tempo de espera da recompensa.

Change reward wait time

Criar um novo aplicativo Python

Crie um novo arquivo Python chamado personalizer-quickstart.py.

Instalar a biblioteca de clientes

Instalar a biblioteca do cliente Personalizador com pip:

pip install azure-cognitiveservices-personalizer

Bloco de códigos 1: gerar dados de exemplo

O Personalizador destina-se a ser executado em aplicativos que recebem e interpretam dados em tempo real. Para o propósito deste início rápido, você usará um código de exemplo para gerar ações imaginárias do cliente em um site de supermercado. O bloco de códigos a seguir define três funções principais: get_actions, get_context e get_reward_score.

  • get_actions retorna uma lista de opções que o site de supermercado precisa classificar. Neste exemplo, as ações são produtos alimentícios. Cada escolha de ação tem detalhes (recursos) que podem afetar o comportamento do usuário mais tarde. As ações são utilizadas como entrada para a API de Classificação

  • get_context retorna uma visita simulada do cliente. Ele seleciona detalhes aleatórios (recursos de contexto), como qual cliente está presente e a que hora do dia a visita está ocorrendo. Em geral, um contexto representa o estado atual do seu aplicativo, sistema, ambiente ou usuário. O objeto de contexto é usado como entrada para a API de Classificação.

    Neste início rápido, os recursos do contexto são simplistas. Entretanto, em um sistema de produção real, projetar seus recursos e avaliar sua eficácia é muito importante. Consulte a documentação vinculada para obter as diretrizes.

  • get_reward_score retorna uma pontuação entre 0 e 1 que representa o êxito de uma interação com o cliente. Ele usa uma lógica simples para determinar como diferentes contextos responderão a diferentes opções de ação. Por exemplo, um determinado usuário sempre dará um 1,0 para produtos vegetarianos e veganos e um 0,0 para outros produtos. Em um cenário real, o Personalizador aprenderá as preferências do usuário com base nos dados enviados em chamadas à API de classificação e recompensa. Você não as definirá explicitamente como no código de exemplo.

    Em um sistema de produção real, a pontuação de recompensa deve ser projetada para se alinhar aos objetivos de negócios e KPIs. Determinar como calcular a métrica de recompensa pode exigir alguma experiência.

    No código abaixo, as preferências e as respostas dos usuários às ações são embutidas em código como uma série de instruções condicionais, e o texto explicativo é incluído no código para fins demonstrativos.

Siga estas etapas para configurar o script do Personalizador.

  1. Encontre sua chave e ponto de extremidade.

    Importante

    Acesse o portal do Azure. Se o recurso do Personalizador que você criou na seção Pré-requisitos tiver sido implantado com êxito, clique no botão Acessar o Recurso em Próximas Etapas. Encontre a chave e o ponto de extremidade na página da chave e do ponto de extremidade do recurso, em gerenciamento de recursos.

    Lembre-se de remover a chave do seu código quando terminar e nunca poste-a publicamente. Para produção, considere o uso de uma maneira segura de armazenar e acessar suas credenciais. Por exemplo, o Azure Key Vault.

  2. Abra o personalizer-quickstart.py em um editor de texto ou IDE e cole no código abaixo.

  3. Cole a chave e o ponto de extremidade no código onde indicado. Seu ponto de extremidade tem a forma https://<your_resource_name>.cognitiveservices.azure.com/.

    Importante

    Lembre-se de remover a chave do seu código quando terminar e nunca poste-a publicamente. Para produção, use um modo seguro para armazenar e acessar as credenciais, como o Azure Key Vault. Para obter mais informações, consulte a segurança dos serviços de IA do Azure.

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
    # ...

Bloco de códigos 2: iterar o loop de aprendizado

O próximo bloco de códigos define a função run_personalizer_cycle e a chama em um loop de comentários simples do usuário. Ele executa uma iteração no loop de aprendizado, na qual gera um contexto (incluindo um cliente), solicita uma classificação de ações nesse contexto usando a API de Classificação, calcula a pontuação da recompensa e passa essa pontuação de volta para o serviço Personalizador usando a API de Recompensa. Ele imprime informações relevantes para o console em cada etapa.

Neste exemplo, cada chamada de Classificação é feita para determinar qual produto deve ser exibido na seção "Produto em Destaque". Em seguida, a chamada de Recompensa indica se o produto em destaque foi ou não comprado pelo usuário. As recompensas são associadas às suas decisões através de um valor EventId comum.

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

Execute o programa

Depois que todo o código acima for incluído no arquivo Python, você poderá executá-lo no diretório do aplicativo.

python personalizer-quickstart.py

Na primeira iteração, o Personalizador recomendará uma ação aleatória, porque ainda não fez nenhum treinamento. Opcionalmente, você pode executar mais iterações. Após cerca de 10 minutos, o serviço começará a mostrar melhorias nas suas recomendações.

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

Gerar muitos eventos para análise (opcional)

Você pode facilmente gerar, digamos, 5.000 eventos a partir desse cenário de início rápido, o que é suficiente para obter experiência usando o modo Aprendiz, o modo Online, executando avaliações offline e criando avaliações de recursos. Substitua o loop while no bloco de códigos acima pelo código a seguir.

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

O código-fonte para este início rápido está disponível no GitHub.

Baixar o modelo treinado

Se você quiser baixar um modelo do Personalizador que tenha sido treinado nos 5.000 eventos do exemplo acima, visite o repositório Exemplos do Personalizador e baixe o arquivo Personalizer_QuickStart_Model.zip. Em seguida, acesse o recurso Personalizador no portal do Azure, vá para a página Configuração e a guia Importar/exportar e importe o arquivo.

Limpar os recursos

Para limpar sua assinatura dos serviços de IA do Azure, você pode excluir o recurso ou excluir o grupo de recursos, que excluirá todos os recursos associados.

Próximas etapas