使用調適型對話建立 BotCreate a bot using adaptive dialogs

適用于: SDK v4APPLIES TO: SDK v4

本文說明如何使用 [調適型對話] 和 [語言生成] 功能,達到使用瀑布模型所取得的相同功能。This article shows how to use Adaptive dialog and Language Generation features to achieve the same functionality obtained with the waterfall model.

必要條件Prerequisites

用於將調適型對話新增至 Bot 的預備步驟Preliminary steps to add an adaptive dialog to a bot

您必須遵循下面所述的步驟,將調適型對話新增至 Bot。You must follow the steps described below to add an adaptive dialog to a bot.

  1. 將所有 Bot Builder NuGet 套件更新為 4.9.x 版。Update all Bot Builder NuGet packages to version 4.9.x.
  2. Microsoft.Bot.Builder.Dialogs.Adaptive 套件新增至 Bot 專案。Add the Microsoft.Bot.Builder.Dialogs.Adaptive package to your bot project.
  3. 更新 Bot 配接器,將儲存體及使用者和交談狀態物件新增至每個回合內容。Update the the bot adapter to add storage and the user and conversation state objects to every turn context.
  4. 在 Bot 程式碼中使用對話管理員,以啟動或繼續每個回合的根對話。Use a dialog manager in the bot code to start or continue the root dialog each turn.

關於範例About the sample

此範例會使用調適型對話、一些提示和元件對話來建立簡單互動,以詢問使用者一系列的問題。This sample uses an adaptive dialog, a few prompts, and a component dialog to create a simple interaction that asks the user a series of questions. 這些問題是使用 LG 範本所建立:The questions are created using LG templates:

程式碼會使用對話方塊來循環下列步驟:The code uses a dialog to cycle through these steps:

步驟Steps LG 範本LG template
要求使用者的運輸模式Ask the user for their mode of transportation ModeOfTransportPrompt
要求使用者的名稱Ask the user for their name AskForName
詢問使用者是否要提供年齡Ask the user if they want to provide their age AgeConfirmPrompt
如果他們回答 [是],則要求年齡If they answered yes, asks for their age 包含驗證的 AskForAge 提示,只接受大於 0 且小於 150 的年齡AskForAge prompt with validation to only accept ages greater than 0 and less than 150
詢問是否可收集資訊Asks if the collected information is "ok" ConfirmPrompt 提示ConfirmPrompt prompt

最後,如果他們回答 [是],則顯示所收集的資訊;否則,告訴使用者將不會保留其資訊。Finally, if they answered yes, display the collected information; otherwise, tell the user that their information will not be kept.

建立主要對話Create the main dialog

若要使用對話,請安裝 Microsoft.Bot.Builder.Dialogs.Adaptive NuGet 套件。To use dialogs, install the Microsoft.Bot.Builder.Dialogs.Adaptive NuGet package.

Bot 會透過根調適型對話方塊與使用者互動。The bot interacts with the user via a root adaptive dialog. Bot 接著會使用 DialogManager.OnTurnAsync 來執行此對話。The bot then uses the DialogManager.OnTurnAsync to run the dialog.

根對話方塊

Dialogs\RootDialog.csDialogs\RootDialog.cs

程式碼一開始會將根調適型對話方塊具現化。The code begins by instantiating the root adaptive dialog. 此時會將下列 WelcomeUserStepsOnBeginDialogSteps 新增至對話。At this time, the following WelcomeUserSteps and OnBeginDialogSteps are added to the dialog. 請注意參考 Dialogs\RootDialog.lg 檔案的 paths 定義,該檔案包含用於建立調適型對話的 LG 範本。Notice the paths definition referencing the Dialogs\RootDialog.lg file that contains the LG templates used in the creation of the adaptive dialog.

public RootDialog() : base(nameof(RootDialog))
{
    string[] paths = { ".", "Dialogs", $"RootDialog.lg" };
    string fullPath = Path.Combine(paths);

    // These steps are executed when this Adaptive Dialog begins
    Triggers = new List<OnCondition>()
        {
            // Add a rule to welcome user
            new OnConversationUpdateActivity()
            {
                Actions = WelcomeUserSteps()
            },

            // Respond to user on message activity
            new OnUnknownIntent()
            {
                Actions = GatheUserInformation()
            },
        };
    Generator = new TemplateEngineLanguageGenerator(Templates.ParseFile(fullPath));
}

另請注意:Notice also:

  • LG 範本產生器會新增至調適型對話,以便使用 LG 範本The LG template generator is added to the adaptive dialog, to enable the use of the LG templates.
  • 已新增這兩個觸發程序,並由兩個協助程式方法提供其動作。The two triggers are added, with their actions being provided by the two helper methods.

WelcomeUserSteps方法會提供觸發程式引發時要執行的動作。The WelcomeUserSteps method provides the actions to perform when the trigger fires. Foreach 動作會逐一查看 membersAdded 清單,以問候加入交談的使用者。The Foreach actions iterates through the membersAdded list to greets the user added to the conversation.

注意

在調適型對話和觸發程序的內容中,所有對話都是有效動作,而動作類型 (ForeachIfConditionSendActivity) 全都是對話。Within the context of adaptive dialogs and triggers, all dialogs are valid actions, and the action types (Foreach, IfCondition, SendActivity) are all dialogs.
有些通道傳送了兩個交談更新事件:一個用於加入交談的 Bot,另一個用於使用者。Some channels send two conversation update events: one for the bot added to the conversation and another for the user. 程式碼會篩選 Bot 本身是訊息收件者的案例。The code filters cases where the bot itself is the recipient of the message. 如需詳細資訊,請參閱依通道分類的活動For more information, see Categorized activities by channel.

private static List<Dialog> WelcomeUserSteps()
{
    return new List<Dialog>()
    {
        // Iterate through membersAdded list and greet user added to the conversation.
        new Foreach()
        {
            ItemsProperty = "turn.activity.membersAdded",
            Actions = new List<Dialog>()
            {
                // Note: Some channels send two conversation update events - one for the Bot added to the conversation and another for user.
                // Filter cases where the bot itself is the recipient of the message. 
                new IfCondition()
                {
                    Condition = "$foreach.value.name != turn.activity.recipient.name",
                    Actions = new List<Dialog>()
                    {
                        new SendActivity("Hello, I'm the multi-turn prompt bot. Please send a message to get started!")
                    }
                }
            }
        }
    };

}

GatherUserInformation 會實作對話使用的步驟The GatherUserInformation implements the steps that the dialog uses. 其會使用 RootDialog.lg 檔案中的 LG 範本來定義提示。It defines the prompts using the LG templates from the RootDialog.lg file. 下列程式碼顯示如何建立 Name 提示。The code below shows how the Name prompt is created.

private static List<Dialog> GatheUserInformation()
{
    return new List<Dialog>()
    {
        // Ask for user's age and set it in user.userProfile scope.
        new TextInput()
        {
            Prompt = new ActivityTemplate("${ModeOfTransportPrompt()}"),
            // Set the output of the text input to this property in memory.
            Property = "user.userProfile.Transport"
        },
        new TextInput()
        {
            Prompt = new ActivityTemplate("${AskForName()}"),
            Property = "user.userProfile.Name"
        },
        // SendActivity supports full language generation resolution.
        // See here to learn more about language generation
        // https://aka.ms/language-generation
        new SendActivity("${AckName()}"),
        new ConfirmInput()
        {
            Prompt = new ActivityTemplate("${AgeConfirmPrompt()}"),
            Property = "turn.ageConfirmation"
        },
        new IfCondition()
        {
            // All conditions are expressed using adaptive expressions.
            // See https://aka.ms/adaptive-expressions to learn more
            Condition = "turn.ageConfirmation == true",
            Actions = new List<Dialog>()
            {
                 new NumberInput()
                 {
                     Prompt = new ActivityTemplate("${AskForAge()}"),
                     Property = "user.userProfile.Age",
                     // Add validations
                     Validations = new List<BoolExpression>()
                     {
                         // Age must be greater than or equal 1
                         "int(this.value) >= 1",
                         // Age must be less than 150
                         "int(this.value) < 150"
                     },
                     InvalidPrompt = new ActivityTemplate("${AskForAge.invalid()}"),
                     UnrecognizedPrompt = new ActivityTemplate("${AskForAge.unRecognized()}")
                 },
                 new SendActivity("${UserAgeReadBack()}")
            },
            ElseActions = new List<Dialog>()
            {
                new SendActivity("${NoName()}")
            }
        },
        new ConfirmInput()
        {
            Prompt = new ActivityTemplate("${ConfirmPrompt()}"),
            Property = "turn.finalConfirmation"
        },
        // Use LG template to come back with the final read out.
        // This LG template is a great example of what logic can be wrapped up in LG sub-system.
        new SendActivity("${FinalUserProfileReadOut()}"), // examines turn.finalConfirmation
        new DeleteProperty() {
            Property = "user.userProfile"
        },
        new EndDialog(),
    };
}

IfCondition 動作會使用調適型運算式來詢問使用者的年齡或傳送通知訊息 (視其對前一個問題的回應而定)。The IfCondition action uses an adaptive expression to either ask the user for their age or send an acknowledgement message, depending on their response to the previous question. 同樣地,其會使用 LG 範本來格式化提示和訊息。Again it uses LG templates to format the prompts and messages.

new IfCondition()
{
    // All conditions are expressed using adaptive expressions.
    // See https://aka.ms/adaptive-expressions to learn more
    Condition = "turn.ageConfirmation == true",
    Actions = new List<Dialog>()
    {
         new NumberInput()
         {
             Prompt = new ActivityTemplate("${AskForAge()}"),
             Property = "user.userProfile.Age",
             // Add validations
             Validations = new List<BoolExpression>()
             {
                 // Age must be greater than or equal 1
                 "int(this.value) >= 1",
                 // Age must be less than 150
                 "int(this.value) < 150"
             },
             InvalidPrompt = new ActivityTemplate("${AskForAge.invalid()}"),
             UnrecognizedPrompt = new ActivityTemplate("${AskForAge.unRecognized()}")
         },
         new SendActivity("${UserAgeReadBack()}")
    },
    ElseActions = new List<Dialog>()
    {
        new SendActivity("${NoName()}")
    }
},

註冊調適型對話Register the adaptive dialog

若要允許使用調適型對話,啟動程式碼必須註冊對話 (如下面醒目提示的程式碼行瑣事) 以及其他服務。To allow the use of the adaptive dialog, the start up code must register the dialog as shown in the lines highlighted below, along with the other services.

建立 bot 時,就會建立根自調適型對話方塊。The root adaptive dialog is created when the bot is created.

執行對話Run the dialog

Bots/Dialogs.csBots/Dialogs.cs

DialogManager.OnTurnAsync 會執行具有活動的調適型對話。The DialogManager.OnTurnAsync runs the adaptive dialog with activities. 所顯示的實作可執行任何類型的 DialogThe implementation shown can run any type of Dialog. ConversationState 是由對話系統使用。The ConversationState is used by the Dialog system. UserState 並不是,不過其可能使用於對話實作中。The UserState isn't, however, it might have been used in a dialog implementation. DialogManager.OnTurnAsync 方法會負責儲存狀態。The DialogManager.OnTurnAsync method takes care of saving the state.

public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
{
    Logger.LogInformation("Running dialog with Activity.");
    await DialogManager.OnTurnAsync(turnContext, cancellationToken: cancellationToken).ConfigureAwait(false);
}

注意

記憶體儲存體僅供測試用途,而不適用於生產環境。Memory storage is used for testing purposes only and is not intended for production use. 針對生產 Bot,請務必使用永續性的儲存體類型。Be sure to use a persistent type of storage for a production bot.

測試 BotTo test the bot

  1. 如果您尚未安裝 Bot Framework Emulator,請進行安裝。If you have not done so already, install the Bot Framework Emulator.
  2. 在您的電腦本機執行範例。Run the sample locally on your machine.
  3. 啟動模擬器、連線到您的 Bot 並傳送如下所示的訊息。Start the Emulator, connect to your bot, and send messages as shown below.

多回合提示對話的執行範例

後續步驟Next steps