Skip to content

Commit

Permalink
Merge pull request #5 from MaxwellPayne/master
Browse files Browse the repository at this point in the history
Add support for custom slot types
  • Loading branch information
mreinstein committed May 17, 2016
2 parents e4dc22f + 8599208 commit 6170c89
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var result = utterances(template, slots, dictionary);

#### slots

The slots object is a simple Name:Type mapping. The type must be one of Amazon's supported slot types: LITERAL, NUMBER, DATE, TIME, DURATION
The slots object is a simple Name:Type mapping. The type must be one of Amazon's supported slot types: LITERAL, NUMBER, DATE, TIME, DURATION. You can use custom slot types, but you cannot integrate them with the slots object here and must instead do so with an [alternate syntax](#custom-slot-types).


#### Using a Dictionary
Expand Down Expand Up @@ -117,3 +117,16 @@ Number ranges can also increment in steps
"what is your color"
"what is your favorite color"
```

#### Custom Slot Types <a name="custom-slot-types"></a>

You may want to work with [Custom Slot Types](https://developer.amazon.com/appsandservices/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface#The Speech Input Data) registered in your interaction model. You can use a special syntax to leave a curly-braced slot name unparsed. For example, if you have defined in your skill a `FRUIT_TYPE` with the values `Apple`, `Orange` and `Lemon` for the slot `Fruit`, you can keep `Fruit` a curly-braced literal as follows

```javascript
"{my|your} {favorite|least favorite} snack is {-|Fruit}"
=>
"my favorite snack is {Fruit}"
"your favorite snack is {Fruit}"
"my least favorite snack is {Fruit}"
"your least favorite snack is {Fruit}"
```
21 changes: 19 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ function expandNumberRange(start, end, by) {
return converted;
}

// Determine if a curly brace expression is a Slot name literal
// Returns true if expression is of the form {-|Name}, false otherwise
function isSlotLiteral(braceExpression) {
return braceExpression.substring(0, 3) == "{-|";
}

// Recognize shortcuts in utterance definitions and swap them out with the actual values
function expandShortcuts(str, slots, dictionary) {
// If the string is found in the dictionary, just provide the matching values
Expand Down Expand Up @@ -90,6 +96,11 @@ function generateUtterances(str, slots, dictionary, exhaustiveUtterances) {
var placeholders=[], utterances=[], slotmap={}, slotValues=[];
// First extract sample placeholders values from the string
str = str.replace(/\{([^\}]+)\}/g, function(match,p1) {

if (isSlotLiteral(match)) {
return match;
}

var expandedValues=[], slot, values = p1.split("|");
// If the last of the values is a SLOT name, we need to keep the name in the utterances
if (values && values.length && values.length>1 && slots && typeof slots[values[values.length-1]]!="undefined") {
Expand Down Expand Up @@ -134,14 +145,20 @@ function generateUtterances(str, slots, dictionary, exhaustiveUtterances) {
});
// Replace slot placeholders
utterance = utterance.replace(/\{(.*?)\}/g,function(match,p1){
return "{"+values[slotmap[p1]]+"|"+p1+"}";
return (isSlotLiteral(match)) ? match : "{"+values[slotmap[p1]]+"|"+p1+"}";
});
utterances.push( utterance );
});
}
else {
return [str];
utterances = [str];
}

// Convert all {-|Name} to {Name} to accomodate slot literals
for (var idx in utterances) {
utterances[idx] = utterances[idx].replace(/\{\-\|/g, "{");
}

return utterances;
}

Expand Down
15 changes: 15 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,18 @@ test('exhaustive vs non-exhaustive expansion', function (t) {
]);
t.end();
});

test('raw curly braces for custom slot types', function (t) {
var dictionary = {};
var slots = {"Artist": "CUSTOM_TYPE"};
var template = "{my|your} {favorite|least favorite} fruit is {-|Fruit}";

var result = utterances(template, slots, dictionary);
t.deepEqual(result, [
"my favorite fruit is {Fruit}",
"your favorite fruit is {Fruit}",
"my least favorite fruit is {Fruit}",
"your least favorite fruit is {Fruit}"
]);
t.end();
});

0 comments on commit 6170c89

Please sign in to comment.