Skip to content

Commit bedbb5c

Browse files
authored
Merge pull request #127558 from erhopf/personalizer-seo
[CogSvcs] Personalizer SEO and Quickstart Improvements
2 parents 8c07afa + 4169a69 commit bedbb5c

File tree

8 files changed

+605
-152
lines changed

8 files changed

+605
-152
lines changed

.openpublishing.redirection.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56349,6 +56349,11 @@
5634956349
"redirect_url": "how-to-upload-media?tabs=rest",
5635056350
"redirect_document_id": false
5635156351
},
56352+
{
56353+
"source_path": "articles/cognitive-services/personalizer/sdk-learning-loop.md",
56354+
"redirect_url": "/azure/cognitive-services/personalizer/quickstart-personalizer-sdk",
56355+
"redirect_document_id": true
56356+
},
5635256357
{
5635356358
"source_path": "articles/service-fabric/service-fabric-scale-up-node-type.md",
5635456359
"redirect_url": "/azure/service-fabric/service-fabric-scale-up-primary-node-type",

articles/cognitive-services/personalizer/includes/change-model-frequency.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ ms.service: cognitive-services
77
ms.subservice: personalizer
88
ms.topic: include
99
ms.custom: include file
10-
ms.date: 01/15/2020
10+
ms.date: 08/25/2020
1111
---
12-
## Change the model update frequency
12+
### Change the model update frequency
1313

1414
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.
1515

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
title: Find your Personalizer resource endpoint and key
3+
titleSuffix: Azure Cognitive Services
4+
services: cognitive-services
5+
author: erhopf
6+
manager: nitinme
7+
ms.service: cognitive-services
8+
ms.topic: include
9+
ms.date: 08/25/2019
10+
ms.author: erhopf
11+
---
12+
13+
> [!IMPORTANT]
14+
> Go to the Azure portal. If the Personalizer resource you created in the **Prerequisites** section deployed successfully, click the **Go to Resource** button under **Next Steps**. You can find your key and endpoint in the resource's **key and endpoint** page, under **resource management**.
15+
>
16+
> Remember to remove the key from your code when you're done, and never post it publicly. For production, consider using a secure way of storing and accessing your credentials. For example, [Azure key vault](https://docs.microsoft.com/azure/key-vault/key-vault-overview).

articles/cognitive-services/personalizer/includes/quickstart-sdk-csharp.md

Lines changed: 221 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,24 @@ manager: nitinme
66
ms.service: cognitive-services
77
ms.subservice: personalizer
88
ms.topic: include
9-
ms.custom: "include file, devx-track-dotnet"
10-
ms.date: 07/30/2020
9+
ms.custom: cog-serv-seo-aug-2020
10+
ms.date: 08/25/2020
1111
---
1212
[Reference documentation](https://docs.microsoft.com/dotnet/api/Microsoft.Azure.CognitiveServices.Personalizer?view=azure-dotnet-preview) | [Library source code](https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/cognitiveservices/Personalizer) | [Package (NuGet)](https://www.nuget.org/packages/Microsoft.Azure.CognitiveServices.Personalizer/) | [Samples](https://github.com/Azure-Samples/cognitive-services-quickstart-code/tree/master/dotnet/Personalizer)
1313

1414
## Prerequisites
1515

1616
* Azure subscription - [Create one for free](https://azure.microsoft.com/free/cognitive-services)
1717
* The current version of [.NET Core](https://dotnet.microsoft.com/download/dotnet-core).
18+
* Once you have your Azure subscription, <a href="https://ms.portal.azure.com/#create/Microsoft.CognitiveServicesPersonalizer" title="Create a Personalizer resource" target="_blank">create a Personalizer resource <span class="docon docon-navigate-external x-hidden-focus"></span></a> in the Azure portal to get your key and endpoint. After it deploys, click **Go to resource**.
19+
* You will need the key and endpoint from the resource you create to connect your application to the Personalizer API. You'll paste your key and endpoint into the code below later in the quickstart.
20+
* You can use the free pricing tier (`F0`) to try the service, and upgrade later to a paid tier for production.
1821

19-
## Using this quickstart
22+
## Setting Up
2023

21-
There are several steps to use this quickstart:
24+
[!INCLUDE [Change model frequency](change-model-frequency.md)]
2225

23-
* In the Azure portal, create a Personalizer resource
24-
* In the Azure portal, for the Personalizer resource, on the **Configuration** page, change the model update frequency to a very short interval
25-
* In a code editor, create a code file and edit the code file
26-
* In the command line or terminal, install the SDK from the command line
27-
* In the command line or terminal, run the code file
28-
29-
[!INCLUDE [Create Azure resource for Personalizer](create-personalizer-resource.md)]
30-
31-
[!INCLUDE [!Change model frequency](change-model-frequency.md)]
32-
33-
## Create a new C# application
26+
### Create a new C# application
3427

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

@@ -56,15 +49,26 @@ Build succeeded.
5649
...
5750
```
5851

59-
## Install the SDK
52+
### Install the client library
6053

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

6356
```console
6457
dotnet add package Microsoft.Azure.CognitiveServices.Personalizer --version 0.8.0-preview
6558
```
6659

67-
If you're using the Visual Studio IDE, the client library is available as a downloadable NuGet package.
60+
> [!TIP]
61+
> If you're using the Visual Studio IDE, the client library is available as a downloadable NuGet package.
62+
63+
From the project directory, open the `Program.cs` file in your preferred editor or IDE. Add the following using directives:
64+
65+
```csharp
66+
using Microsoft.Azure.CognitiveServices.Personalizer;
67+
using Microsoft.Azure.CognitiveServices.Personalizer.Models;
68+
using System;
69+
using System.Collections.Generic;
70+
using System.Linq;
71+
```
6872

6973
## Object model
7074

@@ -80,53 +84,194 @@ Determining the reward score, in this quickstart is trivial. In a production sys
8084

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

83-
* [Create a Personalizer client](#create-a-personalizer-client)
87+
* [Create a Personalizer client](#authenticate-the-client)
8488
* [Rank API](#request-the-best-action)
8589
* [Reward API](#send-a-reward)
8690

87-
## Add the dependencies
8891

89-
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:
92+
## Authenticate the client
9093

91-
[!code-csharp[Using statements](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=Dependencies)]
94+
In this section you'll do two things:
95+
* Specify your key and endpoint
96+
* Create a Personalizer client
9297

93-
## Add Personalizer resource information
98+
Start by adding the following lines to your Program class. Make sure to add your key and endpoint from your Personalizer resource.
9499

95-
In the **Program** class, edit the key and endpoint variables toward the top of the code file for your resource's Azure key and endpoint.
100+
[!INCLUDE [Personalizer find resource info](find-azure-resource-info.md)]
96101

97-
[!code-csharp[Create variables to hold the Personalizer resource key and endpoint values found in the Azure portal.](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=classVariables)]
102+
```csharp
103+
private static readonly string ApiKey = "REPLACE-WITH-YOUR-PERSONALIZER-KEY";
104+
private static readonly string ServiceEndpoint = "https://REPLACE-WITH-YOUR-PERSONALIZER-RESOURCE-NAME.cognitiveservices.azure.com";
105+
```
98106

99-
## Create a Personalizer client
107+
Next, add a method to your program to create a new Personalizer client.
100108

101-
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`.
109+
```csharp
110+
static PersonalizerClient InitializePersonalizerClient(string url)
111+
{
112+
PersonalizerClient client = new PersonalizerClient(
113+
new ApiKeyServiceClientCredentials(ApiKey)) { Endpoint = url };
102114

103-
[!code-csharp[Create the Personalizer client](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=authorization)]
115+
return client;
116+
}
117+
```
104118

105119
## Get food items as rankable actions
106120

107121
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.
108122

109-
[!code-csharp[Food items as actions](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=createAction)]
123+
```csharp
124+
static IList<RankableAction> GetActions()
125+
{
126+
IList<RankableAction> actions = new List<RankableAction>
127+
{
128+
new RankableAction
129+
{
130+
Id = "pasta",
131+
Features =
132+
new List<object>() { new { taste = "salty", spiceLevel = "medium" }, new { nutritionLevel = 5, cuisine = "italian" } }
133+
},
134+
135+
new RankableAction
136+
{
137+
Id = "ice cream",
138+
Features =
139+
new List<object>() { new { taste = "sweet", spiceLevel = "none" }, new { nutritionalLevel = 2 } }
140+
},
141+
142+
new RankableAction
143+
{
144+
Id = "juice",
145+
Features =
146+
new List<object>() { new { taste = "sweet", spiceLevel = "none" }, new { nutritionLevel = 5 }, new { drink = true } }
147+
},
148+
149+
new RankableAction
150+
{
151+
Id = "salad",
152+
Features =
153+
new List<object>() { new { taste = "salty", spiceLevel = "low" }, new { nutritionLevel = 8 } }
154+
}
155+
};
156+
157+
return actions;
158+
}
159+
```
110160

111161
## Get user preferences for context
112162

113163
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.
114164

115-
[!code-csharp[Present time out day preference to the user](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=createUserFeatureTimeOfDay)]
165+
```csharp
166+
static string GetUsersTimeOfDay()
167+
{
168+
string[] timeOfDayFeatures = new string[] { "morning", "afternoon", "evening", "night" };
116169

117-
[!code-csharp[Present food taste preference to the user](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=createUserFeatureTastePreference)]
170+
Console.WriteLine("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night");
171+
if (!int.TryParse(GetKey(), out int timeIndex) || timeIndex < 1 || timeIndex > timeOfDayFeatures.Length)
172+
{
173+
Console.WriteLine("\nEntered value is invalid. Setting feature value to " + timeOfDayFeatures[0] + ".");
174+
timeIndex = 1;
175+
}
176+
177+
return timeOfDayFeatures[timeIndex - 1];
178+
}
179+
```
180+
181+
```csharp
182+
static string GetUsersTastePreference()
183+
{
184+
string[] tasteFeatures = new string[] { "salty", "sweet" };
185+
186+
Console.WriteLine("\nWhat type of food would you prefer (enter number)? 1. salty 2. sweet");
187+
if (!int.TryParse(GetKey(), out int tasteIndex) || tasteIndex < 1 || tasteIndex > tasteFeatures.Length)
188+
{
189+
Console.WriteLine("\nEntered value is invalid. Setting feature value to " + tasteFeatures[0] + ".");
190+
tasteIndex = 1;
191+
}
192+
193+
return tasteFeatures[tasteIndex - 1];
194+
}
195+
```
118196

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

121-
[!code-csharp[Read user's choice from the command line](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=readCommandLine)]
199+
```csharp
200+
private static string GetKey()
201+
{
202+
return Console.ReadKey().Key.ToString().Last().ToString().ToUpper();
203+
}
204+
```
122205

123206
## Create the learning loop
124207

125208
The Personalizer learning loop is a cycle of [Rank](#request-the-best-action) and [Reward](#send-a-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.
126209

127210
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.
128211

129-
[!code-csharp[Learning loop](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=mainLoop)]
212+
```csharp
213+
static void Main(string[] args)
214+
{
215+
int iteration = 1;
216+
bool runLoop = true;
217+
218+
IList<RankableAction> actions = GetActions();
219+
220+
PersonalizerClient client = InitializePersonalizerClient(ServiceEndpoint);
221+
222+
do
223+
{
224+
Console.WriteLine("\nIteration: " + iteration++);
225+
226+
string timeOfDayFeature = GetUsersTimeOfDay();
227+
string tasteFeature = GetUsersTastePreference();
228+
229+
IList<object> currentContext = new List<object>() {
230+
new { time = timeOfDayFeature },
231+
new { taste = tasteFeature }
232+
};
233+
234+
IList<string> excludeActions = new List<string> { "juice" };
235+
236+
string eventId = Guid.NewGuid().ToString();
237+
238+
var request = new RankRequest(actions, currentContext, excludeActions, eventId);
239+
RankResponse response = client.Rank(request);
240+
241+
Console.WriteLine("\nPersonalizer service thinks you would like to have: " + response.RewardActionId + ". Is this correct? (y/n)");
242+
243+
float reward = 0.0f;
244+
string answer = GetKey();
245+
246+
if (answer == "Y")
247+
{
248+
reward = 1;
249+
Console.WriteLine("\nGreat! Enjoy your food.");
250+
}
251+
else if (answer == "N")
252+
{
253+
reward = 0;
254+
Console.WriteLine("\nYou didn't like the recommended food choice.");
255+
}
256+
else
257+
{
258+
Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended food choice.");
259+
}
260+
261+
Console.WriteLine("\nPersonalizer service ranked the actions with the probabilities as below:");
262+
foreach (var rankedResponse in response.Ranking)
263+
{
264+
Console.WriteLine(rankedResponse.Id + " " + rankedResponse.Probability);
265+
}
266+
267+
client.Reward(response.EventId, new RewardRequest(reward));
268+
269+
Console.WriteLine("\nPress q to break, any other key to continue:");
270+
runLoop = !(GetKey() == "Q");
271+
272+
} while (runLoop);
273+
}
274+
```
130275

131276
Add the following methods, which [get the content choices](#get-food-items-as-rankable-actions), before running the code file:
132277

@@ -141,15 +286,57 @@ To complete the Rank request, the program asks the user's preferences to create
141286

142287
This quickstart has simple context features of time of day and user food preference. In production systems, determining and [evaluating](../concept-feature-evaluation.md) [actions and features](../concepts-features.md) can be a non-trivial matter.
143288

144-
[!code-csharp[The Personalizer learning loop ranks the request.](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=rank)]
289+
```csharp
290+
string timeOfDayFeature = GetUsersTimeOfDay();
291+
string tasteFeature = GetUsersTastePreference();
292+
293+
IList<object> currentContext = new List<object>() {
294+
new { time = timeOfDayFeature },
295+
new { taste = tasteFeature }
296+
};
297+
298+
IList<string> excludeActions = new List<string> { "juice" };
299+
300+
string eventId = Guid.NewGuid().ToString();
301+
302+
var request = new RankRequest(actions, currentContext, excludeActions, eventId);
303+
RankResponse response = client.Rank(request);
304+
```
145305

146306
## Send a reward
147307

148308
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.
149309

150310
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](../concept-rewards.md) call can be a non-trivial matter, depending on your specific needs.
151311

152-
[!code-csharp[The Personalizer learning loop ranks the request.](~/cognitive-services-quickstart-code/dotnet/Personalizer/Program.cs?name=reward)]
312+
```csharp
313+
float reward = 0.0f;
314+
string answer = GetKey();
315+
316+
if (answer == "Y")
317+
{
318+
reward = 1;
319+
Console.WriteLine("\nGreat! Enjoy your food.");
320+
}
321+
else if (answer == "N")
322+
{
323+
reward = 0;
324+
Console.WriteLine("\nYou didn't like the recommended food choice.");
325+
}
326+
else
327+
{
328+
Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended food choice.");
329+
}
330+
331+
Console.WriteLine("\nPersonalizer service ranked the actions with the probabilities as below:");
332+
foreach (var rankedResponse in response.Ranking)
333+
{
334+
Console.WriteLine(rankedResponse.Id + " " + rankedResponse.Probability);
335+
}
336+
337+
// Send the reward for the action based on user response.
338+
client.Reward(response.EventId, new RewardRequest(reward));
339+
```
153340

154341
## Run the program
155342

0 commit comments

Comments
 (0)