Handling Multi-Value Slots

Up to this point, the slots we’ve defined only accept a single value per slot: one destination, one departure date, and one return date. But sometimes you need to collect a list of values in a slot rather than a single slot value. For instance, if you were building a skill for ordering pizza, you might want the user to name several toppings to be used when making a pizza.

With a small tweak to a slot definition, we can specify that a slot is able to accept a list of values. To illustrate how this works, suppose that we want to add an intent to the Star Port 75 skill that lets a user state their favorite planets. Such an intent might be declared in the interaction model like this:

 {
 "name"​: ​"FavoritePlanetsIntent"​,
 "samples"​: [
 "my favorite planets are {planets}"​,
 "i like {planets}"​,
 "{planets} are my favorite"
  ],
 "slots"​: [
  {
 "name"​: ​"planets"​,
 "type"​: ​"PLANETS"​,
»"multipleValues"​: {
»"enabled"​: ​true
» }
  }
  ]
 },

For the most part, this intent isn’t much different than ScheduleTripIntent, just with a single slot. The “planets” slot, however, has a multipleValues property with an enabled subproperty set to true. This indicates that the slot value may be a list instead of a single item. In fact, the payload of the intent request will include a type property for each slot value that will be either “Simple” for single slot values or “List” for multi-value slot values. For example, for an utterance of “my favorite planets are Mars, Saturn, and Pluto,” the “planets” slot will look like this in the intent request:

 "planets"​: {
 "name"​: ​"planets"​,
 "confirmationStatus"​: ​"NONE"​,
 "source"​: ​"USER"​,
 "slotValue"​: {
»"type"​: ​"List"​,
 "values"​: [
  {
 "type"​: ​"Simple"​,
 "value"​: ​"mars"​,
 "resolutions"​: { ... }
  },
  {
 "type"​: ​"Simple"​,
 "value"​: ​"mercury"​,
 "resolutions"​: { ... }
  },
  {
 "type"​: ​"Simple"​,
 "value"​: ​"Neptune"​,
 "resolutions"​: { ... }
  }
  ]
  }
 },

Reading the values of a “List” slot requires a different approach than what we used to read the “destinations” slot from the ScheduleTripIntent. The Alexa.getSlot() and Alexa.getSlotValue() functions are remnants of an earlier version of the ASK SDK before multi-value slots were an option. But for multi-value slots, we’ll need to revisit the getResolvedSlotValue() function to use two new functions, Alexa.getSlotValueV2() and Alexa.getSimpleSlotValues(), as shown here:

 const​ getResolvedSlotValue = (requestEnvelope, slotName) => {
 const​ slotValueV2 = Alexa.getSlotValueV2(requestEnvelope, slotName);
 
 const​ simpleSlotValue = Alexa.getSimpleSlotValues(slotValueV2);
 
 return​ simpleSlotValue.map(sv => {
 if​ (sv.resolutions) {
 const​ rpa = sv.resolutions.resolutionsPerAuthority[0];
 return​ rpa.status.code === ​'ER_SUCCESS_MATCH'​ ?
  rpa.values[0].value.name:
  sv.value;
  } ​else​ {
 return​ sv.value;
  }
  });
  }

Alexa.getSlotValueV2() fetches the given slot by name (“planets” in this case), and from that returns the embedded slotValue object. From that, you could examine the type property to determine how to process the rest of the slot. But the Alexa.getResolvedSlotValue() does that for you, returning an array of “Simple” slot values. What’s more, it works equally well for “Simple” slots as it does for “List” slots. In the case of “Simple” slots, it still returns an array, but an array of one value.

This new implementation of getResolvedSlotValue() takes the array of “Simple” slot value object and maps them to an array of string values where each value is either the resolved value name, if the status code is “ER_SUCCESS_MATCH”, or the value property if not. This means that if the user were to state that their favorite planets are Mars, Saturn, and Pluto, then getResolvedSlotValue() will return [’Mars’, ’Saturn’, and ’Pluto’].

Putting getResolvedSlotValue() to work, here’s how it can be used in an intent handler for FavoritePlanetsIntent:

 const​ Alexa = require(​'ask-sdk-core'​);
 const​ getResolvedSlotValue = require(​'./Helpers'​);
 
 const​ FavoritePlanetsIntentHandler = {
  canHandle(handlerInput) {
 return​ Alexa.getRequestType(
  handlerInput.requestEnvelope) === ​'IntentRequest'
  && Alexa.getIntentName(
  handlerInput.requestEnvelope) === ​'FavoritePlanetsIntent'​;
  },
  handle(handlerInput) {
»const​ planets =
» getResolvedSlotValue(handlerInput.requestEnvelope, ​'planets'​);
 
 const​ planetList =
  planets.length ===1 ?
  planets[0] :
  planets.slice(0, -1).join(​', '​) + ​' and '​ + planets.slice(-1);
 const​ speakOutput = ​`I like ​${planetList}​, too!`​;
 return​ handlerInput.responseBuilder
  .speak(speakOutput)
  .getResponse();
  }
 };
 
 module.exports=FavoritePlanetsIntentHandler;

This handler receives the array of planet names return from the call to getResolvedSlotValue() and simply echoes them in the spoken response (after separating them with commas and the word “and”).

After making these changes and deploying the skill, we can try this out with the ask dialog command:

 $ ​​ask​​ ​​dialog​​ ​​--locale​​ ​​en-US
 User > open star port seventy five
 Alexa > Welcome to Star Port 75 Travel. How can I help you?
 User > My favorite planets are Mars Saturn and Pluto
 Alexa > I like Mars, Saturn and Pluto, too!

As you can see, three planets are named in the utterance and those three planets are echoed in the response. But it doesn’t need to be three planets listed. Any number of planets can be named and will be included in the “List” slot and ultimately echoed to the user. For example, if the user is a big fan of several planets, they might list six planets:

 $ ​​ask​​ ​​dialog​​ ​​--locale​​ ​​en-US
 User > open star port seventy five
 Alexa > Welcome to Star Port 75 Travel. How can I help you?
 User > my favorite planets are Mercury Earth Mars Saturn Venus and Neptune
 Alexa > I like Mercury, Earth, Mars, Saturn, Venus and Neptune, too!

Even though more planets were listed, the intent request was handled equally well.

It’s worth noting that although we used getSlot() and getSlotValue() to retrieve the simple “destination” slot in the handler for ScheduleTripIntent, the getSlotValueV2() and getSimpleSlotValues() functions will work as well with single-value slots as it does for multi-value slots.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset