管理对话复杂性

适用于:SDK v4

可以通过组件对话创建独立的对话来处理特定的方案,将大型对话集分解成更易于管理的片段。 其中的每个片段有自身的对话集,可避免与其外的对话集发生名称冲突。 组件对话可重复使用,因为它们可以:

  • 添加到机器人中的其他 ComponentDialogDialogSet
  • 作为包的一部分导出。
  • 在其他机器人中使用。

注意

Bot Framework JavaScript、C# 和 Python SDK 将继续受支持,但 Java SDK 即将停用,最终长期支持将于 2023 年 11 月结束。

使用 Java SDK 构建的现有机器人将继续正常运行。

要生成新的机器人,请考虑使用 Microsoft Copilot Studio 并阅读选择正确的助理解决方案

有关详细信息,请参阅机器人构建的未来

先决条件

关于本示例

在多轮次提示示例中,我们将使用一个瀑布对话、几个提示和一个组件对话来创建交互,向用户提出一系列问题。 代码使用对话来循环执行以下步骤:

步骤 提示类型
请求用户提供其交通方式 选项提示
请求用户输入其姓名 文本提示
询问用户是否愿意提供其年龄 确认提示
如果他们回答“是”,则请求他们提供年龄 附带验证的数字提示仅接受大于 0 且小于 150 的年龄。
询问收集的信息是否“正确” 重用确认提示

最后,如果用户回答“是”,则显示收集的信息;否则,告知用户他们的信息不会保留。

实现组件对话

在多轮次提示示例中,我们将使用一个瀑布对话、几个提示和一个组件对话来创建交互,向用户提出一系列问题。

组件对话可封装一个或多个对话。 组件对话有一个内部对话集,而添加到此内部对话集的对话和提示有其自己的 ID,这些 ID 只能在组件对话内部查看。

若要使用对话,请安装 Microsoft.Bot.Builder.Dialogs NuGet 包。

Dialogs\UserProfileDialog.cs

在这里,UserProfileDialog 类派生自 ComponentDialog 类。

public class UserProfileDialog : ComponentDialog

在构造函数中,AddDialog 方法会将对话和提示添加到组件对话。 使用此方法添加的第一项设置为初始对话。 可以通过显式设置 InitialDialogId 属性来更改初始对话。 启动组件对话框时,它会启动其 initial dialog

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

以下代码表示瀑布对话的第一步。

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

若要详细了解如何实现瀑布对话,请参阅如何实现顺序聊天流

在运行时,组件对话保留其自己的对话堆栈。 启动组件对话时:

  • 会创建一个实例并将其添加到外部对话堆栈
  • 它会创建一个内部对话堆栈并将其添加到状态中
  • 它会启动初始对话并将其添加到内部对话堆栈。

父上下文将组件视为活动对话。 但是,在组件内部,看起来初始对话是活动对话。

从机器人调用对话

在外部对话集(需向其添加组件对话)中,组件对话有一个用于创建对话的 ID。 在外部集中,组件看起来像单个对话,与提示特别相似。

若要使用组件对话,请将其实例添加到机器人的对话集。

Bots\DialogBot.cs

在该示例中,这是使用从机器人的 OnMessageActivityAsync 方法调用的 RunAsync 方法完成的。

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

测试机器人

  1. 安装 Bot Framework Emulator(如果尚未安装)。
  2. 在计算机本地运行示例。
  3. 按如下所示启动 Emulator,连接到机器人,然后发送消息。

多回合提示对话中的示例脚本。

其他信息

如何针对组件对话执行取消操作

如果从组件对话的上下文调用“取消所有对话”,组件对话会取消其内部堆栈上的所有对话,然后结束,将控制返回给外部堆栈上的下一对话。

如果从外部上下文调用“取消所有对话”,则会取消该组件以及外部上下文中的其余对话。

后续步骤

了解如何创建可创建分支和可循环的复杂聊天。