Computer, gib Pfötchen (Linux-Magazin, April 2017)

Mit schlappen zwei Jahren Verzögerung nach dem Start in den USA ist Amazons Sprachassistentin Alexa nun auch in Deutschland in Form von Geräten wie dem Amazon Echo oder Echo Dot zu haben. Programmierhasen bringen ihr sogar neue Tricks bei.

Wer steht schon gerne vom Sofa auf, um etwas im Internet nachzuschauen, wenn das Handy außer Reichweite ist? Im Haushalt der Zukunft steht zu diesem Zweck ein mattschwarzes Gerät wie der Amazon Echo in der Form einer Konservenbüchse im Zimmer. Die darauf stets lauernde Sprachassistentin "Alexa" nimmt Sprachkommandos entgegen, leitet Aktionen im Internet ein und liest die Antwort anschließend dem reglos in dicke Decken eingekuschelten Anwender vor. Im Smart Home schaltet Alexa auch Lampen ein, spielt Musik ab oder stellt die Alarmanlage scharf.

Preisgünstiger als der Echo-Zylinder ist das Nachfolgegerät "Amazon Echo Dot" in der Form eines Eishockey-Pucks (Abbildung 1), der etwa ein Drittel kostet und zwar wegen des kleineren Klangkörpers keine vollwertigen Bässe produziert aber ebenso wie der große Bruder mit der Alexa-Software Kommandos entgegennimmt und antwortet. Amazon träumt natürlich davon, dass der Kunde eines Tages zuhause nur "Alexa, bestell Klopapier" ruft, und schon gibt die Sprachassistentin die Bestellung beim Internetdiscounter auf, der eilenst eine Drohne mit dem dringend benötigten Haushaltsartikel auf den Weg zum Verbraucher schickt.

Abbildung 1: Der kleine Echo Dot lauscht auf Sprachkommandos und gibt Antwort oder leitet Aktionen ein.

Angeblich abhörsicher

Das Gerät lauscht zwar ständig in den Raum hinein, um auf gesprochene Worte zu reagieren, schwebt aber normalerweise in einer Art Dämmerzustand und leitet ins Mikrofon kriechende Geräusche nicht in die Amazon-Cloud zur Analyse weiter. Vielmehr wartet die kleine Sprachbüchse, bis der User das sogenannte Wake-Word, normalerweise "Alexa", spricht und aktiviert dann erst die Verbindung mit der Spracherkennung in der Amazon-Cloud. Statt "Alexa", "Amazon", "Echo" dürfen Star-Trek-Fans auch das Wake-Word "Computer" einstellen (Abbildung 2) und dann mit der Assistentin reden wie Captain James T. Kirk mit dem Bordcomputer auf dem Raumschiff Enterprise.

Abbildung 2: Raumschiff-Enterprise-Fans können Alexa jetzt auch mit "Computer" aufwecken.

Von Haus aus kann Alexa einfache Fragen beantworten im Bereich der Arithmetik ("Alexa, what's 7 plus 8?"), Unterhaltung ("What's Arnold Schwarzenegger's latest movie?") oder Schnäppchenjagd auf Amazon ("What are your deals?"). Sie kann Tagesnachrichten runterrasseln ("What's in the news?"), das Wetter vorhersagen ("What's the weather tomorrow?"), die Eieruhr umdrehen ("Set timer for 5 minutes"), Spotify-Musik abspielen, Audiobücher vorlesen und vieles mehr ([3]).

Abbildung 3: Die bestbewerteten Skills im deutschen Alexa-Skillstore.

Alexa lernt neue Tricks

Mehr Möglichkeiten bieten sogenannte "Skills", die soweit kostenlos (aber wohl irgendwann mal nach dem App-Bezahlmodell) im sogenannten "Skills Store" abrufbar sind ([4] und Abbildung 3). Hierbei handelt es sich um Softwarepakete, die Drittanbieter ähnlich wie Apps im Appstore programmiert und veröffentlicht haben. Vom Runterbeten der aktuellen Kurse im maßgeschneiderten Aktienportfolio ("Motley Fool"), über das Spiel "Jeopardy", bis zur Lampensteuerung im Smart Home ist alles dabei. Um Alexa das Skill beizubringen, aktiviert der User es in der Smartphone-App Alexa oder spricht es einfach ins Mikrofon: "Alexa, enable The Fool". Kurze Zeit später kennt Alexa auch den Aktienmarkt: "Ask the Fool how is the market doing today" und "Ask the Fool to add Microsoft to my watchlist".

Abbildung 4: Entwicklen neuer Alexa Skills auf developers.amazon.com

Abbildung 5: Vom User selbst entwickelte Alexa-Skills

Wen es in den Fingern juckt, Alexa nach seiner eigenen Pfeife tanzen zu lassen, der kann auf developers.amazon.com einen Alexa-Account einrichten, der separat vom AWS-Business läuft und eigentlich der Entwicklung von Android-Apps dient (Abbildung 5). Nach dem Abnicken einer ellenlangen Vorschriftenliste führt ein Klick auf den Reiter "Alexa" und dann auf "Alexa Skills Kit" zu einer Liste mit eigenen Skills mitsamt einem Knopf der "Create New Skill" verheißt.

Snapshot-Ausgabe auf Zuruf

Als praktisches Beispiel soll Alexa auf Zuruf mitteilen, welches die aktuelle Ausgabe des Programmier-Snapshots ist. Dazu liest sie hinter den Kulissen eine JSON-Datei articles.json von meiner Website Perlmeister.com, die alle Ausgaben in umgekehrter chronologischer Reihenfolge auflistet (Abbildung 6), pickt sich den ersten Eintrag in der langen Liste heraus, puhlt daraus Monat und Jahr hervor und übergibt die beiden Werte dem Sprachprozessor, der sie wiederum über den Lautsprecher am Amazon Echo Dot dem User verkündet.

Abbildung 6: Die Snapshot-Ausgaben im JSON-Format as Datenquelle für Alexa.

Spricht also der User den Satz

    "Alexa, ask latest snapshot for issue"

dann leitet Alexa die Anfrage an das neue "Latest Snapshot"-Skill weiter, das die Daten einholt und aufbereitet, damit die Antwort etwa "01 2017" für das Januar-Heft lautet, falls dies gerade die aktuelle Ausgabe des Linux-Magazins ist. Den Namen des Skills, das Alexa beherrscht und an das es Anfragen delegiert, gibt der Entwickler im Web-Flow für ein neues Skill unter "invokation name" an. Mehrere Wörter sind erlaubt, sie dürfen allerdings keine andersweitig verwendeten Schlüsselwörter (wie zum Beispiel "Alexa") enthalten.

Abbildung 7: Intent und Utterances im Alexa-Skill-Setup.

Äußerung und Absicht

Sprachverarbeitungsfüchse unterteilen die Kommunikation des Users mit dem Gerät in "Intent" und "Utterances". Dabei kann der User zum Beispiel "latest release" oder "newest issue" äußern (Utterance) und damit beidesmal die gleiche Absicht kundtun (Intent), nämlich im Skill "latest snapshot" die Funktion aufzurufen, die Monat und Jahr des aktuellen Snapshots aufsagt. Im Web-Flow des neu angelegten Skills trägt der Entwickler auf der Seite "Interaction Model" (Abbildung 7) hierzu die in Listing 1 und 2 angegebenen Daten ein. Listing 1 legt im Json-Format die später erkannten Intents fest und definiert neben der eigentlichen Funktion LatestSnapshot noch ein generisches Hilfe-Menü, das Alexa aufsagt, falls der User "Help" sagt. Listing 2 weist dann jedem Intent verschiedene gesprochene Sätze zu.

Listing 1: IntentSchema.json

    1 { "intents": [ {
    2   "intent": "LatestSnapshotIntent"
    3 }, { 
    4   "intent": "AMAZON.HelpIntent"
    5 } ] }

Listing 2: SampleUtterances.txt

    1 LatestSnapshotIntent issue
    2 LatestSnapshotIntent release
    3 LatestSnapshotIntent last month

Die nächste Screen im Entwicklungs-Flow fragt nach dem "Endpoint" der Anfrage, also dem Webservice, an den der Sprachassistent die Anfrage weiterleiten soll. Im einfachsten Fall ist dies eine Lambda-Funktion der Amazon-Cloud, deren Konfiguration in der letzten Snapshot-Ausgabe ([6]) besprochen wurde. Deren ARN (Amazon Resource Name) trägt der User mit Cut-and-Paste in das Textfeld in Abbildung 8 ein.

Abbildung 8: Endpoint Lambda

Alter Kumpel Lambda

Die Lambda-Funktion auf AWS darf der Entwickler entweder in Java oder nach Node-Art in JavaScript schreiben, neben etwas Boilerplate-Code in AlexaSkill.js aus [5] aus einer Beispielanwendung im Alexa-Tutorial nutzt das neue Skill die Funktionen aus Listing 3, verschnürt das Ganze mit

    $ zip -r upload.zip AlexaSkill.js index.js

in eine Zip-Datei und lädt letztere zu einer neu angelegten Lambda-Funktion hoch (Abbildung 9). Die Handler für die erkannten Intents, die der Webservice bedient, stehen in Listing 1 ab Zeile 15 in einem assoziativen Array. Für das neue "LatestSnapshot"-Skill ruft Zeile 17 die ab Zeile 24 definierte Funktion getData() auf und übergibt ihr das response-Objekt, damit letztere dem Client gleich die gefundene Antwort schicken kann.

Listing 3: index.js

    01 // Alexa helper to fetch latest snapshot issue
    02 // Mike Schilli, 2017 (m@perlmeister.com)
    03 var APP_ID     = undefined;
    04 var AlexaSkill = require('./AlexaSkill');
    05 
    06 var LatestSnapshot = function () {
    07     AlexaSkill.call(this, APP_ID);
    08 };
    09 
    10 var http = require('http');
    11 
    12 LatestSnapshot.prototype = Object.create(AlexaSkill.prototype);
    13 LatestSnapshot.prototype.constructor = LatestSnapshot;
    14 
    15 LatestSnapshot.prototype.intentHandlers = {
    16   "LatestSnapshotIntent": function (intent, session, response) {
    17     getData(response);
    18   },
    19   "AMAZON.HelpIntent": function (intent, session, response) {
    20     response.ask("Hello", "Hello");
    21   }
    22 };
    23 
    24 function getData(response) {
    25   http.get("http://perlmeister.com/articles.json", function(res) {
    26     var json_string = '';
    27 
    28     res.on('data', function(data) {
    29       json_string += data;
    30     });
    31 
    32     res.on('end', function() {
    33       var snapshots = JSON.parse(json_string);
    34       var latest_issue = snapshots.issues[0];
    35       var answer = latest_issue.month + " " +
    36                    latest_issue.year;
    37 
    38       response.tellWithCard(answer, "Latest Snapshot", answer);
    39     });
    40   });
    41 }
    42 
    43 exports.handler = function (event, context) {
    44     var latestSnapshot = new LatestSnapshot();
    45     latestSnapshot.execute(event, context);
    46 };

Asynchrones HTTP

Mittels des der NodeJs-Umgebung beiliegenden http-Moduls und dessen Methode get() holt Zeile 25 dann den Json-Salat von der Perlmeister-Website und entsprechend dem asynchronen Flow in Node-Systemen registriert der Code in den Zeilen 28 und 32 Handler für zurückkommende Daten und dem Abschluss des JSON-Transfers. Ersterer fügt eintrudelnde Stücke im String json_string aneinander und letzterer wirft einen Json-Parser an, der aus dem String eine Datenstruktur füllt. Im Produktionsbetrieb sollten im Code auch noch Handler für Fehlerfälle stehen, damit Alexa den User per Sprachausgabe darüber unterrichten kann, was eigentlich schief gelaufen ist.

Da die Einträge in umgekehrt chronologischer Reihenfolge in der Struktur stehen, holt Zeile 34 einfach das erste Element des Arrays unter issues hervor und die nächste Zeile fieselt den Monat und das Jahr aus der Datenstruktur heraus. Über die Methode tellWithCard() des response-Objektes schickt Zeile 38 dann die Antwort sowohl als Sprachausgabe als auch als sogenannte Home-Card für Geräte mit Video-Ausgabe (zum Beispiel der Amazon Fire, der ebenfalls Alexa fährt), einer Art Karteikarte mit der Antwort zur zusätzlichen visuellen Untermalung.

Abbildung 9: Der Endpoint-Webservice in Lambda als JavaScript-Code

Damit die Lambda-Funktion auch Alexa-Events entgegennimmt, benötigt sie unter dem Reiter "Triggers" die Option Alexa Skills Kit, die der User auswählt, in dem er auf das leere Kästchen klickt, von dem ein Pfeil zur den orangenen Fensterläden der Lambda-Funktion zeigt (Abbildung 10).

Abbildung 10: Event Source Alexa

Und ... Action!

Zurück im Flow der Konfiguration des Alexa-Skills steht nun unter der Rubrik "Test" (Abbildung 11) ein orangener Schalter, der auf "Enabled" steht mit der Mitteilung dass das Skill auf dem persönlichen Account des Users aktiviert wurde. Spricht letzterer nun "Alexa, ask latest snapshot for release|issue|last month", wird Alexa nach kurzer Denkpause auf Englisch mit "01 2017" antworten.

Abbildung 11: Endpoint Lambda

Falls irgendetwas schief geht, kann der User im Alexa-Protokoll (Abbildung 12) nachlesen, was Alexa tatsächlich verstanden hat und anschließend im Logfile der Lambda-Funktion stöbern, ob der Code eventuell abgestürzt ist oder irgendwelche Fehler gemeldet hat.

Abbildung 12: Alexa protokolliert alle Aufrufe mit und hilft bei der Fehlersuche.

Auch auf Deutsch

Neben US-Englisch und UK-Englisch unterstützt Alexa seit neuestem auch deutsche Kommandos und die zugehörige Sprachausgabe. Hierzu muss die App im "Settings"-Menü "Deutsch" eingestellt haben und das Skill auf der ersten Seite in der Auswahlbox "Language" die Option "German" selektiert.

Dann darf der User in einer Art Deutscher Sprache mit Alexa konversieren, die allerdings wegen der vorgeschriebenen syntaktischen Folge der Kommandos etwas komisch klingt: "Alexa, fragen letzten schnappschuss nach ausgabe" und Alexa antwortet dann auf Deutsch: "01 2017". Es erstaunt, dass Amazon nach Englisch tatsächlich Deutsch als zweite Sprache gewählt hat und nicht etwa Spanisch, das weit häufiger gesprochen wird. Scheinbar ist der deutsche Markt lukrativer. Skills können mehrere Sprachen unterstützen, der Endpunkt muss dann in der Sprache antworten, in der die Frage gestellt wurde. Falls vergessen wurde, dem Skill die richtige Sprache beizubringen, geht gar nichts mehr. Abbildung 13 zeigt, dass Alexa "Frogs that was born on no sucks elvis" verstanden hat, als der Tester ein neu geschaffenes bayrisches Skill ansprechen wollte, dass "Servus Beinand" sagt und entsprechend dieser Absicht "Alexa frage servus beinand nach sag servus" kommandierte.

Abbildung 13: "Alexa, frage servus beinand nach sag servus"

Wer mit Alexa sein Smart Home steuern will, muss nicht so weit in die Tiefen der Programmierung hinabsteigen wie hier ausgeführt, sondern kann gleich am Anfang des Flows unter "Skill Type" statt "Custom Interaction Model" die Option "Smart Home Skill API" anwählen und steigt dann auf einer einfacher zu handhabenden höheren Kommandoebene ein. "Flash Briefing" ist eine weitere Option zum Abspielen vorher eingetüteter Radiosendungen. Wer statt einer Lambda-Funktion auf AWS als Endpunkt einen eigenen Webserver nutzen möchte, muss diesen mit SSL fahren und dann das Zertifikat bei Alexa hinterlegen. Und bevor das Skill in der öffentlichen Liste auf der Alexa-App von Amazon erscheint, behält sich Amazon die manuelle Überprüfung und Zertifizierung vor.

Infos

[1]

Listings zu diesem Artikel: http://www.linux-magazin.de/static/listings/magazin/2017/04/snapshot/

[2]

"Getting Started with the Alexa Skills Kit", https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide

[3]

"Complete list of Alexa commands", https://www.cnet.com/how-to/the-complete-list-of-alexa-commands/

[4]

Deutscher "Alexa Skills Store", https://www.alexaskillstore.de/

[5]

Alexa.js boilerplate: https://github.com/amzn/alexa-skills-kit-js/blob/master/samples/helloWorld/src/AlexaSkill.js

[6]

Michael Schilli, "Neue Heimat": Linux-Magazin 02/17, S.XXX, <U>http://www.linux-magazin.de/Ausgaben/2017/02/Snapshot

[7]

Programmierbeispiele für Alexa-Skills auf Github: https://github.com/amzn/alexa-skills-kit-js/tree/master/samples

Michael Schilli

arbeitet als Software-Engineer in der San Francisco Bay Area in Kalifornien. In seiner seit 1997 laufenden Kolumne forscht er jeden Monat nach praktischen Anwendungen verschiedener Programmiersprachen. Unter mschilli@perlmeister.com beantwortet er gerne Ihre Fragen.