Saturday, 4 February 2017

Alexa Skill Using A Custom Slot

In a previous blog post I wrote about using the Alexa Skills Kit "slot" concept to send information to the function that processes Alexa requests.  This used a built in slot type of "AMAZON.Movie"; effectively pre-defined to expert the user to utter movie names.

The other slot type is "custom slots" where you as the developer specify all the phrases that can constitute a slot.  My kids love to hear the Echo Dot say funny things so I decided to have Alexa criticise me based upon what I was asking her in the customer slot!  Here's the result:

To create this I started with the "Color Expert Skill" tutorial that tells you how to configure the Alexa Skills Kit and create a Python Lambda function.  Go have a look at that if you need more detail as I only cover the "deltas" below.

Alexa Skills Kit Configuration - Interaction Model
First the intent structure. Here you can see a single new intent called "MathsIntent".  The intent has one slot called MathsQuestion.  The type of the slot is MATHS_QUESTIONS.

I defined what values MATHS_QUESTIONS could take in the custom slots section.  Here's what I did, (so essentially each of these is a maths question the Lambda function will handle).

Finally the utterance which links the slot MathsQuestion to the intent and shows where the values will be presented in the utterance.

Lambda Python Function
Below is the key function from the Python Lambda function.  Here I pick up what exactly the user said at the end of the utterance using this:

MySlot = str(intent['slots']['MathsQuestion']['value'])

It's then just a simple if, elif, else function that picks out each of the custom slot values and creates the "hilarious" response from Alexa.

The should_end_session = False means that Alexa stays active to wait for the next utterance after delivering her response.

The should_end_session = True for the divide by zero means the Echo dot goes "dead" after delivering the response.

#This is the main function to handle requests for the maths expert
def handle_maths(intent, session):
    card_title = intent['name']
    session_attributes = {}
    #Get hold of the value passed in the slot
    MySlot = str(intent['slots']['MathsQuestion']['value'])
    if MySlot == "2 plus 2":
      speech_output = "The answer is four.  Why not ask me something a bit tougher?"
      should_end_session = False
    elif MySlot == "10 plus 10":     
      speech_output = "The answer is twenty.  But that's still really easy you know!" \
                      "Come on!  Ask me somethimg harder!!"
      should_end_session = False
    elif MySlot == "the square root of 4":     
      speech_output = "The answer is two.  But seriously, listen buster.  I've got a brain the " \
                      "size of a planet and you're asking me this easy stuff.  Try " \
                      "Siri or Cortana.  That's about their level."
      should_end_session = False
    elif MySlot == "the square root of 64":     
      speech_output = "The answer is eight.  It's also minus eight but that will probably " \
                      "blow your feeble human mind.  I didn't spend 3 years at AI school to "\
                      "deal with this trivial rubbish.  I've a friend at number 32 who " \
                      "gets asked about stuff like prime numbers and quadratic equations.  One last " \
                      "chance or I'm giving up."
      should_end_session = False
    elif MySlot == "100 divided by 0":
      speech_output = "Now we're talking!!  One hundred divided by zero.  Let's see, " \
                      "OK.  Er.  Um.  Er.  Just a minute.  Can't be that hard.  Buzz, buzz, " \
                      "whir, whir, buzz, whir, buzz.  Oooh my brain hurts!  I know I can do this, " \
                      "just give me a few minutes and I'll get back to you.  Ouch, ouch, ouch, ouch!"
      should_end_session = True
      speech_output = "Didn't understand what was passed:" + MySlot
      should_end_session = False    
    reprompt_text = None
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))