If FormFlow is too restrictive, you should consider using Dialogs. They allow for a much more open conversation.
I would do the following:
1) Ask the user to choose a category.
If possible, give the user a list of categories to choose from, using buttons. This means you will not have to ask LUIS for the category selected by the user.
Otherwise, allow the user to type an category and pass it to LUIS. The response from LUIS will contain an Entity. The Entity will hold the name of the category.
2) Forward to Dialog for that Category
Depending on the Entity returned from LUIS, forward to the appropriate Dialog which will be responsible for asking the next question
[LuisIntent("AskQuestionAboutCategory")]
public async Task AskQuestion(IDialogContext context, LuisResult result)
{
string category = result.Entities.FirstOrDefault(e => e.Type == "Category")?.Entity;
switch (category)
{
case "Category 1":
await
context.Forward(new Category1Dialog(), ResumeAfter,
new Activity {Text = result.Query}, CancellationToken.None);
break;
case "Category 2":
await
context.Forward(new Category2Dialog(), ResumeAfter,
new Activity {Text = result.Query}, CancellationToken.None);
break;
}
}
private async Task ResumeAfter(IDialogContext context, IAwaitable<object> result)
{
context.Wait(MessageReceived);
}
3) Ask Questions inside Dialog
Inside the Dialog, use a PromptDialog to ask Question 1. Use a switch on the answer of Question 1, to determine what to ask for Question 2.
Continue the conversation like this.
[Serializable]
public class Category1Dialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var prompt = "what is the answer to question 1 ?";
PromptDialog.Text(context, ResumeAfterQuestion1, prompt);
}
private async Task ResumeAfterQuestion1(IDialogContext context, IAwaitable<string> result)
{
var input = await result;
switch (input)
{
case "Answer A":
PromptDialog.Text(context, ResumeAfterQuestion2, "what is the answer to question 2 ?");
break;
case "Answer B":
PromptDialog.Text(context, ResumeAfterQuestion2, "what is the answer to question 2 ?");
break;
}
}
private async Task ResumeAfterQuestion2(IDialogContext context, IAwaitable<string> result)
{
var input = await result;
switch (input)
{
case "Answer C":
PromptDialog.Text(context, ResumeAfterQuestion3, "what is the answer to next question after Answer C ?");
break;
case "Answer D":
PromptDialog.Text(context, ResumeAfterQuestion3, "what is the answer to next question after Answer D ?");
break;
}
}
It looks like you will need to use switch statements to determine what questions to ask next.
click here for more info on Dialogs