【问题标题】:Bot Framework: Tagging messagesBot Framework:标记消息
【发布时间】:2017-07-20 06:57:12
【问题描述】:

因此,当机器人通过 Bot Connecter 发送消息时,它会将其作为 JSON 对象发送,类似于:

{
  "type": "message",
  "timestamp": "2017-07-20T06:35:09.196Z",
  "serviceUrl": "http://127.0.0.1:53484",
  "channelId": "emulator",
  "from": {
  "id": "ijfi3f969c6fij756",
  "name": "Bot"
},
"conversation": {
"id": "g671h707amhch9326"
},
"recipient": {
"id": "default-user"
},
"membersAdded": [],
"membersRemoved": [],
"text": "Hey there!",
"attachments": [],
"entities": [],
"replyToId": "efincfmnc40la0g7c",
"id": "hi959g2a8ji1fn86",
"localTimestamp": "2017-07-20T08:35:09+02:00"
}

我们想添加一些额外的标签,以携带更多关于正在发送的消息的数据。例如,我们可能想要添加一个标签,表明我们希望用户回复一个电子邮件地址。也许是这样的:

{
"type": "message",
"expecting": "email"
“时间戳”:“2017-07-20T06:35:09.196Z”, "serviceUrl": "http://127.0.0.1:53484", "channelId": "模拟器", “来自”:{
“id”:“ijfi3f969c6fij756”, “名称”:“机器人” },

我们的想法是,我们想使用我们的自定义标签来运行额外的代码。例如,我们可能想做的事情是:

if(reply.Expecting.Equals("email")
{
  //Do something awesome here.
}

但是,我们无法找到有关如何自定义这些 JSON 消息的任何信息。是否可以?如果是这样,我们将如何处理?

【问题讨论】:

  • 如果你想获取用户输入,你应该看看 PromptDialog
  • 在 Amio.io 中,我们使用 metadata 来完成该任务。 (我来自 Amio.io。抱歉,我忍不住要分享我们的处理方式。;-) docs.amio.io/v1.0/…

标签: json tags bots botframework


【解决方案1】:

您可以使用中间件完成此操作。这是C# 文档和NodeJS 文档。

基本上,您在 bot 对象之外设置中间件:

bot.use({
    botbuilder: (sess, next) => {
        inbound(sess, next);
    }
    ,send: (evt, next) => {
        outbound(evt, next);
    }
});

...botbuilder 捕获用户发送的内容,send 捕获机器人发送的内容。

然后你可以定义处理消息的函数,如果你认为合适的话可以修改它们:

function inbound(sess: builder.Session, next: Function): void {
     console.log(sess.message);
    next();
}

function outbound(evt: builder.IEvent, next: Function): void {
    console.log(evt);
    next();
}

我的建议是更改消息数据结构本身,而是使用中间件执行您的自定义行为,因为更改这些消息可能会产生副作用。您可以轻松地在中间件中捕获您需要的内容,然后将参数传递给 next() 函数以允许后续对话框处理预期。

此外,如果您所做的只是尝试捕获预期的用户输入,那么正则表达式与意图对话框或触发操作匹配的效果非常好。

【讨论】:

  • 我不确定使用中间件是否符合他们的用例,因为如果他们不想对所有人使用相同的添加,则需要许多代码来检查消息是什么消息
  • @Nicholas R 取决于他们试图做什么。如果他们所做的只是寻找特定的东西,比如电子邮件地址,那么你是对的,这就是为什么我在上一段中提到他们可以使用意图对话或触发带有正则表达式匹配的操作。但是,如果他们真的想更改消息(不推荐)或执行某种中间件行为或对象传递,那么他们可以使用中间件来完成。
  • 是的,如果这是为了改变全局事物,你是对的,但我添加评论是为了向 OP 指出他的例子并不容易
  • @Nicholas R 在 OP 的情况下,如果电子邮件可以随时发送(并且不是被提示的内容),我只会在电子邮件地址上使用带有正则表达式匹配的触发操作。如果他提示您发送电子邮件,那么根据您的评论,这只是一个文本提示。但是,由于他要求更改消息,所以我首先给出了中间件示例,但提到了他如何将结果传递给下一个函数而不是更改消息。
  • 是的。这就是为什么我只评论:太宽泛,无法给出明确的答案
【解决方案2】:

假设您使用的是 .net Framework。

下面是我能想到的一个选项。 为 Activity 引入自定义属性

在您的 CustomActivity 类上实现 Activity 类

 public class CustomActivity : Activity
    {
        [JsonProperty(PropertyName = "cutomprop")]
        public string MyCustomProp { get; set; } = "Custom Prop";
    }

然后在回复回复时考虑创建 CustomActivity 类型的 Activity 并将原始 Activity 的所有道具复制到它(为此目的使用工具 Automapper)

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

        ConnectorClient client = new ConnectorClient(new Uri(activity.ServiceUrl));

      var reply = new CustomActivity
        {

            ChannelData = activity.ChannelData,
            ChannelId = activity.ChannelId,
            ServiceUrl = activity.ServiceUrl,
            Name = activity.Name,
            Action = activity.Action,
            Type = activity.Type,
            Conversation = activity.Conversation,
            Code = activity.Code,
            From = activity.From,
            Value = activity.Value,
            Text = activity.Text,
            InputHint = activity.InputHint,
            Attachments = activity.Attachments,
            Entities = activity.Entities,
            ReplyToId = activity.ReplyToId,
            AttachmentLayout = activity.AttachmentLayout,
            HistoryDisclosed = activity.HistoryDisclosed,
            Id = activity.Id,
            LocalTimestamp = activity.LocalTimestamp,
            Locale = activity.Locale,
            MembersAdded = activity.MembersAdded,
            MembersRemoved = activity.MembersRemoved,
            Properties = activity.Properties,
            Recipient = activity.Recipient,
            RelatesTo = activity.RelatesTo,
            Speak = activity.Speak,
            SuggestedActions = activity.SuggestedActions,
            Summary = activity.Summary,
            TextFormat = activity.TextFormat,
            Timestamp = activity.Timestamp,
            TopicName = activity.TopicName

        };

        reply.Text = "I have colors in mind, but need your help to choose the best one.";
        reply.Type = ActivityTypes.Message;
        reply.TextFormat = TextFormatTypes.Plain;
       //set any other prop you want as per your needs
        await client.Conversations.SendToConversationAsync(reply);
        context.Wait(MessageReceivedAsync);
    }

下面是我得到的输出

{
  "cutomprop": "Custom Prop",
  "type": "message",
  "id": null,
  "timestamp": "2017-07-20T12:44:41.504Z",
  "localTimestamp": "2017-07-20T18:14:41+05:30",
  "serviceUrl": "http://127.0.0.1:56931",
  "channelId": "emulator",
  "from": {
    "id": "default-user",
    "name": "default-user"
  },
  "conversation": {
    "id": "h0j9hn8bicfm8e509"
  },
  "recipient": {
    "id": "mcfimjke5aebemhf",
    "name": "Bot"
  },
  "textFormat": "plain",

希望对您有所帮助...考虑为您的场景验证它并注意任何其他副作用。 **没有在所有频道上测试过,它可以在模拟器上运行

【讨论】:

  • 在您的情况下,您可以在机器人发送的消息中添加信息,但您不会在下一次回复时取回该属性,对吗?回复时频道不会复制/粘贴此块。在这里,OP 要求他在收到回复时能够检查的属性
  • @Nicolas 你是对的.. 我误解了上下文。认为它的 Bot ==> 用户交流。
猜你喜欢
  • 2019-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 2016-09-05
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多