Skip to content

Client Alexa

Keith Sterling edited this page Feb 1, 2019 · 11 revisions

Alexa Client

There are many different ways to create Alexa skills, the 2 primary are to either use amazon lambdas or to create you own service and expose the interface as a restful service

As Programy has a long established history of using rest services to create clients the easiest option was to use this technique. In addition Programy has a large startup footprint that does not lend itself well to lambda function design. Each lambda instantiation could theoretically take several seconds as a new bring is loaded eAch time. It is therefore best to have the brain loaded and running separately from the skill which will call it.

Programy ships with a Python script which easily creates the necessary data structures for all of your intents along with the associated config data required by the client to handle calls from your skill.

One peculiarity of Alexa is that it does not support an intent that is a catch all for text entered and every intent must be atleast 2 words. Under Alexa you cannot have a single intent that processes all questions instead you have to have intents for all possible ways that you can start or respond to a question. This is the purpose of the intents.py script that ships with Programy

Generating Intents

Program-Y and Y-Bot ships with a number of helper scripts and files to ease the pain to setting up you Alexa Skill. The first is a tool which you can use to create all of the file data files required by your skill. It takes as its input a number of mandatory and optional files

  • intents.txt - A list of words that could potentially start a sentence
  • cancels.csv - A csv file of sample sentences to cancel your skill
  • stops.csv - A csv file of sample sentences to stop your skill
  • helps.csv - A csv file of sample sentences to get help about your skill

It will then produce 2 files for you to load into your skill

  • intents.json - A json file of all the intents to load using the JSON Editor
  • intents.maps - A mapping file loaded by the client which helps it map requests to intents

The script to execute this is in 'y-bot/clients/alexa' and is called 'intents.sh', and looks like this

python3 -m programy.clients.restful.flask.alexa.intents -in "servus ai" -ci -cif cancels.csv -si -sif stops.csv -hi -hif helps.csv -if intents.txt -ij intents.json -im intents.maps

If you get a parameter wrong or run it with just the -h flag you will see the following help

usage: intents.py [-h] -in INVOCATION_NAME [-ci] [-cif] SAMPLE_FILE [-hi] [-hif] SAMPLE_FILE [-si] [-sif] SAMPLE_FILE 
                  -if INTENTS_FILE -ij INTENTS_JSON -im INTENTS_MAPS

Program-Y Alexa Client Intent Generatorr

optional arguments:
  -h, --help            show this help message and exit
  -in INVOCATION_NAME, --invocation_name INVOCATION_NAME
                        Invocation Name
  -ci, --cancel_intent  Include Cancel Intent
  -cif, --cancel_intent_file SAMPLE_FILE Cancel Intent Samples File
  -si, --stop_intent    Include Stop Intent
  -sif, --stop_intent_file  SAMPLE_FILE   Stop Intent  Samples File
  -hi, --help_intent    Include Help Intent
  -hif, --help_intent_file SAMPLE_FILE    Help Intent  Samples File
  -if INTENTS_FILE, --intents_file INTENTS_FILE
                        Intents filename
  -ij INTENTS_JSON, --intents_json INTENTS_JSON
                        Intents JSON filename
  -im INTENTS_MAPS, --intents_maps INTENTS_MAPS
                        Intents Map filename

An example intents.txt file is as follows, which shows a small number of words ( or phrases ) which can start a sentence

who
what
where
why
when

An example stops.csv would look like

end servus ai
end conversation
stop servus ai
quit
stop

An example cancels.csv would look like

cancel question
cancel request
cancel servus ai

And an example helps.csv would like like

what can I ask
help

Running this through the script will produce the following intents.json file as follows

{
    "interactionModel": {
        "languageModel": {
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": [
                        "cancel question",
                        "cancel request",
                        "cancel servus ai"
                    ]
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": [
                        "end servus ai",
                        "end conversation",
                        "stop servus ai",
                        "quit",
                        "stop"
                    ]
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": [
                        "what can I ask",
                        "help"
                    ]
                },
                {
                    "name": "AskWho",
                    "samples": [
                        "who {text}"
                    ],
                    "slots": [
                        {
                            "name": "text",
                            "type": "AMAZON.SearchQuery"
                        }
                    ]
                },
                {
                    "name": "AskWhat",
                    "samples": [
                        "what {text}"
                    ],
                    "slots": [
                        {
                            "name": "text",
                            "type": "AMAZON.SearchQuery"
                        }
                    ]
                },
                {
                    "name": "AskWhere",
                    "samples": [
                        "where {text}"
                    ],
                    "slots": [
                        {
                            "name": "text",
                            "type": "AMAZON.SearchQuery"
                        }
                    ]
                },
                {
                    "name": "AskWhy",
                    "samples": [
                        "why {text}"
                    ],
                    "slots": [
                        {
                            "name": "text",
                            "type": "AMAZON.SearchQuery"
                        }
                    ]
                },
                {
                    "name": "AskWhen",
                    "samples": [
                        "when {text}"
                    ],
                    "slots": [
                        {
                            "name": "text",
                            "type": "AMAZON.SearchQuery"
                        }
                    ]
                }
         ],
            "invocationName": "servus ai"
        }
    }
}

And a mapping file that looks like this

{
    "AskWhat": "what",
    "AskWhen": "when",
    "AskWhere": "where",
    "AskWho": "who",
    "AskWhy": "why",
    "AskHow": "how"
 }

Building Your Skill

Head over to the Alexa Console. If you don't have an AWS acccount then follow the steps to create one. Once regsitered login

Step 1. Create a Skill

First we are going to create a new Alexa Skill. This skill is going to use an HTTP endpoint to process the requests. The alternative is to use an AWS Lambda function, but an HTTP endpoint is an easier way to get started with Programy intergration

![./images/alexa/Step1.png]

  • From the console, click Create Skill

Step 2. Define your Skill

Next we define our skill, gve it a name and set up the basic configuration.

![./images/alexa/Step2.png]

  • Enter skill name
  • Select Langauge
  • Under Choose model to add to your skill, select Customer
  • Under Choose a method to host your skill’s backend resources, select Self Hosted
  • Click Create Skill

Step 3. Choose a Template

Once we have defined our skill, the next step is to select a template. For Programy integration we are going to use a blank template so that we can learn skill basics without additional unneccassary functionality getting in the way

![./images/alexa/Step3.png]

  • From Choose a template, select Start from scratch
  • Click Choose

Step 4. Build Your Model

The next step involves creation the neccassary model for our skill. A model is made up of a number of intents, each intent is associated with a set of sample utterances that the skill trains the model to understand and invoke the appropriate intent.

![./images/alexa/Step4.png]

First step is the enter an 'innovation name', this should be the same name you used when you created the intents mapping files in the 'Generating Intents' section above.

Next we are going to create the intents that will recognise the text sent to our client. We could enter them one by one, but we created the JSON file early in 'Generating Intents' section above. Scroll down to the bottom of the intents side bar on the left and click 'JSON Editor' and paste the contents of the file 'intents.json' into the window, then click 'Save Model'

![./images/alexa/Step4.1.png]

Next we need to build our model from the intents we have created. Click 'Build Model' and within a few sections you'll see a pop up in the bottom right hand corner tell you the build was successful ( or not ). If the build fails, check that there are no errors in the JSON file you have pasted in.

![./images/alexa/Step4.2.png]

Finally we need to set the endpoint that the skill will call every time it matches an input to an intent. At the bottom of the sidebar on the left hand side, click the Endpoint link. In the window that appears, ensure HTTPS is selected and in edit box next to 'Default Region' enter the URL of your end point.

![./images/alexa/Step4.3.png]

In the example above I use ngrok to create a temporary URL for development and testing purpose. For more details see Using ngrok. The API endpoint is always '/api/alexa/v1.0/ask' So combine this with the ngrok URL, gives you 'https://87e27269.ngrok.io/api/alexa/v1.0/ask'. To save this click 'Save Endpoints' and you are ready to get your client up and running

Client Configuration

Like all clients the Programy Alexa client requires some configuration which is held in the config.yaml file for the client. The available configuration options are as follows

alexa:
  description: Program-Y Alexa Client
  host: 127.0.0.1
  port: 5001
  debug: False
  launch_text: Hello and welcome
  launch_srai: ALEXA_LAUNCH
  session_end_text:  Good bye matey
  session_end_srai: ALEXA_END
  error_text: Oopsie there has been an error
  error_srai: ALEXA_ERROR
  leave_intent: LeaveIntent
  intent_map_file: intents.map

Client Execution

Y-Bot ships with a unix shell script for running an Alexa client. It can be found in the scripts/xnix folder of your y_bot installation and is called 'y-bot-alexa.sh'.

Alternatively you can use the following command line to run it

python3 -m programy.clients.restful.flask.alexa.client --config ../../config/xnix/config.alexa.yaml --cformat yaml --logging ../../config/xnix/logging.yaml

Test Your Client & Skill

            Start <invocation name>

            Enter questions

            Exit

Publish Your Skill

Distribution and Certification is left as an exercise for the reader given the regulatory nature of much of the information required.

Clone this wiki locally