Dela via


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

Viktigt!

Från och med den 20 september 2023 kommer du inte att kunna skapa nya personaliseringsresurser. Personanpassningstjänsten dras tillbaka den 1 oktober 2026.

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

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

  • Konfigurera personanpassningsnyckel och slutpunkt
  • Samla in funktioner
  • Api:er för samtalsrankning och belöning
  • Visa den översta åtgärden, angiven som rewardActionId

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

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

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

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

  • pasta
  • glass
  • saft
  • sallad
  • popcorn
  • kaffe
  • soppa

Skicka både åtgärder med funktioner och kontextfunktioner för varje Rank API-begäran för att hjälpa personanpassningen att lära sig om dina åtgärder.

En funktion i modellen är information om åtgärden eller kontexten som kan aggregeras (grupperas) mellan medlemmar i webbappens 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 till att särskilja matobjektet.

Funktionerna konfigureras inte som en del av loopkonfigurationen i Azure-portalen. I stället skickas de som ett JSON-objekt med varje Rank API-anrop. Detta gör det möjligt för åtgärderna och deras funktioner att växa, ändra och krympa med tiden, vilket gör att Personanpassning 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

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

  • tid på dagen - morgon, eftermiddag, kväll, natt
  • användarens preferens för smak - salt, söt, bitter, sur 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 Personanpassning?

Webbappen använder Personalizer för att välja den bästa åtgärden i listan över matval. Det gör du genom att skicka följande information med varje Rank API-anrop:

  • åtgärder med sina funktioner, till exempel taste och spiceLevel
  • kontextfunktioner som time dag, användarens taste inställningar och webbläsarens användaragentinformation och kontextfunktioner
  • åtgärder för att exkludera t.ex. juice
  • eventId, som skiljer sig åt för varje anrop till Rank API.

Personanpassningsmodellfunktioner i en webbapp

Personanpassningen 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 mot den aktuella kontexten i modellen. Modellen är en representation av personanpassningens tidigare kunskaper om åtgärder, kontext och deras funktioner som gör att den kan fatta välgrundade beslut.

Modellen, inklusive funktioner, uppdateras enligt ett schema baserat på inställningen För modelluppdateringsfrekvens i Azure-portalen.

Varning

Funktioner i det här programmet är avsedda att illustrera funktioner och funktionsvärden, men inte nödvändigtvis till 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å alla scheman eller modeller i din tekniska arkitektur. Funktionsvärdena kan anges med affärslogik eller tredjepartssystem. Funktionsvärden bör inte vara så mycket specifika att de inte gäller för en grupp eller klass med funktioner.

Generalisera funktionsvärden

Generalisera i kategorier

Den här appen använder time som en funktion men grupperar tid i kategorier som morning, afternoon, eveningoch 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 i 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 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

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 – exempelservern för serverdelen använder .NET Core
  • Node.js – klienten/klientdelen är beroende av det här programmet
  • Visual Studio 2019 eller .NET Core CLI – använd antingen utvecklarmiljön i Visual Studio 2019 eller .NET Core CLI för att skapa och köra appen

Konfigurera exemplet

  1. Klona lagringsplatsen Azure AI Personalizer Samples.

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

    Om du begär det tillåter du att Visual Studio uppdaterar .NET-paketet för Personanpassning.

Konfigurera Azure AI Personalizer Service

  1. Skapa en personanpassningsresurs i Azure-portalen.

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

  3. Fyll i PersonalizerServiceEndpoint i appsettings.json.

  4. PersonalizerApiKey Konfigurera som 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 personanpassningsnycklarna. Genom att göra detta öppnar Visual Studio en secrets.json fil 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 Reward-begäran och se deras svar, samt funktionerna för http-begäran som extraherats från din miljö.

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

Demonstrera personanpassningsloopen

  1. Välj knappen Generera ny rangordningsbegäran för att skapa ett nytt JSON-objekt för ranknings-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 rangordningsbegäran för att skicka JSON-objektet till servern. Servern anropar API:et för personanpassningsrankning. Servern tar emot svaret och returnerar den högst rankade åtgärden till klienten som ska visas.

  3. Ange belöningsvärdet och välj sedan knappen Skicka belöningsbegäran . Om du inte ändrar belöningsvärdet skickar klientprogrammet alltid värdet 1 för till Personanpassning.

    Skärmbild som visar avsnittet Reward Request (Belöningsbegäran).

    För ditt eget framtida program kan genereringen av belöningspoängen inträffa när du har samlat in 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 med funktioner och skickar och tar emot HTTP-anrop till din Personalizer-slutpunkt.

Exempelwebbappen använder ett knockout-klientprogram för klientdelen 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 förklaras de delar av servern och klienten som en utvecklare behöver förstå för att kunna använda Personanpassning.

Rank-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 ensidesprogrammet.

Rank-API: Serverprogram anropar Personanpassning

Det här är en typisk .NET-webbapp med ett klientprogram. Mycket av pannplåtskoden tillhandahålls åt dig. All kod som inte är specifik för Personanpassning tas bort från följande kodfragment så att du kan fokusera på den personanpassningsspecifika koden.

Skapa personanpassningsklient

I serverns Startup.cs används personanpassningsslutpunkten och nyckeln för att skapa personanpassningsklienten. Klientprogrammet behöver inte kommunicera med Personanpassning 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 AI 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örberedelserna för att anropa ranknings-API:et

  • Skapa nytt 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 eventuella exkluderade å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 Personanpassning, 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 det valda belönings-ID:et för bästa åtgärd 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 självstudien rewardActionId visas värdet.

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

Belönings-API: samla in information för 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 delvis beräknas i klientprogrammet, baserat på användarbeteenden och delvis på servern, baserat på affärslogik och mål.

Om servern inte anropar Reward-API:et inom den väntetid för belöning som konfigurerats i Azure-portalen för din Personalizer-resurs används standardbelöningen (även konfigurerad i Azure-portalen) för 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

Exemplet använder flera tidsbaserade händelser som konfigurerats i Azure-portalen för din Personalizer-resurs. Spela med dessa värden och gå sedan tillbaka till den här exempelwebbappen för att se hur ändringarna påverkar ranknings- och belöningsanropen:

  • Väntetid för belöning
  • Uppdateringsfrekvens för modell

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 upp följande resurser:

  • Ta bort exempelprojektkatalogen.
  • Ta bort din Personalizer-resurs – tänk på en personanpassningsresurs som dedikerad till åtgärder och kontext – återanvänd bara resursen om du fortfarande använder livsmedel som åtgärdsämnesdomän.

Nästa steg