Reputation: 3974
I have successfully got a simple "What's the weather" bot using Luis up and running on both Skype and Twilio and it's excellent.
I have now been tasked with setting up what I can only think of describing as a "conversation" bot.
I have looked at as many examples as I can find on the interweb but I am unsure how to approach developing it, and I don't know whether I should be using the FormBuilder for my scenario.
Here is a flow chart of part of what I am trying to do...
I have got my form working down to the part where it branches at "Bill Available"...
I cannot work out how to "change direction" based on the answer.
Upvotes: 3
Views: 416
Reputation: 3974
This, as suspected, turned out to be much easier that I thought..
Here is my solution...
This is my controller:
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
// check if activity is of type message
if (activity != null && activity.GetActivityType() == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new Dialogs.BillSharkDialog());
}
else
{
HandleSystemMessage(activity);
}
return new HttpResponseMessage(System.Net.HttpStatusCode.Accepted);
}
And here is the "Dialog" with just 2 steps...
[Serializable]
public class BillSharkDialog : IDialog<object>
{
Model.Customer customer = new Model.Customer();
public async Task StartAsync(IDialogContext context)
{
context.Wait(WelcomeMessageAsync);
}
public async Task WelcomeMessageAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
IMessageActivity message = await argument;
await context.PostAsync("We're excited to start helping you save! Let's start by getting your name?");
context.Wait(CaptureCustomerNameAsync);
}
public async Task CaptureCustomerNameAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
IMessageActivity message = await argument;
customer.customerName = message.Text;
await context.PostAsync($"Thanks {message.Text}. Now we need your email address?");
context.Wait(CaptureCustomerEmailAsync);
}
}
You can obviously change the route by checking the incoming message..
Here is an example:
public async Task DoesCustomerHaveBillAsync(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
IMessageActivity message = await argument;
switch (message.Text.ToLower())
{
case "yes":
await context.PostAsync($"Great. Go ahead and take a picture of the first couple of pages and attach them to this conversation.\n\n\nWhen you have finished, please send the message 'finished'.");
context.Wait(CustomerHasBillAsync);
break;
case "no":
await context.PostAsync($"That's OK. Do you happen to have the login information for your provider account?");
context.Wait(CustomerDoesntHaveBillAsync);
break;
default:
await context.PostAsync($"Sorry, I didn't undestand. Please reply with 'yes' or 'no'.");
context.Wait(DoesCustomerHaveBillAsync);
break;
}
}
Upvotes: 1
Reputation: 14787
You could consider using the SetNext method of a FormBuilder field to decide what should be coming next based on another field value.
You can take a look to the ContosoFlowers sample. In the Order form; something similar is being done.
public static IForm<Order> BuildOrderForm()
{
return new FormBuilder<Order>()
.Field(nameof(RecipientFirstName))
.Field(nameof(RecipientLastName))
.Field(nameof(RecipientPhoneNumber))
.Field(nameof(Note))
.Field(new FieldReflector<Order>(nameof(UseSavedSenderInfo))
.SetActive(state => state.AskToUseSavedSenderInfo)
.SetNext((value, state) =>
{
var selection = (UseSaveInfoResponse)value;
if (selection == UseSaveInfoResponse.Edit)
{
state.SenderEmail = null;
state.SenderPhoneNumber = null;
return new NextStep(new[] { nameof(SenderEmail) });
}
else
{
return new NextStep();
}
}))
.Field(new FieldReflector<Order>(nameof(SenderEmail))
.SetActive(state => !state.UseSavedSenderInfo.HasValue || state.UseSavedSenderInfo.Value == UseSaveInfoResponse.Edit)
.SetNext(
(value, state) => (state.UseSavedSenderInfo == UseSaveInfoResponse.Edit)
? new NextStep(new[] { nameof(SenderPhoneNumber) })
: new NextStep()))
.Field(nameof(SenderPhoneNumber), state => !state.UseSavedSenderInfo.HasValue || state.UseSavedSenderInfo.Value == UseSaveInfoResponse.Edit)
.Field(nameof(SaveSenderInfo), state => !state.UseSavedSenderInfo.HasValue || state.UseSavedSenderInfo.Value == UseSaveInfoResponse.Edit)
.Build();
}
}
}
Upvotes: 0