From a1e5eca00da22f7532b91e8bd48fb551c8136527 Mon Sep 17 00:00:00 2001 From: John Huang Date: Mon, 31 Jan 2022 14:03:30 -0800 Subject: [PATCH 1/2] 13009290: Create RankProcessor class to Azure Personalizer client library for .NET for multi slot --- .../Models/PersonalizerSlotResult.cs | 2 +- .../src/GlobalSuppressions.cs | 2 + .../src/Models/DecisionContext.cs | 33 +- .../src/Models/DecisionContextDocument.cs | 38 +- .../src/Models/DecisionContextDocumentId.cs | 23 + .../src/Models/PersonalizerClient.cs | 22 +- .../src/Models/PersonalizerSlotOptions.cs | 2 +- .../src/Models/RankProcessor.cs | 34 +- .../src/Models/RlObjectConverter.cs | 53 ++ .../tests/Personalizer/MultiSlotTests.cs | 19 +- .../Personalizer/RlObjectConverterTests.cs | 45 ++ .../MultiSlotLocalInferenceTest.json | 620 ++++++++++++++++++ .../MultiSlotLocalInferenceTestAsync.json | 620 ++++++++++++++++++ 13 files changed, 1492 insertions(+), 21 deletions(-) create mode 100644 sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocumentId.cs create mode 100644 sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTest.json create mode 100644 sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTestAsync.json diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs index 1aceb77b83a0..8bf62de97832 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs @@ -34,6 +34,6 @@ internal PersonalizerSlotResult(string slotId, string rewardActionId) RewardActionId = rewardActionId; } /// RewardActionID is the action ID recommended by Personalizer. - public string RewardActionId { get; } + public string RewardActionId { get; set; } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/GlobalSuppressions.cs b/sdk/personalizer/Azure.AI.Personalizer/src/GlobalSuppressions.cs index 227726867313..1e1c96d25518 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/GlobalSuppressions.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/GlobalSuppressions.cs @@ -4,3 +4,5 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Usage", "AZC0016:Invalid ServiceVersion member name.", Justification = "Generated code: https://github.com/Azure/autorest.csharp/issues/1524", Scope = "type", Target = "~T:Azure.AI.Personalizer.PersonalizerClientOptions.ServiceVersion")] +[assembly: SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "", Scope = "member", Target = "~P:Azure.AI.Personalizer.DecisionContextDocument.SlotJson")] +[assembly: SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "", Scope = "member", Target = "~P:Azure.AI.Personalizer.PersonalizerSlotOptions.Features")] diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs index 158498cf988e..da41f7877cd6 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs @@ -27,10 +27,30 @@ public DecisionContext(IEnumerable contextFeatures, List actionFeatures = action.Features.Select(f => JsonSerializer.Serialize(f)).ToList(); - return new DecisionContextDocument(action.Id, actionFeatures); + return new DecisionContextDocument(action.Id, actionFeatures, null, null); }).ToArray(); } + /// Initializes a new instance of DecisionContext. + /// Personalizer multi-slot rank options + /// A map from slot id to its features + public DecisionContext(PersonalizerRankMultiSlotOptions rankRequest, Dictionary> slotIdToFeatures) + { + this.ContextFeatures = rankRequest.ContextFeatures.Select(f => JsonSerializer.Serialize(f)).ToList(); + + this.Documents = rankRequest.Actions + .Select(action => + { + List actionFeatures = action.Features.Select(f => JsonSerializer.Serialize(f)).ToList(); + + return new DecisionContextDocument(action.Id, actionFeatures, null, null); + }).ToArray(); + this.Slots = rankRequest.Slots? + .Select( + slot => new DecisionContextDocument(null, null, slot.Id, serializeFeatures(slotIdToFeatures[slot.Id])) + ).ToArray(); + } + /// Properties from url [JsonPropertyName("FromUrl")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] @@ -45,5 +65,16 @@ public DecisionContext(IEnumerable contextFeatures, List serializeFeatures(IList features) + { + List result = new List(); + foreach (object feature in features) + { + result.Add(System.Text.Json.JsonSerializer.Serialize(feature)); + } + + return result; + } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocument.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocument.cs index 593e15c2b529..ed7ce55c0b65 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocument.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocument.cs @@ -11,23 +11,41 @@ public class DecisionContextDocument { /// Initializes a new instance of DecisionContextDocument. /// Id of the decision context document - /// The json features - public DecisionContextDocument(string id, List Json) + /// The json features + /// The slot Id + /// The slot json features + public DecisionContextDocument(string id, List json, string slotId, List slotJson) { ID = id; - JSON = Json; + JSON = json; + SlotId = slotId; + SlotJson = slotJson; } - /// - /// Supply _tag for online evaluation - /// - [JsonPropertyName("_tag")] + + /// + /// Supply _tag for online evaluation + /// + [JsonPropertyName("_tag")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string ID { - get; - set; + get { return this?.Marginal?.ID; } + set + { + this.Marginal = value == null ? null : new DecisionContextDocumentId + { + ID = value + }; + } } + /// + /// Provide feature for marginal feature based on document id. + /// + [JsonPropertyName("i")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public DecisionContextDocumentId Marginal { get; set; } + /// /// Provide source set feature. /// @@ -63,6 +81,6 @@ public string ID [JsonPropertyName("sj")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonConverter(typeof(JsonRawStringListConverter))] - public List SlotJson { get; } + public List SlotJson { get; set; } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocumentId.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocumentId.cs new file mode 100644 index 000000000000..20880629e4dc --- /dev/null +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContextDocumentId.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json.Serialization; + +namespace Azure.AI.Personalizer +{ + /// The Decision Context Document. + public class DecisionContextDocumentId + { + /// + /// Required for --marginal + /// + [JsonPropertyName("constant")] + public int Constant { get; set; } = 1; + + /// + /// Included for offline analysis. + /// + [JsonPropertyName("id")] + public string ID { get; set; } + } +} diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerClient.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerClient.cs index 668b8b25f645..a129b654e0bd 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerClient.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerClient.cs @@ -266,7 +266,14 @@ public virtual async Task> RankMultiSl scope.Start(); try { - return await MultiSlotRestClient.RankAsync(options, cancellationToken).ConfigureAwait(false); + if (_isLocalInference) + { + return _rankProcessor.Rank(options); + } + else + { + return await MultiSlotRestClient.RankAsync(options, cancellationToken).ConfigureAwait(false); + } } catch (Exception e) { @@ -316,7 +323,14 @@ public virtual Response RankMultiSlot(Personali scope.Start(); try { - return MultiSlotRestClient.Rank(options, cancellationToken); + if (_isLocalInference) + { + return _rankProcessor.Rank(options); + } + else + { + return MultiSlotRestClient.Rank(options, cancellationToken); + } } catch (Exception e) { @@ -545,8 +559,8 @@ internal Configuration GetConfigurationForLiveModel(string authType, string auth //ToDo: TASK 13057958 Working on changes to support token authentication in RLClient //config["http.token.key"] = authValue; } - config["interaction.http.api.host"] = stringEndpoint+"personalizer/v1.1-preview.1/logs/interactions"; - config["observation.http.api.host"] = stringEndpoint+"personalizer/v1.1-preview.1/logs/observations"; + config["interaction.http.api.host"] = stringEndpoint + "personalizer/v1.1-preview.1/logs/interactions"; + config["observation.http.api.host"] = stringEndpoint + "personalizer/v1.1-preview.1/logs/observations"; //ToDo: TASK 13057958 Working on changes to support model api in RL.Net config["model.blob.uri"] = stringEndpoint + "personalizer/v1.1-preview.1/model"; config["vw.commandline"] = _personalizerPolicy.Arguments; diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerSlotOptions.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerSlotOptions.cs index 603f39a9950e..b169f40dc353 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerSlotOptions.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/PersonalizerSlotOptions.cs @@ -15,7 +15,7 @@ public partial class PersonalizerSlotOptions /// List of dictionaries containing slot features. /// Need to be JSON serializable. https://docs.microsoft.com/azure/cognitive-services/personalizer/concepts-features. /// - public IList Features { get; } + public IList Features { get; set; } /// /// Initializes a new instance of the RankRequest class. diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/RankProcessor.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/RankProcessor.cs index ca6c84111c65..d94ec102065b 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/RankProcessor.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/RankProcessor.cs @@ -6,7 +6,7 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; +using System.Text.Json; using Rl.Net; namespace Azure.AI.Personalizer @@ -68,5 +68,37 @@ public Response Rank(PersonalizerRankOptions options) return Response.FromValue(value, default); } + + /// Submit a Personalizer rank request. Receives a context and a list of actions. Returns which of the provided actions should be used by your application, in rewardActionId. + /// A Personalizer multi-slot Rank request. + public Response Rank(PersonalizerRankMultiSlotOptions options) + { + string eventId = options.EventId; + if (String.IsNullOrEmpty(eventId)) + { + eventId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); + } + + Dictionary actionIdToActionIndex = RlObjectConverter.GetActionIdToIndexMapping(options.Actions); + Dictionary> slotIdToFeatures = new Dictionary>(); + foreach (var slot in options.Slots) + { + slotIdToFeatures.Add(slot.Id, RlObjectConverter.GetIncludedActionsForSlot(slot, actionIdToActionIndex)); + } + + // Convert options to the compatible parameter for ChooseRank + DecisionContext decisionContext = new DecisionContext(options, slotIdToFeatures); + var contextJson = JsonSerializer.Serialize(decisionContext); + ActionFlags flags = options.DeferActivation == true ? ActionFlags.Deferred : ActionFlags.Default; + int[] baselineActions = RlObjectConverter.ExtractBaselineActionsFromRankRequest(options); + + // Call ChooseRank of local RL.Net + MultiSlotResponseDetailed multiSlotResponse = _liveModel.RequestMultiSlotDecisionDetailed(eventId, contextJson, flags, baselineActions); + + // Convert response to PersonalizerRankResult + var value = RlObjectConverter.GenerateMultiSlotRankResponse(options.Actions, multiSlotResponse, eventId); + + return Response.FromValue(value, default); + } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs index 1b99c1e3663d..3453f32fd3f8 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs @@ -5,6 +5,7 @@ using Rl.Net; using System.Collections.Generic; using System.Linq; +using Azure.Core; namespace Azure.AI.Personalizer { @@ -87,5 +88,57 @@ private static PersonalizerRankResult GenerateRankResultInner(List actions, MultiSlotResponseDetailed multiSlotResponse, string eventId) + { + Dictionary actionIndexToActionId = actions + .Select((action, index) => new { action, index = (long)index }) + .ToDictionary(obj => obj.index, obj => obj.action.Id); + + List slots = multiSlotResponse + .Select(slotRanking => new PersonalizerSlotResult(slotRanking.SlotId) + { + RewardActionId = actionIndexToActionId[slotRanking.ChosenAction] + }) + .ToList(); + + return new PersonalizerMultiSlotRankResult(slots, eventId); + } + + public static int[] ExtractBaselineActionsFromRankRequest(PersonalizerRankMultiSlotOptions request) + { + Dictionary actionIdToIndex = GetActionIdToIndexMapping(request.Actions); + return request.Slots + .Select(slot => actionIdToIndex[slot.BaselineAction]).ToArray(); + } + + public static Dictionary GetActionIdToIndexMapping(IList actions) + { + return actions + .Select((action, index) => new { action, index }) + .ToDictionary(obj => obj.action.Id, obj => obj.index); + } + + public static IList GetIncludedActionsForSlot(PersonalizerSlotOptions slot, Dictionary actionIdToActionIndex) + { + IList res = new ChangeTrackingList(); + if (slot.Features != null) + { + foreach (object feature in slot.Features) + { + res.Add(feature); + } + } + if (slot.ExcludedActions != null) + { + List excludeActionIndices = slot.ExcludedActions.Select(id => actionIdToActionIndex[id]).ToList(); + var allActionIndices = new HashSet(actionIdToActionIndex.Values); + List includedActionIndices = allActionIndices.Except(excludeActionIndices).ToList(); + var includedActions = (new { _inc = includedActionIndices }); + res.Add(includedActions); + } + + return res; + } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/MultiSlotTests.cs b/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/MultiSlotTests.cs index a2cc0f39276b..547481a17646 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/MultiSlotTests.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/MultiSlotTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; +using Azure.Core.TestFramework; using NUnit.Framework; namespace Azure.AI.Personalizer.Tests @@ -13,7 +14,7 @@ public MultiSlotTests(bool isAsync) : base(isAsync) { } - private static IList actions = new List() + public static IList actions = new List() { new PersonalizerRankableAction( id: "NewsArticle", @@ -57,13 +58,13 @@ public MultiSlotTests(bool isAsync) : base(isAsync) excludedActions: new List() { "EntertainmentArticle" } ); - private static IList slots = new List() + public static IList slots = new List() { slot1, slot2 }; - private static IList contextFeatures = new List() + public static IList contextFeatures = new List() { new { User = new { ProfileType = "AnonymousUser", LatLong = "47.6,-122.1"} }, new { Environment = new { DayOfMonth = "28", MonthOfYear = "8", Weather = "Sunny"} }, @@ -75,6 +76,18 @@ public MultiSlotTests(bool isAsync) : base(isAsync) public async Task MultiSlotTest() { PersonalizerClient client = await GetPersonalizerClientAsync(isSingleSlot: false); + await MultiSlotTestInner(client); + } + + [Test] + public async Task MultiSlotLocalInferenceTest() + { + PersonalizerClient client = await GetPersonalizerClientAsync(isSingleSlot: false, isLocalInference: true); + await MultiSlotTestInner(client); + } + + private async Task MultiSlotTestInner(PersonalizerClient client) + { await RankMultiSlotNullParameters(client); await RankMultiSlotNoOptions(client); await RankMultiSlot(client); diff --git a/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/RlObjectConverterTests.cs b/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/RlObjectConverterTests.cs index fcced91dc206..b51b62c94194 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/RlObjectConverterTests.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/tests/Personalizer/RlObjectConverterTests.cs @@ -8,6 +8,20 @@ namespace Azure.AI.Personalizer.Tests { public class RlObjectConverterTests { + private PersonalizerSlotOptions slot = new PersonalizerSlotOptions( + id: "Main Article", + baselineAction: "NewsArticle", + features: new List() + { + new + { + Size = "Large", + Position = "Top Middle" + } + }, + excludedActions: new List() { "SportsArticle", "EntertainmentArticle" } + ); + [Test] public void ConvertToContextJsonTest() { @@ -41,5 +55,36 @@ public void ConvertToContextJsonTest() "}"; Assert.IsTrue(contextJson.Equals(expectedJson)); } + + [Test] + public void GetIncludedActionsForSlotTest() + { + Dictionary actionIdToActionIndex = new Dictionary(); + actionIdToActionIndex.Add("NewArticle", 0); + actionIdToActionIndex.Add("SportsArticle", 1); + actionIdToActionIndex.Add("EntertainmentArticle", 2); + IList features = RlObjectConverter.GetIncludedActionsForSlot(slot, actionIdToActionIndex); + } + + [Test] + public void ExtractBaselineActionsFromRankRequestTest() + { + PersonalizerRankMultiSlotOptions request = new PersonalizerRankMultiSlotOptions( + MultiSlotTests.actions, MultiSlotTests.slots, MultiSlotTests.contextFeatures, "testEventId"); + int[] baselineActions = RlObjectConverter.ExtractBaselineActionsFromRankRequest(request); + Assert.AreEqual(2, baselineActions.Length); + Assert.AreEqual(0, baselineActions[0]); + Assert.AreEqual(1, baselineActions[1]); + } + + [Test] + public void GetActionIdToIndexMappingTest() + { + Dictionary idToIndex = RlObjectConverter.GetActionIdToIndexMapping(MultiSlotTests.actions); + Assert.AreEqual(3, idToIndex.Keys.Count); + Assert.AreEqual(idToIndex["NewsArticle"], 0); + Assert.AreEqual(idToIndex["SportsArticle"], 1); + Assert.AreEqual(idToIndex["EntertainmentArticle"], 2); + } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTest.json b/sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTest.json new file mode 100644 index 000000000000..1174eb4855f0 --- /dev/null +++ b/sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTest.json @@ -0,0 +1,620 @@ +{ + "Entries": [ + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/configurations/service", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-9c74aaef3c2d614ab5f080d13d24efa5-d8a8ad2a3170a94c-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "77242a1418c89aed2ca4cffffac5f01d", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "17aa5251-25e6-42f1-a927-2498bac39e06", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "350", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:54:18 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "7343" + }, + "ResponseBody": { + "rewardWaitTime": "PT10M", + "defaultReward": 0.0, + "rewardAggregation": "earliest", + "explorationPercentage": 0.2, + "modelExportFrequency": "PT5M", + "logRetentionDays": 90, + "lastConfigurationEditDate": "1601-01-01T00:00:00", + "learningMode": "Online", + "isAutoOptimizationEnabled": false, + "autoOptimizationFrequency": "P28D", + "autoOptimizationStartDate": "2021-10-30T14:41:23" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/configurations/service", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "358", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-0baceb84bc11f9409b3f6363a2a6e9b8-3de509323a27f945-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "6c2e10c38025c73b07ed276898c74db7", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "rewardWaitTime": "PT10M", + "defaultReward": 0, + "rewardAggregation": "earliest", + "explorationPercentage": 0.200000003, + "modelExportFrequency": "PT5M", + "logRetentionDays": 90, + "lastConfigurationEditDate": "1601-01-01T00:00:00Z", + "learningMode": "Online", + "isAutoOptimizationEnabled": false, + "autoOptimizationFrequency": "P28D", + "autoOptimizationStartDate": "2021-10-30T14:41:23Z" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "197ee618-d5cd-4381-9438-74969f602adb", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "351", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:54:29 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "10620" + }, + "ResponseBody": { + "rewardWaitTime": "PT10M", + "defaultReward": 0.0, + "rewardAggregation": "earliest", + "explorationPercentage": 0.2, + "modelExportFrequency": "PT5M", + "logRetentionDays": 90, + "lastConfigurationEditDate": "1601-01-01T00:00:00", + "learningMode": "Online", + "isAutoOptimizationEnabled": false, + "autoOptimizationFrequency": "P28D", + "autoOptimizationStartDate": "2021-10-30T14:41:23Z" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/configurations/policy", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "107", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-19a0e4612ac1da4581f72b6d18ea8e81-8920b4421300a543-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "2aa28569500ac4cb522cdcabf5ab4e76", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "name": "multiSlot", + "arguments": "--ccb_explore_adf --epsilon 0.2 --power_t 0 -l 0.001 --cb_type mtr -q ::" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "d64f301a-1d7e-4bca-8b41-bec966ada9d4", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "130", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:08 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "9284" + }, + "ResponseBody": { + "name": "8c31472ec8f14f65b37a0b1a14d743c7", + "arguments": "--ccb_explore_adf --epsilon 0.2 --power_t 0 -l 0.001 --cb_type mtr -q ::" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/rank", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "511", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-0c60895e3f2edd4697e2bd613367eb10-cdbbc916d02fc949-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "983383f511bd939def5d6fdbf0840165", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "actions": [ + { + "id": "NewsArticle", + "features": [ + { + "Type": "News" + } + ] + }, + { + "id": "SportsArticle", + "features": [ + { + "Type": "Sports" + } + ] + }, + { + "id": "EntertainmentArticle", + "features": [ + { + "Type": "Entertainment" + } + ] + } + ], + "slots": [ + { + "id": "Main Article", + "features": [ + { + "Size": "Large", + "Position": "Top Middle" + } + ], + "excludedActions": [ + "SportsArticle", + "EntertainmentArticle" + ], + "baselineAction": "NewsArticle" + }, + { + "id": "Side Bar", + "features": [ + { + "Size": "Small", + "Position": "Bottom Right" + } + ], + "excludedActions": [ + "EntertainmentArticle" + ], + "baselineAction": "SportsArticle" + } + ] + }, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "eb35cecc-49a1-477d-a636-7542ebca562d", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "166", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:45 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "6687" + }, + "ResponseBody": { + "slots": [ + { + "id": "Main Article", + "rewardActionId": "NewsArticle" + }, + { + "id": "Side Bar", + "rewardActionId": "SportsArticle" + } + ], + "eventId": "2ae3324436df4819aa636316fd5c9e22-8Io5X" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/rank", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "771", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-dc7d4c7f96b2ef4bbdcb172245f6c48c-b8ca17898f77d54b-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "75961857c5237312446a1af9a48fd15c", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "contextFeatures": [ + { + "User": { + "ProfileType": "AnonymousUser", + "LatLong": "47.6,-122.1" + } + }, + { + "Environment": { + "DayOfMonth": "28", + "MonthOfYear": "8", + "Weather": "Sunny" + } + }, + { + "Device": { + "Mobile": true, + "Windows": true + } + }, + { + "RecentActivity": { + "ItemsInCart": 3 + } + } + ], + "actions": [ + { + "id": "NewsArticle", + "features": [ + { + "Type": "News" + } + ] + }, + { + "id": "SportsArticle", + "features": [ + { + "Type": "Sports" + } + ] + }, + { + "id": "EntertainmentArticle", + "features": [ + { + "Type": "Entertainment" + } + ] + } + ], + "slots": [ + { + "id": "Main Article", + "features": [ + { + "Size": "Large", + "Position": "Top Middle" + } + ], + "excludedActions": [ + "SportsArticle", + "EntertainmentArticle" + ], + "baselineAction": "NewsArticle" + }, + { + "id": "Side Bar", + "features": [ + { + "Size": "Small", + "Position": "Bottom Right" + } + ], + "excludedActions": [ + "EntertainmentArticle" + ], + "baselineAction": "SportsArticle" + } + ], + "deferActivation": false + }, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "75a2d446-8415-4c5e-8898-ac0d56b05a19", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "166", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:46 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "656" + }, + "ResponseBody": { + "slots": [ + { + "id": "Main Article", + "rewardActionId": "NewsArticle" + }, + { + "id": "Side Bar", + "rewardActionId": "SportsArticle" + } + ], + "eventId": "3c8158a8634e45938889eef503eca7c1-8Io5Y" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/rank", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "798", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-5ce193a77854fa4f8cbede3b8b961658-db3b4a8ec090dd4e-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "1473b19eb49357f9e70e3aade0f0d4cd", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "contextFeatures": [ + { + "User": { + "ProfileType": "AnonymousUser", + "LatLong": "47.6,-122.1" + } + }, + { + "Environment": { + "DayOfMonth": "28", + "MonthOfYear": "8", + "Weather": "Sunny" + } + }, + { + "Device": { + "Mobile": true, + "Windows": true + } + }, + { + "RecentActivity": { + "ItemsInCart": 3 + } + } + ], + "actions": [ + { + "id": "NewsArticle", + "features": [ + { + "Type": "News" + } + ] + }, + { + "id": "SportsArticle", + "features": [ + { + "Type": "Sports" + } + ] + }, + { + "id": "EntertainmentArticle", + "features": [ + { + "Type": "Entertainment" + } + ] + } + ], + "slots": [ + { + "id": "Main Article", + "features": [ + { + "Size": "Large", + "Position": "Top Middle" + } + ], + "excludedActions": [ + "SportsArticle", + "EntertainmentArticle" + ], + "baselineAction": "NewsArticle" + }, + { + "id": "Side Bar", + "features": [ + { + "Size": "Small", + "Position": "Bottom Right" + } + ], + "excludedActions": [ + "EntertainmentArticle" + ], + "baselineAction": "SportsArticle" + } + ], + "eventId": "sdkTestEventId", + "deferActivation": false + }, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "5a5ee1b3-3e35-4e59-a67b-1179972d8abb", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "142", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:47 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "438" + }, + "ResponseBody": { + "slots": [ + { + "id": "Main Article", + "rewardActionId": "NewsArticle" + }, + { + "id": "Side Bar", + "rewardActionId": "SportsArticle" + } + ], + "eventId": "sdkTestEventId" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/events/123456789/reward", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "44", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-544c75c6622f6042b29c0e5559b2491d-92512bae864a3745-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "dc54762ad9152f5271c05453f7a4ee60", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "reward": [ + { + "slotId": "testSlot", + "value": 1 + } + ] + }, + "StatusCode": 204, + "ResponseHeaders": { + "apim-request-id": "147e62d7-78a6-4c0b-9712-5d15e21a90a9", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "0", + "Date": "Fri, 15 Oct 2021 14:55:47 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "417" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/events/123456789/reward", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "44", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-76c0680ef4b76c49a79cd70ba19fdbcd-7b068eb1e129124c-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "3e3c138bed11a2d11f3e8d158a649254", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "reward": [ + { + "slotId": "testSlot", + "value": 1 + } + ] + }, + "StatusCode": 204, + "ResponseHeaders": { + "apim-request-id": "514ad45a-8228-44b0-b988-833e3f9f6c0c", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "0", + "Date": "Fri, 15 Oct 2021 14:55:47 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "41" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/events/123456789/activate", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-d9cc3eb2ee96b04cbcea9ee817a9e6c7-c6c37aa27c2f804e-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "2dce4d96f53ac4475e43a2d360a66042", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "apim-request-id": "50174a48-9297-4f7f-bc69-99fd75a90600", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "0", + "Date": "Fri, 15 Oct 2021 14:55:48 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "40" + }, + "ResponseBody": [] + } + ], + "Variables": { + "PERSONALIZER_API_KEY_MULTI_SLOT": "Sanitized", + "PERSONALIZER_ENDPOINT_MULTI_SLOT": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/", + "RandomSeed": "2030725436" + } +} diff --git a/sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTestAsync.json b/sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTestAsync.json new file mode 100644 index 000000000000..c9b6b84d7e3b --- /dev/null +++ b/sdk/personalizer/Azure.AI.Personalizer/tests/SessionRecords/MultiSlotTests/MultiSlotLocalInferenceTestAsync.json @@ -0,0 +1,620 @@ +{ + "Entries": [ + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/configurations/service", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-9c74aaef3c2d614ab5f080d13d24efa5-d8a8ad2a3170a94c-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "77242a1418c89aed2ca4cffffac5f01d", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "17aa5251-25e6-42f1-a927-2498bac39e06", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "350", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:54:18 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "7343" + }, + "ResponseBody": { + "rewardWaitTime": "PT10M", + "defaultReward": 0.0, + "rewardAggregation": "earliest", + "explorationPercentage": 0.2, + "modelExportFrequency": "PT5M", + "logRetentionDays": 90, + "lastConfigurationEditDate": "1601-01-01T00:00:00", + "learningMode": "Online", + "isAutoOptimizationEnabled": false, + "autoOptimizationFrequency": "P28D", + "autoOptimizationStartDate": "2021-10-30T14:41:23" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/configurations/service", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "358", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-0baceb84bc11f9409b3f6363a2a6e9b8-3de509323a27f945-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "6c2e10c38025c73b07ed276898c74db7", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "rewardWaitTime": "PT10M", + "defaultReward": 0, + "rewardAggregation": "earliest", + "explorationPercentage": 0.200000003, + "modelExportFrequency": "PT5M", + "logRetentionDays": 90, + "lastConfigurationEditDate": "1601-01-01T00:00:00Z", + "learningMode": "Online", + "isAutoOptimizationEnabled": false, + "autoOptimizationFrequency": "P28D", + "autoOptimizationStartDate": "2021-10-30T14:41:23Z" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "197ee618-d5cd-4381-9438-74969f602adb", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "351", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:54:29 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "10620" + }, + "ResponseBody": { + "rewardWaitTime": "PT10M", + "defaultReward": 0.0, + "rewardAggregation": "earliest", + "explorationPercentage": 0.2, + "modelExportFrequency": "PT5M", + "logRetentionDays": 90, + "lastConfigurationEditDate": "1601-01-01T00:00:00", + "learningMode": "Online", + "isAutoOptimizationEnabled": false, + "autoOptimizationFrequency": "P28D", + "autoOptimizationStartDate": "2021-10-30T14:41:23Z" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/configurations/policy", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "107", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-19a0e4612ac1da4581f72b6d18ea8e81-8920b4421300a543-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "2aa28569500ac4cb522cdcabf5ab4e76", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "name": "multiSlot", + "arguments": "--ccb_explore_adf --epsilon 0.2 --power_t 0 -l 0.001 --cb_type mtr -q ::" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "d64f301a-1d7e-4bca-8b41-bec966ada9d4", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "130", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:08 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "9284" + }, + "ResponseBody": { + "name": "8c31472ec8f14f65b37a0b1a14d743c7", + "arguments": "--ccb_explore_adf --epsilon 0.2 --power_t 0 -l 0.001 --cb_type mtr -q ::" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/rank", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "511", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-0c60895e3f2edd4697e2bd613367eb10-cdbbc916d02fc949-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "983383f511bd939def5d6fdbf0840165", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "actions": [ + { + "id": "NewsArticle", + "features": [ + { + "Type": "News" + } + ] + }, + { + "id": "SportsArticle", + "features": [ + { + "Type": "Sports" + } + ] + }, + { + "id": "EntertainmentArticle", + "features": [ + { + "Type": "Entertainment" + } + ] + } + ], + "slots": [ + { + "id": "Main Article", + "features": [ + { + "Size": "Large", + "Position": "Top Middle" + } + ], + "excludedActions": [ + "SportsArticle", + "EntertainmentArticle" + ], + "baselineAction": "NewsArticle" + }, + { + "id": "Side Bar", + "features": [ + { + "Size": "Small", + "Position": "Bottom Right" + } + ], + "excludedActions": [ + "EntertainmentArticle" + ], + "baselineAction": "SportsArticle" + } + ] + }, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "eb35cecc-49a1-477d-a636-7542ebca562d", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "166", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:45 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "6687" + }, + "ResponseBody": { + "slots": [ + { + "id": "Main Article", + "rewardActionId": "NewsArticle" + }, + { + "id": "Side Bar", + "rewardActionId": "SportsArticle" + } + ], + "eventId": "2ae3324436df4819aa636316fd5c9e22-8Io5X" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/rank", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "771", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-dc7d4c7f96b2ef4bbdcb172245f6c48c-b8ca17898f77d54b-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "75961857c5237312446a1af9a48fd15c", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "contextFeatures": [ + { + "User": { + "ProfileType": "AnonymousUser", + "LatLong": "47.6,-122.1" + } + }, + { + "Environment": { + "DayOfMonth": "28", + "MonthOfYear": "8", + "Weather": "Sunny" + } + }, + { + "Device": { + "Mobile": true, + "Windows": true + } + }, + { + "RecentActivity": { + "ItemsInCart": 3 + } + } + ], + "actions": [ + { + "id": "NewsArticle", + "features": [ + { + "Type": "News" + } + ] + }, + { + "id": "SportsArticle", + "features": [ + { + "Type": "Sports" + } + ] + }, + { + "id": "EntertainmentArticle", + "features": [ + { + "Type": "Entertainment" + } + ] + } + ], + "slots": [ + { + "id": "Main Article", + "features": [ + { + "Size": "Large", + "Position": "Top Middle" + } + ], + "excludedActions": [ + "SportsArticle", + "EntertainmentArticle" + ], + "baselineAction": "NewsArticle" + }, + { + "id": "Side Bar", + "features": [ + { + "Size": "Small", + "Position": "Bottom Right" + } + ], + "excludedActions": [ + "EntertainmentArticle" + ], + "baselineAction": "SportsArticle" + } + ], + "deferActivation": false + }, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "75a2d446-8415-4c5e-8898-ac0d56b05a19", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "166", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:46 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "656" + }, + "ResponseBody": { + "slots": [ + { + "id": "Main Article", + "rewardActionId": "NewsArticle" + }, + { + "id": "Side Bar", + "rewardActionId": "SportsArticle" + } + ], + "eventId": "3c8158a8634e45938889eef503eca7c1-8Io5Y" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/rank", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "798", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-5ce193a77854fa4f8cbede3b8b961658-db3b4a8ec090dd4e-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "1473b19eb49357f9e70e3aade0f0d4cd", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "contextFeatures": [ + { + "User": { + "ProfileType": "AnonymousUser", + "LatLong": "47.6,-122.1" + } + }, + { + "Environment": { + "DayOfMonth": "28", + "MonthOfYear": "8", + "Weather": "Sunny" + } + }, + { + "Device": { + "Mobile": true, + "Windows": true + } + }, + { + "RecentActivity": { + "ItemsInCart": 3 + } + } + ], + "actions": [ + { + "id": "NewsArticle", + "features": [ + { + "Type": "News" + } + ] + }, + { + "id": "SportsArticle", + "features": [ + { + "Type": "Sports" + } + ] + }, + { + "id": "EntertainmentArticle", + "features": [ + { + "Type": "Entertainment" + } + ] + } + ], + "slots": [ + { + "id": "Main Article", + "features": [ + { + "Size": "Large", + "Position": "Top Middle" + } + ], + "excludedActions": [ + "SportsArticle", + "EntertainmentArticle" + ], + "baselineAction": "NewsArticle" + }, + { + "id": "Side Bar", + "features": [ + { + "Size": "Small", + "Position": "Bottom Right" + } + ], + "excludedActions": [ + "EntertainmentArticle" + ], + "baselineAction": "SportsArticle" + } + ], + "eventId": "sdkTestEventId", + "deferActivation": false + }, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "5a5ee1b3-3e35-4e59-a67b-1179972d8abb", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "142", + "Content-Type": "application/json; charset=utf-8", + "Date": "Fri, 15 Oct 2021 14:55:47 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "timing-allow-origin": "*", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "438" + }, + "ResponseBody": { + "slots": [ + { + "id": "Main Article", + "rewardActionId": "NewsArticle" + }, + { + "id": "Side Bar", + "rewardActionId": "SportsArticle" + } + ], + "eventId": "sdkTestEventId" + } + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/events/123456789/reward", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "44", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-544c75c6622f6042b29c0e5559b2491d-92512bae864a3745-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "dc54762ad9152f5271c05453f7a4ee60", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "reward": [ + { + "slotId": "testSlot", + "value": 1 + } + ] + }, + "StatusCode": 204, + "ResponseHeaders": { + "apim-request-id": "147e62d7-78a6-4c0b-9712-5d15e21a90a9", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "0", + "Date": "Fri, 15 Oct 2021 14:55:47 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "417" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/events/123456789/reward", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "44", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-76c0680ef4b76c49a79cd70ba19fdbcd-7b068eb1e129124c-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "3e3c138bed11a2d11f3e8d158a649254", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "reward": [ + { + "slotId": "testSlot", + "value": 1 + } + ] + }, + "StatusCode": 204, + "ResponseHeaders": { + "apim-request-id": "514ad45a-8228-44b0-b988-833e3f9f6c0c", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "0", + "Date": "Fri, 15 Oct 2021 14:55:47 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "41" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/personalizer/v1.1-preview.1/multislot/events/123456789/activate", + "RequestMethod": "POST", + "RequestHeaders": { + "Accept": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-d9cc3eb2ee96b04cbcea9ee817a9e6c7-c6c37aa27c2f804e-00", + "User-Agent": "azsdk-net-AI.Personalizer/2.0.0-alpha.20211014.1 (.NET Framework 4.8.4420.0; Microsoft Windows 10.0.22000 )", + "x-ms-client-request-id": "2dce4d96f53ac4475e43a2d360a66042", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 204, + "ResponseHeaders": { + "apim-request-id": "50174a48-9297-4f7f-bc69-99fd75a90600", + "Cache-Control": [ + "no-cache", + "no-store", + "must-revalidate" + ], + "Content-Length": "0", + "Date": "Fri, 15 Oct 2021 14:55:48 GMT", + "Expires": "0", + "pragma": "no-cache", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "40" + }, + "ResponseBody": [] + } + ], + "Variables": { + "PERSONALIZER_API_KEY_MULTI_SLOT": "Sanitized", + "PERSONALIZER_ENDPOINT_MULTI_SLOT": "https://sdktestmultislot.ppe.cognitiveservices.azure.com/", + "RandomSeed": "2030725436" + } +} \ No newline at end of file From 12842f2a412a8dc67c818ea5787a9585a4bc9964 Mon Sep 17 00:00:00 2001 From: John Huang Date: Tue, 1 Feb 2022 14:33:49 -0800 Subject: [PATCH 2/2] Address comments --- .../src/Generated/Models/PersonalizerSlotResult.cs | 2 +- .../Azure.AI.Personalizer/src/Models/DecisionContext.cs | 2 +- .../Azure.AI.Personalizer/src/Models/RlObjectConverter.cs | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs index 8bf62de97832..1aceb77b83a0 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Generated/Models/PersonalizerSlotResult.cs @@ -34,6 +34,6 @@ internal PersonalizerSlotResult(string slotId, string rewardActionId) RewardActionId = rewardActionId; } /// RewardActionID is the action ID recommended by Personalizer. - public string RewardActionId { get; set; } + public string RewardActionId { get; } } } diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs index da41f7877cd6..9607b94d182b 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/DecisionContext.cs @@ -71,7 +71,7 @@ private static List serializeFeatures(IList features) List result = new List(); foreach (object feature in features) { - result.Add(System.Text.Json.JsonSerializer.Serialize(feature)); + result.Add(JsonSerializer.Serialize(feature)); } return result; diff --git a/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs b/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs index 3453f32fd3f8..b6810870f7a0 100644 --- a/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs +++ b/sdk/personalizer/Azure.AI.Personalizer/src/Models/RlObjectConverter.cs @@ -96,10 +96,7 @@ public static PersonalizerMultiSlotRankResult GenerateMultiSlotRankResponse(ILis .ToDictionary(obj => obj.index, obj => obj.action.Id); List slots = multiSlotResponse - .Select(slotRanking => new PersonalizerSlotResult(slotRanking.SlotId) - { - RewardActionId = actionIndexToActionId[slotRanking.ChosenAction] - }) + .Select(slotRanking => new PersonalizerSlotResult(slotRanking.SlotId, actionIndexToActionId[slotRanking.ChosenAction])) .ToList(); return new PersonalizerMultiSlotRankResult(slots, eventId);