Rychlý start: Individuální nastavení klientské knihovny

Důležité

Od 20. září 2023 nebudete moct vytvářet nové prostředky personalizace. Služba Personalizace se vyřadí z provozu 1. října 2026.

Začněte s klientskými knihovnami Azure AI Personalizace a nastavte si základní výukovou smyčku. Smyčka učení je systém rozhodnutí a zpětné vazby: aplikace požaduje hodnocení rozhodnutí ze služby, pak používá nejlépe seřazenou volbu a vypočítá skóre odměny z výsledku. Vrátí skóre odměny do služby. Personalizace v průběhu času používá algoritmy AI k lepšímu rozhodování pro jakýkoli daný kontext. Pokud chcete nastavit ukázkovou aplikaci, postupujte podle těchto kroků.

Ukázkový scénář

V tomto rychlém startu chce e-prodejce potravin zvýšit výnosy tím, že na svých webových stránkách zobrazuje relevantní a přizpůsobené produkty pro každého zákazníka. Na hlavní stránce je oddíl Doporučený produkt, který zobrazuje připravený produkt jídla potenciálním zákazníkům. E-prodejce by chtěl určit, jak zobrazit správný produkt správnému zákazníkovi, aby se maximalizovala pravděpodobnost nákupu.

Služba Personalizace tento problém řeší automatizovaným, škálovatelným a přizpůsobitelným způsobem s využitím učení se zesílení. Naučíte se vytvářet akce a jejich funkce, kontextové funkce a skóre odměn. Klientskou knihovnu Personalizace použijete k volání rozhraní Rank and Rewards API.

Referenční dokumentace | – ukázka kódu Knihovny zdrojového kódu | knihovny (NuGet) | .NET

Předpoklady

  • Předplatné Azure: Můžete si ho vytvořit zdarma.
  • Aktuální verze .NET Core.
  • Jakmile budete mít předplatné Azure, vytvořte na webu Azure Portal prostředek Personalizace, abyste získali svůj klíč a koncový bod. Po nasazení vyberte Přejít k prostředku.
    • K připojení aplikace k rozhraní API personalizace budete potřebovat klíč a koncový bod z prostředku, který vytvoříte. Klíč a koncový bod vložíte do kódu níže v rychlém startu.
    • K vyzkoušení služby můžete použít cenovou úroveňF0 Free a později upgradovat na placenou úroveň pro produkční prostředí.

Konfigurace modelu

Změna frekvence aktualizace modelu

Na webu Azure Portal přejděte na stránku Konfigurace prostředku Personalizace a změňte frekvenci aktualizace modelu na 30 sekund. Tato krátká doba trvání model rychle vytrénuje a umožní vám zjistit, jak se doporučené akce mění pro každou iteraci.

Change model update frequency

Změna doby čekání na odměnu

Na webu Azure Portal přejděte na stránku Konfigurace prostředku Personalizace a změňte dobu čekání na odměnu na 10 minut. To určuje, jak dlouho bude model čekat po odeslání doporučení, aby od tohoto doporučení obdržel zpětnou vazbu o odměně. Trénování se neprojeví, dokud nepřejde doba čekání na odměnu.

Change reward wait time

Vytvoření nové aplikace jazyka C#

V preferovaném editoru nebo integrovaném vývojovém prostředí (IDE) vytvořte novou aplikaci .NET Core.

V okně konzoly (například cmd, PowerShell nebo Bash) pomocí dotnet new příkazu vytvořte novou konzolovou aplikaci s názvem personalizer-quickstart. Tento příkaz vytvoří jednoduchý projekt "Hello World" C# s jedním zdrojovým souborem: Program.cs.

dotnet new console -n personalizer-quickstart

Změňte adresář na nově vytvořenou složku aplikace. Pak aplikaci sestavte pomocí:

dotnet build

Výstup sestavení by neměl obsahovat žádná upozornění ani chyby.

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

Instalace klientské knihovny

V adresáři aplikace nainstalujte klientskou knihovnu Personalizace pro .NET pomocí následujícího příkazu:

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

Tip

Pokud používáte integrované vývojové prostředí sady Visual Studio, je klientská knihovna k dispozici jako balíček NuGet ke stažení.

Blok kódu 1: Generování ukázkových dat

Personalizace je určená ke spouštění aplikací, které přijímají a interpretují data v reálném čase. V tomto rychlém startu použijete ukázkový kód k vygenerování imaginárních akcí zákazníků na webu s potravinami. Následující blok kódu definuje tři klíčové metody: GetActions, GetContext a GetRewardScore.

  • GetActions vrátí seznam voleb, které má web potravin zařadit. V tomto příkladu jsou akce pokrmy. Každá volba akce obsahuje podrobnosti (funkce), které můžou mít vliv na chování uživatelů později. Akce se používají jako vstup pro rozhraní Rank API.

  • GetContext vrátí simulovanou návštěvu zákazníka. Vybere randomizované podrobnosti (kontextové funkce), jako je to, který zákazník je k dispozici a kdy probíhá návštěva. Obecně platí, že kontext představuje aktuální stav vaší aplikace, systému, prostředí nebo uživatele. Kontextový objekt se používá jako vstup pro rozhraní Rank API.

    Kontextové funkce v tomto rychlém startu jsou zjednodušené. V reálném produkčním systému je ale důležité navrhovat funkce a vyhodnocovat jejich účinnost. Pokyny najdete v propojené dokumentaci.

  • GetRewardScore vrátí skóre mezi nulou a jedním, které představuje úspěch interakce zákazníka. Používá jednoduchou logiku k určení toho, jak různé kontexty reagují na různé volby akcí. Například určitý uživatel bude vždy dávat 1,0 pro vegetariány a veganské produkty a 0,0 pro ostatní produkty. V reálném scénáři se personalizace naučí předvolby uživatelů z dat odesílaných v voláních rozhraní Rank a Rewards API. Tyto explicitní definice nebudete definovat jako v ukázkovém kódu.

    Ve skutečném produkčním systému by mělo být skóre odměn navrženo tak, aby odpovídalo vašim obchodním cílům a klíčových ukazatelů výkonu. Určení způsobu výpočtu metriky odměny může vyžadovat určité experimentování.

    V následujícím kódu jsou předvolby a odpovědi uživatelů na akce pevně zakódované jako řada podmíněných příkazů a vysvětlující text je součástí kódu pro demonstrační účely.

  1. Najděte svůj klíč a koncový bod.

    Důležité

    Přejděte na Azure Portal. Pokud se prostředek Personalizace, který jste vytvořili v části Požadavky, úspěšně nasadil, klikněte v části Další kroky na tlačítko Přejít k prostředku. Klíč a koncový bod najdete na stránce klíče a koncového bodu prostředku v části Správa prostředků.

    Nezapomeňte klíč z kódu odebrat, až to budete hotovi, a nikdy ho veřejně neposílejte. V produkčním prostředí zvažte použití zabezpečeného způsobu ukládání a přístupu k vašim přihlašovacím údajům. Například Azure Key Vault.

  2. Otevřete Program.cs v textovém editoru nebo integrovaném vývojovém prostředí a vložte následující kód.

    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. Vložte klíč a koncový bod na vyznačená místa v kódu. Váš koncový bod má formulář https://<your_resource_name>.cognitiveservices.azure.com/.

    Důležité

    Nezapomeňte klíč z kódu odebrat, až to budete hotovi, a nikdy ho veřejně neposílejte. V produkčním prostředí použijte bezpečný způsob ukládání přihlašovacích údajů a přístupu k vašim přihlašovacím údajům, jako je Azure Key Vault. Další informace najdete v článku zabezpečení služeb Azure AI.

Blok kódu 2: Iterace smyčky učení

Další blok kódu definuje hlavní metodu a zavře skript. Spustí iteraci smyčky učení, ve které vygeneruje kontext (včetně zákazníka), požádá o pořadí akcí v tomto kontextu pomocí rozhraní Rank API, vypočítá skóre odměny a předá toto skóre zpět do služby Personalizace pomocí rozhraní Api odměny. V každém kroku vypíše příslušné informace do konzoly.

V tomto příkladu se provede každé volání pořadí, které určí, který produkt by se měl zobrazit v části Doporučený produkt. Pak volání odměny označuje, jestli byl vybraný produkt zakoupen uživatelem nebo ne. Odměny jsou spojené s jejich rozhodnutími prostřednictvím společné EventId hodnoty.

    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();
    }

}

Spuštění programu

Spusťte aplikaci příkazem dotnet dotnet run z adresáře vaší aplikace.

dotnet run

Při první iteraci personalizace doporučí náhodnou akci, protože ještě neprovedla žádné trénování. Volitelně můžete spustit další iterace. Po přibližně 10 minutách začne služba zobrazovat vylepšení svých doporučení.

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

Generování mnoha událostí pro analýzu (volitelné)

Z tohoto scénáře rychlého startu můžete snadno vygenerovat 5 000 událostí, což je dostatečné k tomu, abyste získali zkušenosti s používáním režimu Apprentice a online režimu, spouštěním offline vyhodnocení a vytvářením vyhodnocení funkcí. Nahraďte výše uvedenou hlavní metodu:

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

Zdrojový kód pro tento rychlý start je k dispozici na GitHubu.

Referenční dokumentace |– ukázka zdrojového kódu | knihovny (npm) | – ukázka kódu pro rychlý start

Předpoklady

  • Předplatné Azure: Můžete si ho vytvořit zdarma.
  • Nainstalujte Node.js a npm (ověřeno pomocí Node.js v14.16.0 a npm 6.14.11).
  • Jakmile budete mít předplatné Azure, vytvořte na webu Azure Portal prostředek Personalizace, abyste získali svůj klíč a koncový bod. Po nasazení vyberte Přejít k prostředku.
    • K připojení aplikace k rozhraní API personalizace budete potřebovat klíč a koncový bod z prostředku, který vytvoříte. Klíč a koncový bod vložíte do kódu níže v rychlém startu.
    • K vyzkoušení služby můžete použít cenovou úroveňF0 Free a později upgradovat na placenou úroveň pro produkční prostředí.

Konfigurace modelu

Změna frekvence aktualizace modelu

Na webu Azure Portal přejděte na stránku Konfigurace prostředku Personalizace a změňte frekvenci aktualizace modelu na 30 sekund. Tato krátká doba trvání model rychle vytrénuje a umožní vám zjistit, jak se doporučené akce mění pro každou iteraci.

Change model update frequency

Změna doby čekání na odměnu

Na webu Azure Portal přejděte na stránku Konfigurace prostředku Personalizace a změňte dobu čekání na odměnu na 10 minut. To určuje, jak dlouho bude model čekat po odeslání doporučení, aby od tohoto doporučení obdržel zpětnou vazbu o odměně. Trénování se neprojeví, dokud nepřejde doba čekání na odměnu.

Change reward wait time

Vytvoření nové aplikace Node.js

V okně konzoly (například cmd, PowerShell nebo Bash) vytvořte pro vaši aplikaci nový adresář a přejděte do něj.

mkdir myapp && cd myapp

Spuštěním npm init -y příkazu vytvořte package.json soubor.

npm init -y

V preferovaném editoru nebo personalizer-quickstart.js integrovaném vývojovém prostředí vytvořte nový skript Node.js a vytvořte proměnné pro koncový bod prostředku a klíč předplatného.

Instalace klientské knihovny

Pomocí následujícího příkazu nainstalujte klientskou knihovnu Personalizace pro Node.js:

npm install @azure/cognitiveservices-personalizer --save

Nainstalujte zbývající balíčky npm pro účely tohoto rychlého startu:

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

Blok kódu 1: Generování ukázkových dat

Personalizace je určená ke spouštění aplikací, které přijímají a interpretují data v reálném čase. V tomto rychlém startu použijete ukázkový kód k vygenerování imaginárních akcí zákazníků na webu s potravinami. Následující blok kódu definuje tři klíčové metody: getActionsList, getContextFeaturesList a getReward.

  • getActionsList vrátí seznam voleb, které musí web potravin zařadit. V tomto příkladu jsou akce pokrmy. Každá volba akce obsahuje podrobnosti (funkce), které můžou mít vliv na chování uživatelů později. Akce se používají jako vstup pro rozhraní Rank API.

  • getContextFeaturesList vrátí simulovanou návštěvu zákazníka. Vybere randomizované podrobnosti (kontextové funkce), jako je to, který zákazník je k dispozici a kdy probíhá návštěva. Obecně platí, že kontext představuje aktuální stav vaší aplikace, systému, prostředí nebo uživatele. Kontextový objekt se používá jako vstup pro rozhraní Rank API.

    Kontextové funkce v tomto rychlém startu jsou zjednodušené. V reálném produkčním systému je ale důležité navrhovat funkce a vyhodnocovat jejich účinnost. Pokyny najdete v propojené dokumentaci.

  • getReward vyzve uživatele k určení skóre doporučení služby jako úspěchu nebo selhání. Vrátí skóre mezi nulou a jedním, které představuje úspěch interakce zákazníka. V reálném scénáři se personalizace naučí předvolby uživatelů z interakcí zákazníků v reálném čase.

    Ve skutečném produkčním systému by mělo být skóre odměn navrženo tak, aby odpovídalo vašim obchodním cílům a klíčových ukazatelů výkonu. Určení způsobu výpočtu metriky odměny může vyžadovat určité experimentování.

Otevřete soubor personalizace-quickstart.js v textovém editoru nebo integrovaném vývojovém prostředí (IDE) a vložte níže uvedený kód.

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

Blok kódu 2: Iterace smyčky učení

Další blok kódu definuje hlavní metodu a zavře skript. Spustí iteraci smyčky učení, ve které požádá uživatele o své předvolby na příkazovém řádku a odešle informace personalizaci, aby vybral nejlepší akci. Zobrazí vybranou akci uživateli, který zvolí příkazový řádek. Pak pošle službě Personalizace skóre odměny, aby signalizovala, jak dobře služba ve výběru udělala.

Smyčka učení Personalizace je cyklus volání Rank a Rewards . V tomto rychlém startu je za každým voláním pořadí přizpůsobení obsahu následovat volání odměny, které personalizátoru sdělí, jak dobře služba fungovala.

  1. Přidejte následující kód pro personalizaci-quickstart.js.

  2. Najděte svůj klíč a koncový bod. Váš koncový bod má formulář https://<your_resource_name>.cognitiveservices.azure.com/.

    Důležité

    Přejděte na Azure Portal. Pokud se prostředek Personalizace, který jste vytvořili v části Požadavky, úspěšně nasadil, klikněte v části Další kroky na tlačítko Přejít k prostředku. Klíč a koncový bod najdete na stránce klíče a koncového bodu prostředku v části Správa prostředků.

    Nezapomeňte klíč z kódu odebrat, až to budete hotovi, a nikdy ho veřejně neposílejte. V produkčním prostředí zvažte použití zabezpečeného způsobu ukládání a přístupu k vašim přihlašovacím údajům. Například Azure Key Vault.

  3. Vložte klíč a koncový bod na vyznačená místa v kódu.

    Důležité

    Nezapomeňte klíč z kódu odebrat, až to budete hotovi, a nikdy ho veřejně neposílejte. V produkčním prostředí použijte bezpečný způsob ukládání přihlašovacích údajů a přístupu k vašim přihlašovacím údajům, jako je Azure Key Vault. Další informace o zabezpečení najdete v článku zabezpečení služeb Azure AI.

    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));
    

Spuštění programu

Spusťte aplikaci pomocí příkazu Node.js z adresáře vaší aplikace.

node personalizer-quickstart.js

Iterujte několika smyčkami učení. Po přibližně 10 minutách začne služba zobrazovat vylepšení svých doporučení.

Zdrojový kód pro tento rychlý start je k dispozici na GitHubu.

Referenční dokumentace | – ukázka zdrojového kódu | knihovny (pypi) | – ukázka kódu pro rychlý start

Předpoklady

  • Předplatné Azure: Můžete si ho vytvořit zdarma.
  • Python 3.x
  • Po nastavení předplatného Azure vytvořte prostředek Personalizace na webu Azure Portal a získejte svůj klíč a koncový bod. Po nasazení vyberte Přejít k prostředku.
    • Klíč a koncový bod z vytvořeného prostředku budete potřebovat k připojení aplikace k rozhraní API personalizace, které vložíte do níže uvedeného kódu pro rychlý start.
    • K vyzkoušení služby můžete použít cenovou úroveňF0 Free a později upgradovat na placenou úroveň pro produkční prostředí.

Konfigurace modelu

Změna frekvence aktualizace modelu

Na webu Azure Portal přejděte na stránku Konfigurace prostředku Personalizace a změňte frekvenci aktualizace modelu na 30 sekund. Tato krátká doba trvání model rychle vytrénuje a umožní vám zjistit, jak se doporučené akce mění pro každou iteraci.

Change model update frequency

Změna doby čekání na odměnu

Na webu Azure Portal přejděte na stránku Konfigurace prostředku Personalizace a změňte dobu čekání na odměnu na 10 minut. To určuje, jak dlouho bude model čekat po odeslání doporučení, aby od tohoto doporučení obdržel zpětnou vazbu o odměně. Trénování se neprojeví, dokud nepřejde doba čekání na odměnu.

Change reward wait time

Vytvoření nové aplikace v Pythonu

Vytvořte nový soubor Pythonu s názvem personalizer-quickstart.py.

Instalace klientské knihovny

Nainstalujte klientskou knihovnu Personalizace pomocí nástroje pip:

pip install azure-cognitiveservices-personalizer

Blok kódu 1: Generování ukázkových dat

Personalizace je určená ke spouštění aplikací, které přijímají a interpretují data v reálném čase. Pro účely tohoto rychlého startu použijete vzorový kód k vygenerování imaginárních akcí zákazníků na webu s potravinami. Následující blok kódu definuje tři klíčové funkce: get_actions, get_context a get_reward_score.

  • get_actions vrátí seznam voleb, které má web potravin zařadit. V tomto příkladu jsou akce pokrmy. Každá volba akce obsahuje podrobnosti (funkce), které můžou mít vliv na chování uživatelů později. Akce se používají jako vstup pro rozhraní Rank API.

  • get_context vrátí simulovanou návštěvu zákazníka. Vybere randomizované podrobnosti (kontextové funkce), jako je to, který zákazník je k dispozici a kdy probíhá návštěva. Obecně platí, že kontext představuje aktuální stav vaší aplikace, systému, prostředí nebo uživatele. Kontextový objekt se používá jako vstup pro rozhraní Rank API.

    Kontextové funkce v tomto rychlém startu jsou zjednodušené. Ve skutečném produkčním systému je však návrh funkcí a vyhodnocení jejich účinnosti velmi důležité. Pokyny najdete v propojené dokumentaci.

  • get_reward_score vrátí skóre mezi nulou a jedním, které představuje úspěch interakce zákazníka. Používá jednoduchou logiku k určení toho, jak různé kontexty budou reagovat na různé volby akcí. Například určitý uživatel bude vždy dávat 1,0 pro vegetariány a veganské produkty a 0,0 pro ostatní produkty. V reálném scénáři se personalizace naučí předvolby uživatelů z dat odesílaných v voláních rozhraní Rank a Rewards API. Tyto explicitní definice nebudete definovat jako v ukázkovém kódu.

    Ve skutečném produkčním systému by mělo být skóre odměn navrženo tak, aby odpovídalo vašim obchodním cílům a klíčových ukazatelů výkonu. Určení způsobu výpočtu metriky odměny může vyžadovat určité experimentování.

    V následujícím kódu jsou předvolby a odpovědi uživatelů na akce pevně zakódované jako řada podmíněných příkazů a vysvětlující text je součástí kódu pro demonstrační účely.

Postupujte podle těchto kroků a nastavte skript Personalizace.

  1. Najděte svůj klíč a koncový bod.

    Důležité

    Přejděte na Azure Portal. Pokud se prostředek Personalizace, který jste vytvořili v části Požadavky, úspěšně nasadil, klikněte v části Další kroky na tlačítko Přejít k prostředku. Klíč a koncový bod najdete na stránce klíče a koncového bodu prostředku v části Správa prostředků.

    Nezapomeňte klíč z kódu odebrat, až to budete hotovi, a nikdy ho veřejně neposílejte. V produkčním prostředí zvažte použití zabezpečeného způsobu ukládání a přístupu k vašim přihlašovacím údajům. Například Azure Key Vault.

  2. Otevřete personalizer-quickstart.py v textovém editoru nebo integrovaném vývojovém prostředí (IDE) a vložte níže uvedený kód.

  3. Vložte klíč a koncový bod na vyznačená místa v kódu. Váš koncový bod má formulář https://<your_resource_name>.cognitiveservices.azure.com/.

    Důležité

    Nezapomeňte klíč z kódu odebrat, až to budete hotovi, a nikdy ho veřejně neposílejte. V produkčním prostředí použijte zabezpečenou metodu pro ukládání přihlašovacích údajů a přístup k vašim přihlašovacím údajům, jako je Azure Key Vault. Další informace najdete v zabezpečení služeb Azure AI.

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
    # ...

Blok kódu 2: Iterace smyčky učení

Další blok kódu definuje funkci run_personalizer_cycle a volá ji ve smyčce zpětné vazby uživatelů. Spustí iteraci smyčky učení, ve které vygeneruje kontext (včetně zákazníka), požádá o pořadí akcí v tomto kontextu pomocí rozhraní Rank API, vypočítá skóre odměny a předá toto skóre zpět do služby Personalizace pomocí rozhraní Api odměny. V každém kroku vypíše příslušné informace do konzoly.

V tomto příkladu se provede každé volání pořadí, které určí, který produkt by se měl zobrazit v části Doporučený produkt. Pak volání odměny označuje, jestli byl vybraný produkt zakoupen uživatelem nebo ne. Odměny jsou spojené s jejich rozhodnutími prostřednictvím společné EventId hodnoty.

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

Spuštění programu

Jakmile se do souboru Pythonu zahrne veškerý výše uvedený kód, můžete ho spustit z adresáře vaší aplikace.

python personalizer-quickstart.py

Při první iteraci personalizace doporučí náhodnou akci, protože ještě neprovedla žádné trénování. Volitelně můžete spustit další iterace. Po přibližně 10 minutách začne služba zobrazovat vylepšení svých doporučení.

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

Generování mnoha událostí pro analýzu (volitelné)

Z tohoto scénáře rychlého startu můžete snadno vygenerovat 5 000 událostí, což stačí k získání zkušeností s používáním režimu Apprentice, online režimu, spouštění offline vyhodnocení a vytváření vyhodnocení funkcí. Smyčku while ve výše uvedeném bloku kódu nahraďte následujícím kódem.

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

Zdrojový kód pro tento rychlý start je k dispozici na GitHubu.

Stažení natrénovaného modelu

Pokud chcete stáhnout model Personalizace, který byl natrénován na 5 000 událostí z výše uvedeného příkladu, navštivte úložiště Personalizace ukázek a stáhněte si soubor Personalizer_QuickStart_Model.zip . Potom na webu Azure Portal přejděte k prostředku Personalizace, přejděte na stránku Nastavení a kartu Import/export a naimportujte soubor.

Vyčištění prostředků

Pokud chcete vyčistit předplatné služeb Azure AI, můžete odstranit prostředek nebo odstranit skupinu prostředků, která odstraní všechny přidružené prostředky.

Další kroky