Snabbstart: Personalizer-klientbibliotek

Viktigt!

Från och med den 20 september 2023 kommer du inte att kunna skapa nya personaliseringsresurser. Personanpassningstjänsten dras tillbaka den 1 oktober 2026.

Kom igång med Azure AI Personalizer-klientbiblioteken för att konfigurera en grundläggande inlärningsloop. En inlärningsloop är ett system med beslut och feedback: ett program begär en beslutsordning från tjänsten, sedan använder den det högst rankade valet och beräknar en belöningspoäng från resultatet. Den returnerar belöningspoängen till tjänsten. Med tiden använder Personalizer AI-algoritmer för att fatta bättre beslut för en viss kontext. Följ de här stegen för att konfigurera ett exempelprogram.

Exempelscenario

I den här snabbstarten vill en e-handlare öka intäkterna genom att visa relevanta och anpassade produkter för varje kund på sin webbplats. På huvudsidan finns avsnittet "Aktuell produkt" som visar en förberedd måltidsprodukt för potentiella kunder. E-återförsäljaren vill bestämma hur rätt produkt ska visas för rätt kund för att maximera sannolikheten för ett köp.

Tjänsten Personalizer löser problemet på ett automatiserat, skalbart och anpassningsbart sätt med hjälp av förstärkningsinlärning. Du får lära dig hur du skapar åtgärder och deras funktioner, kontextfunktioner och belöningspoäng. Du använder personaliserarens klientbibliotek för att göra anrop till API:erna Rank och Reward.

Referensdokumentation Exempel på källkodspaket för bibliotek | (NuGet) | .NET |

Förutsättningar

  • Azure-prenumeration – Skapa en kostnadsfritt
  • Den aktuella versionen av .NET Core.
  • När du har din Azure-prenumeration skapar du en Personalizer-resurs i Azure-portalen för att hämta din nyckel och slutpunkt. När den har distribuerats väljer du Gå till resurs.
    • Du behöver nyckeln och slutpunkten från resursen som du skapar för att ansluta ditt program till Personanpassnings-API:et. Du klistrar in nyckeln och slutpunkten i koden nedan senare i snabbstarten.
    • Du kan använda den kostnadsfria prisnivån (F0) för att prova tjänsten och uppgradera senare till en betald nivå för produktion.

Modellkonfiguration

Ändra uppdateringsfrekvensen för modellen

I Azure-portalen går du till personaliserarresursens konfigurationssida och ändrar uppdateringsfrekvensen för modell till 30 sekunder. Den här korta varaktigheten tränar modellen snabbt, så att du kan se hur den rekommenderade åtgärden ändras för varje iteration.

Change model update frequency

Ändra väntetiden för belöningen

I Azure-portalen går du till personaliserarresursens konfigurationssida och ändrar väntetiden för belöningen till 10 minuter. Detta avgör hur länge modellen väntar efter att ha skickat en rekommendation för att få belöningsfeedback från den rekommendationen. Träningen sker inte förrän belöningens väntetid har passerat.

Change reward wait time

Skapa ett nytt C#-program

Skapa ett nytt .NET Core-program i önskad redigerare eller IDE.

I ett konsolfönster (till exempel cmd, PowerShell eller Bash) använder du dotnet new kommandot för att skapa en ny konsolapp med namnet personalizer-quickstart. Det här kommandot skapar ett enkelt "Hello World"-C#-projekt med en enda källfil: Program.cs.

dotnet new console -n personalizer-quickstart

Ändra katalogen till den nyligen skapade appmappen. Skapa sedan programmet med:

dotnet build

Kompileringsutdata får inte innehålla några varningar eller fel.

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

Installera klientbiblioteket

I programkatalogen installerar du Personalizer-klientbiblioteket för .NET med följande kommando:

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

Dricks

Om du använder Visual Studio IDE är klientbiblioteket tillgängligt som ett nedladdningsbart NuGet-paket.

Kodblock 1: Generera exempeldata

Personanpassning är avsedd att köras på program som tar emot och tolkar realtidsdata. I den här snabbstarten använder du exempelkod för att generera imaginära kundåtgärder på en livsmedelswebbplats. Följande kodblock definierar tre viktiga metoder: GetActions, GetContext och GetRewardScore.

  • GetActions returnerar en lista över de val som livsmedelswebbplatsen behöver rangordna. I det här exemplet är åtgärderna måltidsprodukter. Varje åtgärdsval innehåller information (funktioner) som kan påverka användarbeteendet senare. Åtgärder används som indata för ranknings-API:et

  • GetContext returnerar ett simulerat kundbesök. Den väljer slumpmässig information (kontextfunktioner) som vilken kund som är närvarande och vilken tid på dagen besöket äger rum. I allmänhet representerar en kontext programmets, systemets, miljöns eller användarens aktuella tillstånd. Kontextobjektet används som indata för ranknings-API:et.

    Kontextfunktionerna i den här snabbstarten är förenklade. Men i ett verkligt produktionssystem är det viktigt att utforma dina funktioner och utvärdera deras effektivitet . Mer information finns i den länkade dokumentationen.

  • GetRewardScore returnerar en poäng mellan noll och en som representerar framgången för en kundinteraktion. Den använder enkel logik för att avgöra hur olika kontexter svarar på olika åtgärdsalternativ. Till exempel ger en viss användare alltid en 1,0 för vegetariska och veganska produkter och en 0,0 för andra produkter. I ett verkligt scenario lär sig Personalizer användarinställningar från de data som skickas i RANK- och Reward API-anrop. Du definierar inte dessa explicit som i exempelkoden.

    I ett verkligt produktionssystem bör belöningspoängen utformas för att överensstämma med dina affärsmål och KPI:er. Att fastställa hur du beräknar belöningsmåttet kan kräva en del experimentering.

    I koden nedan hårdkodas användarnas inställningar och svar på åtgärderna som en serie villkorssatser, och förklarande text ingår i koden i demonstrativt syfte.

  1. Hitta din nyckel och slutpunkt.

    Viktigt!

    Gå till Azure-portalen. Om personanpassningsresursen som du skapade i avsnittet Förutsättningar har distribuerats klickar du på knappen Gå till resurs under Nästa steg. Du hittar din nyckel och slutpunkt på resursens nyckel- och slutpunktssida under resurshantering.

    Kom ihåg att ta bort nyckeln från koden när du är klar och publicera den aldrig offentligt. För produktion bör du överväga att använda ett säkert sätt att lagra och komma åt dina autentiseringsuppgifter. Till exempel Azure Key Vault.

  2. Öppna Program.cs i en textredigerare eller IDE och klistra in följande kod.

    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. Klistra in nyckeln och slutpunkten i koden på angiven plats. Slutpunkten har formuläret https://<your_resource_name>.cognitiveservices.azure.com/.

    Viktigt!

    Kom ihåg att ta bort nyckeln från koden när du är klar och publicera den aldrig offentligt. För produktion använder du ett säkert sätt att lagra och komma åt dina autentiseringsuppgifter som Azure Key Vault. Mer information finns i säkerhetsartikeln för Azure AI-tjänster.

Kodblock 2: Iterera inlärningsloopen

Nästa kodblock definierar huvudmetoden och stänger skriptet. Den kör en iteration för inlärningsslingor, där den genererar en kontext (inklusive en kund), begär en rangordning av åtgärder i den kontexten med hjälp av Rank-API:et, beräknar belöningspoängen och skickar tillbaka poängen till personanpassningstjänsten med hjälp av Reward API. Den skriver ut relevant information till konsolen i varje steg.

I det här exemplet görs varje Rankningsanrop för att avgöra vilken produkt som ska visas i avsnittet "Aktuell produkt". Sedan anger Reward-anropet om den aktuella produkten har köpts av användaren eller inte. Belöningar associeras med deras beslut genom ett gemensamt EventId värde.

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

}

Köra programmet

Kör programmet med dotnet-kommandot dotnet run från programkatalogen.

dotnet run

Vid den första iterationen rekommenderar Personalizer en slumpmässig åtgärd eftersom den inte har tränat ännu. Du kan också köra fler iterationer. Efter cirka 10 minuter börjar tjänsten visa förbättringar i sina rekommendationer.

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

Generera många händelser för analys (valfritt)

Du kan enkelt generera 5 000 händelser från det här snabbstartsscenariot, vilket är tillräckligt för att få erfarenhet av lärlingsläge och onlineläge, köra offlineutvärderingar och skapa funktionsutvärderingar. Ersätt huvudmetoden ovan med:

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

Källkoden för den här snabbstarten är tillgänglig på GitHub.

Referensdokumentation Bibliotek källkodspaket | (npm) | Snabbstartskodexempel |

Förutsättningar

  • Azure-prenumeration – Skapa en kostnadsfritt
  • Installera Node.js och npm (verifieras med Node.js v14.16.0 och npm 6.14.11).
  • När du har din Azure-prenumeration skapar du en Personalizer-resurs i Azure-portalen för att hämta din nyckel och slutpunkt. När den har distribuerats väljer du Gå till resurs.
    • Du behöver nyckeln och slutpunkten från resursen som du skapar för att ansluta ditt program till Personanpassnings-API:et. Du klistrar in nyckeln och slutpunkten i koden nedan senare i snabbstarten.
    • Du kan använda den kostnadsfria prisnivån (F0) för att prova tjänsten och uppgradera senare till en betald nivå för produktion.

Modellkonfiguration

Ändra uppdateringsfrekvensen för modellen

I Azure-portalen går du till personaliserarresursens konfigurationssida och ändrar uppdateringsfrekvensen för modell till 30 sekunder. Den här korta varaktigheten tränar modellen snabbt, så att du kan se hur den rekommenderade åtgärden ändras för varje iteration.

Change model update frequency

Ändra väntetiden för belöningen

I Azure-portalen går du till personaliserarresursens konfigurationssida och ändrar väntetiden för belöningen till 10 minuter. Detta avgör hur länge modellen väntar efter att ha skickat en rekommendation för att få belöningsfeedback från den rekommendationen. Träningen sker inte förrän belöningens väntetid har passerat.

Change reward wait time

Skapa ett nytt Node.js-program

Skapa en ny katalog för din app i ett konsolfönster (till exempel cmd, PowerShell eller bash) och navigera till den.

mkdir myapp && cd myapp

npm init -y Kör kommandot för att skapa en package.json fil.

npm init -y

Skapa ett nytt Node.js-skript i önskad redigerare eller IDE med namnet personalizer-quickstart.js och skapa variabler för resursens slutpunkt och prenumerationsnyckel.

Installera klientbiblioteket

Installera Personalizer-klientbiblioteket för Node.js med följande kommando:

npm install @azure/cognitiveservices-personalizer --save

Installera de återstående npm-paketen för den här snabbstarten:

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

Kodblock 1: Generera exempeldata

Personanpassning är avsedd att köras på program som tar emot och tolkar realtidsdata. I den här snabbstarten använder du exempelkod för att generera imaginära kundåtgärder på en livsmedelswebbplats. Följande kodblock definierar tre viktiga metoder: getActionsList, getContextFeaturesList och getReward.

  • getActionsList returnerar en lista över de val som livsmedelswebbplatsen behöver rangordna. I det här exemplet är åtgärderna måltidsprodukter. Varje åtgärdsval innehåller information (funktioner) som kan påverka användarbeteendet senare. Åtgärder används som indata för ranknings-API:et

  • getContextFeaturesList returnerar ett simulerat kundbesök. Den väljer slumpmässig information (kontextfunktioner) som vilken kund som är närvarande och vilken tid på dagen besöket äger rum. I allmänhet representerar en kontext programmets, systemets, miljöns eller användarens aktuella tillstånd. Kontextobjektet används som indata för ranknings-API:et.

    Kontextfunktionerna i den här snabbstarten är förenklade. Men i ett verkligt produktionssystem är det viktigt att utforma dina funktioner och utvärdera deras effektivitet . Mer information finns i den länkade dokumentationen.

  • getReward uppmanar användaren att bedöma tjänstens rekommendation som en lyckad eller misslyckad. Den returnerar en poäng mellan noll och en som representerar framgången för en kundinteraktion. I ett verkligt scenario lär sig Personalizer användarinställningar från kundinteraktioner i realtid.

    I ett verkligt produktionssystem bör belöningspoängen utformas för att överensstämma med dina affärsmål och KPI:er. Att fastställa hur du beräknar belöningsmåttet kan kräva en del experimentering.

Öppna personalizer-quickstart.js i en textredigerare eller IDE och klistra in koden nedan.

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

Kodblock 2: Iterera inlärningsloopen

Nästa kodblock definierar huvudmetoden och stänger skriptet. Den kör en iteration av inlärningsloopen, där användaren uppmanas att ange sina inställningar på kommandoraden och skickar informationen till Personanpassning för att välja den bästa åtgärden. Den visar den valda åtgärden för användaren, som gör ett val med hjälp av kommandoraden. Sedan skickar den en belöningspoäng till personanpassningstjänsten för att signalera hur bra tjänsten gjorde i sitt val.

Personalizer-inlärningsloopen är en cykel med ranknings- och belöningsanrop . I den här snabbstarten följs varje Rank-anrop, för att anpassa innehållet, av ett Reward-anrop för att berätta för Personanpassning hur väl tjänsten har utförts.

  1. Lägg till koden nedan i personalizer-quickstart.js.

  2. Hitta din nyckel och slutpunkt. Slutpunkten har formuläret https://<your_resource_name>.cognitiveservices.azure.com/.

    Viktigt!

    Gå till Azure-portalen. Om personanpassningsresursen som du skapade i avsnittet Förutsättningar har distribuerats klickar du på knappen Gå till resurs under Nästa steg. Du hittar din nyckel och slutpunkt på resursens nyckel- och slutpunktssida under resurshantering.

    Kom ihåg att ta bort nyckeln från koden när du är klar och publicera den aldrig offentligt. För produktion bör du överväga att använda ett säkert sätt att lagra och komma åt dina autentiseringsuppgifter. Till exempel Azure Key Vault.

  3. Klistra in nyckeln och slutpunkten i koden på angiven plats.

    Viktigt!

    Kom ihåg att ta bort nyckeln från koden när du är klar och publicera den aldrig offentligt. För produktion använder du ett säkert sätt att lagra och komma åt dina autentiseringsuppgifter som Azure Key Vault. Mer information om säkerhet finns i artikeln om Säkerhet för Azure AI-tjänster.

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

Köra programmet

Kör programmet med kommandot Node.js från programkatalogen.

node personalizer-quickstart.js

Iterera genom några inlärningsslingor. Efter cirka 10 minuter börjar tjänsten visa förbättringar i sina rekommendationer.

Källkoden för den här snabbstarten är tillgänglig på GitHub.

Referensdokumentation Exempel på källkodspaket för bibliotek | (pypi) | Snabbstart |

Förutsättningar

  • Azure-prenumeration – Skapa en kostnadsfritt
  • Python 3.x
  • När din Azure-prenumeration har konfigurerats skapar du en Personalizer-resurs i Azure-portalen och hämtar din nyckel och slutpunkt. När den har distribuerats väljer du Gå till resurs.
    • Du behöver nyckeln och slutpunkten från den skapade resursen för att ansluta ditt program till Personanpassnings-API:et, som du klistrar in i snabbstartskoden nedan.
    • Du kan använda den kostnadsfria prisnivån (F0) för att prova tjänsten och sedan uppgradera till en betald nivå för produktion vid ett senare tillfälle.

Modellkonfiguration

Ändra uppdateringsfrekvensen för modellen

I Azure-portalen går du till personaliserarresursens konfigurationssida och ändrar uppdateringsfrekvensen för modell till 30 sekunder. Den här korta varaktigheten tränar modellen snabbt, så att du kan se hur den rekommenderade åtgärden ändras för varje iteration.

Change model update frequency

Ändra väntetiden för belöningen

I Azure-portalen går du till personaliserarresursens konfigurationssida och ändrar väntetiden för belöningen till 10 minuter. Detta avgör hur länge modellen väntar efter att ha skickat en rekommendation för att få belöningsfeedback från den rekommendationen. Träningen sker inte förrän belöningens väntetid har passerat.

Change reward wait time

Skapa ett nytt Python-program

Skapa en ny Python-fil med namnet personalizer-quickstart.py.

Installera klientbiblioteket

Installera Personalizer-klientbiblioteket med pip:

pip install azure-cognitiveservices-personalizer

Kodblock 1: Generera exempeldata

Personanpassning är avsedd att köras på program som tar emot och tolkar realtidsdata. I den här snabbstarten använder du exempelkod för att generera imaginära kundåtgärder på en livsmedelswebbplats. Följande kodblock definierar tre nyckelfunktioner: get_actions, get_context och get_reward_score.

  • get_actions returnerar en lista över de val som livsmedelswebbplatsen behöver rangordna. I det här exemplet är åtgärderna måltidsprodukter. Varje åtgärdsval innehåller information (funktioner) som kan påverka användarbeteendet senare. Åtgärder används som indata för ranknings-API:et

  • get_context returnerar ett simulerat kundbesök. Den väljer slumpmässig information (kontextfunktioner) som vilken kund som är närvarande och vilken tid på dagen besöket äger rum. I allmänhet representerar en kontext programmets, systemets, miljöns eller användarens aktuella tillstånd. Kontextobjektet används som indata för ranknings-API:et.

    Kontextfunktionerna i den här snabbstarten är förenklade. Men i ett verkligt produktionssystem är det mycket viktigt att utforma dina funktioner och utvärdera deras effektivitet . Mer information finns i den länkade dokumentationen.

  • get_reward_score returnerar en poäng mellan noll och en som representerar framgången för en kundinteraktion. Den använder enkel logik för att avgöra hur olika kontexter ska svara på olika åtgärdsalternativ. Till exempel ger en viss användare alltid en 1,0 för vegetariska och veganska produkter och en 0,0 för andra produkter. I ett verkligt scenario lär sig Personalizer användarinställningar från de data som skickas i RANK- och Reward API-anrop. Du definierar inte dessa explicit som i exempelkoden.

    I ett verkligt produktionssystem bör belöningspoängen utformas för att överensstämma med dina affärsmål och KPI:er. Att fastställa hur du beräknar belöningsmåttet kan kräva en del experimentering.

    I koden nedan hårdkodas användarnas inställningar och svar på åtgärderna som en serie villkorssatser, och förklarande text ingår i koden i demonstrativt syfte.

Följ de här stegen för att konfigurera personanpassningsskriptet.

  1. Hitta din nyckel och slutpunkt.

    Viktigt!

    Gå till Azure-portalen. Om personanpassningsresursen som du skapade i avsnittet Förutsättningar har distribuerats klickar du på knappen Gå till resurs under Nästa steg. Du hittar din nyckel och slutpunkt på resursens nyckel- och slutpunktssida under resurshantering.

    Kom ihåg att ta bort nyckeln från koden när du är klar och publicera den aldrig offentligt. För produktion bör du överväga att använda ett säkert sätt att lagra och komma åt dina autentiseringsuppgifter. Till exempel Azure Key Vault.

  2. Öppna personalizer-quickstart.py i en textredigerare eller IDE och klistra in koden nedan.

  3. Klistra in nyckeln och slutpunkten i koden på angiven plats. Slutpunkten har formuläret https://<your_resource_name>.cognitiveservices.azure.com/.

    Viktigt!

    Kom ihåg att ta bort nyckeln från koden när du är klar och publicera den aldrig offentligt. För produktion använder du en säker metod för att lagra och komma åt dina autentiseringsuppgifter som Azure Key Vault. Mer information finns i Säkerhet för Azure AI-tjänster.

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

Kodblock 2: Iterera inlärningsloopen

Nästa kodblock definierar funktionen run_personalizer_cycle och anropar den i en enkel användarfeedback-loop. Den kör en iteration för inlärningsslingor, där den genererar en kontext (inklusive en kund), begär en rangordning av åtgärder i den kontexten med hjälp av Rank-API:et, beräknar belöningspoängen och skickar tillbaka poängen till personanpassningstjänsten med hjälp av Reward API. Den skriver ut relevant information till konsolen i varje steg.

I det här exemplet görs varje Rankningsanrop för att avgöra vilken produkt som ska visas i avsnittet "Aktuell produkt". Sedan anger Reward-anropet om den aktuella produkten har köpts av användaren eller inte. Belöningar associeras med deras beslut genom ett gemensamt EventId värde.

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

Köra programmet

När all ovanstående kod ingår i Python-filen kan du köra den från programkatalogen.

python personalizer-quickstart.py

Vid den första iterationen rekommenderar Personalizer en slumpmässig åtgärd eftersom den inte har tränat ännu. Du kan också köra fler iterationer. Efter cirka 10 minuter börjar tjänsten visa förbättringar i sina rekommendationer.

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

Generera många händelser för analys (valfritt)

Du kan enkelt generera, till exempel, 5 000 händelser från det här snabbstartsscenariot, vilket räcker för att få erfarenhet av lärlingsläge, onlineläge, körning av offlineutvärderingar och skapande av funktionsutvärderingar. Ersätt loopen while i kodblocket ovan med följande kod.

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

Källkoden för den här snabbstarten är tillgänglig på GitHub.

Ladda ned den tränade modellen

Om du vill ladda ned en personanpassningsmodell som har tränats på 5 000 händelser från exemplet ovan går du till lagringsplatsen Personanpassningsexempel och laddar ned filen Personalizer_QuickStart_Model.zip . Gå sedan till din Personanpassningsresurs i Azure-portalen, gå till sidan Installation och fliken Importera/exportera och importera filen.

Rensa resurser

Om du vill rensa din Azure AI-tjänstprenumeration kan du ta bort resursen eller ta bort resursgruppen, vilket tar bort eventuella associerade resurser.

Nästa steg