JustToThePoint English Website Version
JustToThePoint en español
JustToThePoint in Thai

Programming Alexa's skills with Python

Introduction

Alexa is Amazon’s digital assistant. Digital assistants, such as Google Assistant, Amazon’s Alexa, or Siry, can perform some tasks or services based on voice commands or questions.

They are gaining more and more popularity these days with newer technologies being invented on a daily basis. They are becoming ubiquitous and can be found in your office, home, car, hotel, phone, and almost everywhere.

Skills are like apps for Alexa, and provide a new way of interaction with your users or customers. Skill let them use their voices and natural language to perform everyday tasks like listening to music or the news, playing a game, etc. “Voice user interfaces are natural, conversational, and user-centric,” Alexa’s developer documentation. Alexa is Amazon's digital assistant.

Alexa is Amazon's digital assistant.

Let’s create our first Alexa skill

When you create an Alexa-hosted skill, Amazon stores your code and resources on AWS for you and you can build, edit, and publish a skill without leaving the developer console.

Click “Build Model” at the top of the screen, then “Save Model”.- An intent defines an action that fulfills a user’s spoken request. Let’s add two intents by clicking on the Interaction Model and then on the Intent tab on the left side panel, “Add Intent”: jokeIntent and myNumberIntent. We need to add some sample utterances. These are phrases that our users need to say to invoke our intents. For our jokeIntent, some sample utterances could be “do you know any jokes?”, “tell me a math joke”, “I want to hear a joke”, “Tell me a joke”.

You should provide a bunch of sample utterances or phrases that you expect or hope your users will say. These utterances do not need to match exactly the user’s input as Alexa can figure out by his state-of-the-art deep learning model what the user wants from the skill very often.

Intents can optionally have arguments called slots. Slots are input values provided by our users. For example, let’s define these sample utterances for our myNumberIntent intent: tell me anything about {anumber}, do you know something about {anumber}, what do you know about {anumber}, etc. anumber is a slot. Its type is AMAZON.NUMBER.

After you define your intents with their sample utterances, you need to click Build Model, and once the build is successful, you have finished creating the UI part of your skill. Click the Test button from the top navigation bar and from the drop-down menu “Skill testing is enabled in:”, select Development (it is not enabled by default), and test your skill: “Alexa, open the justtothepoint bot” (you always need to start by opening your skill with its invocation name), then invoke some intents, e.g., say “hello” (one of Alexa’s predefined intents).

The interaction model of a skill is represented in a JSON format. It is accessible through the Interaction Model, JSON Editor option from the left side panel of Alexa’s developer console.

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "the justtothepoint bot",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "HelloWorldIntent",
                    "slots": [],
                    "samples": [
                        "hello",
                        "how are you",
                        "say hi world",
                        "say hi",
                        "hi",
                        "say hello world",
                        "say hello"
                    ]
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.FallbackIntent",
                    "samples": []
                },
                {
                    "name": "jokeIntent",
                    "slots": [],
                    "samples": [
                        "do you know any jokes",
                        "tell me a math joke",
                        "I want to hear a joke",
                        "tell me a joke"
                    ]
                },
                {
                    "name": "myNumberIntent",
                    "slots": [
                        {
                            "name": "anumber",
                            "type": "AMAZON.NUMBER"
                        }
                    ],
                    "samples": [
                        "tell me anything about {anumber}",
                        "tell me everything you know about {anumber} ",
                        "tell me everything about {anumber}",
                        "what do you know about {anumber}",
                        "do you know something about {anumber}",
                        "tell me something about {anumber}",
                        "bot tell me something about {anumber}"
                    ]
                }
            ],
            "types": []
        }
    }
}

Building the Skill Backend

Let’s add the necessary code so we can handle our intents. Click on the tab that says code at the top of your screen. The main file is lambday_function.py. This is the main entry point to the backend service for our skill. In other words, this is the backend code for our intents.

import logging
import ask_sdk_core.utils as ask_utils
import random, math
from datetime import date
import calendar

from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.handler_input import HandlerInput

from ask_sdk_model import Response

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

jokes = [
        "I saw my math teacher with a piece of graph paper yesterday. I think he must be plotting something.",
        "What did the triangle say to the circle? “You’re pointless.",
        "What’s a math teacher’s favorite kind of tree? Geometry.",
        "Why doesn’t anybody talk to circles? Because there’s no point.",
        "What are ten things you can always count on? Your fingers.",
        "There are three kinds of people in this world. Those who can count and those who can’t.",
        ]

def is_prime(x):  
    if x < 2:  
        return False  
    for n in range(2, x - 1):  
        if x % n == 0:  
            return False  
    return True

def divisors(n) :
    i = 1
    list = []
    while i <= n :
        if (n % i==0) :
            list.append(i)
        i = i + 1
        
    return " ".join([str(item) for item in list])

class LaunchRequestHandler(AbstractRequestHandler):
    """Handler for Skill Launch."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return ask_utils.is_request_type("LaunchRequest")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        my_date = date.today()
        
        speak_output = "I am justtothepoint, your friendly bot. Today is " + calendar.day_name[my_date.weekday()]

        return (
            handler_input.response_builder
                .speak(speak_output)
                .ask("What do you want to do today?")
                .response
        )

There are three main steps that you need to consider to be able to handle a user’s request.

class JokeIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
    # It takes in handler_input as a parameter that contains all the user's input request information. It tries to figure out what kind of request or intent the user has asked for. ask_utils.is_intent_name("jokeIntent") is a function that returns True if handler_input is appropriate for our intent and it will call JokeIntentHandler.handle. Otherwise, it returns False.
        return ask_utils.is_intent_name("jokeIntent")(handler_input)

    def handle(self, handler_input):
    # It returns an appropriate response by using the response_builder to set the output response (a random joke) to be delivered by Alexa to the user. Whatever we pass into speak(), is going to be spoken back to the user. The ask() method is only to be used when we are asking our users something.      
        speak_output = random.choice(jokes)

        return (
            handler_input.response_builder
                .speak(speak_output)
                .response
        )
class NumberHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return ask_utils.is_intent_name("myNumberIntent")(handler_input)

    def handle(self, handler_input):
        # _This is how to read slot values_
        myNumber = ask_utils.get_slot_value(handler_input=handler_input, slot_name="anumber")
        
        if myNumber:
            speak_output = "The factorial of " + format(myNumber)
            myNumber = int(myNumber)
            factorialNumber = math.factorial(myNumber)
            myDivisors = divisors(myNumber)
            speak_output += "is " + format(factorialNumber)
            if is_prime(myNumber):
                speak_output += ". It is a prime number."
            else:
                speak_output += ". It is not a prime number."
                
            speak_output += ". Its divisors are: " + myDivisors
                
        else:
            speak_output = "The number is not recongnized!"
            

        return (
            handler_input.response_builder
                .speak(speak_output)
                .response
        )

class HelloWorldIntentHandler(AbstractRequestHandler):
    """Handler for Hello World Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return ask_utils.is_intent_name("HelloWorldIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        speak_output = "Hi, I am justtothepoint, your friendly bot!"

        return (
            handler_input.response_builder
                .speak(speak_output)
                # .ask("add a reprompt if you want to keep the session open for the user to respond")
                .response
        )

class HelpIntentHandler(AbstractRequestHandler):
    """Handler for Help Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return ask_utils.is_intent_name("AMAZON.HelpIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        speak_output = "Hi, I am justtothepoint, your friendly bot! How can I help?"

        return (
            handler_input.response_builder
                .speak(speak_output)
                .ask(speak_output)
                .response
        )

class CancelOrStopIntentHandler(AbstractRequestHandler):
    """Single handler for Cancel and Stop Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return (ask_utils.is_intent_name("AMAZON.CancelIntent")(handler_input) or
                ask_utils.is_intent_name("AMAZON.StopIntent")(handler_input))

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        speak_output = "Goodbye!"

        return (
            handler_input.response_builder
                .speak(speak_output)
                .response
        )

class FallbackIntentHandler(AbstractRequestHandler):
    """Single handler for Fallback Intent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return ask_utils.is_intent_name("AMAZON.FallbackIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        logger.info("In FallbackIntentHandler")
        speech = "Hmm, I don't know what you are talking about. What would you like to do?"
        reprompt = "I didn't catch that. What can I help you with?"

        return handler_input.response_builder.speak(speech).ask(reprompt).response

[...]
# The SkillBuilder object acts as the entry point for your skill, routing all request and response payloads to the handlers above. Make sure any new handlers or interceptors you've defined are included below. The order matters - they're processed top to bottom.

sb = SkillBuilder()

sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(JokeIntentHandler())
sb.add_request_handler(NumberHandler())
sb.add_request_handler(HelloWorldIntentHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelOrStopIntentHandler())
sb.add_request_handler(FallbackIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_request_handler(IntentReflectorHandler()) # make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers

sb.add_exception_handler(CatchAllExceptionHandler())

lambda_handler = sb.lambda_handler()
Bitcoin donation

JustToThePoint Copyright © 2011 - 2024 Anawim. ALL RIGHTS RESERVED. Bilingual e-books, articles, and videos to help your child and your entire family succeed, develop a healthy lifestyle, and have a lot of fun.

This website uses cookies to improve your navigation experience.
By continuing, you are consenting to our use of cookies, in accordance with our Cookies Policy and Website Terms and Conditions of use.