Краткое руководство. Клиентская библиотека Персонализатора

Важно!

Начиная с 20 сентября 2023 г. вы не сможете создавать новые ресурсы Персонализатора. Служба Персонализатора отменяется 1 октября 2026 года.

Начало работы с клиентскими библиотеками Персонализатора ИИ Azure для настройки базового цикла обучения. Цикл обучения — это система решений и отзывов: приложение запрашивает ранжирование решений от службы, а затем использует лучший выбор и вычисляет оценку вознаграждения из результата. Он возвращает оценку вознаграждения службе. С течением времени Персонализатор использует алгоритмы ИИ для принятия лучших решений для любого заданного контекста. Выполните следующие действия, чтобы настроить пример приложения.

Пример сценария

В этом кратком руководстве продуктовый интернет-магазин хочет увеличить доход, показывая релевантные и персонализированные продукты каждому клиенту на своем веб-сайте. На главной странице есть раздел "Рекомендуемый продукт", в котором потенциальным покупателям демонстрируется готовая еда. Электронная торговая компания хотела бы определить, как показать правильный продукт правильному клиенту, чтобы максимально повысить вероятность покупки.

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

Справочная документация | Исходный код библиотеки | Пакет (NuGet) | Примеры кода .NET

Необходимые компоненты

  • Подписка Azure — создайте бесплатную учетную запись.
  • Текущая версия .NET Core.
  • После получения подписки Azure создайте ресурс Персонализатора в портал Azure, чтобы получить ключ и конечную точку. После развертывания ресурса выберите элемент Перейти к ресурсу.
    • Вам потребуется ключ и конечная точка из ресурса, создаваемого для подключения приложения к API Персонализатора. Ключ и конечная точка будут вставлены в приведенный ниже код в кратком руководстве.
    • Используйте бесплатную ценовую категорию (F0), чтобы опробовать службу, а затем выполните обновление до платного уровня для рабочей среды.

Конфигурация модели

Изменение частоты обновления модели

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

Change model update frequency

Изменение времени ожидания при вознаграждении

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

Change reward wait time

Создание нового приложения C#

Создайте консольное приложение .NET Core на C# в предпочитаемой интегрированной среде разработки или редакторе.

В окне консоли (cmd, PowerShell или Bash) выполните команду dotnet new, чтобы создать консольное приложение с именем personalizer-quickstart. Эта команда создает простой проект Hello World на языке C# с одним файлом исходного кода: Program.cs.

dotnet new console -n personalizer-quickstart

Измените каталог на созданную папку приложения. Чтобы создать приложение, выполните следующую команду:

dotnet build

Выходные данные сборки не должны содержать предупреждений или ошибок.

...
Build succeeded.
 0 Warning(s)
 0 Error(s)
...

Установка клиентской библиотеки

В каталоге приложения установите клиентскую библиотеку Персонализатора для .NET с помощью следующей команды:

dotnet add package Microsoft.Azure.CognitiveServices.Personalizer --version 1.0.0

Совет

Если вы используете интегрированную среду разработки Visual Studio, клиентская библиотека доступна в виде загружаемого пакета NuGet.

Блок кода 1. Создание примеров данных

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

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

  • GetContext возвращает имитированный визит клиента. Он выбирает случайные сведения (контекстные функции), такие как какой клиент присутствует и какое время дня проводится визит. Как правило, контекст представляет текущее состояние приложения, системы, среды или пользователя. Объект контекста используется в качестве входных данных для API ранжирования.

    Функции контекста в этом кратком руководстве являются упрощенными. Однако в реальной производственной системе разработка функций и оценка их эффективности важна. Дополнительные сведения см. в связанной документации.

  • GetRewardScore возвращает оценку между нулем и одной, которая представляет успех взаимодействия с клиентом. Она использует простую логику, чтобы определить, как разные контексты реагируют на различные варианты действий. Например, определенный пользователь всегда даст 1,0 для вегетарианских и веганского продуктов, а также 0,0 для других продуктов. В реальном сценарии Персонализатор узнает о предпочтениях пользователей на основе данных, отправленных в вызовах API ранжирования и вознаграждения. Эти сведения не определяются явным образом, как в примере кода.

    В реальной производственной системе оценка вознаграждения должна быть разработана для согласования с бизнес-целями и ключевыми показателями эффективности. Определение способа вычисления метрики вознаграждения может потребовать некоторых экспериментов.

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

  1. Найдите ключ и конечную точку.

    Важно!

    Переход на портал Azure. Если ресурс Персонализатора, созданный в соответствии с указаниями в разделе Предварительные требования, успешно развернут, нажмите кнопку Перейти к ресурсу в разделе Дальнейшие действия. Ключ и конечная точка располагаются на странице ключа и конечной точки ресурса в разделе управления ресурсами.

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

  2. Откройте Program.cs в текстовом редакторе или интегрированной среде разработки и вставьте следующий код.

    using Microsoft.Azure.CognitiveServices.Personalizer;
    using Microsoft.Azure.CognitiveServices.Personalizer.Models;
    
    class Program
    {
        private static readonly string ApiKey = "REPLACE_WITH_YOUR_PERSONALIZER_KEY";
        private static readonly string ServiceEndpoint = "REPLACE_WITH_YOUR_ENDPOINT_URL";
    
        static PersonalizerClient InitializePersonalizerClient(string url)
        {
            PersonalizerClient client = new PersonalizerClient(
                new ApiKeyServiceClientCredentials(ApiKey))
            { Endpoint = url };
    
            return client;
        }
    
        static Dictionary<string, ActionFeatures> actions = new Dictionary<string, ActionFeatures>
        {
        {"pasta", new ActionFeatures(
                        new BrandInfo(company: "pasta_inc"),
                        new ItemAttributes(
                            quantity: 1,
                            category: "Italian",
                            price: 12),
                        new DietaryAttributes(
                            vegan: false,
                            lowCarb: false,
                            highProtein: false,
                            vegetarian: false,
                            lowFat: true,
                            lowSodium: true))},
        {"bbq", new ActionFeatures(
                        new BrandInfo(company: "ambisco"),
                        new ItemAttributes(
                            quantity: 2,
                            category: "bbq",
                            price: 20),
                        new DietaryAttributes(
                            vegan: false,
                            lowCarb: true,
                            highProtein: true,
                            vegetarian: false,
                            lowFat: false,
                            lowSodium: false))},
        {"bao", new ActionFeatures(
                        new BrandInfo(company: "bao_and_co"),
                        new ItemAttributes(
                            quantity: 4,
                            category: "Chinese",
                            price: 8),
                        new DietaryAttributes(
                            vegan: false,
                            lowCarb: true,
                            highProtein: true,
                            vegetarian: false,
                            lowFat: true,
                            lowSodium: false))},
        {"hummus", new ActionFeatures(
                        new BrandInfo(company: "garbanzo_inc"),
                        new ItemAttributes(
                            quantity: 1,
                            category: "Breakfast",
                            price: 5),
                        new DietaryAttributes(
                            vegan: true,
                            lowCarb: false,
                            highProtein: true,
                            vegetarian: true,
                            lowFat: false,
                            lowSodium: false))},
        {"veg_platter", new ActionFeatures(
                        new BrandInfo(company: "farm_fresh"),
                        new ItemAttributes(
                            quantity: 1,
                            category: "produce",
                            price: 7),
                        new DietaryAttributes(
                            vegan: true,
                            lowCarb: true,
                            highProtein: false,
                            vegetarian: true,
                            lowFat: true,
                            lowSodium: true ))},
    };
    
        static IList<RankableAction> GetActions()
        {
            IList<RankableAction> rankableActions = new List<RankableAction>();
            foreach (var action in actions)
            {
                rankableActions.Add(new RankableAction
                {
                    Id = action.Key,
                    Features = new List<object>() { action.Value }
                });
            }
    
            return rankableActions;
        }
    
        public class BrandInfo
        {
            public string Company { get; set; }
            public BrandInfo(string company)
            {
                Company = company;
            }
        }
    
        public class ItemAttributes
        {
            public int Quantity { get; set; }
            public string Category { get; set; }
            public double Price { get; set; }
            public ItemAttributes(int quantity, string category, double price)
            {
                Quantity = quantity;
                Category = category;
                Price = price;
            }
        }
    
        public class DietaryAttributes
        {
            public bool Vegan { get; set; }
            public bool LowCarb { get; set; }
            public bool HighProtein { get; set; }
            public bool Vegetarian { get; set; }
            public bool LowFat { get; set; }
            public bool LowSodium { get; set; }
            public DietaryAttributes(bool vegan, bool lowCarb, bool highProtein, bool vegetarian, bool lowFat, bool lowSodium)
            {
                Vegan = vegan;
                LowCarb = lowCarb;
                HighProtein = highProtein;
                Vegetarian = vegetarian;
                LowFat = lowFat;
                LowSodium = lowSodium;
    
            }
        }
    
        public class ActionFeatures
        {
            public BrandInfo BrandInfo { get; set; }
            public ItemAttributes ItemAttributes { get; set; }
            public DietaryAttributes DietaryAttributes { get; set; }
            public ActionFeatures(BrandInfo brandInfo, ItemAttributes itemAttributes, DietaryAttributes dietaryAttributes)
            {
                BrandInfo = brandInfo;
                ItemAttributes = itemAttributes;
                DietaryAttributes = dietaryAttributes;
            }
        }
    
        public static Context GetContext()
        {
            return new Context(
                    user: GetRandomUser(),
                    timeOfDay: GetRandomTimeOfDay(),
                    location: GetRandomLocation(),
                    appType: GetRandomAppType());
        }
    
        static string[] timesOfDay = new string[] { "morning", "afternoon", "evening" };
    
        static string[] locations = new string[] { "west", "east", "midwest" };
    
        static string[] appTypes = new string[] { "edge", "safari", "edge_mobile", "mobile_app" };
    
        static IList<UserProfile> users = new List<UserProfile>
    {
        new UserProfile(
            name: "Bill",
            dietaryPreferences: new Dictionary<string, bool> { { "low_carb", true } },
            avgOrderPrice: "0-20"),
        new UserProfile(
            name: "Satya",
            dietaryPreferences: new Dictionary<string, bool> { { "low_sodium", true} },
            avgOrderPrice: "201+"),
        new UserProfile(
            name: "Amy",
            dietaryPreferences: new Dictionary<string, bool> { { "vegan", true }, { "vegetarian", true } },
            avgOrderPrice: "21-50")
    };
    
        static string GetRandomTimeOfDay()
        {
            var random = new Random();
            var timeOfDayIndex = random.Next(timesOfDay.Length);
            Console.WriteLine($"TimeOfDay: {timesOfDay[timeOfDayIndex]}");
            return timesOfDay[timeOfDayIndex];
        }
    
        static string GetRandomLocation()
        {
            var random = new Random();
            var locationIndex = random.Next(locations.Length);
            Console.WriteLine($"Location: {locations[locationIndex]}");
            return locations[locationIndex];
        }
    
        static string GetRandomAppType()
        {
            var random = new Random();
            var appIndex = random.Next(appTypes.Length);
            Console.WriteLine($"AppType: {appTypes[appIndex]}");
            return appTypes[appIndex];
        }
    
        static UserProfile GetRandomUser()
        {
            var random = new Random();
            var userIndex = random.Next(users.Count);
            Console.WriteLine($"\nUser: {users[userIndex].Name}");
            return users[userIndex];
        }
    
        public class UserProfile
        {
            // Mark name as non serializable so that it is not part of the context features
            [NonSerialized()]
            public string Name;
            public Dictionary<string, bool> DietaryPreferences { get; set; }
            public string AvgOrderPrice { get; set; }
    
            public UserProfile(string name, Dictionary<string, bool> dietaryPreferences, string avgOrderPrice)
            {
                Name = name;
                DietaryPreferences = dietaryPreferences;
                AvgOrderPrice = avgOrderPrice;
            }
        }
    
        public class Context
        {
            public UserProfile User { get; set; }
            public string TimeOfDay { get; set; }
            public string Location { get; set; }
            public string AppType { get; set; }
    
            public Context(UserProfile user, string timeOfDay, string location, string appType)
            {
                User = user;
                TimeOfDay = timeOfDay;
                Location = location;
                AppType = appType;
            }
        }
        public static float GetRewardScore(Context context, string actionId)
        {
            float rewardScore = 0.0f;
            string userName = context.User.Name;
            ActionFeatures actionFeatures = actions[actionId];
            if (userName.Equals("Bill"))
            {
                if (actionFeatures.ItemAttributes.Price < 10 && !context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill likes to be economical when he's not in the midwest visiting his friend Warren. He bought {actionId} because it was below a price of $10.");
                }
                else if (actionFeatures.DietaryAttributes.LowCarb && context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill is visiting his friend Warren in the midwest. There he's willing to spend more on food as long as it's low carb, so Bill bought {actionId}.");
                }
                else if (actionFeatures.ItemAttributes.Price >= 10 && !context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill didn't buy {actionId} because the price was too high when not visting his friend Warren in the midwest.");
                }
                else if (actionFeatures.DietaryAttributes.LowCarb && context.Location.Equals("midwest"))
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nBill didn't buy {actionId} because it's not low-carb, and he's in the midwest visitng his friend Warren.");
                }
            }
            else if (userName.Equals("Satya"))
            {
                if (actionFeatures.DietaryAttributes.LowSodium)
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nSatya is health conscious, so he bought {actionId} since it's low in sodium.");
                }
                else
                {
                    Console.WriteLine($"\nSatya did not buy {actionId} because it's not low sodium.");
                }
            }
            else if (userName.Equals("Amy"))
            {
                if (actionFeatures.DietaryAttributes.Vegan || actionFeatures.DietaryAttributes.Vegetarian)
                {
                    rewardScore = 1.0f;
                    Console.WriteLine($"\nAmy likes to eat plant-based foods, so she bought {actionId} because it's vegan or vegetarian friendly.");
                }
                else
                {
                    Console.WriteLine($"\nAmy did not buy {actionId} because it's not vegan or vegetarian.");
                }
            }
            return rewardScore;
        }
        // ...
    
  3. Вставьте ключ и конечную точку в код там, где это указано. У конечной точки есть форма https://<your_resource_name>.cognitiveservices.azure.com/.

    Важно!

    Обязательно удалите ключ из кода, когда завершите работу, и ни в коем случае не публикуйте его в открытом доступе. Для рабочей среды используйте безопасный способ хранения и доступа к учетным данным, например Azure Key Vault. Дополнительные сведения см. в статье по безопасности служб ИИ Azure.

Блок кода 2. Итерацию цикла обучения

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

В этом примере каждый вызов ранжирования выполняется для определения того, какой продукт должен отображаться в разделе "Избранный продукт". Затем вызов Reward указывает, был ли продукт приобретен пользователем. Вознаграждения связаны с их решениями через общую EventId ценность.

    static void Main(string[] args)
    {
        int iteration = 1;
        bool runLoop = true;

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

        // Initialize Personalizer client.
        PersonalizerClient client = InitializePersonalizerClient(ServiceEndpoint);

        do
        {
            Console.WriteLine("\nIteration: " + iteration++);

            // Get context information.
            Context context = GetContext();

            // Create current context from user specified data.
            IList<object> currentContext = new List<object>() {
            context
        };

            // Generate an ID to associate with the request.
            string eventId = Guid.NewGuid().ToString();

            // Rank the actions
            var request = new RankRequest(actions: actions, contextFeatures: currentContext, eventId: eventId);
            RankResponse response = client.Rank(request);

            Console.WriteLine($"\nPersonalizer service thinks {context.User.Name} would like to have: {response.RewardActionId}.");

            float reward = GetRewardScore(context, response.RewardActionId);

            // Send the reward for the action based on user response.
            client.Reward(response.EventId, new RewardRequest(reward));

            Console.WriteLine("\nPress q to break, any other key to continue:");
            runLoop = !(GetKey() == "Q");

        } while (runLoop);
    }

        private static string GetKey()
    {
        return Console.ReadKey().Key.ToString().Last().ToString().ToUpper();
    }

}

Запуск программы

Перейдите к каталогу приложения и запустите приложение с помощью команды dotnet dotnet run.

dotnet run

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

The quickstart program asks a couple of questions to gather user preferences, known as features, then provides the top action.

Создание большого количества событий для анализа (необязательно)

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

    static void Main(string[] args)
    {
    int iteration = 1;
    int runLoop = 0;

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

    // Initialize Personalizer client.
    PersonalizerClient client = InitializePersonalizerClient(ServiceEndpoint);

    do
    {
        Console.WriteLine("\nIteration: " + iteration++);

        // Get context information.
        Context context = GetContext();

        // Create current context from user specified data.
        IList<object> currentContext = new List<object>() {
            context
        };

        // Generate an ID to associate with the request.
        string eventId = Guid.NewGuid().ToString();

        // Rank the actions
        var request = new RankRequest(actions: actions, contextFeatures: currentContext, eventId: eventId);
        RankResponse response = client.Rank(request);

        Console.WriteLine($"\nPersonalizer service thinks {context.User.Name} would like to have: {response.RewardActionId}.");

        float reward = GetRewardScore(context, response.RewardActionId);

        // Send the reward for the action based on user response.
        client.Reward(response.EventId, new RewardRequest(reward));

        runLoop = runLoop + 1;

    } while (runLoop < 1000);
}

Исходный код для этого краткого руководства доступен на сайте GitHub.

Пример кода исходного кода | библиотеки ссылок |(npm) | Quickstart

Необходимые компоненты

  • Подписка Azure — создайте бесплатную учетную запись.
  • Установите Node.js и npm (проверено с помощью Node.js v14.16.0 и npm 6.14.11).
  • После получения подписки Azure создайте ресурс Персонализатора в портал Azure, чтобы получить ключ и конечную точку. После развертывания ресурса выберите элемент Перейти к ресурсу.
    • Вам потребуется ключ и конечная точка из ресурса, создаваемого для подключения приложения к API Персонализатора. Ключ и конечная точка будут вставлены в приведенный ниже код в кратком руководстве.
    • Используйте бесплатную ценовую категорию (F0), чтобы опробовать службу, а затем выполните обновление до платного уровня для рабочей среды.

Конфигурация модели

Изменение частоты обновления модели

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

Change model update frequency

Изменение времени ожидания при вознаграждении

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

Change reward wait time

Создание нового приложения Node.js

В окне консоли (например, cmd, PowerShell или Bash) создайте новый каталог для приложения и перейдите в него.

mkdir myapp && cd myapp

Выполните команду npm init -y, чтобы создать файл package.json.

npm init -y

Создайте скрипт Node.js в предпочтительном редакторе или интегрированной среде разработки с именем personalizer-quickstart.js и создайте переменные для конечной точки и ключа подписки ресурса.

Установка клиентской библиотеки

Установите клиентскую библиотеку Персонализатора для Node.js с помощью следующей команды:

npm install @azure/cognitiveservices-personalizer --save

Установите оставшиеся пакеты npm для этого краткого руководства:

npm install @azure/ms-rest-azure-js @azure/ms-rest-js readline-sync uuid --save

Блок кода 1. Создание примеров данных

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

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

  • GetContextFeaturesList возвращает имитированный визит клиента. Он выбирает случайные сведения (контекстные функции), такие как какой клиент присутствует и какое время дня проводится визит. Как правило, контекст представляет текущее состояние приложения, системы, среды или пользователя. Объект контекста используется в качестве входных данных для API ранжирования.

    Функции контекста в этом кратком руководстве являются упрощенными. Однако в реальной производственной системе разработка функций и оценка их эффективности важна. Дополнительные сведения см. в связанной документации.

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

    В реальной производственной системе оценка вознаграждения должна быть разработана для согласования с бизнес-целями и ключевыми показателями эффективности. Определение способа вычисления метрики вознаграждения может потребовать некоторых экспериментов.

Откройте персонализатор-quickstart.js в текстовом редакторе или интегрированной среде разработки и вставьте приведенный ниже код.

const uuidv1 = require('uuid/v1');
const Personalizer = require('@azure/cognitiveservices-personalizer');
const CognitiveServicesCredentials = require('@azure/ms-rest-azure-js').CognitiveServicesCredentials;
const readline = require('readline-sync');

function getReward() {
  const answer = readline.question("\nIs this correct (y/n)\n");
  if (answer.toLowerCase() === 'y') {
    console.log("\nGreat| Enjoy your food.");
    return 1;
  }
  console.log("\nYou didn't like the recommended food choice.");
  return 0;
}

function getContextFeaturesList() {
  const timeOfDayFeatures = ['morning', 'afternoon', 'evening', 'night'];
  const tasteFeatures = ['salty', 'sweet'];

  let answer = readline.question("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night\n");
  let selection = parseInt(answer);
  const timeOfDay = selection >= 1 && selection <= 4 ? timeOfDayFeatures[selection - 1] : timeOfDayFeatures[0];

  answer = readline.question("\nWhat type of food would you prefer (enter number)? 1. salty 2. sweet\n");
  selection = parseInt(answer);
  const taste = selection >= 1 && selection <= 2 ? tasteFeatures[selection - 1] : tasteFeatures[0];

  console.log("Selected features:\n");
  console.log("Time of day: " + timeOfDay + "\n");
  console.log("Taste: " + taste + "\n");

  return [
    {
      "time": timeOfDay
    },
    {
      "taste": taste
    }
  ];
}

function getExcludedActionsList() {
  return [
    "juice"
  ];
}

function getActionsList() {
  return [
    {
      "id": "pasta",
      "features": [
        {
          "taste": "salty",
          "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": "salty",
          "spiceLevel": "low"
        },
        {
          "nutritionLevel": 8
        }
      ]
    }
  ];
}

Блок кода 2. Итерацию цикла обучения

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

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

  1. Добавьте приведенный ниже код в персонализатор-quickstart.js.

  2. Найдите ключ и конечную точку. У конечной точки есть форма https://<your_resource_name>.cognitiveservices.azure.com/.

    Важно!

    Переход на портал Azure. Если ресурс Персонализатора, созданный в соответствии с указаниями в разделе Предварительные требования, успешно развернут, нажмите кнопку Перейти к ресурсу в разделе Дальнейшие действия. Ключ и конечная точка располагаются на странице ключа и конечной точки ресурса в разделе управления ресурсами.

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

  3. Вставьте ключ и конечную точку в код там, где это указано.

    Важно!

    Обязательно удалите ключ из кода, когда завершите работу, и ни в коем случае не публикуйте его в открытом доступе. Для рабочей среды используйте безопасный способ хранения и доступа к учетным данным, например Azure Key Vault. Дополнительные сведения о безопасности см. в статье по безопасности служб искусственного интеллекта Azure.

    async function main() {
    
        // The key specific to your personalization service instance; e.g. "0123456789abcdef0123456789ABCDEF"
        const serviceKey = "PASTE_YOUR_PERSONALIZER_SUBSCRIPTION_KEY_HERE";
      
        // The endpoint specific to your personalization service instance; 
        // e.g. https://<your-resource-name>.cognitiveservices.azure.com
        const baseUri = "PASTE_YOUR_PERSONALIZER_ENDPOINT_HERE";
      
        const credentials = new CognitiveServicesCredentials(serviceKey);
      
        // Initialize Personalization client.
        const personalizerClient = new Personalizer.PersonalizerClient(credentials, baseUri);
      
      
        let runLoop = true;
      
        do {
      
          let rankRequest = {}
      
          // Generate an ID to associate with the request.
          rankRequest.eventId = uuidv1();
      
          // Get context information from the user.
          rankRequest.contextFeatures = getContextFeaturesList();
      
          // Get the actions list to choose from personalization with their features.
          rankRequest.actions = getActionsList();
      
          // Exclude an action for personalization ranking. This action will be held at its current position.
          rankRequest.excludedActions = getExcludedActionsList();
      
          rankRequest.deferActivation = false;
      
          // Rank the actions
          const rankResponse = await personalizerClient.rank(rankRequest);
      
          console.log("\nPersonalization service thinks you would like to have:\n")
          console.log(rankResponse.rewardActionId);
      
          // Display top choice to user, user agrees or disagrees with top choice
          const reward = getReward();
      
          console.log("\nPersonalization service ranked the actions with the probabilities as below:\n");
          for (let i = 0; i < rankResponse.ranking.length; i++) {
            console.log(JSON.stringify(rankResponse.ranking[i]) + "\n");
          }
      
          // Send the reward for the action based on user response.
      
          const rewardRequest = {
            value: reward
          }
      
          await personalizerClient.events.reward(rankRequest.eventId, rewardRequest);
      
          runLoop = continueLoop();
      
        } while (runLoop);
      }
      
      function continueLoop() {
        const answer = readline.question("\nPress q to break, any other key to continue.\n")
        if (answer.toLowerCase() === 'q') {
          return false;
        }
        return true;
      }
    
    main()
    .then(result => console.log("done"))
    .catch(err=> console.log(err));
    

Запуск программы

Запустите приложение с помощью команды Node.js из каталога приложения.

node personalizer-quickstart.js

Выполните итерацию нескольких циклов обучения. Через 10 минут служба начнет отображать улучшения в своих рекомендациях.

Исходный код для этого краткого руководства доступен на сайте GitHub.

Справочная документация | Исходный код библиотеки | Пакет (pypi) | Учебные примеры кода

Необходимые компоненты

  • Подписка Azure — создайте бесплатную учетную запись.
  • Python 3.x
  • После настройки подписки Azure создайте ресурс Персонализатора в портал Azure и получите ключ и конечную точку. После развертывания ресурса выберите элемент Перейти к ресурсу.
    • Ключ и конечная точка из созданного ресурса вам понадобятся для подключения вашего приложения к API Персонализатора. Вы вставите их в приведенный ниже код быстрого запуска.
    • Используйте бесплатную ценовую категорию (F0), чтобы опробовать службу, а затем выполните обновление до платного уровня для рабочей среды.

Конфигурация модели

Изменение частоты обновления модели

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

Change model update frequency

Изменение времени ожидания при вознаграждении

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

Change reward wait time

Создание приложения Python

Создайте файл Python с именем personalizer-quickstart.py.

Установка клиентской библиотеки

Установите клиентская библиотека Персонализатора с помощью pip:

pip install azure-cognitiveservices-personalizer

Блок кода 1. Создание примеров данных

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

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

  • get_context возвращает имитированный визит клиента. Он выбирает случайные сведения (контекстные функции), такие как какой клиент присутствует и какое время дня проводится визит. Как правило, контекст представляет текущее состояние приложения, системы, среды или пользователя. Объект контекста используется в качестве входных данных для API ранжирования.

    Функции контекста в этом кратком руководстве являются упрощенными. Однако в реальной производственной системе проектирование функций и оценка их эффективности очень важно. Дополнительные сведения см. в связанной документации.

  • get_reward_score возвращает оценку от нуля до единицы, представляющей успех взаимодействия с клиентом. Она использует простую логику для определения того, как различные контексты будут реагировать на различные варианты действий. Например, определенный пользователь всегда даст 1,0 для вегетарианских и веганского продуктов, а также 0,0 для других продуктов. В реальном сценарии Персонализатор узнает о предпочтениях пользователей на основе данных, отправленных в вызовах API ранжирования и вознаграждения. Эти сведения не определяются явным образом, как в примере кода.

    В реальной производственной системе оценка вознаграждения должна быть разработана для согласования с бизнес-целями и ключевыми показателями эффективности. Определение способа вычисления метрики вознаграждения может потребовать некоторых экспериментов.

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

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

  1. Найдите ключ и конечную точку.

    Важно!

    Переход на портал Azure. Если ресурс Персонализатора, созданный в соответствии с указаниями в разделе Предварительные требования, успешно развернут, нажмите кнопку Перейти к ресурсу в разделе Дальнейшие действия. Ключ и конечная точка располагаются на странице ключа и конечной точки ресурса в разделе управления ресурсами.

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

  2. Откройте personalizer-quickstart.py в текстовом редакторе или интегрированной среде разработки и вставьте приведенный ниже код.

  3. Вставьте ключ и конечную точку в код там, где это указано. У конечной точки есть форма https://<your_resource_name>.cognitiveservices.azure.com/.

    Важно!

    Обязательно удалите ключ из кода, когда завершите работу, и ни в коем случае не публикуйте его в открытом доступе. Для рабочей среды используйте безопасный метод хранения и доступа к учетным данным, например Azure Key Vault. Дополнительные сведения см. в разделе "Безопасность служб искусственного интеллекта Azure".

from azure.cognitiveservices.personalizer import PersonalizerClient
from azure.cognitiveservices.personalizer.models import RankableAction, RewardRequest, RankRequest
from msrest.authentication import CognitiveServicesCredentials

import datetime, json, os, time, uuid, random

key = "paste_your_personalizer_key_here"
endpoint = "paste_your_personalizer_endpoint_here"

# Instantiate a Personalizer client
client = PersonalizerClient(endpoint, CognitiveServicesCredentials(key))

actions_and_features = {
    'pasta': {
        'brand_info': {
            'company':'pasta_inc'
        }, 
        'attributes': {
            'qty':1, 'cuisine':'italian',
            'price':12
        },
        'dietary_attributes': {
            'vegan': False,
            'low_carb': False,
            'high_protein': False,
            'vegetarian': False,
            'low_fat': True,
            'low_sodium': True
        }
    },
    'bbq': {
        'brand_info' : {
            'company': 'ambisco'
        },
        'attributes': {
            'qty': 2,
            'category': 'bbq',
            'price': 20
        }, 
        'dietary_attributes': {
            'vegan': False,
            'low_carb': True,
            'high_protein': True,
            'vegetarian': False,
            'low_fat': False,
            'low_sodium': False
        }
    },
    'bao': {
        'brand_info': {
            'company': 'bao_and_co'
        },
        'attributes': {
            'qty': 4,
            'category': 'chinese',
            'price': 8
        }, 
        'dietary_attributes': {
            'vegan': False,
            'low_carb': True,
            'high_protein': True,
            'vegetarian': False,
            'low_fat': True,
            'low_sodium': False
        }
    },
    'hummus': {
        'brand_info' : { 
            'company': 'garbanzo_inc'
        },
        'attributes' : {
            'qty': 1,
            'category': 'breakfast',
            'price': 5
        }, 
        'dietary_attributes': {
            'vegan': True, 
            'low_carb': False,
            'high_protein': True,
            'vegetarian': True,
            'low_fat': False, 
            'low_sodium': False
        }
    },
    'veg_platter': {
        'brand_info': {
            'company': 'farm_fresh'
        }, 
        'attributes': {
            'qty': 1,
            'category': 'produce', 
            'price': 7
        },
        'dietary_attributes': {
            'vegan': True,
            'low_carb': True,
            'high_protein': False,
            'vegetarian': True,
            'low_fat': True,
            'low_sodium': True
        }
    }
}

def get_actions():
    res = []
    for action_id, feat in actions_and_features.items():
        action = RankableAction(id=action_id, features=[feat])
        res.append(action)
    return res

user_profiles = {
    'Bill': {
        'dietary_preferences': 'low_carb', 
        'avg_order_price': '0-20',
        'browser_type': 'edge'
    },
    'Satya': {
        'dietary_preferences': 'low_sodium',
        'avg_order_price': '201+',
        'browser_type': 'safari'
    },
    'Amy': {
        'dietary_preferences': {
            'vegan', 'vegetarian'
        },
        'avg_order_price': '21-50',
        'browser_type': 'edge'},
    }

def get_context(user):
    location_context = {'location': random.choice(['west', 'east', 'midwest'])}
    time_of_day = {'time_of_day': random.choice(['morning', 'afternoon', 'evening'])}
    app_type = {'application_type': random.choice(['edge', 'safari', 'edge_mobile', 'mobile_app'])}
    res = [user_profiles[user], location_context, time_of_day, app_type]
    return res

def get_random_users(k = 5):
    return random.choices(list(user_profiles.keys()), k=k)


def get_reward_score(user, actionid, context):
    reward_score = 0.0
    action = actions_and_features[actionid]
    
    if user == 'Bill':
        if action['attributes']['price'] < 10 and (context[1]['location'] !=  "midwest"):
            reward_score = 1.0
            print("Bill likes to be economical when he's not in the midwest visiting his friend Warren. He bought", actionid, "because it was below a price of $10.")
        elif (action['dietary_attributes']['low_carb'] == True) and (context[1]['location'] ==  "midwest"):
            reward_score = 1.0
            print("Bill is visiting his friend Warren in the midwest. There he's willing to spend more on food as long as it's low carb, so Bill bought" + actionid + ".")
            
        elif (action['attributes']['price'] >= 10) and (context[1]['location'] != "midwest"):
            print("Bill didn't buy", actionid, "because the price was too high when not visting his friend Warren in the midwest.")
            
        elif (action['dietary_attributes']['low_carb'] == False) and (context[1]['location'] ==  "midwest"):
            print("Bill didn't buy", actionid, "because it's not low-carb, and he's in the midwest visitng his friend Warren.")
             
    elif user == 'Satya':
        if action['dietary_attributes']['low_sodium'] == True:
            reward_score = 1.0
            print("Satya is health conscious, so he bought", actionid,"since it's low in sodium.")
        else:
            print("Satya did not buy", actionid, "because it's not low sodium.")   
            
    elif user == 'Amy':
        if (action['dietary_attributes']['vegan'] == True) or (action['dietary_attributes']['vegetarian'] == True):
            reward_score = 1.0
            print("Amy likes to eat plant-based foods, so she bought", actionid, "because it's vegan or vegetarian friendly.")       
        else:
            print("Amy did not buy", actionid, "because it's not vegan or vegetarian.")
                
    return reward_score
    # ...

Блок кода 2. Итерацию цикла обучения

Следующий блок кода определяет функцию run_personalizer_cycle и вызывает ее в простом цикле обратной связи пользователя. Он запускает итерацию цикла обучения, в которой он создает контекст (включая клиента), запрашивает ранжирование действий в этом контексте с помощью API ранжирования, вычисляет оценку вознаграждения и передает этот показатель обратно в службу Персонализатора с помощью API вознаграждения. Он печатает соответствующие сведения в консоли на каждом шаге.

В этом примере каждый вызов ранжирования выполняется для определения того, какой продукт должен отображаться в разделе "Избранный продукт". Затем вызов Reward указывает, был ли продукт приобретен пользователем. Вознаграждения связаны с их решениями через общую EventId ценность.

def run_personalizer_cycle():
    actions = get_actions()
    user_list = get_random_users()
    for user in user_list:
        print("------------")
        print("User:", user, "\n")
        context = get_context(user)
        print("Context:", context, "\n")
        
        rank_request = RankRequest(actions=actions, context_features=context)
        response = client.rank(rank_request=rank_request)
        print("Rank API response:", response, "\n")
        
        eventid = response.event_id
        actionid = response.reward_action_id
        print("Personalizer recommended action", actionid, "and it was shown as the featured product.\n")
        
        reward_score = get_reward_score(user, actionid, context)
        client.events.reward(event_id=eventid, value=reward_score)     
        print("\nA reward score of", reward_score , "was sent to Personalizer.")
        print("------------\n")

continue_loop = True
while continue_loop:
    run_personalizer_cycle()
    
    br = input("Press Q to exit, or any other key to run another loop: ")
    if(br.lower()=='q'):
        continue_loop = False

Запуск программы

После включения приведенного выше кода в файл Python его можно запустить из каталога приложения.

python personalizer-quickstart.py

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

The quickstart program asks a couple of questions to gather user preferences, known as features, then provides the top action.

Создание большого количества событий для анализа (необязательно)

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

for i in range(0,1000):
    run_personalizer_cycle()

Исходный код для этого краткого руководства доступен на сайте GitHub.

Скачивание обученной модели

Если вы хотите скачать модель Персонализатора, которая была обучена на 5000 событий из приведенного выше примера, посетите репозиторий примеров персонализатора и скачайте файл Personalizer_QuickStart_Model.zip . Затем перейдите к ресурсу Персонализатора в портал Azure, перейдите на страницу установки и вкладку "Импорт и экспорт" и импортируйте файл.

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

Чтобы очистить подписку на службы ИИ Azure, можно удалить ресурс или удалить группу ресурсов, которая приведет к удалению всех связанных ресурсов.

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