Freigeben über


Lernprogramm: Hinzufügen von Personalizer zu einer .NET Web-App

Wichtig

Ab dem 20. September 2023 können Sie keine neuen Personalizer-Ressourcen erstellen. Der Personalizer-Dienst wird am 1. Oktober 2026 eingestellt. Wir empfehlen, zu dem Open-Source-Projekt microsoft/learning-loop zu migrieren.

Passen Sie eine C#-.NET Web-App mit einer Personalizer-Schleife an, um dem Benutzer basierend auf Aktionen (mit Features) und Kontextfeatures den richtigen Inhalt bereitzustellen.

In diesem Tutorial lernen Sie Folgendes:

  • Einrichten von Schlüssel und Endpunkt für die Personalisierung
  • Sammeln von Features
  • Aufrufen von Rangfolge- und Belohnungs-APIs
  • Anzeigen der obersten Aktion, die als rewardActionId gekennzeichnet wird

Auswählen des optimalen Inhalts für eine Web-App

Eine Web-App sollte Personalisierung verwenden, wenn auf der Webseite eine Liste von Aktionen (Inhalte beliebiger Art) vorhanden ist, die für die Anzeige im Hinblick auf ein einzelnes oberstes Element (rewardActionId) personalisiert werden muss. Beispiele für solche Aktionslisten sind etwa Nachrichtenartikel, Positionen für die Schaltflächenplatzierung oder die gewählten Wörter für Produktnamen.

Sie senden die Liste der Aktionen zusammen mit Kontextmerkmalen an die Personalisierungsschleife. Die Personalisierung wählt die einzelne beste Aktion aus, anschließend zeigt Ihre Web-App diese Aktion an.

In diesem Tutorial werden die Aktionen durch Lebensmitteltypen dargestellt:

  • Pasta
  • Eiskrem
  • Saft
  • Salat
  • Popcorn
  • Kaffee
  • Suppe

Um dem Personalizer zu helfen, Ihre Aktionen kennenzulernen, senden Sie mit jeder Rank-API-Anforderung sowohl Aktionen mit Features als auch Kontextmerkmale.

Ein Feature des Modells sind Informationen über die Aktion oder den Kontext, die über Mitglieder Ihrer Web-App-Benutzerbasis hinweg aggregiert sein können. Ein Feature ist kein individuell spezifisches (wie eine Benutzer-ID) oder hochgradig spezifisches Merkmal (wie eine genaue Uhrzeit).

Aktionen mit Features

Jede Aktion (Inhaltselement) weist Features (Merkmale) auf, die die Unterscheidung des Lebensmittels erleichtern.

Die Features werden nicht als Teil der Schleifenkonfiguration im Azure-Portal konfiguriert. Stattdessen werden sie zusammen mit jedem Aufruf der Rangfolge-API als JSON-Objekt gesendet. Auf diese Weise wird Flexibilität für die Aktionen und ihre Features erreicht, sodass sie im Lauf der Zeit zunehmen, sich ändern oder abnehmen können, wodurch die Personalisierung Trends folgen kann.

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

Kontextmerkmale

Kontextfeatures helfen der Personalisierung dabei, den Kontext der Aktionen zu verstehen. Der Kontext für diese Beispielanwendung beinhaltet:

  • Die Tageszeit: Morgen, Nachmittag, Abend, Nacht
  • Die Geschmacksvorliebe des Benutzers: salzig, süß, bitter, sauer oder herzhaft
  • Den Browserkontext: Benutzer-Agent, geografischen Standort, Verweiser
/// <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];
}

Wie verwendet die Web-App die Personalisierung?

Die Web-App verwendet die Personalisierung, um in der Liste der zur Wahl stehenden Lebensmittel die beste Aktion auszuwählen. Sie tut dies, indem sie zusammen mit jedem Aufruf der Rank-API die folgenden Informationen sendet:

  • Aktionen mit ihren Features wie taste und spiceLevel
  • Kontextfeatures wie time am Tag, taste-Präferenz des Benutzers und die Benutzer-Agentinformationen des Browsers sowie Kontextfeatures
  • Auszuschließende Aktionen wie z. B. Saft
  • Ereignis-ID, die sich für jeden Aufruf der Rangfolge-API unterscheidet

Features von Personalisierungsmodellen in einer Web-App

Die Personalisierung benötigt Features für die Aktionen (Inhalte) und den aktuellen Kontext (Benutzer und Umgebung). Features werden verwendet, um Aktionen am aktuellen Kontext im Modell auszurichten. Das Modell ist eine Darstellung des früheren Wissens des Personalizers über Aktionen, Kontext und deren Merkmale, wodurch es ihm ermöglicht wird, fundierte Entscheidungen zu treffen.

Das Modell, einschließlich der Features, wird basierend auf Ihrer Einstellung der Aktualisierungshäufigkeit des Modells im Azure-Portal aktualisiert.

Achtung

In dieser Anwendung sollen Funktionen und deren Werte veranschaulicht werden, sie stellen jedoch nicht zwangsläufig die besten Funktionen für den Einsatz in einer Web-App dar.

Planen von Features und ihren Werten

Features sollten mit dem gleichen Maß an Planung und Überlegung ausgewählt werden, das Sie Schemas oder Modellen in Ihrer technischen Architektur widmen. Die Werte der Features können mithilfe von Geschäftslogik oder Drittanbietersystemen festgelegt werden. Featurewerte sollten nicht so hochgradig spezifisch sein, dass sie nicht für eine Gruppe oder Klasse von Features gelten.

Generalisieren von Featurewerten

Nach Kategorien generalisieren

Diese App verwendet time als Feature, gruppiert die Zeit aber in Kategorien wie morning, afternoon, evening und night. Dies ist ein Beispiel dafür, wie die Zeitinformation zwar verwendet wird, aber nicht in einer hochspezifischen Weise wie in 10:05:01 UTC+2.

Generalisieren in Teile

Diese App verwendet die HTTP-Anforderungsfeatures vom Browser. Dies beginnt mit einer sehr spezifischen Zeichenfolge mit allen Daten, beispielsweise:

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

Die HttpRequestFeatures-Klassenbibliothek generalisiert diese Zeichenfolge zu einem userAgentInfo-Objekt mit einzelnen Werten. Alle Werte, die zu spezifisch sind, werden auf eine leere Zeichenfolge festgelegt. Wenn die Kontextfeatures für die Anforderung gesendet werden, weisen sie das folgende JSON-Format auf:

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

Verwenden der Beispiel-Web-App

Für das Ausführen der browserbasierten Web-App (der Code steht vollständig zur Verfügung) müssen die folgenden Anwendungen installiert sein.

Installieren Sie folgende Software:

  • .NET Core 2.1 – der Back-End-Beispielserver verwendet .NET Core
  • Node.js: Der Client/das Front-End hängt von dieser Anwendung ab
  • Visual Studio 2019 oder .NET Core CLI – verwenden Sie entweder die Entwicklerumgebung von Visual Studio 2019 oder die .NET Core CLI, um die App zu erstellen und auszuführen.

Beispiel einrichten

  1. Klonen Sie das Repository Azure KI Personalisierung Samples.

    git clone https://github.com/Azure-Samples/cognitive-services-personalizer-samples.git
    
  2. Navigieren Sie zu samples/HttpRequestFeatures, um die Lösung HttpRequestFeaturesExample.sln zu öffnen.

    Wenn angefordert, erlauben Sie Visual Studio, das .NET Paket für Personalizer zu aktualisieren.

Einrichten Azure KI Personalisierung -Diensts

  1. Erstellen Sie eine Personalizer-Ressource im Azure-Portal.

  2. Suchen Sie im Azure-Portal die Endpoint und entweder Key1 oder Key2 (beide Optionen sind möglich) auf der Registerkarte Keys und Endpoints. Dies sind Ihre PersonalizerServiceEndpoint und Ihre PersonalizerApiKey.

  3. Setzen Sie den PersonalizerServiceEndpoint in appsettings.json ein.

  4. Konfigurieren Sie auf eine der folgenden Weisen den PersonalizerApiKey als ein App-Geheimnis:

    • Wenn Sie die .NET Core CLI verwenden, können Sie den Befehl dotnet user-secrets set "PersonalizerApiKey" "<API Key>" verwenden.
    • Wenn Sie Visual Studio verwenden, können Sie mit der rechten Maustaste auf das Projekt klicken und die Menüoption Manage User Secrets auswählen, um die Personalizer-Tasten zu konfigurieren. Dadurch öffnet Visual Studio eine datei secrets.json, in der Sie die Schlüssel wie folgt hinzufügen können:
    {
      "PersonalizerApiKey": "<your personalizer key here>",
    }
    

Beispiel ausführen

Erstellen Sie HttpRequestFeaturesExample mit einer der folgenden Methoden, und führen Sie es anschließend aus:

  • Visual Studio 2019: Drücken Sie F5
  • .NET Core CLI: dotnet build, dann dotnet run

Über einen Webbrowser können Sie eine Rangfolge- und eine Belohnungsanforderung senden und deren Antworten sowie die aus Ihrer Umgebung extrahierten HTTP-Anforderungsfeatures anzeigen.

Screenshot: Beispiel des HTTP-Anforderungsfeatures in einem Webbrowser

Veranschaulichung der Personalisierungsschleife

  1. Wählen Sie die Schaltfläche Generate new Rank Request (Neue Rangfolgenanforderung generieren) aus, um ein neues JSON-Objekt für den Aufruf der Rangfolgen-API zu erstellen. Dadurch werden die Aktionen (mit Features) und Kontextfeatures erstellt und die Werte angezeigt, sodass Sie sehen können, wie der JSON-Code aussieht.

    Für Ihre eigene zukünftige Anwendung kann die Generierung der Aktionen und Features auf dem Client, auf dem Server, gemischt auf beiden oder durch Aufrufen von anderen Diensten erfolgen.

  2. Wählen Sie Send Rank Request (Rangfolgenanforderung senden) aus, um das JSON-Objekt an den Server zu senden. Der Server ruft die Rangfolgen-API für die Personalisierung auf. Der Server empfängt die Antwort und gibt die Aktion mit der höchsten Rangfolge zum Anzeigen an den Client zurück.

  3. Legen Sie den Belohnungswert fest, und wählen Sie dann die Schaltfläche Send Reward Request (Belohnungsanforderung senden) aus. Wenn Sie den Belohnungswert nicht ändern, sendet die Clientanwendung den Wert 1 immer an Personalizer.

    Der Screenshot zeigt den Abschnitt Anforderung für Belohnungen.

    Bei Ihrer eigenen zukünftigen Anwendung kann die Generierung des Belohnungsergebnisses nach dem Sammeln von Informationen über das Benutzerverhalten auf dem Client zusammen mit Geschäftslogik auf dem Server erfolgen.

Verstehen der Beispiel-Web-App

Die Beispielweb-App verfügt über einen C#-.NET-Server, der die Sammlung von Features verwaltet und HTTP-Aufrufe an Ihren Personalizer-Endpunkt sendet und empfängt.

Die Beispielweb-App verwendet eine knockout-Front-End-Clientanwendung zum Erfassen von Features und Verarbeiten von Benutzeroberflächenaktionen wie klicken auf Schaltflächen und Senden von Daten an den .NET Server.

In den folgenden Abschnitten werden die Teile von Server und Client erläutert, die ein Entwickler verstehen muss, um die Personalisierung zu verwenden.

Rangfolge-API: Clientanwendung sendet Kontext an Server

Die Clientanwendung erfasst den Benutzer-Agent auf dem Browser des Benutzers.

Erstellen Sie das Projekt „HTTPRequestFeaturesExample“ und führen Sie es aus. Ein Browserfenster wird geöffnet, in dem die Single-Page-Anwendung angezeigt wird.

Rank-API: Serveranwendung ruft Personalizer auf

Dies ist eine typische .NET Web-App mit einer Clientanwendung, ein Großteil des Kesselplattencodes wird für Sie bereitgestellt. Jeglicher nicht für die Personalisierung spezifischer Code wurde aus den Codeausschnitten entfernt, Sie können sich also auf den spezifischen Code der Personalisierung konzentrieren.

Personalisierungs-Client erstellen

In der Startup.cs-Datei des Servers werden der Personalizer-Endpunkt und der Schlüssel verwendet, um den Personalizer-Client zu erstellen. Die Clientanwendung braucht nicht mit der Personalisierung in dieser App zu kommunizieren, sie kann sich stattdessen darauf verlassen, dass der Server die SDK-Aufrufe vornimmt.

Der .NET Startcode des Webservers lautet:

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
    }
}

Auswählen der besten Aktion

In der Datei PersonalizerController.cs des Servers fasst die GenerateRank-Server-API die Vorbereitung für den Aufruf der Rangfolge-API zusammen.

  • Erstellen einer neuen eventId für den Aufruf der Rangfolge-API
  • Abrufen der Liste der Aktionen
  • Die Liste der Funktionen vom Benutzer abrufen und Kontextfunktionen erstellen.
  • Optional Festlegen aller ausgeschlossenen Aktionen
  • Aufrufen der Rangfolge-API, Rückgabe der Ergebnisse an den Client
/// <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);
}

Der an die Personalisierung gesendete JSON-Code, der sowohl Aktionen (mit Merkmalen) als auch die aktuellen Kontextmerkmale enthält, sieht folgendermaßen aus:

{
    "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
}

Rückgabe der „rewardActionId“ des Personalizers an den Client

Die Rangfolge-API gibt die ausgewählte beste Aktion rewardActionId an den Server zurück.

Die in rewardActionId zurückgegebene Aktion wird angezeigt.

{
    "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"
}

Im Client wird die Aktion „rewardActionId“ angezeigt.

In diesem Tutorial wird der Wert von rewardActionId angezeigt.

In ihrer eigenen zukünftigen Anwendung kann es sich um einen genauen Text, eine Schaltfläche oder einen hervorgehobenen Abschnitt der Webseite handeln. Die Liste wird für eine eventuelle Analyse nach der Bewertung zurückgegeben, nicht für eine Ordnung der Inhalte. Es sollte nur der rewardActionId-Inhalt angezeigt werden.

Belohnungs-API: Sammeln der Informationen für die Belohnung

Das Belohnungsergebnis sollte sorgfältig geplant werden, ebenso wie die Funktionen. Das Belohnungsergebnis sollte typischerweise ein Wert zwischen 0 und 1 sein. Der Wert kann zum Teil in der Clientanwendung berechnet werden, ausgehend vom Benutzerverhalten, und zum Teil auf der Server, basierend auf Geschäftslogik und Zielen.

Wenn der Server die Belohnungs-API nicht innerhalb der Belohnungs-Wartezeit aufruft, die im Azure-Portal für Ihre Personalizer-Ressource konfiguriert ist, wird die Standard-Belohnung (auch im Azure-Portal konfiguriert) für dieses Ereignis verwendet.

In dieser Beispielanwendung können Sie einen Wert auswählen, um zu sehen, welchen Einfluss die Belohnung auf die Auswahl hat.

Zusätzliche Möglichkeiten, von diesem Beispiel zu lernen

Im Beispiel werden mehrere zeitbasierte Ereignisse verwendet, die im Azure-Portal für Ihre Personalizer-Ressource konfiguriert sind. Experimentieren Sie mit diesen Werten, und kehren Sie dann zu dieser Beispielwebanwendung zurück, um zu sehen, wie sich die Änderungen auf die Rangfolge- und Belohnungsaufrufe auswirken:

  • Belohnungswartezeit
  • Häufigkeit der Modellaktualisierung

Dies sind weitere Einstellungen, mit denen Sie experimentieren können:

  • Standardbelohnung
  • Prozentsatz der Erkundung

Bereinigen von Ressourcen

Wenn Sie dieses Tutorial abgeschlossen haben, bereinigen Sie die folgenden Ressourcen:

  • Löschen Sie Ihr Beispielprojektverzeichnis.
  • Löschen Sie Ihre Personalisierungsressource – stellen Sie sich die Personalisierungsressource als für Aktionen und Kontext dediziert vor – verwenden Sie die Ressource nur dann wieder, wenn Sie die Lebensmittel weiterhin als Themendomäne für Aktionen verwenden.

Nächste Schritte