Quickstart: Personalizer client library

Display personalized content in this python quickstart with the Personalizer service.

Get started with the Personalizer client library. Follow these steps to install the package and try out the example code for basic tasks.

  • Rank API - Selects the best item, from content items, based on real-time information you provide about content and context.
  • Reward API - You determine the reward score based on your business needs, then send it to Personalizer with this API. That score can be a single value such as 1 for good, and 0 for bad, or an algorithm you create based on your business needs.

Reference documentation | Library source code | Package (NuGet) | Samples

Prerequisites

Using this quickstart

There are several steps to use this quickstart:

  • In the Azure portal, create a Personalizer resource
  • In the Azure portal, for the Personalizer resource, on the Configuration page, change the model update frequency to a very short interval
  • In a code editor, create a code file and edit the code file
  • In the command line or terminal, install the SDK from the command line
  • In the command line or terminal, run the code file

Create a Personalizer Azure resource

Create a resource for Personalizer using the Azure portal or Azure CLI on your local machine. You can also:

After you get a key from your trial subscription or resource, create two environment variable:

  • PERSONALIZER_RESOURCE_KEY for the resource key.
  • PERSONALIZER_RESOURCE_ENDPOINT for the resource endpoint.

In the Azure portal, both the key and endpoint values are available from the quickstart page.

Change the model update frequency

In the Azure portal, in the Personalizer resource on the Configuration page, change the Model update frequency to 10 seconds. This short duration will train the service rapidly, allowing you to see how the top action changes for each iteration.

Change model update frequency

When a Personalizer loop is first instantiated, there is no model since there has been no Reward API calls to train from. Rank calls will return equal probabilities for each item. Your application should still always rank content using the output of RewardActionId.

Create a new C# application

Create a new .NET Core application in your preferred editor or IDE.

In a console window (such as cmd, PowerShell, or Bash), use the dotnet new command to create a new console app with the name personalizer-quickstart. This command creates a simple "Hello World" C# project with a single source file: Program.cs.

dotnet new console -n personalizer-quickstart

Change your directory to the newly created app folder. You can build the application with:

dotnet build

The build output should contain no warnings or errors.

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

Install the SDK

Within the application directory, install the Personalizer client library for .NET with the following command:

dotnet add package Microsoft.Azure.CognitiveServices.Personalizer --version 0.8.0-preview

If you're using the Visual Studio IDE, the client library is available as a downloadable NuGet package.

Object model

The Personalizer client is a PersonalizerClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your key.

To ask for the single best item of the content, create a RankRequest, then pass it to client.Rank method. The Rank method returns a RankResponse.

To send a reward score to Personalizer, create a RewardRequest, then pass it to the client.Reward method.

Determining the reward score, in this quickstart is trivial. In a production system, the determination of what impacts the reward score and by how much can be a complex process, that you may decide to change over time. This design decision should be one of the primary decisions in your Personalizer architecture.

Code examples

These code snippets show you how to do the following tasks with the Personalizer client library for .NET:

Add the dependencies

From the project directory, open the Program.cs file in your preferred editor or IDE. Replace the existing using code with the following using directives:

using Microsoft.Azure.CognitiveServices.Personalizer;
using Microsoft.Azure.CognitiveServices.Personalizer.Models;
using System;
using System.Collections.Generic;
using System.Linq;

Add Personalizer resource information

In the Program class, create variables for your resource's Azure key and endpoint pulled from the environment variables, named PERSONALIZER_RESOURCE_KEY and PERSONALIZER_RESOURCE_ENDPOINT. If you created the environment variables after the application is launched, the editor, IDE, or shell running it will need to be closed and reloaded to access the variable. The methods will be created later in this quickstart.

// The key specific to your personalizer resource instance; e.g. "0123456789abcdef0123456789ABCDEF"
private static readonly string ApiKey = Environment.GetEnvironmentVariable("PERSONALIZER_RESOURCE_KEY");

// The endpoint specific to your personalizer resource instance; e.g. https://westus2.api.cognitive.microsoft.com/
private static readonly string ServiceEndpoint = Environment.GetEnvironmentVariable("PERSONALIZER_RESOURCE_ENDPOINT");

Create a Personalizer client

Next, create a method to return a Personalizer client. The parameter to the method is the PERSONALIZER_RESOURCE_ENDPOINT and the ApiKey is the PERSONALIZER_RESOURCE_KEY.

/// <summary>
/// Initializes the personalizer client.
/// </summary>
/// <param name="url">Azure endpoint</param>
/// <returns>Personalizer client instance</returns>
static PersonalizerClient InitializePersonalizerClient(string url)
{
    PersonalizerClient client = new PersonalizerClient(
        new ApiKeyServiceClientCredentials(ApiKey)) {Endpoint = url};

    return client;
}

Get food items as rankable actions

Actions represent the content choices from which you want Personalizer to select the best content item. Add the following methods to the Program class to represent the set of actions and their features.

/// <summary>
/// Creates personalizer actions feature list.
/// </summary>
/// <returns>List of actions for personalizer.</returns>
static IList<RankableAction> GetActions()
{
    IList<RankableAction> actions = new List<RankableAction>
    {
        new RankableAction
        {
            Id = "pasta",
            Features =
            new List<object>() { new { taste = "salty", spiceLevel = "medium" }, new { nutritionLevel = 5, cuisine = "italian" } }
        },

        new RankableAction
        {
            Id = "ice cream",
            Features =
            new List<object>() { new { taste = "sweet", spiceLevel = "none" }, new { nutritionalLevel = 2 } }
        },

        new RankableAction
        {
            Id = "juice",
            Features =
            new List<object>() { new { taste = "sweet", spiceLevel = "none" }, new { nutritionLevel = 5 }, new { drink = true } }
        },

        new RankableAction
        {
            Id = "salad",
            Features =
            new List<object>() { new { taste = "salty", spiceLevel = "low" }, new { nutritionLevel = 8 } }
        }
    };

    return actions;
}

Get user preferences for context

Add the following methods to the Program class to get a user's input from the command line for the time of day and current food preference. These will be used as context features.

/// <summary>
/// Get users time of the day context.
/// </summary>
/// <returns>Time of day feature selected by the user.</returns>
static string GetUsersTimeOfDay()
{
    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];
}
/// <summary>
/// Gets user food preference.
/// </summary>
/// <returns>Food taste feature selected by the user.</returns>
static string GetUsersTastePreference()
{
    string[] tasteFeatures = new string[] { "salty", "sweet" };

    Console.WriteLine("\nWhat type of food would you prefer (enter number)? 1. salty 2. sweet");
    if (!int.TryParse(GetKey(), out int tasteIndex) || tasteIndex < 1 || tasteIndex > tasteFeatures.Length)
    {
        Console.WriteLine("\nEntered value is invalid. Setting feature value to " + tasteFeatures[0] + ".");
        tasteIndex = 1;
    }

    return tasteFeatures[tasteIndex - 1];
}

Both methods use the GetKey method to read the user's selection from the command line.

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

Create the learning loop

The Personalizer learning loop is a cycle of Rank and Reward calls. In this quickstart, each Rank call, to personalize the content, is followed by a Reward call to tell Personalizer how well the service performed.

The following code loops through a cycle of asking the user their preferences at the command line, sending that information to Personalizer to select the best action, presenting the selection to the customer to choose from among the list, then sending a reward score to Personalizer signaling how well the service did in its selection.

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 from the user.
        string timeOfDayFeature = GetUsersTimeOfDay();
        string tasteFeature = GetUsersTastePreference();

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

        // Exclude an action for personalizer ranking. This action will be held at its current position.
        // This simulates a business rule to force the action "juice" to be ignored in the ranking.
        // As juice is excluded, the return of the API will always be with a probability of 0.
        IList<string> excludeActions = new List<string> { "juice" };

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

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

        Console.WriteLine("\nPersonalizer service thinks you would like to have: " + response.RewardActionId + ". Is this correct? (y/n)");

        float reward = 0.0f;
        string answer = GetKey();

        if (answer == "Y")
        {
            reward = 1;
            Console.WriteLine("\nGreat! Enjoy your food.");
        }
        else if (answer == "N")
        {
            reward = 0;
            Console.WriteLine("\nYou didn't like the recommended food choice.");
        }
        else
        {
            Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended food choice.");
        }

        Console.WriteLine("\nPersonalizer service ranked the actions with the probabilities as below:");
        foreach (var rankedResponse in response.Ranking)
        {
            Console.WriteLine(rankedResponse.Id + " " + rankedResponse.Probability);
        }

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

Add the following methods, which get the content choices, before running the code file:

  • GetActions
  • GetUsersTimeOfDay
  • GetUsersTastePreference
  • GetKey

Request the best action

To complete the Rank request, the program asks the user's preferences to create a currentContent of the content choices. The process can create content to exclude from the actions, shown as excludeActions. The Rank request needs the actions and their features, currentContext features, excludeActions, and a unique event ID, to receive the response.

This quickstart has simple context features of time of day and user food preference. In production systems, determining and evaluating actions and features can be a non-trivial matter.

// Get context information from the user.
string timeOfDayFeature = GetUsersTimeOfDay();
string tasteFeature = GetUsersTastePreference();

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

// Exclude an action for personalizer ranking. This action will be held at its current position.
// This simulates a business rule to force the action "juice" to be ignored in the ranking.
// As juice is excluded, the return of the API will always be with a probability of 0.
IList<string> excludeActions = new List<string> { "juice" };

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

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

Send a reward

To get the reward score to send in the Reward request, the program gets the user's selection from the command line, assigns a numeric value to the selection, then sends the unique event ID and the reward score as the numeric value to the Reward API.

This quickstart assigns a simple number as a reward score, either a zero or a 1. In production systems, determining when and what to send to the Reward call can be a non-trivial matter, depending on your specific needs.

float reward = 0.0f;
string answer = GetKey();

if (answer == "Y")
{
    reward = 1;
    Console.WriteLine("\nGreat! Enjoy your food.");
}
else if (answer == "N")
{
    reward = 0;
    Console.WriteLine("\nYou didn't like the recommended food choice.");
}
else
{
    Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended food choice.");
}

Console.WriteLine("\nPersonalizer service ranked the actions with the probabilities as below:");
foreach (var rankedResponse in response.Ranking)
{
    Console.WriteLine(rankedResponse.Id + " " + rankedResponse.Probability);
}

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

Run the program

Run the application with the dotnet run command from your application directory.

dotnet run

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

The source code for this quickstart is available in the Personalizer samples GitHub repository.

Reference documentation | Library source code | Package (pypi) | Samples

Prerequisites

Using this quickstart

There are several steps to use this quickstart:

  • In the Azure portal, create a Personalizer resource
  • In the Azure portal, for the Personalizer resource, on the Configuration page, change the model update frequency to a very short interval
  • In a code editor, create a code file and edit the code file
  • In the command line or terminal, install the SDK from the command line
  • In the command line or terminal, run the code file

Create a Personalizer Azure resource

Create a resource for Personalizer using the Azure portal or Azure CLI on your local machine. You can also:

After you get a key from your trial subscription or resource, create two environment variable:

  • PERSONALIZER_RESOURCE_KEY for the resource key.
  • PERSONALIZER_RESOURCE_ENDPOINT for the resource endpoint.

In the Azure portal, both the key and endpoint values are available from the quickstart page.

Change the model update frequency

In the Azure portal, in the Personalizer resource on the Configuration page, change the Model update frequency to 10 seconds. This short duration will train the service rapidly, allowing you to see how the top action changes for each iteration.

Change model update frequency

When a Personalizer loop is first instantiated, there is no model since there has been no Reward API calls to train from. Rank calls will return equal probabilities for each item. Your application should still always rank content using the output of RewardActionId.

Install the Python library for Personalizer

Install the Personalizer client library for Python with the following command:

pip install azure-cognitiveservices-personalizer

Object model

The Personalizer client is a PersonalizerClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your key.

To ask for the single best item of the content, create a RankRequest, then pass it to client.Rank method. The Rank method returns a RankResponse.

To send a reward score to Personalizer, set the event ID and the reward score (value) to send to the Reward method on the EventOperations class.

Determining the reward, in this quickstart is trivial. In a production system, the determination of what impacts the reward score and by how much can be a complex process, that you may decide to change over time. This should be one of the primary design decisions in your Personalizer architecture.

Code examples

These code snippets show you how to do the following with the Personalizer client library for Python:

Create a new python application

Create a new Python application in your preferred editor or IDE named sample.py.

Add the dependencies

From the project directory, open the sample.py file in your preferred editor or IDE. Add the following:

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

Add Personalizer resource information

Create variables for your resource's Azure key and endpoint pulled from the environment variables, named PERSONALIZER_RESOURCE_KEY and PERSONALIZER_RESOURCE_ENDPOINT. If you created the environment variables after the application is launched, the editor, IDE, or shell running it will need to be closed and reloaded to access the variable. The methods will be created later in this quickstart.

The resource name is part of the endpoint URL: https://<your-resource-name>.api.cognitive.microsoft.com/.

key_var_name = 'PERSONALIZER_KEY'
if not key_var_name in os.environ:
    raise Exception('Please set/export the environment variable: {}'.format(key_var_name))
personalizer_key = os.environ[key_var_name]

# Replace <your-resource-name>: https://<your-resource-name>.api.cognitive.microsoft.com/
endpoint_var_name = 'PERSONALIZER_ENDPOINT'
if not endpoint_var_name in os.environ:
    raise Exception('Please set/export the environment variable: {}'.format(endpoint_var_name))
personalizer_endpoint = os.environ[endpoint_var_name]

Create a Personalizer client

Next, create a method to return a Personalizer client. The parameter to the method is the PERSONALIZER_RESOURCE_ENDPOINT and the ApiKey is the PERSONALIZER_RESOURCE_KEY.

# Instantiate a Personalizer client
client = PersonalizerClient(personalizer_endpoint, CognitiveServicesCredentials(personalizer_key))

Get content choices represented as actions

Actions represent the content choices from which you want Personalizer to select the best content item. Add the following methods to the Program class to represent the set of actions and their features.

def get_actions():
    action1 = RankableAction(id='pasta', features=[{"taste":"salty", "spice_level":"medium"},{"nutrition_level":5,"cuisine":"italian"}])
    action2 = RankableAction(id='ice cream', features=[{"taste":"sweet", "spice_level":"none"}, { "nutritional_level": 2 }])
    action3 = RankableAction(id='juice', features=[{"taste":"sweet", 'spice_level':'none'}, {'nutritional_level': 5}, {'drink':True}])
    action4 = RankableAction(id='salad', features=[{'taste':'salty', 'spice_level':'none'},{'nutritional_level': 2}])
    return [action1, action2, action3, action4]
def get_user_timeofday():
    res={}
    time_features = ["morning", "afternoon", "evening", "night"]
    time = input("What time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n")
    try:
        ptime = int(time)
        if(ptime<=0 or ptime>len(time_features)):
            raise IndexError
        res['time_of_day'] = time_features[ptime-1]
    except (ValueError, IndexError):
        print("Entered value is invalid. Setting feature value to", time_features[0] + ".")
        res['time_of_day'] = time_features[0]
    return res
def get_user_preference():
    res = {}
    taste_features = ['salty','sweet']
    pref = input("What type of food would you prefer? Enter number 1.salty 2.sweet\n")
    
    try:
        ppref = int(pref)
        if(ppref<=0 or ppref>len(taste_features)):
            raise IndexError
        res['taste_preference'] = taste_features[ppref-1]
    except (ValueError, IndexError):
        print("Entered value is invalid. Setting feature value to", taste_features[0]+ ".")
        res['taste_preference'] = taste_features[0]
    return res

Create the learning loop

The Personalizer learning loop is a cycle of Rank and Reward calls. In this quickstart, each rank call, to personalize the content, is followed by a reward call to tell Personalizer how well the service performed.

The following code loops through a cycle of asking the user their preferences at the command line, sending that information to Personalizer to select the best action, presenting the selection to the customer to choose from among the list, then sending a reward to Personalizer signaling how well the service did in its selection.

keep_going = True
while keep_going:

    eventid = str(uuid.uuid4())

    context = [get_user_preference(), get_user_timeofday()]
    actions = get_actions()

    rank_request = RankRequest( actions=actions, context_features=context, excluded_actions=['juice'], event_id=eventid)
    response = client.rank(rank_request=rank_request)
    
    print("Personalizer service ranked the actions with the probabilities listed below:")
    
    rankedList = response.ranking
    for ranked in rankedList:
        print(ranked.id, ':',ranked.probability)

    print("Personalizer thinks you would like to have", response.reward_action_id+".")
    answer = input("Is this correct?(y/n)\n")[0]

    reward_val = "0.0"
    if(answer.lower()=='y'):
        reward_val = "1.0"
    elif(answer.lower()=='n'):
        reward_val = "0.0"
    else:
        print("Entered choice is invalid. Service assumes that you didn't like the recommended food choice.")

    client.events.reward(event_id=eventid, value=reward_val)

    br = input("Press Q to exit, any other key to continue: ")
    if(br.lower()=='q'):
        keep_going = False

Add the following methods, which get the content choices, before running the code file:

  • get_user_preference
  • get_user_timeofday
  • get_actions

Request the best action

To complete the Rank request, the program asks the user's preferences to create a currentContent of the content choices. The process can create content to exclude from the actions, shown as excludeActions. The Rank request needs the actions and their features, currentContext features, excludeActions, and a unique event ID, to receive the response.

This quickstart has simple context features of time of day and user food preference. In production systems, determining and evaluating actions and features can be a non-trivial matter.

rank_request = RankRequest( actions=actions, context_features=context, excluded_actions=['juice'], event_id=eventid)
response = client.rank(rank_request=rank_request)

Send a reward

To get the reward score to send in the Reward request, the program gets the user's selection from the command line, assigns a numeric value to the selection, then sends the unique event ID and the reward score as the numeric value to the Reward API.

This quickstart assigns a simple number as a reward score, either a zero or a 1. In production systems, determining when and what to send to the Reward call can be a non-trivial matter, depending on your specific needs.

reward_val = "0.0"
if(answer.lower()=='y'):
    reward_val = "1.0"
elif(answer.lower()=='n'):
    reward_val = "0.0"
else:
    print("Entered choice is invalid. Service assumes that you didn't like the recommended food choice.")

client.events.reward(event_id=eventid, value=reward_val)

Run the program

Run the application with the python from your application directory.

python sample.py

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

Reference documentation |Library source code | Package (NPM) | Samples

Prerequisites

Using this quickstart

There are several steps to use this quickstart:

  • In the Azure portal, create a Personalizer resource
  • In the Azure portal, for the Personalizer resource, on the Configuration page, change the model update frequency to a very short interval
  • In a code editor, create a code file and edit the code file
  • In the command line or terminal, install the SDK from the command line
  • In the command line or terminal, run the code file

Create a Personalizer Azure resource

Create a resource for Personalizer using the Azure portal or Azure CLI on your local machine. You can also:

After you get a key from your trial subscription or resource, create two environment variable:

  • PERSONALIZER_RESOURCE_KEY for the resource key.
  • PERSONALIZER_RESOURCE_ENDPOINT for the resource endpoint.

In the Azure portal, both the key and endpoint values are available from the quickstart page.

Change the model update frequency

In the Azure portal, in the Personalizer resource on the Configuration page, change the Model update frequency to 10 seconds. This short duration will train the service rapidly, allowing you to see how the top action changes for each iteration.

Change model update frequency

When a Personalizer loop is first instantiated, there is no model since there has been no Reward API calls to train from. Rank calls will return equal probabilities for each item. Your application should still always rank content using the output of RewardActionId.

Create a new Node.js application

In a console window (such as cmd, PowerShell, or Bash), create a new directory for your app, and navigate to it.

mkdir myapp && cd myapp

Run the npm init -y command to create a package.json file.

npm init -y

Install the Node.js library for Personalizer

Install the Personalizer client library for Node.js with the following command:

npm install @azure/cognitiveservices-personalizer --save

Install the remaining NPM packages for this quickstart:

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

Object model

The Personalizer client is a PersonalizerClient object that authenticates to Azure using Microsoft.Rest.ServiceClientCredentials, which contains your key.

To ask for the single best item of the content, create a RankRequest, then pass it to client.Rank method. The Rank method returns a RankResponse.

To send a reward to Personalizer, create a RewardRequest, then pass it to the Reward method on the Events class.

Determining the reward, in this quickstart is trivial. In a production system, the determination of what impacts the reward score and by how much can be a complex process, that you may decide to change over time. This should be one of the primary design decisions in your Personalizer architecture.

Code examples

These code snippets show you how to do the following with the Personalizer client library for Node.js:

Create a new Node.js application

Create a new Node.js application in your preferred editor or IDE named sample.js.

Add the dependencies

Open the sample.js file in your preferred editor or IDE. Add the following requires to add the NPM packages:

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

Add Personalizer resource information

Create variables for your resource's Azure key and endpoint pulled from the environment variables, named PERSONALIZER_KEY and PERSONALIZER_ENDPOINT. If you created the environment variables after the application is launched, the editor, IDE, or shell running it will need to be closed and reloaded to access the variable. The methods will be created later in this quickstart.

// The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
let serviceKey = process.env.PERSONALIZER_KEY;

// The endpoint specific to your personalization service instance; 
// e.g. https://westus2.api.cognitive.microsoft.com
let baseUri = process.env.PERSONALIZER_ENDPOINT;

Create a Personalizer client

Next, create a method to return a Personalizer client. The parameter to the method is the PERSONALIZER_RESOURCE_ENDPOINT and the ApiKey is the PERSONALIZER_RESOURCE_KEY.

let credentials = new CognitiveServicesCredentials(serviceKey);

// Initialize Personalization client.
let personalizerClient = new Personalizer.PersonalizerClient(credentials, baseUri);

Get content choices represented as actions

Actions represent the content choices from which you want Personalizer to select the best content item. Add the following methods to the Program class to represent the set of actions and their features.

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

  var answer = readline.question("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n");
  var selection = parseInt(answer);
  var 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);
  var 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 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
        }
      ]
    }
  ];
}

Create the learning loop

The Personalizer learning loop is a cycle of Rank and Reward calls. In this quickstart, each Rank call, to personalize the content, is followed by a Reward call to tell Personalizer how well the service performed.

The following code loops through a cycle of asking the user their preferences at the command line, sending that information to Personalizer to select the best action, presenting the selection to the customer to choose from among the list, then sending a reward to Personalizer signaling how well the service did in its selection.

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
  let 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
  let reward = getReward();

  console.log("\nPersonalization service ranked the actions with the probabilities as below:\n");
  for (var 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.

  let rewardRequest = {
    value: reward
  }

  await personalizerClient.events.reward(rankRequest.eventId, rewardRequest);

  runLoop = continueLoop();

} while (runLoop);

Take a closer look at the rank and reward calls in the following sections.

Add the following methods, which get the content choices, before running the code file:

  • getActionsList
  • getContextFeaturesList

Request the best action

To complete the Rank request, the program asks the user's preferences to create content choices. The process can create content to exclude from the actions, shown as excludeActions. The Rank request needs the actions and their features, currentContext features, excludeActions, and a unique rank event ID, to receive the ranked response.

This quickstart has simple context features of time of day and user food preference. In production systems, determining and evaluating actions and features can be a non-trivial matter.

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
let rankResponse = await personalizerClient.rank(rankRequest);

Send a reward

To get the reward score to send in the Reward request, the program gets the user's selection from the command line, assigns a numeric value to the selection, then sends the unique event ID and the reward score as the numeric value to the Reward API.

This quickstart assigns a simple number as a reward score, either a zero or a 1. In production systems, determining when and what to send to the Reward call can be a non-trivial matter, depending on your specific needs.

let rewardRequest = {
  value: reward
}

await personalizerClient.events.reward(rankRequest.eventId, rewardRequest);

Run the program

Run the application with the Node.js from your application directory.

node sample.js

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

Clean up resources

If you want to clean up and remove a Cognitive Services subscription, you can delete the resource or resource group. Deleting the resource group also deletes any other resources associated with it.

Next steps