Introdução aos vários slots para o Personalizador do Azure

A personalização de vários slots (versão prévia) permite direcionar o conteúdo em layouts da Web, carrossel e listas em que mais de uma ação (como um produto ou conteúdo) é mostrada aos usuários. Com as APIs de vários slots do Personalizador, você pode fazer com que os modelos de IA no Personalizador aprendam quais contextos e produtos do usuário conduzem determinados comportamentos, considerando e aprendendo com o posicionamento em sua interface do usuário. Por exemplo, o Personalizador pode aprender que determinados produtos ou conteúdos induzem a mais cliques como uma barra lateral ou rodapé do que como um destaque principal em uma página.

Neste guia, você aprenderá a usar as APIs de vários slots do Personalizador.

Documentação de referência | Código-fonte da biblioteca | Pacote (NuGet) | Conceito de vários slots | Exemplos

Pré-requisitos

  • Assinatura do Azure – Criar uma gratuitamente
  • A versão atual do .NET Core.
  • Depois de obter a assinatura do Azure, 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 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 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.

Configurando

Atualizar a instância do Personalizador para vários slots

Observação

A personalização de vários slots (versão prévia) afeta outra funcionalidade do serviço Personalizador. Essa alteração não pode ser desfeita. Antes de habilitar a personalização de vários slots, confira Personalização de vários slots (versão prévia).

  1. Desabilite a Otimização Automática no portal do Azure, no recurso Personalizador, em Gerenciamento de Recursos, na página Configurações de modelo e de aprendizado, desative a Otimização Automática e salve a seleção.

Observação

A personalização de vários slots não funcionará, a menos que você desabilite a Otimização Automática. A Otimização Automática para a personalização de vários slots terá suporte no futuro.

  1. Atualize o Personalizador para vários slots no portal do Azure, no recurso Personalizador, em Gerenciamento de Recursos, na página Configurações de modelo e de aprendizado, clique em Exportar configurações de aprendizado. O campo argumentos no arquivo json baixado começará com --cb_explore_adf. Altere isso para --ccb_explore_adf e salve o arquivo. CB (Bandits contextuais) e CCB (Bandits contextuais condicionais) são os algoritmos que o Personalizador usa para personalização de slot único e de vários slots, respectivamente. ADF (recursos dependentes de ação) significa que as ações são expressas/identificadas com recursos.

Configurações de aprendizado antes da alteração

Configurações de aprendizado após a alteração

Na mesma guia no portal, em importar configurações de aprendizado, navegue até encontrar o arquivo json modificado recentemente e faça o upload. Isso atualizará sua instância do Personalizador para ser um Personalizador de "Vários Slots", e agora dará suporte a chamadas de Classificação e de Recompensa de vários slots.

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

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

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

Quando o loop do Personalizador é instanciado pela primeira vez, não há modelo, pois não houve nenhuma chamada à API de Recompensa com base na qual treinar. Chamadas de classificação retornarão probabilidades iguais para cada item. Seu aplicativo ainda deve classificar sempre o conteúdo usando a saída de RewardActionId.

Alterar o tempo de espera da recompensa

No portal do Azure, no recurso do Personalizador na página Configuração, altera o Tempo de espera da recompensa para 10 segundos. Essa duração curta treinará o serviço rapidamente, permitindo que você veja como a ação superior é alterada a cada iteração.

Alterar tempo de espera para a recompensa

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 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. É possível criar 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 Azure.AI.Personalizer --version 2.0.0-beta.2

No diretório do projeto, abra o arquivo Program.cs no IDE ou no editor de sua preferência. Adicione o seguinte usando as orientações:

using System;
using Azure;
using Azure.AI.Personalizer;
using System.Collections.Generic;
using System.Linq;

Modelo de objeto

O cliente do Personalizador é um objeto PersonalizerClient que se autentica no Azure usando Azure.AzureKeyCredential, que contém sua chave.

Para solicitar o melhor item do conteúdo de cada slot, crie um objeto PersonalizerRankMultiSlotOptions e passe-o para [PersonalizerClient.RankMultiSlot](/dotnet/api/azure.ai.personalizer.personalizerclient.rankmultislot?branch=main#azure-ai-personalizer-personalizerclient-rankmultislot(azure-ai-personalizer-personalizerrankmultislotoptions-system-threading-cancellationtoken). O método RankMultiSlot retorna um PersonalizerMultiSlotRankResult.

Para enviar uma pontuação de recompensa ao Personalizador, crie um PersonalizerRewardMultiSlotOptions e transmita-o para o método PersonalizerClient.RewardMultiSlot com a ID de evento correspondente.

A pontuação de recompensa neste início rápido é trivial. Em um sistema de produção, a determinação do que afeta a pontuação de recompensa e em que medida pode ser um processo complexo; você pode decidir alterá-lo ao longo do tempo. Essa decisão de design deve ser uma das principais decisões na arquitetura do Personalizador.

Exemplos de código

Esses snippets de código mostram como realizar as seguintes tarefas com a biblioteca de clientes do Personalizador para .NET:

Autenticar o cliente

Nesta seção, você executará duas etapas:

  • Especificar a sua chave e o ponto de extremidade
  • Criar um cliente do Personalizador

Comece adicionando as linhas a seguir à sua classe do Programa. Certifique-se de adicionar a sua chave e o ponto de extremidade do recurso do Personalizador.

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.

private const string ServiceEndpoint  = "https://REPLACE-WITH-YOUR-PERSONALIZER-RESOURCE-NAME.cognitiveservices.azure.com";
private const string ResourceKey = "<REPLACE-WITH-YOUR-PERSONALIZER-KEY>";

Em seguida, construir as URLs de Classificação e Recompensa.

static PersonalizerClient InitializePersonalizerClient(Uri url)
{
    return new PersonalizerClient(url, new AzureKeyCredential(ResourceKey));
}

Obter opções de conteúdo representadas como ações

As ações representam as opções de conteúdo entre as quais você deseja que o Personalizador selecione o melhor item de conteúdo. Adicione os métodos a seguir à classe Program para representar o conjunto de ações e os recursos.

private static IList<PersonalizerRankableAction> GetActions()
{
    IList<PersonalizerRankableAction> actions = new List<PersonalizerRankableAction>
    {
        new PersonalizerRankableAction(
            id: "Red-Polo-Shirt-432",
            features:
            new List<object>() { new { onSale = "true", price = "20", category = "Clothing" } }
        ),

        new PersonalizerRankableAction(
            id: "Tennis-Racket-133",
            features:
            new List<object>() { new { onSale = "false", price = "70", category = "Sports" } }
        ),

        new PersonalizerRankableAction(
            id: "31-Inch-Monitor-771",
            features:
            new List<object>() { new { onSale = "true", price = "200", category = "Electronics" } }
        ),

        new PersonalizerRankableAction(
            id: "XBox-Series X-117",
            features:
            new List<object>() { new { onSale = "false", price = "499", category = "Electronics" } }
        )
    };

    return actions;
}

Obter slots

Os slots compõem a página com a qual o usuário irá interagir. O Personalizador decidirá qual ação será exibida em cada um dos slots definidos. As ações podem ser excluídas de slots específicos, mostrados como ExcludeActions. BaselineAction é a ação padrão para o slot que teria sido exibido sem o uso do Personalizador.

Este guia de início rápido possui recursos de slot simples. Em sistemas de produção, determinar e avaliarrecursos pode ser uma questão não trivial.

private static IList<PersonalizerSlotOptions> GetSlots()
{
    IList<PersonalizerSlotOptions> slots = new List<PersonalizerSlotOptions>
    {
        new PersonalizerSlotOptions(
            id: "BigHeroPosition",
            features: new List<object>() { new { size = "large", position = "left" } },
            excludedActions: new List<string>() { "31-Inch-Monitor-771" },
            baselineAction: "Red-Polo-Shirt-432"

        ),

        new PersonalizerSlotOptions(
            id: "SmallSidebar",
            features: new List<object>() { new { size = "small", position = "right" } },
            excludedActions: new List<string>() { "Tennis-Racket-133" },
            baselineAction: "XBox-Series X-117"
        ),
    };

    return slots;
}

Obter preferências do usuário para o contexto

Adicione os seguintes métodos à Classe do programa para obter a entrada de um usuário da linha de comando para a hora do dia e o tipo de dispositivo no qual o usuário está. Esses métodos serão usados como recursos de contexto.

static string GetTimeOfDayForContext()
{
    string[] timeOfDayFeatures = new string[] { "morning", "afternoon", "evening", "night" };

    Console.WriteLine("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night");
    if (!int.TryParse(GetKey(), out int timeIndex) || timeIndex < 1 || timeIndex > timeOfDayFeatures.Length)
    {
        Console.WriteLine("\nEntered value is invalid. Setting feature value to " + timeOfDayFeatures[0] + ".");
        timeIndex = 1;
    }

    return timeOfDayFeatures[timeIndex - 1];
}
static string GetDeviceForContext()
{
    string[] deviceFeatures = new string[] { "mobile", "tablet", "desktop" };

    Console.WriteLine("\nWhat is the device type (enter number)? 1. Mobile 2. Tablet 3. Desktop");
    if (!int.TryParse(GetKey(), out int deviceIndex) || deviceIndex < 1 || deviceIndex > deviceFeatures.Length)
    {
        Console.WriteLine("\nEntered value is invalid. Setting feature value to " + deviceFeatures[0] + ".");
        deviceIndex = 1;
    }

    return deviceFeatures[deviceIndex - 1];
}

Os dois métodos usam o método GetKey para ler a seleção do usuário na linha de comando.

private static string GetKey()
{
    return Console.ReadKey().Key.ToString().Last().ToString().ToUpper();
}
private static IList<object> GetContext(string time, string device)
{
    return new List<object>()
    {
        new { time = time },
        new { device = device }
    };
}

Criar o loop de aprendizado

O loop de aprendizado do Personalizador é um ciclo de chamadas de RankMultiSlot e RewardMultiSlot. 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.

O código a seguir executa um loop em um ciclo que inclui perguntas sobre as preferências do usuário através da linha de comando, envio dessas informações ao Personalizador para seleção da melhor ação de cada slot, apresentação da seleção ao cliente para escolha de uma opção na lista e, em seguida, envio de uma pontuação de recompensa ao Personalizador, sinalizando o nível de desempenho do serviço na seleção.

static void Main(string[] args)
{
    Console.WriteLine($"Welcome to this Personalizer Quickstart!\n" +
    $"This code will help you understand how to use the Personalizer APIs (multislot rank and multislot reward).\n" +
    $"Each iteration represents a user interaction and will demonstrate how context, actions, slots, and rewards work.\n" +
    $"Note: Personalizer AI models learn from a large number of user interactions:\n" +
    $"You won't be able to tell the difference in what Personalizer returns by simulating a few events by hand.\n" +
    $"If you want a sample that focuses on seeing how Personalizer learns, see the Python Notebook sample.");

    int iteration = 1;
    bool runLoop = true;

    IList<PersonalizerRankableAction> actions = GetActions();
    IList<PersonalizerSlotOptions> slots = GetSlots();
    PersonalizerClient client = InitializePersonalizerClient(new Uri(ServiceEndpoint));

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

        string timeOfDayFeature = GetTimeOfDayForContext();
        string deviceFeature = GetDeviceForContext();

        IList<object> currentContext = GetContext(timeOfDayFeature, deviceFeature);

        string eventId = Guid.NewGuid().ToString();

        var multiSlotRankOptions = new PersonalizerRankMultiSlotOptions(actions, slots, currentContext, eventId);
        PersonalizerMultiSlotRankResult multiSlotRankResult = client.RankMultiSlot(multiSlotRankOptions);

        for (int i = 0; i < multiSlotRankResult.Slots.Count(); ++i)
        {
            string slotId = multiSlotRankResult.Slots[i].SlotId;
            Console.WriteLine($"\nPersonalizer service decided you should display: { multiSlotRankResult.Slots[i].RewardActionId} in slot {slotId}. Is this correct? (y/n)");

            string answer = GetKey();

            if (answer == "Y")
            {
                client.RewardMultiSlot(eventId, slotId, 1f);
                Console.WriteLine("\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.");
            }
            else if (answer == "N")
            {
                client.RewardMultiSlot(eventId, slotId, 0f);
                Console.WriteLine("\nYou didn't like the recommended item. The application will send Personalizer a reward of 0 for this choice of action for this slot.");
            }
            else
            {
                client.RewardMultiSlot(eventId, slotId, 0f);
                Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended item.");
            }
        }

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

    } while (runLoop);
}

Examine mais detalhadamente as chamadas de classificação e de recompensa nas seções a seguir. Adicione os seguintes métodos, obter as opções de conteúdo, obter slots e enviar solicitações de classificação e recompensa de vários slots antes de executar o arquivo de código:

  • GetActions
  • GetSlots
  • GetTimeOfDayForContext
  • GetDeviceForContext
  • GetKey
  • GetContext

Solicitar a melhor ação

Para concluir a solicitação de Classificação, o programa pergunta as preferências do usuário para criar um Context das opções de conteúdo. A solicitação contém os contextos, as ações e os slots com os respectivos recursos e uma ID de evento exclusiva para receber uma resposta.

Este início rápido tem recursos de contexto simples da hora do dia e do dispositivo do usuário. Em sistemas de produção, determinar e avaliarações e recursos pode ser uma questão não trivial.

string timeOfDayFeature = GetTimeOfDayForContext();
string deviceFeature = GetDeviceForContext();

IList<object> currentContext = GetContext(timeOfDayFeature, deviceFeature);

string eventId = Guid.NewGuid().ToString();

var multiSlotRankOptions = new PersonalizerRankMultiSlotOptions(actions, slots, currentContext, eventId);
PersonalizerMultiSlotRankResult multiSlotRankResult = client.RankMultiSlot(multiSlotRankOptions);

Enviar uma recompensa

Para obter a pontuação de recompensa para a solicitação de Recompensa, o programa obtém a seleção do usuário para cada slot por meio da linha de comando, atribui um valor numérico (pontuação de recompensa) à seleção e envia a ID exclusiva do evento, a ID de slot e a pontuação de recompensa de cada slot como o valor numérico à API de Recompensa. Uma recompensa não precisa ser definida para cada slot.

Este início rápido atribui um número simples como uma pontuação de recompensa, um zero ou um 1. Em sistemas de produção, determinar quando e o que enviar para a chamada de Recompensa pode ser uma questão não trivial, dependendo das suas necessidades específicas.

for (int i = 0; i < multiSlotRankResult.Slots.Count(); ++i)
{
    string slotId = multiSlotRankResult.Slots[i].SlotId;
    Console.WriteLine($"\nPersonalizer service decided you should display: { multiSlotRankResult.Slots[i].RewardActionId} in slot {slotId}. Is this correct? (y/n)");

    string answer = GetKey();

    if (answer == "Y")
    {
        client.RewardMultiSlot(eventId, slotId, 1f);
        Console.WriteLine("\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.");
    }
    else if (answer == "N")
    {
        client.RewardMultiSlot(eventId, slotId, 0f);
        Console.WriteLine("\nYou didn't like the recommended item. The application will send Personalizer a reward of 0 for this choice of action for this slot.");
    }
    else
    {
        client.RewardMultiSlot(eventId, slotId, 0f);
        Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended item.");
    }
}

Execute o programa

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

dotnet run

O programa de Início Rápido faz algumas perguntas para coletar as preferências do usuário, conhecidas como recursos e, em seguida, fornece a ação principal.

O código-fonte desse início rápido está disponível.

Documentação de referência | Vários slots conceituais | Amostras

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, crie um recurso do Personalizador no portal do Azure para obter a chave e o ponto de extremidade. Após a implantação, clique em Ir para o 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 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.

Configurando

Atualizar a instância do Personalizador para vários slots

Observação

A personalização de vários slots (versão prévia) afeta outra funcionalidade do serviço Personalizador. Essa alteração não pode ser desfeita. Antes de habilitar a personalização de vários slots, confira Personalização de vários slots (versão prévia).

  1. Desabilite a Otimização Automática no portal do Azure, no recurso Personalizador, em Gerenciamento de Recursos, na página Configurações de modelo e de aprendizado, desative a Otimização Automática e salve a seleção.

Observação

A personalização de vários slots não funcionará, a menos que você desabilite a Otimização Automática. A Otimização Automática para a personalização de vários slots terá suporte no futuro.

  1. Atualize o Personalizador para vários slots no portal do Azure, no recurso Personalizador, em Gerenciamento de Recursos, na página Configurações de modelo e de aprendizado, clique em Exportar configurações de aprendizado. O campo argumentos no arquivo json baixado começará com --cb_explore_adf. Altere isso para --ccb_explore_adf e salve o arquivo. CB (Bandits contextuais) e CCB (Bandits contextuais condicionais) são os algoritmos que o Personalizador usa para personalização de slot único e de vários slots, respectivamente. ADF (recursos dependentes de ação) significa que as ações são expressas/identificadas com recursos.

Configurações de aprendizado antes da alteração

Configurações de aprendizado após a alteração

Na mesma guia no portal, em importar configurações de aprendizado, navegue até encontrar o arquivo json modificado recentemente e faça o upload. Isso atualizará sua instância do Personalizador para ser um Personalizador de "Vários Slots", e agora dará suporte a chamadas de Classificação e de Recompensa de vários slots.

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

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

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

Quando o loop do Personalizador é instanciado pela primeira vez, não há modelo, pois não houve nenhuma chamada à API de Recompensa com base na qual treinar. Chamadas de classificação retornarão probabilidades iguais para cada item. Seu aplicativo ainda deve classificar sempre o conteúdo usando a saída de RewardActionId.

Alterar o tempo de espera da recompensa

No portal do Azure, no recurso do Personalizador na página Configuração, altera o Tempo de espera da recompensa para 10 segundos. Essa duração curta treinará o serviço rapidamente, permitindo que você veja como a ação superior é alterada a cada iteração.

Alterar tempo de espera para a recompensa

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 aplicativo Node.js no seu editor ou IDE preferencial chamado sample.js e crie variáveis para o ponto de extremidade e a chave de assinatura do recurso.

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.

const axios = require('axios');
const { v4: uuidv4 } = require('uuid');
const readline = require('readline-sync');
// The endpoint specific to your personalization service instance; 
// e.g. https://<your-resource-name>.cognitiveservices.azure.com
const PersonalizationBaseUrl = '<REPLACE-WITH-YOUR-PERSONALIZER-ENDPOINT>';
// The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
const ResourceKey = '<REPLACE-WITH-YOUR-PERSONALIZER-KEY>';

Instalar os pacotes NPM para início rápido

npm install readline-sync uuid axios --save

Modelo de objeto

Para solicitar o melhor item do conteúdo para cada slot, crie uma rankRequest e envie uma solicitação de postagem para multislot/rank. Em seguida, a resposta será analisada em uma rankResponse.

Para enviar uma pontuação de recompensa para o Personalizador, crie uma rewards e envie uma solicitação de postagem para multislot/events/{eventId}/reward.

Determinar a pontuação de recompensa neste início rápido é trivial. Em um sistema de produção, a determinação do que afeta a pontuação de recompensa e em que medida pode ser um processo complexo; você pode decidir alterá-lo ao longo do tempo. Essa decisão de design deve ser uma das principais decisões na arquitetura do Personalizador.

Exemplos de código

Esses trechos de código mostram como realizar as seguintes tarefas enviando solicitações HTTP para NodeJS:

Criar URLs base

Nesta seção, você construirá as URLs de Classificação/Recompensa usando a URL base e os cabeçalhos de solicitação usando a chave de recurso.

const MultiSlotRankUrl = PersonalizationBaseUrl.concat('personalizer/v1.1-preview.1/multislot/rank');
const MultiSlotRewardUrlBase = PersonalizationBaseUrl.concat('personalizer/v1.1-preview.1/multislot/events/');
const Headers = {
    'ocp-apim-subscription-key': ResourceKey,
    'Content-Type': 'application/json'
};

Obter opções de conteúdo representadas como ações

As ações representam as opções de conteúdo entre as quais você deseja que o Personalizador selecione o melhor item de conteúdo. Adicione os métodos a seguir ao script para representar o conjunto de ações e os recursos.

function getActions() {
    return [
        {
            'id': 'Red-Polo-Shirt-432',
            'features': [
                {
                    'onSale': 'true',
                    'price': 20,
                    'category': 'Clothing'
                }
            ]
        },
        {
            'id': 'Tennis-Racket-133',
            'features': [
                {
                    'onSale': 'false',
                    'price': 70,
                    'category': 'Sports'
                }
            ]
        },
        {
            'id': '31-Inch-Monitor-771',
            'features': [
                {
                    'onSale': 'true',
                    'price': 200,
                    'category': 'Electronics'
                }
            ]
        },
        {
            'id': 'XBox-Series X-117',
            'features': [
                {
                    'onSale': 'false',
                    'price': 499,
                    'category': 'Electronics'
                }
            ]
        }
    ];
}

Obter preferências do usuário para o contexto

Adicione os seguintes métodos ao script para obter a entrada de um usuário da linha de comando para a hora do dia e o tipo de dispositivo no qual o usuário está. Eles serão usados como recursos de contexto.

function getContextFeatures() {
    const timeOfDayFeatures = ['morning', 'afternoon', 'evening', 'night'];
    const deviceFeatures = ['mobile', 'tablet', 'desktop'];

    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 device is the user on (enter number)? 1. mobile 2. tablet 3. desktop\n');
    selection = parseInt(answer);
    const device = selection >= 1 && selection <= 3 ? deviceFeatures[selection - 1] : deviceFeatures[0];

    console.log('Selected features:\n');
    console.log('Time of day: ' + timeOfDay + '\n');
    console.log('Device: ' + device + '\n');

    return [
        {
            'time': timeOfDay
        },
        {
            'device': device
        }
    ];
}

Obter slots

Os slots compõem a página com a qual o usuário irá interagir. O Personalizador decidirá qual ação será exibida em cada um dos slots definidos. As ações podem ser excluídas de slots específicos, mostrados como ExcludeActions. BaselineAction é a ação padrão para o slot que teria sido exibido sem o uso do Personalizador.

Este guia de início rápido possui recursos de slot simples. Em sistemas de produção, determinar e avaliarrecursos pode ser uma questão não trivial.

function getSlots() {
    return [
        {
            'id': 'BigHeroPosition',
            'features': [
                {
                    'size': 'large',
                    'position': 'left',
                }
            ],
            'excludedActions': ['31-Inch-Monitor-771'],
            'baselineAction': 'Red-Polo-Shirt-432'
        },
        {
            'id': 'SmallSidebar',
            'features': [
                {
                    'size': 'small',
                    'position': 'right',
                }
            ],
            'excludedActions': ['Tennis-Racket-133'],
            'baselineAction': 'XBox-Series X-117'
        }
    ];
}

Fazer solicitações HTTP

Adicione estas funções para enviar solicitações de postagem ao ponto de extremidade do Personalizador para as chamadas de classificação e de recompensa de vários slots.

async function sendMultiSlotRank(rankRequest) {
    try {
        let response = await axios.post(MultiSlotRankUrl, rankRequest, { headers: Headers })
        return response.data;
    }
    catch (err) {
        if(err.response)
        {
            throw err.response.data
        }
        console.log(err)
        throw err;
    }
}
async function sendMultiSlotReward(rewardRequest, eventId) {
    try {
        let rewardUrl = MultiSlotRewardUrlBase.concat(eventId, '/reward');
        let response = await axios.post(rewardUrl, rewardRequest, { headers: Headers })
    }
    catch (err) {
        console.log(err);
        throw err;
    }
}

Obter comentários sobre decisões do Personalizador

Adicione o método a seguir ao script. Você irá sinalizar se o Personalizador tomou uma boa decisão para cada slot através do prompt de linha de comando.

function getRewardForSlot() {
    let answer = readline.question('\nIs this correct? (y/n)\n').toUpperCase();
    if (answer === 'Y') {
        console.log('\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.\n');
        return 1;
    }
    else if (answer === 'N') {
        console.log('\nYou didn\'t like the recommended item.The application will send Personalizer a reward of 0 for this choice of action for this slot.\n');
        return 0;
    }
    console.log('\nEntered choice is invalid. Service assumes that you didn\'t like the recommended item.\n');
    return 0;
}

Criar o loop de aprendizado

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.

O código a seguir executa um loop em um ciclo que inclui perguntas sobre as preferências do usuário através da linha de comando, envio dessas informações ao Personalizador para seleção da melhor ação de cada slot, apresentação da seleção ao cliente para escolha de uma opção na lista e, em seguida, envio de uma pontuação de recompensa ao Personalizador, sinalizando o nível de desempenho do serviço na seleção.

let runLoop = true;

(async () => {
    do {

        let multiSlotRankRequest = {};

        // Generate an ID to associate with the request.
        multiSlotRankRequest.eventId = uuidv4();

        // Get context information from the user.
        multiSlotRankRequest.contextFeatures = getContextFeatures();

        // Get the actions list to choose from personalization with their features.
        multiSlotRankRequest.actions = getActions();

        // Get the list of slots for which Personalizer will pick the best action.
        multiSlotRankRequest.slots = getSlots();

        multiSlotRankRequest.deferActivation = false;

        try {
            //Rank the actions for each slot
            let multiSlotRankResponse = await sendMultiSlotRank(multiSlotRankRequest);
            let multiSlotrewards = {};
            multiSlotrewards.reward = [];
    
            for (let i = 0; i < multiSlotRankResponse.slots.length; i++) {
                console.log('\nPersonalizer service decided you should display: '.concat(multiSlotRankResponse.slots[i].rewardActionId, ' in slot ', multiSlotRankResponse.slots[i].id, '\n'));
    
                let slotReward = {};
                slotReward.slotId = multiSlotRankResponse.slots[i].id;
                // User agrees or disagrees with Personalizer decision for slot
                slotReward.value = getRewardForSlot();
                multiSlotrewards.reward.push(slotReward);
            }
    
            // Send the rewards for the event
            await sendMultiSlotReward(multiSlotrewards, multiSlotRankResponse.eventId);
    
            let answer = readline.question('\nPress q to break, any other key to continue:\n').toUpperCase();
            if (answer === 'Q') {
                runLoop = false;
            }
        }
        catch (err) {
            console.log(err);
            throw err;
        }



    } while (runLoop);
})()

Examine mais detalhadamente as chamadas de classificação e de recompensa nas seções a seguir.

Adicione os seguintes métodos, obter as opções de conteúdo, obter as preferências do usuário para contexto, obter os slots, Fazer solicitações HTTP, Obter recompensa para cada slot antes de executar o arquivo de código:

  • getActions
  • getContextFeatures
  • getSlots
  • sendRank
  • sendReward
  • getRewardForSlot

Solicitar a melhor ação

Para concluir a solicitação de Classificação, o programa pergunta as preferências do usuário para criar as opções de conteúdo. O corpo da solicitação contém o contexto, as ações e os slots com os respectivos recursos. O método sendMultiSlotRank ingere uma rankRequest e executa a solicitação de classificação de vários slots.

Este início rápido tem recursos de contexto simples da hora do dia e do dispositivo do usuário. Em sistemas de produção, determinar e avaliarações e recursos pode ser uma questão não trivial.

let multiSlotRankRequest = {};

// Generate an ID to associate with the request.
multiSlotRankRequest.eventId = uuidv4();

// Get context information from the user.
multiSlotRankRequest.contextFeatures = getContextFeatures();

// Get the actions list to choose from personalization with their features.
multiSlotRankRequest.actions = getActions();

// Get the list of slots for which Personalizer will pick the best action.
multiSlotRankRequest.slots = getSlots();

multiSlotRankRequest.deferActivation = false;

//Rank the actions for each slot
try {
    let multiSlotRankResponse = await sendMultiSlotRank(multiSlotRankRequest);
}
catch (err) {
    console.log(err);
    throw err;
}

Enviar uma recompensa

Para obter a pontuação de recompensa para a solicitação de Recompensa, o programa obtém a seleção do usuário para cada slot por meio da linha de comando, atribui um valor numérico (pontuação de recompensa) à seleção e envia a ID exclusiva do evento, a ID de slot e a pontuação de recompensa de cada slot ao método sendMultiSlotReward. Uma recompensa não precisa ser definida para cada slot.

Este início rápido atribui um número simples como uma pontuação de recompensa, um zero ou um 1. Em sistemas de produção, determinar quando e o que enviar para a chamada de Recompensa pode ser uma questão não trivial, dependendo das suas necessidades específicas.

let multiSlotrewards = {};
multiSlotrewards.reward = [];

for (i = 0; i < multiSlotRankResponse.slots.length; i++) {
    console.log('\nPersonalizer service decided you should display: '.concat(multiSlotRankResponse.slots[i].rewardActionId, ' in slot ', multiSlotRankResponse.slots[i].id, '\n'));

    let slotReward = {};
    slotReward.slotId = multiSlotRankResponse.slots[i].id;
    // User agrees or disagrees with Personalizer decision for slot
    slotReward.value = getRewardForSlot();
    multiSlotrewards.reward.push(slotReward);
}

// Send the rewards for the event
await sendMultiSlotReward(multiSlotrewards, multiSlotRankResponse.eventId);

Execute o programa

Execute o aplicativo com o Node.js no diretório do aplicativo.

node sample.js

O programa de Início Rápido faz algumas perguntas para coletar as preferências do usuário, conhecidas como recursos e, em seguida, fornece a ação principal.

O código-fonte desse início rápido está disponível.

Vários slots conceituais | Amostras

Pré-requisitos

  • Assinatura do Azure – Criar uma gratuitamente
  • Python 3.x
  • Depois de obter a assinatura do Azure, crie um recurso do Personalizador no portal do Azure para obter a chave e o ponto de extremidade. Após a implantação, clique em Ir para o 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 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.

Configurando

Atualizar a instância do Personalizador para vários slots

Observação

A personalização de vários slots (versão prévia) afeta outra funcionalidade do serviço Personalizador. Essa alteração não pode ser desfeita. Antes de habilitar a personalização de vários slots, confira Personalização de vários slots (versão prévia).

  1. Desabilite a Otimização Automática no portal do Azure, no recurso Personalizador, em Gerenciamento de Recursos, na página Configurações de modelo e de aprendizado, desative a Otimização Automática e salve a seleção.

Observação

A personalização de vários slots não funcionará, a menos que você desabilite a Otimização Automática. A Otimização Automática para a personalização de vários slots terá suporte no futuro.

  1. Atualize o Personalizador para vários slots no portal do Azure, no recurso Personalizador, em Gerenciamento de Recursos, na página Configurações de modelo e de aprendizado, clique em Exportar configurações de aprendizado. O campo argumentos no arquivo json baixado começará com --cb_explore_adf. Altere isso para --ccb_explore_adf e salve o arquivo. CB (Bandits contextuais) e CCB (Bandits contextuais condicionais) são os algoritmos que o Personalizador usa para personalização de slot único e de vários slots, respectivamente. ADF (recursos dependentes de ação) significa que as ações são expressas/identificadas com recursos.

Configurações de aprendizado antes da alteração

Configurações de aprendizado após a alteração

Na mesma guia no portal, em importar configurações de aprendizado, navegue até encontrar o arquivo json modificado recentemente e faça o upload. Isso atualizará sua instância do Personalizador para ser um Personalizador de "Vários Slots", e agora dará suporte a chamadas de Classificação e de Recompensa de vários slots.

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

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

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

Quando o loop do Personalizador é instanciado pela primeira vez, não há modelo, pois não houve nenhuma chamada à API de Recompensa com base na qual treinar. Chamadas de classificação retornarão probabilidades iguais para cada item. Seu aplicativo ainda deve classificar sempre o conteúdo usando a saída de RewardActionId.

Alterar o tempo de espera da recompensa

No portal do Azure, no recurso do Personalizador na página Configuração, altera o Tempo de espera da recompensa para 10 segundos. Essa duração curta treinará o serviço rapidamente, permitindo que você veja como a ação superior é alterada a cada iteração.

Alterar tempo de espera para a recompensa

Criar um novo aplicativo Python

Crie um arquivo Python e as variáveis para a chave de assinatura e o ponto de extremidade do recurso.

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.

import json, uuid, requests

# The endpoint specific to your personalization service instance; 
# e.g. https://<your-resource-name>.cognitiveservices.azure.com
PERSONALIZATION_BASE_URL = "<REPLACE-WITH-YOUR-PERSONALIZER-ENDPOINT>"
# The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
RESOURCE_KEY = "<REPLACE-WITH-YOUR-PERSONALIZER-KEY>"

Modelo de objeto

Para solicitar o melhor item do conteúdo para cada slot, crie uma rank_request e envie uma solicitação de postagem para multislot/rank. A resposta é analisada em um rank_response.

Para enviar uma pontuação de recompensa para o Personalizador, crie um rewards e envie uma solicitação de postagem para multislot/events/{eventId}/reward.

Neste início rápido, determinar a pontuação de recompensa é trivial. Em um sistema de produção, a determinação do que afeta a pontuação de recompensa e em que medida pode ser um processo complexo, você pode decidir alterá-lo ao longo do tempo. Essa decisão de design deve ser uma das principais decisões na arquitetura do Personalizador.

Exemplos de código

Esses trechos de código mostram como realizar as seguintes tarefas enviando solicitações HTTP para Python:

Criar URLs base

Nesta seção, você construirá as URLs de Classificação/Recompensa usando a URL base e os cabeçalhos de solicitação usando a chave de recurso.

MULTI_SLOT_RANK_URL = '{0}personalizer/v1.1-preview.1/multislot/rank'.format(PERSONALIZATION_BASE_URL)
MULTI_SLOT_REWARD_URL_BASE = '{0}personalizer/v1.1-preview.1/multislot/events/'.format(PERSONALIZATION_BASE_URL)
HEADERS = {
    'ocp-apim-subscription-key': RESOURCE_KEY,
    'Content-Type': 'application/json'
}

Obter opções de conteúdo representadas como ações

As ações representam as opções de conteúdo entre as quais você deseja que o Personalizador selecione o melhor item de conteúdo. Adicione os métodos a seguir ao script para representar o conjunto de ações e os recursos.

def get_actions():
    return [
        {
            "id": "Red-Polo-Shirt-432",
            "features": [
                {
                    "onSale": "true",
                    "price": 20,
                    "category": "Clothing"
                }
            ]
        },
        {
            "id": "Tennis-Racket-133",
            "features": [
                {
                    "onSale": "false",
                    "price": 70,
                    "category": "Sports"
                }
            ]
        },
        {
            "id": "31-Inch-Monitor-771",
            "features": [
                {
                    "onSale": "true",
                    "price": 200,
                    "category": "Electronics"
                }
            ]
        },
        {
            "id": "XBox-Series X-117",
            "features": [
                {
                    "onSale": "false",
                    "price": 499,
                    "category": "Electronics"
                }
            ]
        }
    ]

Obter preferências do usuário para o contexto

Adicione os seguintes métodos ao script para obter a entrada de um usuário da linha de comando para a hora do dia e o tipo de dispositivo no qual o usuário está. Eles serão usados como recursos de contexto.

def get_context_features():
    time_features = ["morning", "afternoon", "evening", "night"]
    time_pref = input("What time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n")
    try:
        parsed_time = int(time_pref)
        if(parsed_time <=0 or parsed_time > len(time_features)):
            raise IndexError
        time_of_day = time_features[parsed_time-1]
    except (ValueError, IndexError):
        print("Entered value is invalid. Setting feature value to", time_features[0] + ".")
        time_of_day = time_features[0]

    device_features = ['mobile', 'tablet', 'desktop']
    device_pref = input("What type of device is the user on (enter number)? 1. mobile 2. tablet 3. desktop\n")
    try:
        parsed_device = int(device_pref)
        if(parsed_device <=0 or parsed_device > len(device_features)):
            raise IndexError
        device = device_features[parsed_device-1]
    except (ValueError, IndexError):
        print("Entered value is invalid. Setting feature value to", device_features[0]+ ".")
        device = device_features[0]

    return [
        {'time': time_of_day},
        {'device': device}
        ]

Obter slots

Os slots compõem a página com a qual o usuário irá interagir. O Personalizador decidirá qual ação será exibida em cada um dos slots definidos. As ações podem ser excluídas de slots específicos, mostrados como ExcludeActions. BaselineAction é a ação padrão para o slot que teria sido exibido sem o uso do Personalizador.

Este guia de início rápido possui recursos de slot simples. Em sistemas de produção, determinar e avaliarrecursos pode ser uma questão não trivial.

def get_slots():
    return [
        {
            "id": "BigHeroPosition",
            "features": [
                {
                    "size": "large",
                    "position": "left",
                }
            ],
            "excludedActions": ["31-Inch-Monitor-771"],
            "baselineAction": "Red-Polo-Shirt-432"
        },
        {
            "id": "SmallSidebar",
            "features": [
                {
                    "size": "small",
                    "position": "right",
                }
            ],
            "excludedActions": ["Tennis-Racket-133"],
            "baselineAction": "XBox-Series X-117"
        }
    ]

Fazer solicitações HTTP

Adicione estas funções para enviar solicitações de postagem ao ponto de extremidade do Personalizador para as chamadas de classificação e de recompensa de vários slots.

def send_multi_slot_rank(rank_request):
multi_slot_response = requests.post(MULTI_SLOT_RANK_URL, data=json.dumps(rank_request), headers=HEADERS)
if multi_slot_response.status_code != 201:
    raise Exception(multi_slot_response.text)
return json.loads(multi_slot_response.text)
def send_multi_slot_reward(reward_request, event_id):
    reward_url = '{0}{1}/reward'.format(MULTI_SLOT_REWARD_URL_BASE, event_id)
    requests.post(reward_url, data=json.dumps(reward_request), headers=HEADERS)

Obter comentários sobre decisões do Personalizador

Adicione o método a seguir ao script. Você irá sinalizar se o Personalizador tomou uma boa decisão para cada slot através do prompt de linha de comando.

def get_reward_for_slot():
    answer = input('\nIs this correct? (y/n)\n').upper()
    if (answer == 'Y'):
        print('\nGreat! The application will send Personalizer a reward of 1 so it learns from this choice of action for this slot.\n')
        return 1
    elif (answer == 'N'):
        print('\nYou didn\'t like the recommended item.The application will send Personalizer a reward of 0 for this choice of action for this slot.\n')
        return 0
    print('\nEntered choice is invalid. Service assumes that you didn\'t like the recommended item.\n')
    return 0

Criar o loop de aprendizado

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.

O código a seguir executa um loop em um ciclo que inclui perguntas sobre as preferências do usuário através da linha de comando, envio dessas informações ao Personalizador para seleção da melhor ação de cada slot, apresentação da seleção ao cliente para escolha de uma opção na lista e, em seguida, envio de uma pontuação de recompensa ao Personalizador, sinalizando o nível de desempenho do serviço na seleção.

run_loop = True

while run_loop:

    eventId = str(uuid.uuid4())
    context = get_context_features()
    actions = get_actions()
    slots = get_slots()

    rank_request = {
        "eventId": eventId,
        "contextFeatures": context,
        "actions": actions,
        "slots": slots,
        "deferActivation": False
      }

    #Rank the actions for each slot
    multi_slot_rank_response = send_multi_slot_rank(rank_request)
    multi_slot_rewards = {"reward": []}

    for i in range(len(multi_slot_rank_response['slots'])):
        print('\nPersonalizer service decided you should display: {0} in slot {1}\n'.format(multi_slot_rank_response['slots'][i]['rewardActionId'], multi_slot_rank_response['slots'][i]['id']))

        slot_reward = {'slotId': multi_slot_rank_response['slots'][i]['id']}
        # User agrees or disagrees with Personalizer decision for slot
        slot_reward['value'] = get_reward_for_slot()
        multi_slot_rewards['reward'].append(slot_reward)

    # Send the rewards for the event
    send_multi_slot_reward(multi_slot_rewards, multi_slot_rank_response['eventId'])

    answer = input('\nPress q to break, any other key to continue:\n').upper()
    if (answer == 'Q'):
        run_loop = False

Examine mais detalhadamente as chamadas de classificação e de recompensa nas seções a seguir.

Adicione os seguintes métodos, obter as opções de conteúdo, obter as preferências do usuário para contexto, obter os slots, Fazer solicitações HTTP, Obter recompensa para cada slot antes de executar o arquivo de código:

  • get_actions
  • get_context_features
  • get_slots
  • send_rank
  • send_reward
  • get_reward_for_dsot

Solicitar a melhor ação

Para concluir a solicitação de Classificação, o programa pergunta as preferências do usuário para criar as opções de conteúdo. O corpo da solicitação contém o contexto, as ações e os slots com os respectivos recursos. O método send_multi_slot_rank ingere uma rankRequest e executa a solicitação de classificação de vários slots.

Este início rápido tem recursos de contexto simples da hora do dia e do dispositivo do usuário. Em sistemas de produção, determinar e avaliarações e recursos pode ser uma questão não trivial.

eventId = str(uuid.uuid4())
context = get_context_features()
actions = get_actions()
slots = get_slots()

rank_request = {
    "eventId": eventId,
    "contextFeatures": context,
    "actions": actions,
    "slots": slots,
    "deferActivation": False
    }

#Rank the actions for each slot
multi_slot_rank_response = send_multi_slot_rank(rank_request)

Enviar uma recompensa

Para obter a pontuação de recompensa para a solicitação de Recompensa, o programa obtém a seleção do usuário para cada slot por meio da linha de comando, atribui um valor numérico (pontuação de recompensa) à seleção e envia a ID exclusiva do evento, a ID de slot e a pontuação de recompensa de cada slot ao método send_multi_slot_reward. Uma recompensa não precisa ser definida para cada slot.

Este início rápido atribui um número simples como uma pontuação de recompensa, um zero ou um 1. Em sistemas de produção, determinar quando e o que enviar para a chamada de Recompensa pode ser uma questão não trivial, dependendo das suas necessidades específicas.

multi_slot_rewards = {"reward": []}

for i in range(len(multi_slot_rank_response['slots'])):
    print('\nPersonalizer service decided you should display: {0} in slot {1}\n'.format(multi_slot_rank_response['slots'][i]['rewardActionId'], multi_slot_rank_response['slots'][i]['id']))

    slot_reward = {'slotId': multi_slot_rank_response['slots'][i]['id']}
    # User agrees or disagrees with Personalizer decision for slot
    slot_reward['value'] = get_reward_for_slot()
    multi_slot_rewards['reward'].append(slot_reward)

# Send the rewards for the event
send_multi_slot_reward(multi_slot_rewards, multi_slot_rank_response['eventId'])

Execute o programa

Execute o aplicativo com o Python no diretório do aplicativo.

python sample.py

O programa de Início Rápido faz algumas perguntas para coletar as preferências do usuário, conhecidas como recursos e, em seguida, fornece a ação principal.

O código-fonte desse início rápido está disponível.

Próximas etapas