Поделиться через


Руководство. Добавление персонализатора в веб-приложение .NET

Внимание

Начиная с 20 сентября 2023 г. вы не сможете создавать новые ресурсы Персонализатора. Служба Персонализатора выводится из эксплуатации 1 октября 2026 года. Рекомендуем перейти на проект с открытым исходным кодом microsoft/learning-loop.

Настройте веб-приложение C# .NET с циклом Персонализатора для предоставления пользователю правильного содержимого на основе действий и их особенностей, а также контекстных характеристик.

В этом руководстве рассмотрено, как выполнять следующие задачи.

  • Настройте ключ и конечную точку для Персонализатора.
  • Сбор признаков.
  • Вызов API-интерфейсов ранжирования и вознаграждения.
  • Отображение популярных действий, обозначенных как rewardActionId.

Выбор лучшего содержимого для веб-приложения

Веб-приложение должно использовать Персонализатор при наличии списка действий (определенный тип содержимого) на веб-странице, который необходимо настроить, чтобы отображался один верхний элемент (rewardActionId). Примерами списков действий являются новые статьи, расположения размещения кнопок и подбор слов для названий продуктов.

Вы отправляете список действий вместе с признаками контекста в цикл Personalizer. Персонализатор выбирает одно лучшее действие, которое затем отображается в веб-приложении.

В рамках этого учебника в качестве действий будут использоваться типы пищи:

  • макароны;
  • мороженое;
  • сок;
  • cалат;
  • попкорн;
  • кофе;
  • суп

Чтобы помочь Персонализатору узнать о ваших действиях, отправляйте действия с признаками и признаки контекста с каждым запросом API ранжирования.

Особенность модели заключается в том, что информация о действиях или контексте может быть агрегирована (сгруппирована) среди участников вашей базы пользователей веб-приложения. Характеристика не является индивидуальной (как идентификатор пользователя) или очень специфичной (как точное время дня).

Действия с функциями.

Каждое действие (элемент содержимого) имеет признаки, позволяющие различить блюдо.

Функции не входят в конфигурацию цикла на портале Azure. Вместо этого они отправляются в виде объекта JSON с каждым вызовом API ранжирования. Это предоставляет действиям и их признакам возможность увеличиваться, изменяться и сжиматься в течение периода времени, что позволяет Персонализатору отслеживать тенденции.

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

Признаки контекста

Признаки контекста помогают Персонализатору понять контекст действий. Контекст этого примера приложения включает следующее:

  • время суток — утро, полдень, вечер, ночь;
  • вкусовые предпочтения пользователя — соленое, сладкое, горькое, кислое или острое;
  • контекст браузера — агент пользователя, географическое расположение, источник ссылки.
/// <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];
}

Как веб-приложение использует Персонализатор?

Веб-приложение использует Персонализатор, чтобы выбрать из списка предложенных продуктов лучшее действие. Для этого при каждом вызове API ранжирования отправляется следующая информация:

  • действия с их признаками, такими как taste и spiceLevel;
  • признаки контекста, например time дня, предпочтения taste пользователя, а также сведения об агенте пользователя браузера и признаки контекста;
  • исключаемые действия, например сок;
  • код события, который отличается для каждого вызова API ранжирования.

Характеристики модели Personalizer в веб-приложении

Для Персонализатора необходимо предоставить признаки действий (содержимое) и текущий контекст (контекст пользователя и среды). Функции используются для выравнивания действий в соответствии с текущим контекстом в этой модели. Модель — это представление прошлых знаний Персонализатора о действиях, контексте и их признаках, которые позволяют принимать обоснованные решения.

Модель, включая особенности, обновляется по расписанию на основе вашей настройки Частота обновления модели в портале Azure.

Внимание

Функции в этом приложении предназначены для демонстрации возможностей и значений функций, но они не обязательно являются лучшими для использования в веб-приложении.

Планируйте функции и их значения

Признаки следует выбирать в соответствии с теми же параметрами планирования и разработки, которые вы будете применять ко всем схемам или моделям в системной архитектуре. Значения признаков можно задать с помощью бизнес-логики или сторонних систем. Значения признаков не должны быть настолько специфичными, чтобы их нельзя было применить в группе или классе признаков.

Обобщение значений признаков

Группирование по категориям

Это приложение использует time в качестве признака, однако группирует значения времени по категориям, таким как morning, afternoon, evening и night. Это пример использования информации о времени не в особо специфическом виде, например как 10:05:01 UTC+2.

Обобщение на части

Это приложение использует функции HTTP-запросов из браузера. Цикл начинается с очень конкретной строки со всеми данными, например:

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

Библиотека классов HttpRequestFeatures обобщает эту строку для объекта userAgentInfo, используя отдельные значения. Для всех значений, которые являются слишком конкретными, задается пустая строка. При отправке признаков контекста для запроса они имеют следующий формат JSON:

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

Использование примера веб-приложения

Для запуска приложения с помощью примера веб-приложения на основе браузера (со всеми предоставленными кодами) необходимо иметь указанные ниже установленные приложения.

Установите следующее программное обеспечение:

  • .NET Core 2.1 — образец серверного сервера использует ядро .NET
  • Node.js — от этого приложения зависят клиент и внешний интерфейс.
  • Visual Studio 2019 или .NET Core CLI — используйте среду разработчика Visual Studio 2019 или .NET Core CLI для создания и запуска приложения.

Настройка примера

  1. Клонируйте репозиторий Персонализатор ИИ Azure Samples.

    git clone https://github.com/Azure-Samples/cognitive-services-personalizer-samples.git
    
  2. Перейдите в раздел samples/HttpRequestFeatures, чтобы открыть решение HttpRequestFeaturesExample.sln.

    При запросе разрешите Visual Studio обновить пакет .NET для Персонализатора.

Настройка службы Персонализатор ИИ Azure

  1. Создание ресурса Персонализатора на портале Azure.

  2. На портале Azure найдите Endpoint и Key1 или Key2 (будет работать) на вкладке Keys and Endpoints. Это ваш PersonalizerServiceEndpoint и PersonalizerApiKey.

  3. Укажите значение PersonalizerServiceEndpoint в файле appsettings.json.

  4. Настройте PersonalizerApiKey в качестве секрета приложения одним из следующих способов:

    • Если вы используете интерфейс командной строки .NET Core, можно использовать команду dotnet user-secrets set "PersonalizerApiKey" "<API Key>".
    • Если вы используете Visual Studio, щелкните проект правой кнопкой мыши и выберите пункт меню Manage User Secret, чтобы настроить ключи Персонализатора. Для этого Visual Studio откроется файл secrets.json, где можно добавить ключи следующим образом:
    {
      "PersonalizerApiKey": "<your personalizer key here>",
    }
    

Запустите пример

Создайте и запустите HttpRequestFeaturesExample с помощью одного из следующих методов:

  • Visual Studio 2019: нажмите F5
  • .NET Core CLI: dotnet build затем dotnet run

С помощью веб-браузера вы можете отправлять запросы на ранк и вознаграждение, получать ответы на эти запросы, а также видеть характеристики HTTP-запросов, извлеченные из вашей среды.

Снимок экрана показывает пример функции HTTP-запроса в веб-браузере.

Продемонстрируйте цикл Персонализатора

  1. Нажмите кнопку Generate new Rank Request (Создать запрос ранжирования), чтобы создать объект JSON для вызова API ранжирования. При этом будут созданы действия (с признаками) и признаки контекста, а также отображены значения, чтобы вы могли увидеть, как будет выглядеть файл JSON.

    В вашем собственном будущем приложении создание действий и признаков может выполняться на стороне клиента, сервера или с использованием обоих этих вариантов, а также посредством вызовов к другим службам.

  2. Выберите Send Rank Request (Отправить запрос ранжирования), чтобы отправить объект JSON на сервер. Сервер вызывает API ранжирования Персонализатора. Затем сервер получает ответ и возвращает высокоприоритетное действие клиенту для отображения.

  3. Задайте значение вознаграждения, а затем нажмите кнопку Send Reward Request (Отправить запрос вознаграждения). Если вы не меняли значение вознаграждения, приложение клиента будет всегда отправлять значение 1 Персонализатору.

    Снимок экрана: раздел запроса вознаграждения

    В вашем будущем приложении создание оценки вознаграждения может выполняться после сбора информации на основе данных поведения пользователя на стороне клиента, а также бизнес-логики на стороне сервера.

Общие сведения о примере веб-приложения

В примере веб-приложения есть сервер C# .NET, который управляет коллекцией функций и отправкой и приемом HTTP-вызовов в конечную точку Персонализатора.

В примере веб-приложения используется клиентское приложение knockout для фронтенда для сбора функций и обработки действий в пользовательском интерфейсе, таких как нажатие кнопок и отправка данных на .NET-сервер.

В следующих разделах подробно описаны компоненты сервера и клиента, которые помогут разработчикам лучше понять, как использовать Персонализатор.

API ранжирования: клиентское приложение отправляет контекст на сервер

Клиентское приложение собирает данные об агенте пользователя браузера.

Создайте и запустите проект HTTPRequestFeaturesExample. Откроется окно браузера для отображения одностраничного приложения.

API Rank: вызовы приложения сервера к персонализатору

Это типичное веб-приложение .NET с клиентским приложением, большая часть заготовочного кода предоставлена для вас. Любой код, который не относится к Персонализатору, будет удален из указанных ниже фрагментов кода. Это позволит вам сосредоточиться на конкретном коде Персонализатора.

Создание клиента Персонализатора

В файле Startup.cs сервера используется конечная точка и ключ Персонализатора для создания его клиента. Клиентскому приложению не нужно взаимодействовать с Персонализатором в этом приложении, вместо того оно использует сервер, чтобы отправить вызовы SDK.

Код запуска веб-сервера .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
    }
}

Выбор оптимального действия

В файле PersonalizerController.cs сервера API GenerateRank описываются этапы подготовки для вызова API ранжирования.

  • Создание eventId для вызова ранжирования.
  • Получите список действий.
  • Получите список характеристик от пользователя и создайте характеристики контекста.
  • Настройка исключенных действий (при необходимости).
  • Вызов API ранжирования и возвращение результатов клиенту.
/// <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, отправленный в Персонализатор, содержащий действия (с характеристиками) и текущие характеристики контекста, выглядит следующим образом:

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

Возвращение значения rewardActionId Персонализатора клиенту

API ранжирования возвращает выбранное оптимальное действие rewardActionId на сервер.

Отобразите действие, возвращенное в 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"
}

Клиент отображает действие с идентификатором rewardActionId

В этом учебнике отображается значение rewardActionId.

В вашем собственном будущем приложении это значение может представлять собой некоторый точный текст, кнопку или раздел выделенной веб-страницы. Список возвращается для любого пост-анализа оценок, а не для упорядочения содержимого. Должно отображаться только содержимое rewardActionId.

API вознаграждения: сбор информации о вознаграждении

Оценку вознаграждения следует тщательно планировать, точно так же, как и функции. Оценка вознаграждения обычно должна иметь значение от 0 до 1. Значение можно частично вычислить в клиентском приложении на основе поведения пользователя и частично на сервере на основе бизнес-логики и целей.

Если сервер не вызывает API награды в течение времени ожидания вознаграждения, настроенного на портале Azure для ресурса персонализатора, то вознаграждение по умолчанию (также настроенное на портале Azure) используется для этого события.

В этом примере приложения вы можете выбрать значение, чтобы увидеть, как вознаграждения влияют на выбранные элементы.

Дополнительные способы изучения этого примера

В этом примере использованы несколько событий, основанных на времени, настроенных в портале Azure для ресурса Personalizer. Поэкспериментируйте с этими значениями, а затем вернитесь к этому примеру веб-приложения, чтобы увидеть, как изменения влияют на вызовы ранжирования и вознаграждения.

  • Время ожидания результата
  • Частота обновления модели

Другие возможности, с которыми вы можете поэкспериментировать:

  • Вознаграждение по умолчанию
  • Процент исследования.

Очистка ресурсов

Когда вы завершите работу с этим учебником, очистите следующие ресурсы:

  • Удалите пример каталога проекта.
  • Удалите ресурс "Персонализатор" — думайте о ресурсе «Персонализатор» как о предназначенном для действий и контекста. Ресурс следует использовать повторно, только если вы всё ещё используете область продуктов как предметную область действий.

Следующие шаги