我有一個機器人,我正在做這樣的事情:嵌套對話框:消息被髮送兩次
1)一個新的活動(消息)到達。
2)我將消息發送到RootDialog。
3)取決於一些邏輯,RootDialog可以:
a) Call a LuisDialog (handling natural language)
b) Call a CustomDialog (handles some business logic).
但是,當用戶狀態爲復位,並且流程導致LuisDialog內部的意圖時,它調用意圖方法兩次。只是第一次這個州是空的,那麼它工作的很好。
讓我告訴你的代碼:
MessagesController:
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
try
{
await Conversation.SendAsync(activity,() => new RootDialog());
}
catch (HttpRequestException e)
{
...
}
}
RootDialog:
public class RootDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
await MessageReceivedAsync(context, Awaitable.FromItem(context.Activity.AsMessageActivity()));
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> awaitable)
{
bool value = DoSomeCustomLogic();
if (value)
{
string message = DoSomething();
await context.PostAsync(message);
} else {
bool value2 = DoSomeCustomLogic2();
if (value2)
{
var answerValidationDialog = new ValidateAnswerWithUserDialog();
context.Call(answerValidationDialog, ValidateAnswerWithUserDialogCompletedCallback);
} else {
var luisDialog = new LuisDialog();
await context.Forward(luisDialog,LuisDialogCompletedCallback, context.Activity, CancellationToken.None);
}
}
}
回調只做context.Done(真);
而LuisDialog有哪些是這樣一種意圖:
[LuisIntent(LuisUtils.INTENT_MENU_SALUTE)]
public async Task SaluteOrMenu(IDialogContext context, LuisResult result)
{
if (LuisUtils.IntentScoreIsHighEnough(result))
{
string userName = context.Activity.From.Name;
ContextHelper helper = new ContextHelper(MessageReceived);
await helper.AskUserToDoSomeInitialAction(context, saluteWord, userName);
context.Done(true);
}
else
{
await None(context, result);
}
}
最後類ContextHelper:
public class ContextHelper
{
private Func<IDialogContext, IAwaitable<IMessageActivity>, Task> MessageReceived;
public ContextHelper(Func<IDialogContext, IAwaitable<IMessageActivity>, Task> messageReceived)
{
MessageReceived = messageReceived;
}
public async Task AskUserToDoSomeInitialAction(IDialogContext context, string saluteWord, string userName)
{
var reply = context.MakeMessage();
List<CardAction> buttons = BuildInitialOptionActions();
List<CardImage> images = BuildInitialOptionImages();
string initialText = $"Hi stranger!"
var card = new HeroCard
{
Title = "Hello!"
Text = initialText,
Buttons = buttons,
Images = images
};
reply.Attachments = new List<Attachment> { card.ToAttachment() };
await context.PostAsync(reply);
context.Wait(AfterUserChoseOptionInSalute);
}
private async Task AfterUserChoseOptionInSalute(IDialogContext context, IAwaitable<IMessageActivity> result)
{
await ReDispatchMessageReceivedToDialog(context);
}
private async Task ReDispatchMessageReceivedToDialog(IDialogContext context)
{
await MessageReceived(context, Awaitable.FromItem(context.Activity.AsMessageActivity()));
}
}
的SaluteOrMenu意向被調用兩次(僅在第一次我與機器人交互或當我刪除狀態。調試後,我看到做context.Wait(AfterUserChoseOptionInSalute);
後,機器人調用該函數(ins tead等待一個事件來稱呼它)
任何想法?
在此先感謝。
你可以創建一個小樣本,其中這可以重現? –
0)正如我在帖子中所說的,當機器人狀態爲空(第一次用戶使用它或當我執行/刪除配置文件時)時會發生這種情況。 1)用戶類型「hi」。 2)我說的邏輯是評估的(在我的情況下,DoSomeLogic()調用QnA服務,並根據分數回答問題或不)。由於「嗨」不是一個有效的問題,它將msg轉發給LuisDialog。 3)致敬意向被調用並顯示一個小的英雄卡。它完成一個context.Wait(AfterUserChoseOptionInSalute); 4)本身,AfterUserChoseOption被調用,並重新分派活動(導致另一個調用)。 –
是的,我讀過這篇文章,但除非你想讓某人編寫完全相同的場景以嘗試重現該問題,否則將很難......轉發/調用對話框按預期工作;所以問題出現在你的代碼中。 –