如何识别回复是用户输入还是建议操作点击 - Bot Framework

How do identify if the reply is user input or suggest action click - Bot Framework

我们使用 BotFramework V4 和 C# (.Net Core) 在我们的组织中构建了一个供内部使用的 QnA 机器人。 我们还想使用 Bing 拼写检查来修复问题中的拼写错误。

但是"correction"在一些多轮对话中造成麻烦:Bing拼写检查可能会取代缩写和特殊术语,然后QnA服务可能无法捕捉到正确的问题和答案。

我们以教程中的例子为例,使用CardAction提示相关问题:

foreach (var prompt in result.Context.Prompts) {
    buttonList.Add(
        new CardAction()
        {
            Value = prompt.DisplayText,
            Type = ActionTypes.ImBack,
            Title = prompt.DisplayText,
        });
}

以下示例(法语)在 Microsoft Teams 上使用机器人时:

我的问题是: 我如何确定消息是否来自用户点击建议按钮(例如,获取对象 CardAction 及其 属性 Type)? 我查看了 OnMessageActivityAsync 方法中提供的 turnContext 参数。但没有找到。

我想对直接用户输入应用 Bing 拼写检查,但不对建议操作应用拼写检查。

谢谢。 (p.s.) 我发现了一个与 botframework v3 类似的问题,但没有接受答案,我正在使用 v4。

在像 Teams 这样的频道中,有一个特定的 imBack 操作类型不同于 postBackmessageBack,通常无法区分传入的 imBack键入消息的操作。

要获得您想要的行为,您应该使用 postBackmessageBack。他们在 Teams 中的工作方式相同,但 messageBack 会更好地传达您的意图。这个想法是,您将在从用户到机器人的同一消息中发送可见文本和不可见元数据。

foreach (var prompt in result.Context.Prompts) {
    buttonList.Add(
        new CardAction()
        {
            Type = ActionTypes.MessageBack,
            Value = new { source = "button" },
            Title = prompt.DisplayText,
            Text = prompt.DisplayText,
            DisplayText = prompt.DisplayText,
        });
}

为什么我们在这里使用了三次 prompt.DisplayText?标题显示为按钮上的标签,文本填充 activity 的 Text 属性,显示文本是对话中呈现的内容。

在 Teams 中,postBackmessageBackValue 属性 必须是 object 而不是字符串。如果你试图说 Value = "button" 那么你会在传入的 activity 中得到一个空的 object。由于操作的 Value 属性 填充 activity 的 Value 属性,您可以判断传入的 activity 是否来自按钮像这样:

if (turnContext.Activity.Value != null
    && JToken.FromObject(turnContext.Activity.Value) is JObject value
    && value["source"] == "button")

由于我的测试到目前为止表明键入的消息永远不会填充 Value 属性,您可以将检查简化为:

if (turnContext.Activity.Value != null)

请注意,此答案仅适用于 Teams。有不同的规则来确定 activity 是否来自不同频道上的按钮,这些规则目前没有在任何地方记录。如果您有兴趣,I have written a method for my cards library that accomplishes the task of determining if an activity came from a button on any channel。库发布后,您可以调用该方法并查看它是否 returns null.