Reputation: 75
I have 3 Independent waterfall models which are triggered by intents using Luis. I want to link these 3 models sequentially, I have been following the PictureBot coding style, and each dialog/waterfall has it's on state properties.
The 3 Waterfall Methods are as follows,
As of now, I have been passing the values through the chat-window, as the 3 Waterfall steps are loosely coupled, they can be called by the user as an independent component/feature of the bot, so my questions are
How do link the 3 Models, ie in If the user has triggered waterfall_1, and goes to 2 or 3, the dialog where the "Users" are asked is to be skipped? I am thinking that I would need both a Global and Local Getters and Setters for each Waterfall.
In the WaterFall_1, the last response sends the Query Result from Azure Search, ie the "Names", Should I endDialog right after or does the WaterFall_1 call the WaterFall_2 and/if WaterFall_3 and then I endDialog for 3,2,1?
The figure might give more context Simple figure
Upvotes: 3
Views: 860
Reputation: 2227
You have the general idea down, in your question 1. What you would need is a 'shared' or global state not unlike the state demonstrated in the Bot Framework's CafeBot (Look under samples => dotnet => #50).
If you have a 'global' state set, you could save the list of user names retrieved in your Waterfall 1 to that. Then, when your second or third waterfall are called via your LUIS intents, you pass in the state accessor to the Waterfall 1 results to the parent class of Waterfall 2, thus making them accessible to the other waterfalls.
You would not need to make them sequential, if you're relying on LUIS. You could use LUIS to have 'Search Users' trigger WF1, 'Do XYZ to Users' trigger 2, and 'Do ABC to Users' trigger 3. This would make your bot less rigid for your bot users, as they could do a search, then do either 2 OR 3, (or both) as needed.
I was able to simulate this by simply adding an extra, waterfall based class to the Bot Framework MessageRoutingBot (samples => dotnet => #09)
Here is the waterfall setup for the 'Favorite Animal' prompt, including accessing the greetingState from the original sample bot:
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));
}
With the greetingState accessor pulled in, it allowed me to continue to call my user by name, from a second waterfall, without needing to reprompt for it:
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();
}
Hope this helps!
Upvotes: 2