Condividi tramite


Tutorial: usare Personalizza esperienze in un'app Web .NET

Importante

A partire dal 20 settembre 2023 non sarà possibile creare nuove risorse di Personalizer. Il servizio Personalizer sarà ritirato il 1° ottobre 2026. Consigliamo di migrare al microsoft/learning-loop open-source.

Personalizzare un'app Web C# .NET con un ciclo di Personalizer per fornire il contenuto corretto a un utente, basato su azioni (con caratteristiche) e sulle caratteristiche del contesto.

In questa esercitazione si imparerà come:

  • Configurare la chiave e l'endpoint di Personalizer
  • Raccogliere caratteristiche
  • Chiamare le API di Ranking e Ricompensa
  • Visualizzare l'azione principale, designata come rewardActionId

Selezionare il contenuto migliore per un'app Web

Un'app Web dovrebbe utilizzare Personalizer quando è presente un elenco di azioni (alcuni tipi di contenuto) nella pagina Web che devono essere personalizzate per visualizzare un singolo elemento principale (rewardActionId). Gli esempi di elenchi di azioni includono articoli di notizie, posizioni di selezione dei pulsanti e scelte di parole per i nomi di prodotti.

Invii l'elenco di azioni, insieme alle caratteristiche del contesto, al ciclo Personalizer. Il Personalizzatore seleziona la singola azione migliore e la tua app Web visualizza quell'azione.

In questa esercitazione le azioni sono tipi di cibo:

  • pasta
  • gelato
  • juice
  • insalata
  • popcorn
  • caffè
  • minestra

Per consentire a Personalizer di acquisire informazioni sulle tue azioni, inviare sia azioni con caratteristiche che caratteristiche del contesto con ogni richiesta al Rank API.

Una caratteristica del modello è costituita da informazioni sull'azione o sul contesto che possono essere aggregate (raggruppate) tra i membri della base di utenti dell'app Web. Una caratteristica non è specifica per un individuo, come un ID utente, né altamente specifica, come l'ora esatta del giorno.

Azioni con caratteristiche

Ogni azione (contenuto) include caratteristiche per distinguere l'alimento.

Le funzionalità non sono configurate come parte della configurazione del ciclo nel portale di Azure. Vengono invece inviate come oggetto JSON con ogni chiamata all'API Classificazione. In questo modo, le azioni e le relative caratteristiche possono aumentare, cambiare e diminuire con flessibilità, consentendo a Personalizer di seguire le tendenze.

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

Caratteristiche del contesto

Le caratteristiche del contesto consentono a Personalizer di comprendere il contesto delle azioni. Il contesto per questa applicazione di esempio include:

  • ora del giorno: mattina, pomeriggio, sera, notte
  • preferenza di gusto dell'utente: salato, dolce, amaro, acido oppure umami
  • contesto del browser: user agent, posizione geografica, referrer
/// <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];
}

In che modo l'app Web usa Personalizer?

L'app web utilizza Personalizer per selezionare l'azione migliore dall'elenco delle scelte alimentari. A questo scopo invia le informazioni seguenti con ogni chiamata all'API Classificazione:

  • Azioni, con relative caratteristiche, ad esempio taste e spiceLevel
  • Caratteristiche del contesto, ad esempio time del giorno, preferenza di taste dell'utente e informazioni sull'agente utente del browser e caratteristiche del contesto.
  • Azioni da escludere, ad esempio succo
  • ID evento, che è diverso per ogni chiamata all'API Classificazione.

Funzionalità del modello Personalizer in un'applicazione web

Personalizer ha bisogno delle caratteristiche per le azioni (contenuto) e il contesto corrente (utente e ambiente). Le caratteristiche vengono usate per allineare le azioni al contesto corrente nel modello. Il modello è una rappresentazione delle conoscenze passate di Personalizer riguardanti azioni, contesto e relative caratteristiche che consente al servizio di prendere decisioni informate.

Il modello, incluse le funzionalità, viene aggiornato in base a una pianificazione basata sulla frequenza di aggiornamento Model nel portale di Azure.

Attenzione

In questa applicazione sono illustrate le caratteristiche e i relativi valori, ma non necessariamente quelle migliori da usare in un'app Web.

Pianificare le caratteristiche e i relativi valori

Le caratteristiche devono essere selezionate con la stessa pianificazione e gli stessi criteri che si applicherebbero a qualsiasi schema o modello nell'architettura tecnica. I valori delle caratteristiche possono essere impostati con la logica di business o con sistemi di terze parti. I valori delle caratteristiche non devono essere talmente specifici da non essere applicabili a un gruppo o a una categoria di caratteristiche.

Generalizzare i valori delle caratteristiche

Generalizzare in categorie

Questa app usa time come caratteristica ma raggruppa il tempo in categorie come morning, afternoon, evening e night. Questo è un esempio dell'uso delle informazioni sul tempo, ma in modo non altamente specifico, come ad esempio 10:05:01 UTC+2.

Generalizzare in componenti

Questa app usa le caratteristiche delle richieste HTTP del browser. Inizia con una stringa molto specifica con tutti i dati, ad esempio:

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

La libreria di classi HttpRequestFeatures generalizza questa stringa in un oggetto userAgentInfo con singoli valori. Tutti i valori troppo specifici vengono impostati su una stringa vuota. Quando vengono inviate le caratteristiche del contesto per la richiesta, il formato JSON è il seguente:

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

Uso dell'app Web di esempio

Per eseguire l'app Web di esempio basata su browser (viene fornito tutto il codice), è necessario che siano installate le applicazioni seguenti.

Installare il software seguente:

  • .NET Core 2.1: il server back-end di esempio usa .NET core
  • Node.js: il client/front-end dipende da questa applicazione
  • Visual Studio 2019 o .NET Core CLI: usare l'ambiente per sviluppatori di Visual Studio 2019 o l'interfaccia della riga di comando di .NET Core per compilare ed eseguire l'app

Configurare l'esempio

  1. Clonare il repository Personalizza esperienze di Azure AI Samples.

    git clone https://github.com/Azure-Samples/cognitive-services-personalizer-samples.git
    
  2. Passare a samples/HttpRequestFeatures per aprire la soluzione HttpRequestFeaturesExample.sln.

    Se richiesto, consentire a Visual Studio di aggiornare il pacchetto .NET per Personalizer.

Configurare il servizio Personalizza esperienze di Azure AI

  1. Creare una risorsa Personalizer nel portale Azure.

  2. Nel portale di Azure, trova il Endpoint e Key1 o Key2 (entrambe andranno bene) nella scheda Chiavi ed Endpoint. Questi sono il tuo PersonalizerServiceEndpoint e il tuo PersonalizerApiKey.

  3. Inserire PersonalizerServiceEndpoint in appsettings.json.

  4. Configurare PersonalizerApiKey come segreti dell'app in uno dei modi seguenti:

    • Se si usa l'interfaccia della riga di comando di .NET Core, è possibile usare il comando dotnet user-secrets set "PersonalizerApiKey" "<API Key>".
    • Se si usa Visual Studio, è possibile fare clic con il pulsante destro del mouse sul progetto e selezionare l'opzione di menu Gestisci segreti utente per configurare le chiavi di Personalizza esperienze. In questo modo, Visual Studio aprirà un file secrets.json in cui è possibile aggiungere le chiavi come indicato di seguito:
    {
      "PersonalizerApiKey": "<your personalizer key here>",
    }
    

Eseguire il campione di codice

Compilare ed eseguire HttpRequestFeaturesExample con uno dei metodi seguenti:

  • Visual Studio 2019: Premere F5
  • .NET Core CLI: dotnet build quindi dotnet run

Tramite un Web browser è possibile inviare una richiesta di classificazione e una richiesta di ricompensa e visualizzare le rispettive risposte, oltre alle caratteristiche delle richieste HTTP estratte dalle ambiente.

Screenshot che mostra un esempio della funzionalità delle richieste HTTP in un Web browser.

Dimostrazione del ciclo di Personalizer

  1. Selezionare il pulsante Generate new Rank Request (Genera nuova richiesta di classificazione) per creare un nuovo oggetto JSON per la chiamata all'API Classificazione. Vengono create le azioni (con caratteristiche) e le caratteristiche del contesto, quindi vengono visualizzati i valori per mostrare l'aspetto dell'oggetto JSON.

    Per le applicazioni future, la generazione di azioni e caratteristiche potrebbe essere eseguita nel client, nel server, in una combinazione di questi due o con chiamate ad altri servizi.

  2. Selezionare Send Rank Request (Invia richiesta di classificazione) per inviare l'oggetto JSON al server. Il server chiama l'API Classificazione di Personalizza esperienze. Il server riceve la risposta e restituisce l'azione con la classificazione più alta al client per la visualizzazione.

  3. Impostare il valore della ricompensa, quindi selezionare il pulsante Send Reward Request (Invia richiesta di ricompensa). Se non si cambia il valore della ricompensa, l'applicazione client invia sempre il valore 1 a Personalizer.

    La schermata mostra la sezione Richiesta di ricompensa.

    Per le applicazioni future, la generazione del punteggio di ricompensa potrebbe essere eseguita dopo la raccolta di informazioni dal comportamento dell'utente nel client, oltre che dalla logica di business nel server.

Comprendi l'App Web di esempio

L'app Web di esempio include un server C# .NET, che gestisce la raccolta di funzionalità e l'invio e la ricezione di chiamate HTTP all'endpoint personalizzatore.

L'app Web di esempio usa un'applicazione client front-end knockout per acquisire funzionalità ed elaborare azioni dell'interfaccia utente, ad esempio facendo clic sui pulsanti e inviando dati al server .NET.

Le sezioni seguenti illustrano le parti del server e del client che uno sviluppatore deve comprendere per usare Personalizer.

API Classificazione: l'applicazione client invia il contesto al server

L'applicazione client raccoglie l'agente utente del browser dell'utente.

Compilare ed eseguire il progetto HTTPRequestFeaturesExample. Viene visualizzata una finestra del browser con l'applicazione a pagina singola.

API di ordinamento: l'applicazione server chiama Personalizer

Si tratta di un'app Web .NET tipica che include un'applicazione client, e gran parte del codice boilerplate viene fornito automaticamente. Qualsiasi codice non specifico di Personalizza esperienze è stato rimosso dai frammenti di codice seguente, in modo da potersi concentrare sul codice specifico di Personalizza esperienze.

Creare il client di Personalizer

Nel file Startup.cs del server, l'endpoint e la chiave di Personalizer vengono utilizzati per creare il client di Personalizer. L'applicazione client non deve comunicare con Personalizer in questa app, ma si affida al server per effettuare queste chiamate SDK.

Il codice di avvio del server Web .NET è:

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

Selezionare l'azione migliore

Nel file PersonalizerController.cs del server l'API server GenerateRank riepiloga la preparazione della chiamata all'API Classificazione

  • Creare nuovo oggetto eventId per la chiamata a Classificazione
  • Ottenere l'elenco di azioni
  • Ottenere l'elenco delle funzionalità dall'utente e creare le caratteristiche del contesto
  • Facoltativamente, impostare eventuali azioni escluse
  • Chiamare l'API Classificazione e restituire i risultati al 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);
}

Il codice JSON inviato a Personalizer, contenente sia le azioni (con funzionalità) sia le funzionalità del contesto corrente, avrà l'aspetto seguente:

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

Restituire al client il rewardActionId di Personalizer.

L'API Classificazione restituisce al server l'azione migliore selezionata in rewardActionId.

Visualizzare l'azione restituita in 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"
}

Il client visualizza l'azione rewardActionId

Per questa esercitazione, viene visualizzato il valorerewardActionId.

Nelle applicazioni future potrebbe essere un testo esatto, un pulsante o una sezione evidenziata di una pagina Web. L'elenco viene restituito per un'eventuale analisi successiva dei punteggi, non per l'ordinamento del contenuto. Dovrebbe essere visualizzato solo il contenuto di rewardActionId.

API Ricompensa: raccogliere informazioni per la ricompensa

Il punteggio di ricompensa dovrà essere pianificato con cautela, proprio come le caratteristiche. Il punteggio di ricompensa è in genere un valore compreso tra 0 e 1. Il valore può essere calcolato parzialmente nell'applicazione client, in base ai comportamenti degli utenti, e parzialmente nel server, in base alla logica di business e agli obiettivi.

Se il server non chiama l'API Reward entro il Tempo di attesa della ricompensa configurato nel portale di Azure per la risorsa Personalizer, viene utilizzata la ricompensa predefinita (anch'essa configurata nel portale di Azure) per quell'evento.

In questa applicazione di esempio è possibile selezionare un valore per vedere l'effetto della ricompensa sulle selezioni.

Altre informazioni ricavabili da questo esempio

L'esempio utilizza diversi eventi temporali configurati nel portale di Azure per la risorsa Personalizer. Sperimentare con questi valori, quindi tornare in questa app Web di esempio per verificare l'effetto delle modifiche sulle chiamate a Classificazione e a Ricompensa:

  • Tempo di attesa per la ricompensa
  • Model update frequency (Frequenza di aggiornamento del modello)

Altre impostazioni con cui sperimentare includono:

  • Ricompensa predefinita
  • Percentuale di esplorazione

Pulire le risorse

Al termine di questa esercitazione, pulire le risorse seguenti:

  • Eliminare la directory del progetto di esempio.
  • Elimina la risorsa di Personalizza esperienze, che può essere considerata una risorsa dedicata ad azioni e contesto, da riutilizzare solo se si usa ancora il cibo come dominio delle azioni.

Passaggi successivi