Självstudie: Lägga till personanpassare i en .NET-webbapp

Anpassa en C# .NET-webbapp med en loop för personanpassare för att tillhandahålla rätt innehåll till en användare baserat på åtgärder (med funktioner) och kontextfunktioner.

I den här guiden får du lära dig att:

  • Konfigurera personanpassarnyckel och slutpunkt
  • Samla in funktioner
  • Anropa API:er för rangordning och belöning
  • Visa den översta åtgärden, angiven som rewardActionId

Välja det bästa innehållet för en webbapp

En webbapp bör använda Personanpassare när det finns en lista över åtgärder (någon typ av innehåll) på webbsidan som måste anpassas till ett enskilt toppobjekt (rewardActionId) för att visas. Exempel på åtgärdslistor är nyhetsartiklar, knappplaceringsplatser och ordval för produktnamn.

Du skickar listan över åtgärder, tillsammans med kontextfunktioner, till loopen Personanpassare. Personanpassaren väljer den enskilt bästa åtgärden och sedan visar webbappen den åtgärden.

I den här självstudien är åtgärderna olika typer av mat:

  • Pasta
  • Glass
  • Juice
  • Sallad
  • Popcorn
  • Kaffe
  • Soppa

Om du vill hjälpa Personanpassaren att lära sig mer om dina åtgärder skickar du både åtgärder med funktioner och kontextfunktioner med varje Rank API-begäran.

En funktion i modellen är information om åtgärden eller kontexten som kan aggregeras (grupperas) mellan medlemmar i din webbapps användarbas. En funktion är inte individuellt specifik (till exempel ett användar-ID) eller mycket specifik (till exempel en exakt tid på dagen).

Åtgärder med funktioner

Varje åtgärd (innehållsobjekt) har funktioner som hjälper dig att särskilja livsmedelsobjektet.

Funktionerna konfigureras inte som en del av loopkonfigurationen i Azure Portal. I stället skickas de som ett JSON-objekt med varje Rank API-anrop. Detta ger flexibilitet för åtgärderna och deras funktioner att växa, ändras och krympa med tiden, vilket gör att Personanpassare kan följa trender.

 /// <summary>
  /// Creates personalizer actions feature list.
  /// </summary>
  /// <returns>List of actions for personalizer.</returns>
  private IList<RankableAction> GetActions()
  {
      IList<RankableAction> actions = new List<RankableAction>
      {
          new RankableAction
          {
              Id = "pasta",
              Features =
              new List<object>() { new { taste = "savory", 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 = "sour", spiceLevel = "low" }, new { nutritionLevel = 8 } }
          },

          new RankableAction
          {
              Id = "popcorn",
              Features =
              new List<object>() { new { taste = "salty", spiceLevel = "none" }, new { nutritionLevel = 3 } }
          },

          new RankableAction
          {
              Id = "coffee",
              Features =
              new List<object>() { new { taste = "bitter", spiceLevel = "none" }, new { nutritionLevel = 3 }, new { drink = true } }
          },

          new RankableAction
          {
              Id = "soup",
              Features =
              new List<object>() { new { taste = "sour", spiceLevel = "high" }, new { nutritionLevel =  7} }
          }
      };

      return actions;
  }

Kontextfunktioner

Sammanhangsfunktioner hjälper Personanpassare att förstå kontexten för åtgärderna. Kontexten för det här exempelprogrammet omfattar:

  • tid på dagen – morgon, kväll, kväll, natt
  • användarens smakpreferens – salt, ljig, älsklig, älsklig eller salt
  • webbläsarens kontext – användaragent, geografisk plats, referens
/// <summary>
/// Get users time of the day context.
/// </summary>
/// <returns>Time of day feature selected by the user.</returns>
private string GetUsersTimeOfDay()
{
    Random rnd = new Random();
    string[] timeOfDayFeatures = new string[] { "morning", "noon", "afternoon", "evening", "night", "midnight" };
    int timeIndex = rnd.Next(timeOfDayFeatures.Length);
    return timeOfDayFeatures[timeIndex];
}

/// <summary>
/// Gets user food preference.
/// </summary>
/// <returns>Food taste feature selected by the user.</returns>
private string GetUsersTastePreference()
{
    Random rnd = new Random();
    string[] tasteFeatures = new string[] { "salty", "bitter", "sour", "savory", "sweet" };
    int tasteIndex = rnd.Next(tasteFeatures.Length);
    return tasteFeatures[tasteIndex];
}

Hur använder webbappen Personanpassare?

Webbappen använder Personanpassare för att välja den bästa åtgärden i listan med matalternativ. Den gör detta genom att skicka följande information med varje Rank API-anrop:

  • åtgärder med deras funktioner, till exempel taste och spiceLevel
  • kontextfunktioner som time t.ex. dag, taste användarpreferenser och webbläsarens användaragentinformation och kontextfunktioner
  • åtgärder som ska undantas, till exempel apelsinjuice
  • eventId, som är olika för varje anrop till Rank API.

Personanpassarmodellfunktioner i en webbapp

Personanpassaren behöver funktioner för åtgärderna (innehållet) och den aktuella kontexten (användare och miljö). Funktioner används för att justera åtgärder till den aktuella kontexten i modellen. Modellen är en representation av Personanpassare tidigare kunskaper om åtgärder, kontext och deras funktioner som gör att den kan fatta utbildningsbeslut.

Modellen, inklusive funktioner, uppdateras enligt ett schema baserat på inställningen Modelluppdateringsfrekvens i Azure Portal.

Varning

Funktioner i det här programmet är avsedda att illustrera funktioner och funktionsvärden, men inte nödvändigtvis de bästa funktionerna som ska användas i en webbapp.

Planera för funktioner och deras värden

Funktioner bör väljas med samma planering och design som du skulle tillämpa på scheman eller modeller i din tekniska arkitektur. Funktionsvärdena kan anges med affärslogik eller system från tredje part. Funktionsvärden bör inte vara så specifika att de inte gäller för en grupp eller en klass med funktioner.

Generalisera funktionsvärden

Generalisera till kategorier

Den här appen time använder som en funktion men grupperar tid i kategorier som , , och morning afternoon evening night . Det är ett exempel på hur du använder tidsinformationen men inte på ett mycket specifikt sätt, till exempel 10:05:01 UTC+2 .

Generalisera till delar

Den här appen använder http-begärandefunktionerna från webbläsaren. Detta börjar med en mycket specifik sträng med alla data, till exempel:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/530.99 (KHTML, like Gecko) Chrome/80.0.3900.140 Safari/537.36

Klassbiblioteket HttpRequestFeatures generaliserar den här strängen till ett userAgentInfo-objekt med enskilda värden. Alla värden som är för specifika anges till en tom sträng. När kontextfunktionerna för begäran skickas har den följande JSON-format:

{
  "httpRequestFeatures": {
    "_synthetic": false,
    "OUserAgent": {
      "_ua": "",
      "_DeviceBrand": "",
      "_DeviceFamily": "Other",
      "_DeviceIsSpider": false,
      "_DeviceModel": "",
      "_OSFamily": "Windows",
      "_OSMajor": "10",
      "DeviceType": "Desktop"
    }
  }
}

Använda exempelwebbapp

Den webbläsarbaserade exempelwebbappen (all kod tillhandahålls) behöver följande program installerade för att köra appen.

Installera följande programvara:

  • .NET Core 2.1 – Serverexempelserver använder .NET Core
  • Node.js – klienten/klientsidan är beroende av det här programmet
  • Visual Studio 2019eller .NET Core CLI – använd antingen utvecklingsmiljön för Visual Studio 2019 eller .NET Core CLI för att skapa och köra appen

Konfigurera exemplet

  1. Klona lagringsplatsen För personanpassade Azure-exempel.

    git clone https://github.com/Azure-Samples/cognitive-services-personalizer-samples.git
    
  2. Gå till samples/HttpRequestFeatures för att öppna lösningen, HttpRequestFeaturesExample.sln .

    Om det begärs tillåter Visual Studio att uppdatera .NET-paketet för Personanpassare.

Konfigurera Tjänsten för personanpassare i Azure

  1. Skapa en resurs för personanpassare i Azure Portal.

  2. I Azure Portal du och Endpoint antingen Key1 eller Key2 (antingen fungerar) på fliken Nycklar och slutpunkter. Det här är PersonalizerServiceEndpoint din och din PersonalizerApiKey .

  3. Fyll i PersonalizerServiceEndpoint iappsettings.js .

  4. Konfigurera som PersonalizerApiKey en apphemlighet på något av följande sätt:

    • Om du använder .NET Core CLI kan du använda dotnet user-secrets set "PersonalizerApiKey" "<API Key>" kommandot .
    • Om du använder Visual Studio kan du högerklicka på projektet och välja menyalternativet Hantera användarhemligheter för att konfigurera personanpassarnycklarna. När du gör det Visual Studio en fil secrets.json där du kan lägga till nycklarna på följande sätt:
    {
      "PersonalizerApiKey": "<your personalizer key here>",
    }
    

Kör exemplet

Skapa och kör HttpRequestFeaturesExample med någon av följande metoder:

  • Visual Studio 2019: Tryck på F5
  • .NET Core CLI: dotnet build sedan dotnet run

Via en webbläsare kan du skicka en Rank-begäran och en belöningsbegäran och se deras svar, samt de http-begärandefunktioner som extraherats från din miljö.

Skärmbild som visar ett exempel på funktionen http-begäran i en webbläsare.

Visa loopen För personanpassare

  1. Välj knappen Generera ny rangordningsbegäran för att skapa ett nytt JSON-objekt för RANK API-anropet. Detta skapar åtgärderna (med funktioner) och kontextfunktionerna och visar värdena så att du kan se hur JSON ser ut.

    För ditt eget framtida program kan generering av åtgärder och funktioner ske på klienten, på servern, en blandning av de två eller med anrop till andra tjänster.

  2. Välj Skicka rank-begäran för att skicka JSON-objektet till servern. Servern anropar API:et För personanpassare rankning. Servern tar emot svaret och returnerar den översta rangordnade åtgärden till klienten som ska visas.

  3. Ange belöningsvärdet och välj sedan knappen Skicka belöningsförfrågan. Om du inte ändrar belöningsvärdet skickar klientprogrammet alltid värdet för 1 till Personanpassare.

    Skärmbild som visar avsnittet Belöningsförfrågan.

    För ditt eget framtida program kan genereringen av belöningspoängen ske efter insamling av information från användarens beteende på klienten, tillsammans med affärslogik på servern.

Förstå exempelwebbappen

Exempelwebbappen har en C# .NET-server som hanterar samlingen av funktioner och skickar och tar emot HTTP-anrop till din personanpassarslutpunkt.

Exempelwebbappen använder ett bra klientprogram på klientsidan för att samla in funktioner och bearbeta användargränssnittsåtgärder som att klicka på knappar och skicka data till .NET-servern.

I följande avsnitt beskrivs de delar av servern och klienten som en utvecklare behöver förstå för att använda Personanpassare.

Rangordnings-API: Klientprogrammet skickar kontext till servern

Klientprogrammet samlar in användarens webbläsaranvändaragent.

Skapa och kör PROJEKTET HTTPRequestFeaturesExample. Ett webbläsarfönster öppnas för att visa ensidesapplikationen.

Rangordnings-API: Serverprogram anropar Personanpassare

Det här är en typisk .NET-webbapp med ett klientprogram. En stor del av den försedd med den försedd med en stor mängd kod. All kod som inte är specifik för Personanpassare tas bort från följande kodfragment så att du kan fokusera på personanpassarspecifik kod.

Skapa personanpassarklient

I serverns Startup.cs används personanpassarslutpunkten och nyckeln för att skapa personanpassarklienten. Klientprogrammet behöver inte kommunicera med Personanpassare i den här appen, utan förlitar sig i stället på servern för att göra dessa SDK-anrop.

Webbserverns .NET-startkod är:

using Microsoft.Azure.CognitiveServices.Personalizer;
// ... other using statements removed for brevity

namespace HttpRequestFeaturesExample
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            string personalizerApiKey = Configuration.GetSection("PersonalizerApiKey").Value;
            string personalizerEndpoint = Configuration.GetSection("PersonalizerConfiguration:ServiceEndpoint").Value;
            if (string.IsNullOrEmpty(personalizerEndpoint) || string.IsNullOrEmpty(personalizerApiKey))
            {
                throw new ArgumentException("Missing Azure Personalizer endpoint and/or api key.");
            }
            services.AddSingleton(client =>
            {
                return new PersonalizerClient(new ApiKeyServiceClientCredentials(personalizerApiKey))
                {
                    Endpoint = personalizerEndpoint
                };
            });

            services.AddMvc();
        }

        // ... code removed for brevity
    }
}

Välj bästa åtgärd

I serverns PersonalizerController.cs sammanfattar GenerateRank-server-API:et förberedelsen för att anropa Rank-API:et

  • Skapa ny eventId för Rank-anropet
  • Hämta listan över åtgärder
  • Hämta listan över funktioner från användaren och skapa kontextfunktioner
  • Du kan också ange undantagna åtgärder
  • Anropa Rank API, returnera resultat till klienten
/// <summary>
/// Creates a RankRequest with user time of day, HTTP request features,
/// and taste as the context and several different foods as the actions
/// </summary>
/// <returns>RankRequest with user info</returns>
[HttpGet("GenerateRank")]
public RankRequest GenerateRank()
{
    string eventId = Guid.NewGuid().ToString();

    // Get the actions list to choose from personalizer with their features.
    IList<RankableAction> actions = GetActions();

    // Get context information from the user.
    HttpRequestFeatures httpRequestFeatures = GetHttpRequestFeaturesFromRequest(Request);
    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 },
            new { httpRequestFeatures }
    };

    // Exclude an action for personalizer ranking. This action will be held at its current position.
    IList<string> excludeActions = new List<string> { "juice" };

    // Rank the actions
    return new RankRequest(actions, currentContext, excludeActions, eventId);
}

JSON som skickas till Personanpassaren, som innehåller båda åtgärderna (med funktioner) och de aktuella kontextfunktionerna, ser ut så här:

{
    "contextFeatures": [
        {
            "time": "morning"
        },
        {
            "taste": "savory"
        },
        {
            "httpRequestFeatures": {
                "_synthetic": false,
                "MRefer": {
                    "referer": "http://localhost:51840/"
                },
                "OUserAgent": {
                    "_ua": "",
                    "_DeviceBrand": "",
                    "_DeviceFamily": "Other",
                    "_DeviceIsSpider": false,
                    "_DeviceModel": "",
                    "_OSFamily": "Windows",
                    "_OSMajor": "10",
                    "DeviceType": "Desktop"
                }
            }
        }
    ],
    "actions": [
        {
            "id": "pasta",
            "features": [
                {
                    "taste": "savory",
                    "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": "sour",
                    "spiceLevel": "low"
                },
                {
                    "nutritionLevel": 8
                }
            ]
        },
        {
            "id": "popcorn",
            "features": [
                {
                    "taste": "salty",
                    "spiceLevel": "none"
                },
                {
                    "nutritionLevel": 3
                }
            ]
        },
        {
            "id": "coffee",
            "features": [
                {
                    "taste": "bitter",
                    "spiceLevel": "none"
                },
                {
                    "nutritionLevel": 3
                },
                {
                    "drink": true
                }
            ]
        },
        {
            "id": "soup",
            "features": [
                {
                    "taste": "sour",
                    "spiceLevel": "high"
                },
                {
                    "nutritionLevel": 7
                }
            ]
        }
    ],
    "excludedActions": [
        "juice"
    ],
    "eventId": "82ac52da-4077-4c7d-b14e-190530578e75",
    "deferActivation": null
}

Returnera Personalizer rewardActionId till klienten

Rank-API:et returnerar den valda bästa åtgärden rewardActionId till servern.

Visa åtgärden som returnerades i rewardActionId.

{
    "ranking": [
        {
            "id": "popcorn",
            "probability": 0.833333254
        },
        {
            "id": "salad",
            "probability": 0.03333333
        },
        {
            "id": "juice",
            "probability": 0
        },
        {
            "id": "soup",
            "probability": 0.03333333
        },
        {
            "id": "coffee",
            "probability": 0.03333333
        },
        {
            "id": "pasta",
            "probability": 0.03333333
        },
        {
            "id": "ice cream",
            "probability": 0.03333333
        }
    ],
    "eventId": "82ac52da-4077-4c7d-b14e-190530578e75",
    "rewardActionId": "popcorn"
}

Klienten visar åtgärden rewardActionId

I den här rewardActionId självstudien visas värdet.

I ditt eget framtida program kan det vara en viss exakt text, en knapp eller ett avsnitt på webbsidan markerat. Listan returneras för all postanalys av poäng, inte en ordningsföljd av innehållet. Endast rewardActionId innehållet ska visas.

Belönings-API: samla in information om belöning

Belöningspoängen bör planeras noggrant, precis som funktionerna planeras. Belöningspoängen bör vanligtvis vara ett värde från 0 till 1. Värdet kan beräknas delvis i klientprogrammet, baserat på användarbeteenden och delvis på servern, baserat på affärslogik och mål.

Om servern inte anropar API:et för belöning inom väntetiden för belöning som konfigurerats i Azure Portal för din personanpassarresurs används standardbelöning (som också konfigureras i Azure Portal) för den händelsen.

I det här exempelprogrammet kan du välja ett värde för att se hur belöningen påverkar valen.

Ytterligare sätt att lära sig från det här exemplet

I exemplet används flera tidsbaserade händelser som konfigurerats i Azure Portal för din personalresurs. Testa dessa värden och gå sedan tillbaka till den här exempelwebbappen för att se hur ändringarna påverkar anropen rankning och belöning:

  • Väntetid för belöning
  • Frekvens för modelluppdatering

Ytterligare inställningar att spela upp med är:

  • Standardbelöning
  • Utforskningsprocent

Rensa resurser

När du är klar med den här självstudien rensar du följande resurser:

  • Ta bort exempelprojektkatalogen.
  • Ta bort din personanpassarresurs – tänk på en personalresurs som dedikerad till åtgärderna och kontexten – återanvänd bara resursen om du fortfarande använder livsmedel som åtgärdsämnesdomän.

Nästa steg