Szekvenciális beszélgetési folyamat implementálása

A KÖVETKEZŐKRE VONATKOZIK: SDK v4

A robotok a felhasználókkal való interakció egyik fő módja, hogy kérdéseket tehetnek fel az információk gyűjtésére. A párbeszédpanel-kódtár olyan hasznos beépített funkciókat biztosít, mint például a parancssori osztályok, amelyek megkönnyítik a kérdések feltevését, és ellenőrzik a választ annak ellenőrzéséhez, hogy megfelel-e egy adott adattípusnak, vagy megfelelnek-e az egyéni érvényesítési szabályoknak.

A párbeszédtár használatával lineáris és összetettebb beszélgetési folyamatokat is kezelhet. Lineáris interakció esetén a robot rögzített lépések sorozatán fut végig, és a beszélgetés befejeződik. A párbeszédpanel akkor hasznos, ha a robotnak adatokat kell gyűjtenie a felhasználótól.

Ez a cikk bemutatja, hogyan valósíthatja meg a lineáris beszélgetési folyamatot a parancssorok létrehozásával és egy vízesés párbeszédpanelről való meghívásával. A saját kérések párbeszédpanel-kódtár használata nélküli írására vonatkozó példákért tekintse meg a Saját kérések létrehozása a felhasználói beviteli cikk gyűjtéséhez című témakört.

Feljegyzés

A Bot Framework JavaScript, C# és Python SDK-k továbbra is támogatottak lesznek, a Java SDK-t azonban 2023 novemberében végső hosszú távú támogatással kivonják.

A Java SDK-val létrehozott meglévő robotok továbbra is működni fognak.

Új robotépítéshez fontolja meg a Power Virtual Agents használatát, és olvassa el a megfelelő csevegőrobot-megoldás kiválasztását.

További információ: A robotépítés jövője.

Előfeltételek

  • A robot alapjainak, az állapot kezelésének és a párbeszédpanelek kódtárának ismerete.
  • A többes turn mintapéldánya C#, JavaScript, Java vagy Python nyelven kéri a mintát.

A minta ismertetése

A többfordulós kérések minta egy vízesés párbeszédpanelt, néhány kérdést és egy összetevő párbeszédpanelt használ egy lineáris interakció létrehozásához, amely kérdések sorozatát kérdezi fel a felhasználótól. A kód egy párbeszédpanel használatával lépeget az alábbi lépéseken:

Lépések Parancssor típusa
Kérje meg a felhasználót a szállítás módjára Választási lehetőségekre vonatkozó kérdés
Kérje meg a felhasználót, hogy adja meg a nevét Szöveges üzenet
Kérdezze meg a felhasználót, hogy meg szeretné-e adni az életkorát Megerősítési kérés
Ha igennel válaszoltak, kérjék meg a korukat Számkérés, amely csak 0-nál nagyobb és 150-nél kisebb életkort fogad el érvényesítéssel
Ha nem a Microsoft Teamst használják, kérjen profilképet Melléklet kérése a hiányzó melléklet engedélyezéséhez érvényesítéssel
Kérdezze meg, hogy az összegyűjtött adatok "rendben" vannak-e Ismételt megerősítési kérés

Végül, ha igennel válaszoltak, jelenítse meg az összegyűjtött információkat; ellenkező esetben közölje a felhasználóval, hogy az adatai nem lesznek megőrzve.

A fő párbeszédpanel létrehozása

A párbeszédpanelek használatához telepítse a Microsoft.Bot.Builder.Dialogs NuGet csomagot.

A robot a felhasználóval a használatával UserProfileDialogkommunikál. A robot osztályának DialogBot létrehozásakor a UserProfileDialog robot a fő párbeszédpanelként van beállítva. A robot ezután egy Run segédmetódussal éri el a párbeszédpanelt.

A C#-minta osztálydiagramja.

Párbeszédpanelek\UserProfileDialog.cs

Először hozza létre az UserProfileDialog osztályból ComponentDialog származót, és hét lépésből áll.

A konstruktorban UserProfileDialog hozza létre a vízesés lépéseit, a parancssorokat és a vízesés párbeszédpanelt, és adja hozzá őket a párbeszédpanel-készlethez. A kéréseknek ugyanabban a párbeszédpanelen kell lenniük, amelyben használják őket.

public UserProfileDialog(UserState userState)
    : base(nameof(UserProfileDialog))
{
    _userProfileAccessor = userState.CreateProperty<UserProfile>("UserProfile");

    // This array defines how the Waterfall will execute.
    var waterfallSteps = new WaterfallStep[]
    {
        TransportStepAsync,
        NameStepAsync,
        NameConfirmStepAsync,
        AgeStepAsync,
        PictureStepAsync,
        SummaryStepAsync,
        ConfirmStepAsync,
    };

    // Add named dialogs to the DialogSet. These names are saved in the dialog state.
    AddDialog(new WaterfallDialog(nameof(WaterfallDialog), waterfallSteps));
    AddDialog(new TextPrompt(nameof(TextPrompt)));
    AddDialog(new NumberPrompt<int>(nameof(NumberPrompt<int>), AgePromptValidatorAsync));
    AddDialog(new ChoicePrompt(nameof(ChoicePrompt)));
    AddDialog(new ConfirmPrompt(nameof(ConfirmPrompt)));
    AddDialog(new AttachmentPrompt(nameof(AttachmentPrompt), PicturePromptValidatorAsync));

    // The initial child Dialog to run.
    InitialDialogId = nameof(WaterfallDialog);
}

Ezután adja hozzá azokat a lépéseket, amelyeket a párbeszédpanel a bemenet kéréséhez használ. A parancssor használatához hívja meg a párbeszédpanel egyik lépéséből, és kérje le a következő lépésben kapott eredményt a következő lépésben stepContext.Result. A színfalak mögött a kérések kétlépéses párbeszédpanelek. Először a kérés bemenetet kér. Ezután visszaadja az érvényes értéket, vagy az elejétől kezdve újrakezdi a hibát, amíg érvényes bemenetet nem kap.

A vízeséslépésből mindig null értékű DialogTurnResult értéket kell visszaadnia. Ha nem, előfordulhat, hogy a párbeszédpanel nem a tervezett módon működik. Az alábbiakban a vízesés párbeszédpanel implementációja NameStepAsync látható.

private static async Task<DialogTurnResult> NameStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    stepContext.Values["transport"] = ((FoundChoice)stepContext.Result).Value;

    return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions { Prompt = MessageFactory.Text("Please enter your name.") }, cancellationToken);
}

Ebben AgeStepAsynca mezőben adjon meg egy újrapróbálkozáshoz szükséges kérést arra az esetben, ha a felhasználó bemenete nem érvényesíthető, vagy mert olyan formátumban van, amelyet a parancssor nem tud elemezni, vagy a bemenet nem tud érvényesítési feltételeket megadni. Ebben az esetben, ha nem adott meg újrapróbálkozási kérést, a parancssor a kezdeti parancssori szöveg használatával fogja újrakényelmesíteni a felhasználót a bemenethez.

private async Task<DialogTurnResult> AgeStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    if ((bool)stepContext.Result)
    {
        // User said "yes" so we will be prompting for the age.
        // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
        var promptOptions = new PromptOptions
        {
            Prompt = MessageFactory.Text("Please enter your age."),
            RetryPrompt = MessageFactory.Text("The value entered must be greater than 0 and less than 150."),
        };

        return await stepContext.PromptAsync(nameof(NumberPrompt<int>), promptOptions, cancellationToken);
    }
    else
    {
        // User said "no" so we will skip the next step. Give -1 as the age.
        return await stepContext.NextAsync(-1, cancellationToken);
    }
}

UserProfile.cs

A rendszer az osztály egy példányában menti a felhasználó szállítási módját, nevét és életkorát UserProfile .

public class UserProfile
{
    public string Transport { get; set; }

    public string Name { get; set; }

    public int Age { get; set; }

    public Attachment Picture { get; set; }
}

Párbeszédpanelek\UserProfileDialog.cs

Az utolsó lépésben ellenőrizze az stepContext.Result előző vízesés lépésben hívott párbeszédpanel által visszaadott hibát. Ha a visszatérési érték igaz, a felhasználói profil tartozéka lekéri és frissíti a felhasználói profilt. A felhasználói profil lekéréséhez hívja megGetAsync, majd állítsa be a , userProfile.NameuserProfile.Age és userProfile.Picture a userProfile.Transporttulajdonságok értékeit. Végül foglalja össze a felhasználó adatait a hívás EndDialogAsyncelőtt, amely véget vet a párbeszédpanelnek. A párbeszédpanel befejezése kiugrik a párbeszédpanel vereméből, és opcionális eredményt ad vissza a párbeszédpanel szülőjének. A szülő az a párbeszédpanel vagy metódus, amely elindította az imént befejezett párbeszédpanelt.

    else
    {
        msg += $" Your profile will not be kept.";
    }

    await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);

    // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is the end.
    return await stepContext.EndDialogAsync(cancellationToken: cancellationToken);
}

private async Task<DialogTurnResult> SummaryStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    stepContext.Values["picture"] = ((IList<Attachment>)stepContext.Result)?.FirstOrDefault();

    // Get the current profile object from user state.
    var userProfile = await _userProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile(), cancellationToken);

    userProfile.Transport = (string)stepContext.Values["transport"];
    userProfile.Name = (string)stepContext.Values["name"];
    userProfile.Age = (int)stepContext.Values["age"];
    userProfile.Picture = (Attachment)stepContext.Values["picture"];

    var msg = $"I have your mode of transport as {userProfile.Transport} and your name as {userProfile.Name}";

    if (userProfile.Age != -1)
    {
        msg += $" and your age as {userProfile.Age}";
    }

    msg += ".";

    await stepContext.Context.SendActivityAsync(MessageFactory.Text(msg), cancellationToken);

    if (userProfile.Picture != null)
    {
        try
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Attachment(userProfile.Picture, "This is your profile picture."), cancellationToken);
        }
        catch
        {
            await stepContext.Context.SendActivityAsync(MessageFactory.Text("A profile picture was saved but could not be displayed here."), cancellationToken);

A párbeszédpanel futtatása

Robotok\DialogBot.cs

A OnMessageActivityAsync kezelő a RunAsync metódus használatával indítja el vagy folytatja a párbeszédpanelt. OnTurnAsync A robot állapotkezelési objektumait használja a tároló állapotváltozásainak megőrzéséhez. A ActivityHandler.OnTurnAsync metódus meghívja a különböző tevékenységkezelő metódusokat, például OnMessageActivityAsync. Ily módon az állapot az üzenetkezelő befejeződése után, de a fordulás befejezése előtt lesz mentve.

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

    // Save any state changes that might have occurred during the turn.
    await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
}

protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
    Logger.LogInformation("Running dialog with Message Activity.");

    // Run the Dialog with the new message Activity.
    await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
}

Szolgáltatások regisztrálása a robothoz

Ez a robot a következő szolgáltatásokat használja:

  • A robot alapvető szolgáltatásai: hitelesítőadat-szolgáltató, adapter és robot implementációja.
  • Az állapot kezelésére szolgáló szolgáltatások: tárolás, felhasználói állapot és beszélgetési állapot.
  • A robot által használt párbeszédpanel.

Startup.cs

Szolgáltatások regisztrálása a robothoz a következőben Startup: . Ezek a szolgáltatások függőséginjektáláson keresztül érhetők el a kód más részei számára.

{
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpClient().AddControllers().AddNewtonsoftJson(options =>
        {
            options.SerializerSettings.MaxDepth = HttpHelper.BotMessageSerializerSettings.MaxDepth;
        });

        // Create the Bot Framework Authentication to be used with the Bot Adapter.
        services.AddSingleton<BotFrameworkAuthentication, ConfigurationBotFrameworkAuthentication>();

        // Create the Bot Adapter with error handling enabled.
        services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithErrorHandler>();

        // Create the storage we'll be using for User and Conversation state. (Memory is great for testing purposes.)
        services.AddSingleton<IStorage, MemoryStorage>();

        // Create the User state. (Used in this bot's Dialog implementation.)
        services.AddSingleton<UserState>();

        // Create the Conversation state. (Used by the Dialog system itself.)
        services.AddSingleton<ConversationState>();

Feljegyzés

A memóriatároló csak tesztelési célokra használható, és nem éles használatra szolgál. Mindenképpen használjon állandó típusú tárolót egy éles robothoz.

A robot tesztelése

  1. Ha még nem tette meg, telepítse a Bot Framework Emulatort.
  2. Futtassa a mintát helyileg a számítógépen.
  3. Indítsa el az Emulátort, csatlakozzon a robothoz, és küldjön üzeneteket az alábbiak szerint.

A többfordulós parancssori robottal folytatott beszélgetés példaátirata.

További információk

Tudnivalók a párbeszédpanelről és a robot állapotáról

Ebben a robotban két állapottulajdonság-tartozék van definiálva:

  • A párbeszédpanel állapottulajdonságához a beszélgetési állapoton belül létrehozott. A párbeszédpanel állapota nyomon követi, hogy a felhasználó hol található egy párbeszédpanel-csoport párbeszédpaneljén, és a párbeszédpanel környezete frissíti, például amikor meghívja a kezdő vagya folytatás párbeszédpanel-metódust .
  • A felhasználói profil tulajdonság felhasználói állapotában létrehozott. A robot ezzel nyomon követi a felhasználóval kapcsolatos információkat, és ezt az állapotot explicit módon kell kezelnie a párbeszédpanel kódjában.

Az állapottulajdonság-tartozék lekérési és beállítási módszerei lekérik és beállítják a tulajdonság értékét az állapotkezelési objektum gyorsítótárában. A gyorsítótár akkor lesz feltöltve, amikor egy állapottulajdonság értékét először kéri a rendszer, de kifejezetten meg kell őrizni. A két állapottulajdonság módosításainak megőrzése érdekében a rendszer meghívja a megfelelő állapotkezelési objektum mentési módosítási metódusát.

Ez a minta frissíti a felhasználói profil állapotát a párbeszédpanelen. Ez a gyakorlat egyes robotok esetében működhet, de nem fog működni, ha több roboton szeretné újra használni a párbeszédpaneleket.

A párbeszédpanel lépéseinek és a robot állapotának elkülönítésére különböző lehetőségek állnak rendelkezésre. Ha például a párbeszédpanel teljes információkat gyűjt, a következőt teheti:

  • A záró párbeszédpanel metódusával visszaadott értékként adja meg az összegyűjtött adatokat a szülőkörnyezetnek. Ez lehet a robot forgatókezelője vagy a párbeszédpanel-verem egy korábbi aktív párbeszédpanelje, és így lettek kialakítva a parancssori osztályok.
  • Kérés létrehozása egy megfelelő szolgáltatáshoz. Ez akkor lehet hasznos, ha a robot előtérként szolgál egy nagyobb szolgáltatáshoz.

A prompt validator metódus definíciója

UserProfileDialog.cs

Az alábbiakban egy validátorkód-példa látható a AgePromptValidatorAsync metódusdefinícióhoz. promptContext.Recognized.Value az elemzési értéket tartalmazza, amely itt a számkérés egésze. promptContext.Recognized.Succeeded azt jelzi, hogy a kérés elemezni tudta-e a felhasználó bemenetét. Az érvényesítőnek hamis értéket kell visszaadnia, amely azt jelzi, hogy az érték nem lett elfogadva, és a parancssori párbeszédpanelnek újra meg kell akadályoznia a felhasználót; ellenkező esetben igaz visszatérés a bemenet elfogadásához és a parancssori párbeszédpanelről való visszatéréshez. Az érték a forgatókönyv szerint módosítható az érvényesítőben.

    }

    // WaterfallStep always finishes with the end of the Waterfall or with another dialog; here it is a Prompt Dialog.
    return await stepContext.PromptAsync(nameof(ConfirmPrompt), new PromptOptions { Prompt = MessageFactory.Text("Is this ok?") }, cancellationToken);
}

Következő lépések