Botframework-sdk: [Facebook Messenger] Emoji Response from Prompts.choice() not working with FB Messenger channel

Created on 3 Jan 2017  ยท  9Comments  ยท  Source: microsoft/botframework-sdk

Hi,

I'm sending these choices to the user as prompts: 'Low ๐Ÿ˜Š', 'Moderate ๐Ÿ˜', 'High ๐Ÿ˜ฃ'

And on Facebook I'm getting the response: I didn't understand. Please choose an option from the list.

It works fine in the emulator. Any ideas?

I'm logging the output of bot.use({receive to an external logging service and the response of event.text is Low ๏ฟฝ

bug investigate

Most helpful comment

Hi people, I played around a bunch to get a workaround.

The problem: Basically, the emoji comes back wrong, as mentioned by @gilesbutler gilesbutler, and is counted two characters. Then the answer is only accepted if the best match is above the default threshold of 0.6 [correct characters divided by total]. Not to mention spaces are alway counted as incorrect.

Before getting into the workaround, I think all that needs to be done on the BotBuilder side is to set the payloads to be the index corresponding to that quick reply because I think it is the payload that gets evaluated when identifying the response. The payloads are already being set to something ("value") here on line 689, but I can't seem to figure out where action.value is set. Any help on this would be appreciated, such as by @Stevenic. Maybe we can just change line 689 to parseInt(ind+1) and add an ind variable in the foreach of buttons. I haven't gotten a local build going so I haven't tried it myself.

Workaround: You can reconstruct Prompts.choice using Prompts.text and your validation loop (not necessary). You can also change the threshold for matching this way. Caveat - the buttons don't appear in the emulator, but you can just enter 1,2,3 or the correct text to test it there. Also, I pass variables to the validation loop dialog using session.userData, but there's probably a better way.

```// in the dialog where you want this to happen
session.quick_reply("your question", ['Low ๐Ÿ˜Š', 'Moderate ๐Ÿ˜', 'High ๐Ÿ˜ฃ']);

```// somewhere outside the dialogs
// start validation loop
Object.defineProperty(builder.Session.prototype, 'quick_reply', {
    enumerable: false,
    value: function(text, options) {
        this.userData.context.options = options;
        this.userData.context.text = text;
        this.beginDialog('/check-for-response');
    }
});

// send quick replies
Object.defineProperty(builder.Session.prototype, 'quick_replies', {
    enumerable: false,
  value: function(text, options) {
        var qrs = options.map(function(option, ind) {
            return {
                "content_type": "text",
                "title": option,
                "payload": parseInt(ind+1)
            };
        });
        var msg = new builder.Message(this)
      .text(text)
      .sourceEvent({
        facebook: {
          "quick_replies": qrs
        }
      });
        builder.Prompts.text(this, msg);
    }
});

// validation loop to check quick reply responses
bot.dialog('/check-for-response',
  new builder.SimpleDialog(function(session, results) {
        if (results && results.response) {
            var rsp = results.response;
            //console.log(rsp);
            var options = session.userData.context.options;
            var threshold = .6;
            var match = builder.EntityRecognizer.findBestMatch(options,
                rsp, threshold);
            if (match) {
                var num = match.index;
                var score = match.score;
            } else if(!isNaN(rsp) && rsp > 0 && rsp <= options.length) {
                var num = Number(rsp);
                var score = 1.0;
            }
            if(num) {
                var res = {response:{
                    'entity': rsp,
                    'index': (num-1),
                    'score': score
                }};
          session.endDialogWithResult(res);
            }   else {
                session.quick_replies(
                    "I didn't understand. Please choose an option from the list.",
                    options);
            }
        } else {
            session.quick_replies(session.userData.context.text,
                session.userData.context.options);
        }
  })
);

All 9 comments

I've just tested this by trying to use just an emoji as the buttons value (๐Ÿ˜Š) and it doesn't work when it's just an emoji but does if it's just text. I've seen other frameworks that support the user sending emojis through. The strange thing is that some buttons with emojis work, in my previous example Moderate ๐Ÿ˜ works.

I double that! I just couldnt get this to work on messenger, i however managed to work it out on the bot framework emulator, any suggestions on what you did around it @gilesbutler

@slidenerd removed the emojis ๐Ÿ˜ฉ๐Ÿ˜”๐Ÿ™๐Ÿ‘Ž

Hi people, I played around a bunch to get a workaround.

The problem: Basically, the emoji comes back wrong, as mentioned by @gilesbutler gilesbutler, and is counted two characters. Then the answer is only accepted if the best match is above the default threshold of 0.6 [correct characters divided by total]. Not to mention spaces are alway counted as incorrect.

Before getting into the workaround, I think all that needs to be done on the BotBuilder side is to set the payloads to be the index corresponding to that quick reply because I think it is the payload that gets evaluated when identifying the response. The payloads are already being set to something ("value") here on line 689, but I can't seem to figure out where action.value is set. Any help on this would be appreciated, such as by @Stevenic. Maybe we can just change line 689 to parseInt(ind+1) and add an ind variable in the foreach of buttons. I haven't gotten a local build going so I haven't tried it myself.

Workaround: You can reconstruct Prompts.choice using Prompts.text and your validation loop (not necessary). You can also change the threshold for matching this way. Caveat - the buttons don't appear in the emulator, but you can just enter 1,2,3 or the correct text to test it there. Also, I pass variables to the validation loop dialog using session.userData, but there's probably a better way.

```// in the dialog where you want this to happen
session.quick_reply("your question", ['Low ๐Ÿ˜Š', 'Moderate ๐Ÿ˜', 'High ๐Ÿ˜ฃ']);

```// somewhere outside the dialogs
// start validation loop
Object.defineProperty(builder.Session.prototype, 'quick_reply', {
    enumerable: false,
    value: function(text, options) {
        this.userData.context.options = options;
        this.userData.context.text = text;
        this.beginDialog('/check-for-response');
    }
});

// send quick replies
Object.defineProperty(builder.Session.prototype, 'quick_replies', {
    enumerable: false,
  value: function(text, options) {
        var qrs = options.map(function(option, ind) {
            return {
                "content_type": "text",
                "title": option,
                "payload": parseInt(ind+1)
            };
        });
        var msg = new builder.Message(this)
      .text(text)
      .sourceEvent({
        facebook: {
          "quick_replies": qrs
        }
      });
        builder.Prompts.text(this, msg);
    }
});

// validation loop to check quick reply responses
bot.dialog('/check-for-response',
  new builder.SimpleDialog(function(session, results) {
        if (results && results.response) {
            var rsp = results.response;
            //console.log(rsp);
            var options = session.userData.context.options;
            var threshold = .6;
            var match = builder.EntityRecognizer.findBestMatch(options,
                rsp, threshold);
            if (match) {
                var num = match.index;
                var score = match.score;
            } else if(!isNaN(rsp) && rsp > 0 && rsp <= options.length) {
                var num = Number(rsp);
                var score = 1.0;
            }
            if(num) {
                var res = {response:{
                    'entity': rsp,
                    'index': (num-1),
                    'score': score
                }};
          session.endDialogWithResult(res);
            }   else {
                session.quick_replies(
                    "I didn't understand. Please choose an option from the list.",
                    options);
            }
        } else {
            session.quick_replies(session.userData.context.text,
                session.userData.context.options);
        }
  })
);

Thanks for the workaround @bmperrea - it would definitely be nicer to get a proper fix for this though, interested to hear what the MS guys think

agreed. It would be nice to

  1. get the emojis to come back intact (somewhere along the line there must be a problem with Unicode support?)

  2. be able to make use of payloads when routing to facebook so that the correct answer is always found when a quick-reply is clicked.

  3. fix the EntityRecognizer not to penalize spaces.

  4. add the option to set the threshold for built-in prompts.

Hey guys... Sorry for the delay on this. I agree that we should probably do a better job with this. Let me investigate this some.

This is a very early iteration as to how I'm getting around the issue:

The correct response with emoji appears on the context.message.sourceEvent message, so a cheeky little override, swapping in this message text if it exists, is doing the trick.

My buttons are emoji only, so the previous workaround is sadly of no use.

var builder = require('botbuilder');
var origPromptRecognize = builder.Prompts.prototype.recognize;
builder.Prompts.prototype.recognize = function (context, cb) {
  if (context.message && context.message.sourceEvent && context.message.sourceEvent.message && context.message.sourceEvent.message.text) {
    context.message.text = context.message.sourceEvent.message.text
  }
  origPromptRecognize.call(this, context, cb)
};

Thank you for opening an issue against the Bot Framework SDK v3. As part of the Bot Framework v4 release, weโ€™ve moved all v3 work to a new repo located at https://github.com/microsoft/botbuilder-v3. We will continue to support and offer maintenance updates to v3 via this new repo.

From now on, https://github.com/microsoft/botbuilder repo will be used as hub, with pointers to all the different SDK languages, tools and samples repos.

As part of this restructuring, we are closing all tickets in this repo.

For defects or feature requests, please create a new issue in the new Bot Framework v3 repo found here:
https://github.com/microsoft/botbuilder-v3/issues

For Azure Bot Service Channel specific defects or feature requests (e.g. Facebook, Twilio, Teams, Slack, etc.), please create a new issue in the new Bot Framework Channel repo found here:
https://github.com/microsoft/botbuilder-channels/issues

For product behavior, how-to, or general understanding questions, please use Stackoverflow.
https://stackoverflow.com/search?q=bot+framework

Thank you.

The Bot Framework Team

Was this page helpful?
0 / 5 - 0 ratings