【问题标题】:Start conversation with a PromptDialog in MS BotFramework在 MS BotFramework 中使用 PromptDialog 开始对话
【发布时间】:2019-01-11 03:38:14
【问题描述】:

bot 是否有合适的方式在 Direct Line 频道中与 PromptDialog.Choice 开始对话?

我正在尝试一个丑陋的 hack,抓住拳头 ConversationUpdate 活动并创建来自用户的假消息来初始化对话框,如下所示:

IMessageActivity greetingMessage = Activity.CreateMessageActivity();
greetingMessage.From = message.Recipient;//from bot
greetingMessage.Recipient = userAccount;//to user
greetingMessage.Conversation = message.Conversation;
greetingMessage.Text = "Hello, I am a bot";
greetingMessage.Locale = "en-us";
greetingMessage.Id = Guid.NewGuid().ToString();

await connector.Conversations.SendToConversationAsync((Activity)greetingMessage);

IMessageActivity dialogEntryMessage = Activity.CreateMessageActivity();
dialogEntryMessage.Recipient = message.Recipient;//to bot
dialogEntryMessage.From = message.From;//from user
dialogEntryMessage.Conversation = message.Conversation;
dialogEntryMessage.Text = "any text";
dialogEntryMessage.Locale = "en-us";
dialogEntryMessage.ChannelId = message.ChannelId;
dialogEntryMessage.ServiceUrl = message.ServiceUrl;
dialogEntryMessage.Id = Guid.NewGuid().ToString();
dialogEntryMessage.ReplyToId = greetingMessage.Id;

await Conversation.SendAsync(dialogEntryMessage, () => new Dialogs.RootDialog());

其中message 是来自ConversationUpdate 的消息。在 RootDialog 中,我以 PromptDialog.Choice 开头。

它在模拟器中工作,但在 Direct Line 频道中,机器人不记得对话状态,当用户选择其中一个对话选项并发送他的第一条真实消息时,根对话再次从 PromptDialog.Choice 开始,因此出现两次。

更新

我找到了来自微软的相关博文:https://blog.botframework.com/2018/07/12/how-to-properly-send-a-greeting-message-and-common-issues-from-customers/

【问题讨论】:

  • in Direct Line channel bot doesn't remember the dialog state and when user choose one of dialog options and send his first real message, root dialog starts again from the PromptDialog.Choice, so it appears twice. 您是否启用了 Direct Line 频道并在您的网站中嵌入了聊天机器人?还是构建了 Direct Line 客户端应用程序?
  • 嵌入到网页中。我正在使用具有一些 UI 自定义的 BotFramework WebChat 的分支github.com/Microsoft/BotFramework-WebChat

标签: c# botframework chatbot direct-line-botframework


【解决方案1】:

在 Direct Line 频道中,机器人不记得对话状态,当用户选择其中一个对话选项并发送他的第一条真实消息时,根对话会从 PromptDialog.Choice 再次启动,因此它会出现两次。

我可以在我这边重现同样的问题,我发现当机器人和用户都添加到对话中时,ConversationUpdate 处理程序将被执行。

要解决这个问题,您可以参考以下代码示例。

在 MessagesController 中:

else if (message.Type == ActivityTypes.ConversationUpdate)
{
    // Handle conversation state changes, like members being added and removed
    // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
    // Not available in all channels

    if (update.MembersAdded != null && update.MembersAdded.Any())
    {
        foreach (var newMember in update.MembersAdded)
        {
            if (newMember.Name == "{your_botid_here}")
            {
                IMessageActivity greetingMessage = Activity.CreateMessageActivity();

                //...
                //your code logic
                //...

                IMessageActivity dialogEntryMessage = Activity.CreateMessageActivity();
                dialogEntryMessage.Recipient = message.Recipient;//to bot
                dialogEntryMessage.From = message.From;//from user
                dialogEntryMessage.Conversation = message.Conversation;
                dialogEntryMessage.Text = "show choices";
                dialogEntryMessage.Locale = "en-us";
                dialogEntryMessage.ChannelId = message.ChannelId;
                dialogEntryMessage.ServiceUrl = message.ServiceUrl;
                dialogEntryMessage.Id = System.Guid.NewGuid().ToString();
                dialogEntryMessage.ReplyToId = greetingMessage.Id;

                await Conversation.SendAsync(dialogEntryMessage, () => new Dialogs.RootDialog());
            }
        }
    }
}

在 RootDialog 中:

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
    var activity = await result as Activity;

    var mes = activity.Text.ToLower();

    string[] choices = new string[] { "choice 1", "choice 2" };

    if (Array.IndexOf(choices, mes) > -1)
    {
        await context.PostAsync($"You selected {mes}");
    }
    else if(mes == "show choices")
    {
        PromptDialog.Choice(context, resumeAfterPrompt, choices, "please choose an option.");
    }
    else
    {
        await context.PostAsync($"You sent {activity.Text} which was {length} characters.");
        context.Wait(MessageReceivedAsync);
    }

}

private async Task resumeAfterPrompt(IDialogContext context, IAwaitable<string> result)
{
    string choice = await result;

    await context.PostAsync($"You selected {choice}");
}

测试结果:

【讨论】:

  • 感谢您的回复。检查 MembersAdded 没有帮助,但我使用检查 RootDialog 中的消息文本的想法来确定行为。现在可以了。
猜你喜欢
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多