Bild von Amazon Echo Dot 2

Was ist eigentlich Amazon Echo und Alexa

Das Thema Smarthome und künstliche Intelligenz zieht zunehmend auch in unsere Haushalte ein. Besonders für Programmierer ist das ein Grund sich mit den neuen Systemen auseinander zu setzen.
Als ein Assistenzsystem für Smarthome und künstliche Intelligenz findet sich seit geraumer Zeit Amazons Echo mit der Sprachassistentin Alexa.

Amazons Echo ist ein kleiner W-Lan Lautsprecher in welchem außerdem noch ein Mikro mit Fernfeldaufnahmemöglichkeit etwas Licht und einige Buttons verbaut sind. Damit ist es dem Gerät möglich über Spracheingaben verschiedene Anfragen zu stellen. Die Kommunikation mit dem Gerät wird wahlweise über die Wörter „Alexa“,“Echo“ oder „Computer“ gestartet und kann durch „Stop“ an jedem beliebigen Punkt beendet werden. Die Fähigkeit von Amazons Echo Geräten auf die Anfragen zu reagieren bezeichnet Amazon als „Skills“ die über einen speziellen Store hinzugefügt werden können um euer Gerät um neue Funktionen zu erweitern.

Wir haben euch oben den Amazon Echo Dot verlinkt. Dieser ist die kleine Version vom Amazon Echo und besitzt lediglich einen kleineren Lautsprecher ist damit aber wesentlich günstiger und ihr könnt ihn trotz allem mittels Auxkabel oder Bluetooth mit euren bestehenden Lautsprechern verbinden.

Die Entwicklung eures Skills

Wenn ihr diesen Artikel offen habt wisst ihr aber sicher schon einiges über Amazons Echo und besitzt wahrscheinlich sogar schon ein Gerät. Um das Thema eigene Skills zu programmieren geht es heute.

Vorausetzungen

Welche Kenntnisse ihr hierfür mitbringen solltet:

  • Kenntnisse mit JavaScript
  • Kenntnisse mit NodeJS
  • grundlegendes Verständniss von Serverkommunikation und JSON
  • grundlegende Englischkenntnisse

Als Vorraussetzung benötigt ihr zunächst einen Account bei developers.amazon.com und bei aws.amazon.com. Für den zweiteren wird zur Anmeldung eine Kreditkarte benötigt aber der Account ist das erste Jahr kostenfrei und kann danach auch gekündigt werden.

Wichtig ist das der Account bei developers.amazon.com der gleiche sein sollte mit welchem euer Echo verknüpft ist, denn so könnt ihr die Skills mit eurem Gerät testen und müsst diese nicht in den Store stellen. Zum testen eures Skill benötigt ihr übrigens kein Echo denn Amazon bietet eine Testumgebung um das Verhalten eures Skills zu simulieren.

Der Code für euren ersten Hallo Welt Skill

Der gesamte Code für dieses kleine Projekt kann auch über GitHub abgerufen werden:
Watch

Die Skills für den Amazon Echo werden im Amazon Lambda Service hinterlegt und mit NodeJS programmiert.
Dabei besteht die JavaScript Datei für Lambda aus verschiedenen Abschnitten.
Sie beginnt zunächst mit einem try-catch welches den Request überprüft und gegebenenfalls in bestimmte Funktionen springt um diesen zu verarbeiten.
Falls ein ungültiger Request eingeht wird die Lambda Funktion dann abgebrochen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
'use strict';
 
exports.handler = function (event, context) {
    try {
        console.log("event.session.application.applicationId=" + event.session.application.applicationId);
 
        if (event.session.new) {
            onSessionStarted({requestId: event.request.requestId}, event.session);
        }
 
        if (event.request.type === "LaunchRequest") {
            onLaunch(event.request,
                event.session,
                function callback(sessionAttributes, speechletResponse) {
                    context.succeed(buildResponse(sessionAttributes, speechletResponse));
                });
        } else if (event.request.type === "IntentRequest") {
            onIntent(event.request,
                event.session,
                function callback(sessionAttributes, speechletResponse) {
                    context.succeed(buildResponse(sessionAttributes, speechletResponse));
                });
        } else if (event.request.type === "SessionEndedRequest") {
            onSessionEnded(event.request, event.session);
            context.succeed();
        }
    } catch (e) {
        context.fail("Exception: " + e);
    }
};

Nach der Überprüfung des eingehenden Requests folgen die Definitionen unserer Funtionen. Zu allererst definieren wir eine funktion in welcher wir die Session starten in der unser Nutzer mit Alexa kommuniziert. Die Nutzung der Session ermöglicht es uns werte über mehrere Fragen und Antworten weiter zu geben und ein regelrechtes „Gespräch“ mit dem Gerät aufzubauen. Diese Funktion wird beim ersten Aufruf unseres Skills ausgeführt (siehe oben – if (event.session.new) )

31
32
33
34
function onSessionStarted(sessionStartedRequest, session) {
    console.log("onSessionStarted requestId=" + sessionStartedRequest.requestId
        + ", sessionId=" + session.sessionId);
}

Nun folgt die eigentliche Start Funktion diese wird definiert um dem Nutzer ein Feedback zu geben falls er unseren Skill startet ohne Anweisungen zu geben.

35
36
37
38
39
40
41
42
43
function onLaunch(launchRequest, session, callback) {
    console.log("onLaunch requestId=" + launchRequest.requestId
        + ", sessionId=" + session.sessionId);
 
    var cardTitle = "Hallo Welt"
    var speechOutput = "Sage Hallo Welt um Hallo Welt als Antwort zu bekommen!"
    callback(session.attributes,
        buildSpeechletResponse(cardTitle, speechOutput, "", true));
}

Die für uns wichtigste Funktion ist die hier als onIntent() bezeichnete. Diese wird immer ausgeführt wenn der Nutzer ein Kommando für einen Intent gibt.
Beim ausführen wird dann abgefragt um welchen Intent es sich handelt und auf die passende Funktion referenziert was aufgrund des Intents zu tun ist.

44
45
46
47
48
49
50
51
52
53
54
55
56
57
function onIntent(intentRequest, session, callback) {
    console.log("onIntent requestId=" + intentRequest.requestId
        + ", sessionId=" + session.sessionId);
 
    var intent = intentRequest.intent,
        intentName = intentRequest.intent.name;
 
    if (intentName == 'HalloIntent') {
        handleHalloWeltRequest(intent, session, callback);
    }
    else {
        throw "Invalid intent";
    }
}

Die Funktion onSessionEnded haben wir für das beenden der Session definiert und geben hier lediglich der Konsole die Informationen zur beendeten Session aus.
Hier kann später auch noch Logik eingebaut werden um Beispielsweise ein letztes mal eine API anzusprechen.

58
59
60
61
function onSessionEnded(sessionEndedRequest, session) {
    console.log("onSessionEnded requestId=" + sessionEndedRequest.requestId
        + ", sessionId=" + session.sessionId);
}

In Zeile 51/52 Referenzieren wir im Falle des ‚HalloIntent‘ nun auf folgende Funktion in welcher mit unserer Hilfsfunktion ein Response an den Amazon Echo erstellt wird.

function handleHalloWeltRequest(intent, session, callback) {
    callback(session.attributes,
        buildSpeechletResponseWithoutCard("Hallo, Welt!", "", "true"));
}

Zum generieren eines Response an den Amazon Echo haben wir uns zwei Helfsfunktionen angelegt. Diese unterscheiden sich lediglich darin, wie der Response übergeben wird.
Amazon Echo kann zum einen einfach nur einen Text ausgeben der gesprochen wird.
Es gibt aber auch die Möglichkeit dem nutzer auf seinem Mobiltelefon innerhalb der Alexa App eine Karte mit weiteren Informationen anzuzeigen.

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
    return {
        outputSpeech: {
            type: "PlainText",
            text: output
        },
        card: {
            type: "Simple",
            title: title,
            content: output
        },
        reprompt: {
            outputSpeech: {
                type: "PlainText",
                text: repromptText
            }
        },
        shouldEndSession: shouldEndSession
    };
}
 
function buildSpeechletResponseWithoutCard(output, repromptText, shouldEndSession) {
    return {
        outputSpeech: {
            type: "PlainText",
            text: output
        },
        reprompt: {
            outputSpeech: {
                type: "PlainText",
                text: repromptText
            }
        },
        shouldEndSession: shouldEndSession
    };
}
function buildResponse(sessionAttributes, speechletResponse) {
    return {
        version: "1.0",
        sessionAttributes: sessionAttributes,
        response: speechletResponse
    };
}

Den JavaScript Code für den HalloWelt Skill in Lambda einbinden

Den im vorherigen Abschnitt erklärten Code müssen wir nun bei Amazon Web Services im Lambda Service als Funktion einrichten. Dazu melden wir uns unter
aws.amazon.com an gehen auf die Region Europa/Irland und dann auf den Service Lambda.

Startseite von Amazon Web Services

Wir wählen hier den Service Lambda über die Suche oder das Menü aus.

Übersichtseite von AWS nach der Anmeldung

Nun Kommen wir auf die Oberfläche der Lambdaverwaltung und wählen hier unter Functions -> Create a Lambda function aus um eine neue Schnittstelle für unseren Skill anzulegen.

Konfigurationsoberfläche für AWS Lambda

Im folgenden Dialog bietet sich dem Nutzer nun die Möglichkeit, zwischen verschiedenen Blaupausen zu wählen. Dies ist für uns nicht notwendig so das wir die Option „Blank Function“ wählen und fortfahren.

Blaupausenauswahl von AWS Lambda

Im nächsten Schritt konfigurieren wir den Auslöser für unsere Schnittstelle. Hierbei Klicken wir in das punktierte Quadrat und wählen „Alexa Skills Kit“ um unsere Lambda Funktion durch Alexa steuerbar zu machen.

Schalterkonfiguration von Lambdafunktionen

Nun werden wir nach der Konfiguration für unsere Funktion gefragt. Im obersten bereich vergeben wir einen einzigartigen Namen und wählen als Runtime „Node.js 4.3“ aus.
Darunter folgt außerdem der JavaScript Code welchen wir oben besprochen haben und welcher außerdem in der GitHub Repo in der Datei index.js zu finden ist.

Konfiguration der Lambdafunktion

Zur weiteren Konfiguration gehört dann auch noch die Auswahl der Rolle die Lambda ausführt. Solltet ihr noch keine Nutzerrolle angelegt haben So legt so wählt „Create new role“ ansonsten wählt eure „lambda_basic_execution“ Rolle aus. In den Erweiterten Einstellungen solltet ihr dann noch den Timeout auf 10 Sekunden anpassen.

Weitere Konfiguration der Lambdafunktion

Wenn ihr fertig seid und alles bestätig habt findet ihr eine Übersicht eurer Funktion. In der oberen rechten Ecke findet sich dann außerdem die ARN. Die Zeichenkette hinter ARN: benötigt ihr dann für euren Alexa Skill damit dieser ein Ziel hat welches er ansteuert. Notiert euch diese deshalb oder kopiert sie in die zwischenablage

Lambda Funktion in der Übersicht nach Erstellung

Den Alexa Skill bei Amazon Developers einrichten

Die eben angelegte Lambda Funktion kann nun in einen Amazon Alexa Skill eingebunden werden. Aus diesem Grund loggen wir uns auf developers.amazon.com ein oder legen hier einen Account an.
Wir gehen dann auf den Link Alexa und wählen den Punkt „Alexa Skills Kit“ aus.

Alexa Menü bei Amazon Developers

Um nun unseren Hallo Welt Skill anzulegen wählen wir „Add a New Skill“ und werden zur Oberfläche zum Anlegen eines Skills für Alexa geleitet.

Übersicht im Alexa Skills Kit

Für unseren Skill und die meisten allgemeinen Skills nutzen wir folgende Einstellungen:
Skill Type : Custom Interaction Model
Language : German
Name : HalloWelt
Invocation Name : Hallo Welt (Achtung der Invocation Name darf nicht aus einem Wort bestehen wenn ihr den Skill in den Store einreichen wollt)
Audio Player : no

Haben wir alle Einstellungen gesetzt gelangen wir über „Next“ zur nächsten Oberfläche

Oberfläche zum Anlegen eines Skills - Skill Informationen

Unter dem Menü zum Interaction Modal spielt sich die restliche Konfiguration für Alexas Logik unseres Skills ab.
Zum einen finden wir hier das Intent Schema : Dieses definiert welche Intents als welche Interaktionsräume es mit Alexa gibt und welche Slots spricht werte darin übertragen werden können. Außerdem können wir für den Slot auch eigene Datentypen anlegen was für diese Anleitung aber erstmal unrelevant ist.

Oberfläche zum Anlegen eines Skills -Intent und Interaktionseinstellungen

In das Feld Intent Schema folgen wir nun folgende Inhalte ein (GitHub: intent_schema.json):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
   intents: [
              {
                 intent: "HalloIntent"
              },
              {
                 intent: "HalloNameIntent",
                     slots: [
                              {
                                name: "PersonName",
                                type: "AMAZON.DE_FIRST_NAME"
                              }
                            ]
              }
            ]
}

Das Intentschema unserer Anwendung sagt aus das es Zwei Interaktionsräume geben soll: den „HalloIntent“ und den „HalloNameIntent“. Außerdem enthält der „HalloNameIntent“ einen slot namens „PersonName“ vom Typ „AMAZON.DE_FIRST_NAME“.

Außerdem werden unter Sample Utterances die Aufrufe angegeben wie der Nutzer mit Alexa und unserem Skill interagiert.
Die Sample Utterances sind immer nach dem Schema aufgebaut – IntentName Nutzeranweisung {SlotWert}
In unserem Fall sieht das ganze wie in der GitHub Repo in sample_utterances.conf aus:

1
2
3
4
5
6
HalloIntent Hallo Welt
HalloIntent Hi Welt
HalloIntent Guten Morgen Welt
HalloIntent Wie geht es Welt
HalloNameIntent Hallo Welt ich bin {PersonName}
HalloNameIntent Hi Welt ich bin {PersonName}

Oberfläche zum Anlegen eines Skills - Ausgefüllte Interaktionsinformationen

Sind wir Fertig klicken wir auf Next und kommen zum Konfigurationsfeld. Hier wählen wir als Endpunkt AWS Lambda und als Region Europa aus. In das Feld ARN fügen wir außerdem die ARN Nummer aus der vorherigen Konfiguration in Amazon Lambda ein

Oberfläche zum Anlegen eines Skills - Endpunkt Konfiguration

Nun ist unser Skill bereit zum Testen. Über den folgenden Dialog aktivieren wir den Skill zum testen in unserem Account. Das ermöglicht, das wir den Skill durch unsere Mailadresse mit unserem Echo Gerät nutzen und testen können ohne das wir ihn veröffentlichen.
Im Abschnitt Service Simulator können wir unter „Enter Utterance“ simulieren was wir zum Echo sagen und bekommen im Feld Service Response angezeigt was unsere Lamda Schnittstelle zurückgibt.

Oberfläche zum Anlegen eines Skills - Testumgebung

Fazit

Abschließend ist eigentlich nur zu sagen als Entwickler macht es richtig Spaß die Skills für Amazons Echo oder Echo Dot zu Entwickeln. Über die einzelnen Services kann mit mit vernünftigem Wissen in JavaScript schnell erste Skills entwickeln und diese immer mehr Erweitern. Auch das Gerät selber punktet mit zunehmend coolen Funktionen und erleichtert einem den Alltag durch Funktionen wie den Wetterbericht oder Nachrichten. Einfach nur cool!

Die nächsten Wochen folgt übrigens ein weiterer Artikel zum Thema „Skills mit HTTP/HTTPS Requests um Schnittstellen anzusteuern“ darin wird noch einmal gezeigt was ihr beachten müsst um einen Skill zu bauen der auch eine API oder sonstiges ansteuern kann.