0

I'm trying to handle Entity Resolution by using slot synonyms in an Alexa skill. I started my skill with the Amazon provided quiz game template, which contains a data array for city names, state abbreviations, and capitals. I modified it to use NFL team names. During a quiz interaction, as an example the user may be asked "What NFL football team plays in Philadelphia?". The user may answer "Eagles" or "Philadelphia Eagles", which both should be acceptable to get a correct score. The phrase "Philadelphia Eagles" is defined in the data array within my lambda function. In the interaction model, in my AnswerIntent I have a slot defined as TeamName. I tried adding values for both "Philadelphia Eagles" and "Eagles" in Synonyms. I'm using BIRDS as a Synonym ID, Eagles as a value and Philadelphia Eagles as a synonym value. But when I answer the question with "Eagles" I get a wrong answer.

How do I correct this?

Here is my AnswerIntent function in Lambda:

"AnswerIntent": function() {
    let response = "";
    let speechOutput = "";
    let item = this.attributes["quizitem"];
    let property = this.attributes["quizproperty"];

    let correct = compareSlots(this.event.request.intent.slots, item[property]);

    if (correct)
    {
        response = getSpeechCon(true);
        this.attributes["quizscore"]++;
    }
    else
    {
        response = getSpeechCon(false);
    }

    response += getAnswer(property, item);

    if (this.attributes["counter"] < 10)
    {
        response += getCurrentScore(this.attributes["quizscore"], this.attributes["counter"]);
        this.attributes["response"] = response;
        this.emitWithState("AskQuestion");
    }
    else
    {
        response += getFinalScore(this.attributes["quizscore"], this.attributes["counter"]);
        speechOutput = response + " " + EXIT_SKILL_MESSAGE;

        this.response.speak(speechOutput);
        this.emit(":responseReady");
    }
},

Here's the compareSlot function:

function compareSlots(slots, value)

for (let slot in slots)
{
    if (slots[slot].value != undefined)
    {
        if (slots[slot].value.toString().toLowerCase() == value.toString().toLowerCase())
        {
            return true;
        }
    }
}
return false;

Updated: compareSlots function has been modified to this:

    function compareSlots(slots, value)
{
    let slotId = slot.value; // fallback if you don't have resolutions
    let resolution = (slot.resolutions && slot.resolutions.resolutionsPerAuthority && slot.resolutions.resolutionsPerAuthority.length > 0) ? slot.resolutions.resolutionsPerAuthority[0] : null;

    if (resolution && resolution.status.code === 'ER_SUCCESS_MATCH') {

        if (resolution.values && resolution.values.length > 0) {
             slotId = resolution.values[0].value.id;
        }
    }

    if (slotId.toString().toLowerCase() == value.toString().toLowerCase()) {
        return true;
            }
}
Hackbrew
  • 349
  • 1
  • 10
  • 23

1 Answers1

0

If you want to use synonyms you have to use the entity resolutions. There you have one id for several synonyms which you can check.

Thus, your compareSlots function should look something like this:

[...]
let slotId = slot.value; // fallback if you don't have resolutions
let resolution = (slot.resolutions && slot.resolutions.resolutionsPerAuthority && slot.resolutions.resolutionsPerAuthority.length > 0) ? slot.resolutions.resolutionsPerAuthority[0] : null;

if (resolution && resolution.status.code === 'ER_SUCCESS_MATCH') {

    if (resolution.values && resolution.values.length > 0) {
         slotId = resolution.values[0].value.id;
    }
}

if (slotId.toString().toLowerCase() == value.toString().toLowerCase()) {
[...]
oxnkeen
  • 16
  • 2
  • I modified the compareSlots function accordingly, but when executed I get an error "Unexpected exeception 'ReferenceError: slot is not defined':. – Hackbrew Feb 15 '18 at 17:47
  • In your compareSlots function you use "slots" instead of a single "slot": – oxnkeen Feb 17 '18 at 07:53
  • You have two options: Either you already choose the right slot in your AnswerIntent and call the function with this slot. `function compareSlots(slot, value) {` Or you put your for-loop in the compareSlots function und use the slot: `function compareSlots(slots, value) { for (let slot of slots) { let slotId = slot.value; // fallback if you don't have resolutions [...]` Also a good read: [difference between ( for… in ) and ( for… of ) in javascript](https://stackoverflow.com/questions/29285897/what-is-the-difference-between-for-in-and-for-of-in-javascript) – oxnkeen Feb 17 '18 at 08:01