Когда я запускаю приложение в первый раз, я выполняю некоторые шаги инициализации, такие как запрос имени и режима связи (в чате или разговоре), я использовал BeginDialogAsync, чтобы запустить соответствующее диалоговое окно с приглашением. Но после ответа на приглашение он возвращается к созданному мною MainDialog.cs, чтобы проверить ввод пользователя с помощью LUIS, вместо того, чтобы перейти к следующему шагу водопада.
CODE
OptionsDialog.cs
private void InitializeWaterfallDialog()
{
var waterfallSteps = new WaterfallStep[]
{
InitialStepAsync,
FinalStepAsync
};
AddDialog(new WaterfallDialog($"{nameof(OptionsDialog)}.mainFlow", waterfallSteps));
AddDialog(new ChoicePrompt($"{nameof(OptionsDialog)}.communicationMode"));
InitialDialogId = $"{nameof(OptionsDialog)}.mainFlow";
}
private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.PromptAsync($"{nameof(OptionsDialog)}.communicationMode",
new PromptOptions
{
Prompt = MessageFactory.Text("Please select how you want to continue interacting with me."),
Choices = ChoiceFactory.ToChoices(new List<string> { "Chat", "Speak" }),
}, cancellationToken);
}
private async Task<DialogTurnResult> FinalStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
var attachments = new List<Attachment>();
var reply = MessageFactory.Attachment(attachments);
switch (((FoundChoice)stepContext.Result).Value)
{
case "Chat":
reply.Text = "Type something to start";
break;
case "Speak":
reply.Text = "This option is yet to be configured. Continuing with chat option. Type something to start";
break;
}
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
return await stepContext.EndDialogAsync(null, cancellationToken);
}
}
MainDialog.cs
private void InitializeWaterfallDialog()
{
var waterfallSteps = new WaterfallStep[]
{
InitialStepAsync,
FinalStepAsync
};
AddDialog(new OptionsDialog($"{nameof(MainDialog)}.options", _botStateService));
AddDialog(new GreetingDialog($"{nameof(MainDialog)}.greeting", _botStateService));
AddDialog(new RevenueDialog($"{nameof(MainDialog)}.revenue", _botStateService, _botServices, _financialServices, _currencyService));
AddDialog(new QuarterlyRevenueDialog($"{nameof(MainDialog)}.quarterlyRevenue", _botStateService, _botServices, _financialServices, _currencyService));
AddDialog(new ProfitDialog($"{nameof(MainDialog)}.profit", _botStateService, _botServices, _financialServices, _currencyService));
AddDialog(new QuarterlyProfitDialog($"{nameof(MainDialog)}.quarterlyProfit", _botStateService, _botServices, _financialServices, _currencyService));
AddDialog(new StockPriceDialog($"{nameof(MainDialog)}.stockPrice", _botStateService, _botServices, _financialServices, _currencyService));
AddDialog(new PersonNameDialog($"{nameof(MainDialog)}.personName", _botStateService, _botServices));
AddDialog(new FarewellDialog($"{nameof(MainDialog)}.farewell", _botStateService, _botServices));
AddDialog(new WaterfallDialog($"{nameof(MainDialog)}.mainFlow", waterfallSteps));
InitialDialogId = $"{nameof(MainDialog)}.mainFlow";
}
private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
try
{
UserProfile userProfile = await _botStateService.UserProfileAccessor.GetAsync(stepContext.Context, () => new UserProfile());
var recognizerResult = await _botServices.Dispatch.RecognizeAsync(stepContext.Context, cancellationToken);
// Top intent tell us which cognitive service to use.
var topIntent = recognizerResult?.GetTopScoringIntent();
if(userProfile.HasRestartedConversation)
{
userProfile.HasRestartedConversation = false;
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.options", null, cancellationToken);
}
else
{
switch (topIntent?.intent)
{
case "GreetingIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.greeting", null, cancellationToken);
case "FindRevenueIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.revenue", null, cancellationToken);
case "FindQuarterlyRevenueIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.quarterlyRevenue", null, cancellationToken);
case "FindProfitIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.profit", null, cancellationToken);
case "FindQuarterlyProfitIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.quarterlyProfit", null, cancellationToken);
case "FindStockPriceIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.stockPrice", null, cancellationToken);
case "FindPersonNameIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.personName", null, cancellationToken);
case "FarewellIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.farewell", null, cancellationToken);
case "CommunicationSelectIntent":
return await stepContext.BeginDialogAsync($"{nameof(MainDialog)}.options", null, cancellationToken);
case null:
break;
default:
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Sorry, I don’t have an answer for that. " +
$"(Please try something like 'What is revenue of google?')"), cancellationToken);
break;
}
}
await _botStateService.UserProfileAccessor.SetAsync(stepContext.Context, userProfile);
}
catch (Exception e)
{
await stepContext.Context.SendActivityAsync(MessageFactory.Text($"Sorry, there was an error sending your message. Please try again."), cancellationToken);
}
return await stepContext.NextAsync(null, cancellationToken);
}
После ответа на приглашение в InitialStepAsync в OptionsDialog он должен перейти к следующему шагу водопада, FinalStepAsync, но он перейдет к MainDialog ипроверка ответа с помощью LUIS.
Код триггера активности в основной программе бота DialogBot.cs:
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
await base.OnTurnAsync(turnContext, cancellationToken);
// Save any state changes that might have occured during the turn.
await _botStateService.UserState.SaveChangesAsync(turnContext, false, cancellationToken);
await _botStateService.ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
}
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.Run(turnContext, _botStateService.DialogStateAccessor, cancellationToken);
}
Метод запуска:
public static async Task Run(this Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor<DialogState> accessor, CancellationToken cancellationToken = default(CancellationToken))
{
var dialogSet = new DialogSet(accessor);
dialogSet.Add(dialog);
var dialogContext = await dialogSet.CreateContextAsync(turnContext, cancellationToken);
var results = await dialogContext.ContinueDialogAsync(cancellationToken);
if (results.Status == DialogTurnStatus.Empty)
{
await dialogContext.BeginDialogAsync(dialog.Id, null, cancellationToken);
}
}
Проблема здесьзаключается в том, что после ответа на приглашение он собирается использовать BeginDialogAsync вместо ContinueDialogAsync, что происходит только при первом запуске бота. Если я вызову OptionsDialog в любое время, шаги водопада выполняются правильно.