Kurz: Použití personalizace v chatovacím robotovi .NET

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.

Pomocí chatovacího robota v jazyce C# .NET s smyčkou Personalizace poskytněte uživateli správný obsah. Tento chatovací robot uživateli navrhne konkrétní kávu nebo čaj. Uživatel může tento návrh přijmout nebo odmítnout. Díky tomu získáte informace o personalizaci, které vám pomůžou lépe navrhnout další návrh.

V tomto kurzu se naučíte:

  • Nastavení prostředků Azure
  • Konfigurace a spuštění robota
  • Interakce s robotem pomocí bot Framework Emulatoru
  • Vysvětlení toho, kde a jak robot používá personalizaci

Jak chatovací robot funguje?

Chatovací robot je obvykle back-and-forth konverzace s uživatelem. Tento konkrétní chatovací robot používá personalizaci k výběru nejlepší akce (kávy nebo čaje) pro nabízení uživatele. Personalizace využívá k výběru výztužné učení.

Chatovací robot musí spravovat konverzace. Chatovací robot používá Bot Framework ke správě architektury robota a konverzaci a k pochopení záměru přirozeného jazyka od uživatele používá službu Azure AI Language Understanding (LUIS).

Chatovací robot je web s konkrétní trasou, která je k dispozici pro odpovědi na žádosti, http://localhost:3978/api/messages. Emulátor služby Bot Framework můžete použít k vizuální interakci se spuštěným chatovacím robotem při místním vývoji robota.

Interakce uživatelů s robotem

Jedná se o jednoduchého chatovacího robota, který umožňuje zadávat textové dotazy.

Uživatel zadá text. Robot odpoví textem Popis akce robota k určení textu odpovědi
Nebyl zadán žádný text – chatbot zahájí konverzaci. This is a simple chatbot example that illustrates how to use Personalizer. The bot learns what coffee or tea order is preferred by customers given some context information (such as weather, temperature, and day of the week) and information about the user.
To use the bot, just follow the prompts. To try out a new imaginary context, type “Reset” and a new one will be randomly generated.
Welcome to the coffee bot, please tell me if you want to see the menu or get a coffee or tea suggestion for today. Once I’ve given you a suggestion, you can reply with ‘like’ or ‘don’t like’. It’s Tuesday today and the weather is Snowy.
Robot zahájí konverzaci s instrukčním textem a informuje vás o tom, co je kontext: Tuesday, Snowy.
Show menu Here is our menu: Coffee: Cappuccino Espresso Latte Macchiato Mocha Tea: GreenTea Rooibos Určete záměr dotazu pomocí služby LUIS a pak zobrazte volby nabídky kávy a čaje. Funkce akcí jsou
What do you suggest How about Latte? Určete záměr dotazu pomocí služby LUIS, pak volejte rozhraní API pro hodnocení a jako otázku How about {response.RewardActionId}?zobrazte nejvyšší volbu . Zobrazí se také volání JSON a odpověď pro ilustrační účely.
I like it That’s great! I’ll keep learning your preferences over time.
Would you like to get a new suggestion or reset the simulated context to a new day?
Určete záměr dotazu pomocí služby LUIS a pak volejte rozhraní API odměny s odměnou 1, zobrazí volání JSON a odpověď pro ilustrace.
I don't like it Oh well, maybe I’ll guess better next time.
Would you like to get a new suggestion or reset the simulated context to a new day?
Určete záměr dotazu pomocí služby LUIS a pak volejte rozhraní API odměny s odměnou 0, zobrazí volání JSON a odpověď pro ilustrace.
Reset Vrátí instrukční text. Určete záměr dotazu pomocí služby LUIS a pak zobrazte instrukční text a resetuje kontext.

Personalizace v tomto robotovi

Tento chatovací robot používá personalizaci k výběru hlavní akce (konkrétní káva nebo čaj) na základě seznamu akcí (některého typu obsahu) a kontextových funkcí.

Robot odešle seznam akcí spolu s kontextovými funkcemi do smyčky Personalizace. Personalizace vrátí robotovi jedinou nejlepší akci, kterou váš robot zobrazí.

V tomto kurzu jsou akce typy kávy a čaje:

Káva Čaj
Cappuccino
Espresso
Latte
Mocha
GreenTea
Rooibos

Rozhraní API pro hodnocení: Aby se robot mohl dozvědět o vašich akcích, odešle robot následující informace s každou žádostí rozhraní Rank API:

  • Akce s funkcemi
  • Kontextové funkce

Funkce modelu je informace o akci nebo kontextu, které je možné agregovat (seskupit) mezi členy uživatelské základny chatovacího robota. Funkce není specifická jednotlivě (například ID uživatele) nebo vysoce specifická (například přesná denní doba).

Funkce se používají ke sladění akcí s aktuálním kontextem modelu. Model je reprezentace minulých znalostí personalizace o akcích, kontextu a jejich funkcích, které mu umožňují provádět kvalifikovaná rozhodnutí.

Model, včetně funkcí, se aktualizuje podle plánu na základě nastavení frekvence aktualizace modelu na webu Azure Portal.

Funkce by měly být vybrány se stejným plánováním a návrhem, které byste použili u jakéhokoli schématu nebo modelu ve vaší technické architektuře. Hodnoty funkcí je možné nastavit pomocí obchodní logiky nebo systémů třetích stran.

Upozornění

Funkce v této aplikaci slouží k předvedení a nemusí být nutně nejlepšími funkcemi, které můžete použít ve webové aplikaci pro váš případ použití.

Funkce akcí

Každá akce (položka obsahu) má funkce, které pomáhají odlišit položku kávy nebo čaje.

Funkce nejsou nakonfigurované jako součást konfigurace smyčky na webu Azure Portal. Místo toho se posílají jako objekt JSON s každým voláním rozhraní Rank API. To umožňuje flexibilitu pro akce a jejich funkce, aby se v průběhu času zvětšovaly, měnily a zmenšovaly, což umožňuje personalizaci sledovat trendy.

Mezi funkce kávy a čaje patří:

  • Místo původu kávového beanu, jako je Keňa a Brazílie
  • Je káva nebo čaj organické?
  • Světlé nebo tmavé pražení kávy

Zatímco káva má tři funkce v předchozím seznamu, čaj má pouze jeden. Předat funkce Personalizace, které mají smysl pro danou akci. Nepředávejte prázdnou hodnotu funkce, pokud se na akci nevztahuje.

Kontextové funkce

Kontextové funkce pomáhají personalizaci porozumět kontextu prostředí, jako je například zobrazovací zařízení, uživatel, umístění a další funkce, které jsou relevantní pro váš případ použití.

Kontext tohoto chatovacího robota zahrnuje:

  • Typ počasí (sníh, deštivý, slunečno)
  • Den v týdnu

Výběr funkcí je v tomto chatovacím robotovi randomizován. Ve skutečném robotovi používejte skutečná data pro vaše kontextové funkce.

Aspekty návrhu tohoto robota

V této konverzaci si můžete všimnout několika upozornění:

  • Interakce robota: Konverzace je velmi jednoduchá, protože demonstruje pořadí a odměnu v jednoduchém případě použití. Neukazuje plnou funkčnost sady SDK služby Bot Framework ani emulátoru.
  • Personalizace: Funkce jsou vybrány náhodně pro simulaci využití. V produkčním scénáři personalizace nechodil náhodně funkce.
  • Language Understanding (LUIS): Několik ukázkových promluv modelu LUIS je určené jenom pro tuto ukázku. Nepoužívejte v produkční aplikaci LUIS tolik ukázkových promluv.

Instalace požadovaného softwaru

  • Visual Studio 2019 Úložiště ukázek ke stažení obsahuje pokyny, pokud chcete použít .NET Core CLI.
  • Microsoft Bot Framework Emulator je desktopová aplikace, která vývojářům robotů umožňuje testovat a ladit roboty na místním hostiteli nebo vzdáleně spouštět prostřednictvím tunelu.

Stažení ukázkového kódu chatovacího robota

Chatovací robot je k dispozici v úložišti ukázek Personalizace. Naklonujte nebo stáhněte úložiště a pak otevřete ukázku /samples/ChatbotExample v adresáři pomocí sady Visual Studio 2019.

Pokud chcete naklonovat úložiště, použijte následující příkaz Gitu v prostředí Bash (terminálu).

git clone https://github.com/Azure-Samples/cognitive-services-personalizer-samples.git

Vytvoření a konfigurace prostředků Personalizace a LUIS

Vytvoření zdrojů Azure

Pokud chcete použít tohoto chatovacího robota, musíte vytvořit prostředky Azure pro personalizaci a službu Language Understanding (LUIS).

  • Vytvoření prostředků SLUŽBY LUIS Vytvořte prostředek pro vytváření i predikci.
  • Vytvořte prostředek Personalizace a pak zkopírujte klíč a koncový bod z webu Azure Portal. Tyto hodnoty budete muset nastavit v appsettings.json souboru projektu .NET.

Vytvoření aplikace LUIS

Pokud s luis začínáte, musíte se přihlásit a okamžitě migrovat svůj účet. Nemusíte vytvářet nové prostředky, místo toho vyberte prostředky, které jste vytvořili v předchozí části tohoto kurzu.

  1. Pokud chcete vytvořit novou aplikaci LUIS, vyberte na portálu LUIS své předplatné a prostředek pro vytváření.
  2. Pak na stejné stránce vyberte + Nová aplikace pro konverzaci a pak importujte jako JSON.
  3. V automaticky otevíraných dialogech vyberte Zvolit soubor a pak soubor vyberte /samples/ChatbotExample/CognitiveModels/coffeebot.json . Zadejte název Personalizer Coffee bot.
  4. V pravém horním navigačním panelu portálu LUIS vyberte tlačítko Trénovat.
  5. Výběrem tlačítka Publikovat publikujte aplikaci do produkčního slotu pro modul runtime predikce.
  6. Vyberte Spravovat a pak Nastavení. Zkopírujte hodnotu ID aplikace. Tuto hodnotu budete muset nastavit v appsettings.json souboru projektu .NET.
  7. Stále v části Spravovat vyberte Prostředky Azure. Zobrazí se přidružené prostředky v aplikaci.
  8. Vyberte Přidat prostředek předpovědi. V automaticky otevíraných dialogech vyberte své předplatné a prostředek předpovědi vytvořený v předchozí části tohoto kurzu a pak vyberte Hotovo.
  9. Zkopírujte hodnoty primárního klíče a adresy URL koncového bodu. Tyto hodnoty budete muset nastavit v appsettings.json souboru projektu .NET.

Konfigurace robota se souborem appsettings.json

  1. Otevřete soubor řešení chatovacího robota v ChatbotSamples.slnsadě Visual Studio 2019.

  2. Otevřete appsettings.json v kořenovém adresáři projektu.

  3. Nastavte všechna pět nastavení zkopírovaná v předchozí části tohoto kurzu.

    {
      "PersonalizerChatbot": {
        "LuisAppId": "",
        "LuisAPIKey": "",
        "LuisServiceEndpoint": "",
        "PersonalizerServiceEndpoint": "",
        "PersonalizerAPIKey": ""
      }
    }
    

Sestavení a spuštění robota

Jakmile nakonfigurujete appsettings.jsonchatovacího robota, jste připraveni sestavit a spustit chatovacího robota. Když to uděláte, otevře se prohlížeč na běžícím webu http://localhost:3978.

Screenshot of browser displaying chat bot web site.

Nechte web spuštěný, protože tento kurz vysvětluje, co robot dělá, abyste mohli s robotem pracovat.

Nastavení bot Framework Emulatoru

  1. Otevřete Bot Framework Emulator a vyberte Otevřít robota.

    Screenshot of Bot Framework Emulator startup screen.

  2. Nakonfigurujte robota s následující adresou URL robota a pak vyberte Připojení:

    http://localhost:3978/api/messages

    Screenshot of Bot Framework Emulator open bot settings.

    Emulátor se připojí k chatbotovi a zobrazí instrukční text spolu s informacemi o protokolování a ladění, které jsou užitečné pro místní vývoj.

    Screenshot of Bot Framework Emulator in first turn of conversation.

Použití robota v bot Framework Emulatoru

  1. Požádejte, aby se nabídka zobrazila zadáním I would like to see the menu. Chatovací robot zobrazí položky.

  2. Nechte robota navrhnout položku tak, že zadáte Please suggest a drink for me. emulátor, zobrazí žádost o pořadí a odpověď v okně chatu, abyste viděli celý JSON. A robot vytvoří návrh, třeba How about Latte?

  3. Odpověď, že chcete, což znamená, že přijímáte nejlépe hodnocený výběr personalizace, I like it. emulátor zobrazí žádost o odměnu s skóre odměny 1 a odpovědí v okně chatu, takže uvidíte celý KÓD JSON. A robot odpoví a That’s great! I’ll keep learning your preferences over time.Would you like to get a new suggestion or reset the simulated context to a new day?

    Pokud odpovíte no na výběr, pošle se do Personalizace skóre odměny 0.

Vysvětlení kódu .NET pomocí personalizace

Řešení .NET je jednoduchý chatovací robot bot framework. Kód související s Personalizace je v následujících složkách:

  • /samples/ChatbotExample/Bots
    • PersonalizerChatbot.cs soubor pro interakci mezi robotem a personalizátorem
  • /samples/ChatbotExample/ReinforcementLearning – spravuje akce a funkce pro model Personalizace.
  • /samples/ChatbotExample/Model – soubory pro akce a funkce personalizace a záměry LUIS

PersonalizaceChatbot.cs - práce s Personalizace

Třída PersonalizerChatbot je odvozena z Microsoft.Bot.Builder.ActivityHandler. Má tři vlastnosti a metody pro správu toku konverzace.

Upozornění

Nekopírujte kód z tohoto kurzu. Použijte vzorový kód v úložišti ukázek Personalizace.

public class PersonalizerChatbot : ActivityHandler
{

    private readonly LuisRecognizer _luisRecognizer;
    private readonly PersonalizerClient _personalizerClient;

    private readonly RLContextManager _rlFeaturesManager;

    public PersonalizerChatbot(LuisRecognizer luisRecognizer, RLContextManager rlContextManager, PersonalizerClient personalizerClient)
            {
                _luisRecognizer = luisRecognizer;
                _rlFeaturesManager = rlContextManager;
                _personalizerClient = personalizerClient;
            }
    }

    public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
    {
        await base.OnTurnAsync(turnContext, cancellationToken);

        if (turnContext.Activity.Type == ActivityTypes.Message)
        {
            // Check LUIS model
            var recognizerResult = await _luisRecognizer.RecognizeAsync(turnContext, cancellationToken);
            var topIntent = recognizerResult?.GetTopScoringIntent();
            if (topIntent != null && topIntent.HasValue && topIntent.Value.intent != "None")
            {
                Intents intent = (Intents)Enum.Parse(typeof(Intents), topIntent.Value.intent);
                switch (intent)
                {
                    case Intents.ShowMenu:
                        await turnContext.SendActivityAsync($"Here is our menu: \n Coffee: {CoffeesMethods.DisplayCoffees()}\n Tea: {TeaMethods.DisplayTeas()}", cancellationToken: cancellationToken);
                        break;
                    case Intents.ChooseRank:
                        // Here we generate the event ID for this Rank.
                        var response = await ChooseRankAsync(turnContext, _rlFeaturesManager.GenerateEventId(), cancellationToken);
                        _rlFeaturesManager.CurrentPreference = response.Ranking;
                        await turnContext.SendActivityAsync($"How about {response.RewardActionId}?", cancellationToken: cancellationToken);
                        break;
                    case Intents.RewardLike:
                        if (!string.IsNullOrEmpty(_rlFeaturesManager.CurrentEventId))
                        {
                            await RewardAsync(turnContext, _rlFeaturesManager.CurrentEventId, 1, cancellationToken);
                            await turnContext.SendActivityAsync($"That's great! I'll keep learning your preferences over time.", cancellationToken: cancellationToken);
                            await SendByebyeMessageAsync(turnContext, cancellationToken);
                        }
                        else
                        {
                            await turnContext.SendActivityAsync($"Not sure what you like. Did you ask for a suggestion?", cancellationToken: cancellationToken);
                        }

                        break;
                    case Intents.RewardDislike:
                        if (!string.IsNullOrEmpty(_rlFeaturesManager.CurrentEventId))
                        {
                            await RewardAsync(turnContext, _rlFeaturesManager.CurrentEventId, 0, cancellationToken);
                            await turnContext.SendActivityAsync($"Oh well, maybe I'll guess better next time.", cancellationToken: cancellationToken);
                            await SendByebyeMessageAsync(turnContext, cancellationToken);
                        }
                        else
                        {
                            await turnContext.SendActivityAsync($"Not sure what you dislike. Did you ask for a suggestion?", cancellationToken: cancellationToken);
                        }

                        break;
                    case Intents.Reset:
                        _rlFeaturesManager.GenerateRLFeatures();
                        await SendResetMessageAsync(turnContext, cancellationToken);
                        break;
                    default:
                        break;
                }
            }
            else
            {
                var msg = @"Could not match your message with any of the following LUIS intents:
                        'ShowMenu'
                        'ChooseRank'
                        'RewardLike'
                        'RewardDislike'.
                        Try typing 'Show me the menu','What do you suggest','I like it','I don't like it'.";
                await turnContext.SendActivityAsync(msg);
            }
        }
        else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
        {
            // Generate a new weekday and weather condition
            // These will act as the context features when we call rank with Personalizer
            _rlFeaturesManager.GenerateRLFeatures();

            // Send a welcome message to the user and tell them what actions they may perform to use this bot
            await SendWelcomeMessageAsync(turnContext, cancellationToken);
        }
        else
        {
            await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected", cancellationToken: cancellationToken);
        }
    }

    // code removed for brevity, full sample code available for download
    private async Task SendWelcomeMessageAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    private async Task SendResetMessageAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    private async Task SendByebyeMessageAsync(ITurnContext turnContext, CancellationToken cancellationToken)
    private async Task<RankResponse> ChooseRankAsync(ITurnContext turnContext, string eventId, CancellationToken cancellationToken)
    private async Task RewardAsync(ITurnContext turnContext, string eventId, double reward, CancellationToken cancellationToken)
}

Metody s předponou Send správa konverzací s robotem a službou LUIS. Metody ChooseRankAsync a RewardAsync interakce s personalizátorem.

Volání rozhraní API pořadí a zobrazení výsledků

Metoda ChooseRankAsync sestaví data JSON pro odesílání do rozhraní API pro pořadí personalizace shromažďováním akcí s funkcemi a kontextovými funkcemi.

private async Task<RankResponse> ChooseRankAsync(ITurnContext turnContext, string eventId, CancellationToken cancellationToken)
{
    IList<object> contextFeature = new List<object>
    {
        new { weather = _rlFeaturesManager.RLFeatures.Weather.ToString() },
        new { dayofweek = _rlFeaturesManager.RLFeatures.DayOfWeek.ToString() },
    };

    Random rand = new Random(DateTime.UtcNow.Millisecond);
    IList<RankableAction> actions = new List<RankableAction>();
    var coffees = Enum.GetValues(typeof(Coffees));
    var beansOrigin = Enum.GetValues(typeof(CoffeeBeansOrigin));
    var organic = Enum.GetValues(typeof(Organic));
    var roast = Enum.GetValues(typeof(CoffeeRoast));
    var teas = Enum.GetValues(typeof(Teas));

    foreach (var coffee in coffees)
    {
        actions.Add(new RankableAction
        {
            Id = coffee.ToString(),
            Features =
            new List<object>()
            {
                new { BeansOrigin = beansOrigin.GetValue(rand.Next(0, beansOrigin.Length)).ToString() },
                new { Organic = organic.GetValue(rand.Next(0, organic.Length)).ToString() },
                new { Roast = roast.GetValue(rand.Next(0, roast.Length)).ToString() },
            },
        });
    }

    foreach (var tea in teas)
    {
        actions.Add(new RankableAction
        {
            Id = tea.ToString(),
            Features =
            new List<object>()
            {
                new { Organic = organic.GetValue(rand.Next(0, organic.Length)).ToString() },
            },
        });
    }

    // Sending a rank request to Personalizer
    // Here we are asking Personalizer to decide which drink the user is most likely to want
    // based on the current context features (weather, day of the week generated in RLContextManager)
    // and the features of the drinks themselves
    var request = new RankRequest(actions, contextFeature, null, eventId);
    await turnContext.SendActivityAsync(
        "===== DEBUG MESSAGE CALL TO RANK =====\n" +
        "This is what is getting sent to Rank:\n" +
        $"{JsonConvert.SerializeObject(request, Formatting.Indented)}\n",
        cancellationToken: cancellationToken);
    var response = await _personalizerClient.RankAsync(request, cancellationToken);
    await turnContext.SendActivityAsync(
        $"===== DEBUG MESSAGE RETURN FROM RANK =====\n" +
        "This is what Rank returned:\n" +
        $"{JsonConvert.SerializeObject(response, Formatting.Indented)}\n",
        cancellationToken: cancellationToken);
    return response;
}

Rozhraní API odměny pro volání a zobrazení výsledků

Metoda RewardAsync sestaví data JSON, která se mají odeslat do rozhraní API personalizace odměny určením skóre. Skóre se určuje ze záměru LUIS zjištěného v textu uživatele a odeslaném OnTurnAsync z metody.

private async Task RewardAsync(ITurnContext turnContext, string eventId, double reward, CancellationToken cancellationToken)
{
    await turnContext.SendActivityAsync(
        "===== DEBUG MESSAGE CALL REWARD =====\n" +
        "Calling Reward:\n" +
        $"eventId = {eventId}, reward = {reward}\n",
        cancellationToken: cancellationToken);

    // Sending a reward request to Personalizer
    // Here we are responding to the drink ranking Personalizer provided us
    // If the user liked the highest ranked drink, we give a high reward (1)
    // If they did not, we give a low reward (0)
    await _personalizerClient.RewardAsync(eventId, new RewardRequest(reward), cancellationToken);
}

Aspekty návrhu robota

Tato ukázka je určená k předvedení jednoduchého komplexního řešení personalizace v robotovi. Váš případ použití může být složitější.

Pokud chcete použít personalizaci v produkčním robotovi, naplánujte následující:

  • Přístup k personalizaci v reálném čase pokaždé, když potřebujete seřazený výběr. Rozhraní Rank API nemůže být dávkové ani uložené v mezipaměti. Volání odměny může být zpožděné nebo přesměrované na samostatný proces a pokud v časovém období nevrátíte odměnu, nastaví se pro událost výchozí hodnota odměny.
  • Výpočet odměny na základě případu použití: V tomto příkladu se zobrazily dvě odměny nuly a jedna bez rozsahu mezi skóre a žádnou zápornou hodnotou pro skóre. Váš systém potřeboval podrobnější bodování.
  • Kanály robota: Tato ukázka používá jeden kanál, ale pokud máte v úmyslu použít více než jeden kanál nebo varianty robotů v jednom kanálu, může být potřeba ho považovat za součást kontextových funkcí modelu Personalizace.

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

Po dokončení tohoto kurzu vyčistěte následující prostředky:

  • Odstraňte svůj ukázkový adresář projektu.
  • Odstraňte prostředek Personalizace a LUIS na webu Azure Portal.

Další kroky