具有复杂对话流的顺序瀑布模型Bot框架C#v4

具有复杂对话流的顺序瀑布模型Bot框架C#v4,c#,botframework,C#,Botframework,我有3个独立的瀑布模型,它们是由使用Luis的意图触发的。 我想按顺序链接这3个模型,我一直遵循编码风格,每个对话框/瀑布都有它的状态属性 3种瀑布式方法如下: 瀑布1-查询Azure搜索,基于用户提供的过滤器,响应是一个名称列表 瀑布_2-将执行一些REST操作,使用瀑布_1中的名称 瀑布3-将再次执行一些REST操作,使用瀑布1中的名称 到目前为止,我一直在通过聊天窗口传递这些值,因为3个瀑布式步骤是松散耦合的,用户可以将它们作为机器人的独立组件/功能调用,所以我的问题是 如何链接3个模

我有3个独立的瀑布模型,它们是由使用Luis的意图触发的。 我想按顺序链接这3个模型,我一直遵循编码风格,每个对话框/瀑布都有它的状态属性

3种瀑布式方法如下:

  • 瀑布1-查询Azure搜索,基于用户提供的过滤器,响应是一个名称列表
  • 瀑布_2-将执行一些REST操作,使用瀑布_1中的名称
  • 瀑布3-将再次执行一些REST操作,使用瀑布1中的名称
到目前为止,我一直在通过聊天窗口传递这些值,因为3个瀑布式步骤是松散耦合的,用户可以将它们作为机器人的独立组件/功能调用,所以我的问题是

  • 如何链接3个模型,即如果用户触发了瀑布_1,并转到2或3,则将跳过询问“用户”的对话框?我在想,对于每个瀑布,我都需要一个全球和本地的getter和setter

  • 在瀑布1中,最后一个响应从Azure Search发送查询结果,即“名称”,我应该在后面立即结束对话,还是瀑布1调用瀑布2和/如果瀑布3,然后我结束对话3,2,1


  • 图中可能会给出更多的上下文

    在问题1中,您已经记下了大致的想法。您需要的是一个“共享”或全局状态,与Bot框架中演示的状态没有什么不同(请参见samples=>dotnet=>50)

    如果您有一个“全局”状态集,您可以将瀑布1中检索到的用户名列表保存到该状态集。然后,当通过LUIS意图调用第二个或第三个瀑布时,将瀑布1结果的状态访问器传递给瀑布2的父类,从而使其他瀑布可以访问它们

    如果你依赖路易斯,你就不需要把它们按顺序排列。您可以使用LUIS让“搜索用户”触发WF1、“对用户执行XYZ”触发2和“对用户执行ABC”触发3。这将使你的机器人对你的机器人用户不那么严格,因为他们可以进行搜索,然后根据需要进行2或3次(或两者兼有)

    我可以通过简单地向Bot框架MessageRoutingBot(samples=>dotnet=>09)添加一个额外的、基于瀑布的类来模拟这一点

    下面是“Favorite Animal”提示的瀑布式设置,包括从原始示例机器人访问问候状态:

    public TestDialog(IStatePropertyAccessor<TestState> testStateAccessor, IStatePropertyAccessor<GreetingState> greetingStateAccessor, ILoggerFactory loggerFactory)
            : base(nameof(TestDialog))
        {
            TestStateAccessor = testStateAccessor ?? throw new ArgumentNullException(nameof(testStateAccessor));
            GreetingStateAccessor = greetingStateAccessor ?? throw new ArgumentNullException(nameof(greetingStateAccessor));
    
            // Add control flow dialogs
            var waterfallSteps = new WaterfallStep[]
            {
                    InitializeStateStepAsync,
                    PromptForAnimalStepAsync,
                    // PromptForCityStepAsync,
                    DisplayTestStateStepAsync,
            };
            AddDialog(new WaterfallDialog(ProfileDialog, waterfallSteps));
    
            // AddDialog(new TextPrompt(NamePrompt, ValidateName));
            AddDialog(new TextPrompt(AnimalPrompt));
        }
    
    公共测试对话框(IStatePropertyAccessor testStateAccessor、IStatePropertyAccessor greetingStateAccessor、ILoggerFactory)
    :base(name of(TestDialog))
    {
    TestStateAccessor=TestStateAccessor??抛出新的ArgumentNullException(nameof(TestStateAccessor));
    GreetingStateAccessor=GreetingStateAccessor??抛出新的ArgumentNullException(nameof(GreetingStateAccessor));
    //添加控制流对话框
    var waterwallsteps=新的waterwallstep[]
    {
    初始化TestePasync,
    PromptForAnimalStepAsync,
    //PromptForCitySepasync,
    DisplayTestStateStepAsync,
    };
    AddDialog(新建WaterWallDialog(ProfileDialog,WaterWallSteps));
    //AddDialog(新文本提示(namepropt,ValidateName));
    AddDialog(新文本提示(AnimalPrompt));
    }
    
    随着greetingState访问器的引入,它允许我从第二个瀑布中继续按名称调用我的用户,而无需重新编程:

     private async Task<DialogTurnResult> GreetUser(WaterfallStepContext stepContext)
        {
            var context = stepContext.Context;
            var testState = await TestStateAccessor.GetAsync(context);
            var greetingState = await GreetingStateAccessor.GetAsync(context);
    
            // Display their profile information and end dialog.
            await context.SendActivityAsync($"Hi {greetingState.Name}, who likes {testState.Animal}s, nice to meet you!");
            return await stepContext.EndDialogAsync();
        }
    
    专用异步任务GreetUser(WaterWallStepContext)
    {
    var context=stepContext.context;
    var testState=await TestStateAccessor.GetAsync(上下文);
    var greetingState=await GreetingStateAccessor.GetAsync(上下文);
    //显示其配置文件信息并结束对话框。
    wait context.SendActivityAsync($“你好{greetingState.Name},谁喜欢{testState.Animal},很高兴认识你!”);
    返回wait-stepContext.EndDialogAsync();
    }
    

    希望这有帮助

    我想你是在问如何保持从瀑布1到其他瀑布的状态?这就是你想要的吗?