Erstellen eines Alexa Skill mit Python und AWS Lambda

Veröffenticht am 16.02.2017    von     in der Kategorie Alexa, Internet of Things     bisher 6 Reaktionen


Amazon Echo DotDieser Beitrag soll einen Überblick über die Entwicklung eines benutzerdefinierten Alexa Skill für den Sprachassistenten von Amazon geben. Dabei greifen wir für die Ausgabe der Sensorwerte, wie zum Beispiel Temperatur, Luftfeuchtigkeit und Spannung, auf eine eigene Datenbank per Request über eine AWS Lambda Funktion zurück.

 

Aufbau eines Alexa Skill

Um ein Custom Skill zu entwickeln, sollte man sich den Ablauf von der Spracheingabe bis zur passenden Antwort einmal vor Augen führen.

Der Ablaufplan sieht ungefähr so aus:

 

  • Der Benutzer spricht mit Echo unter Verwendung von Triggerwörtern, sodass Alexa weiß, dass eine Interaktion stattfindet und welches zugeordnete Skill verwendet werden soll. Zum Beispiel: “Alexa, frage Zentrale nach Temperatur in Küche”. In diesem Fall sind die Auslöseworte “Alexa” zur Aktivierung des Echo und “Zentrale” zur Verwendung bzw. der Weitergabe der Daten an das gewünschten Skill.
  • Echo sendet die Anforderung an die Alexa Service Plattform, die die Spracherkennung verarbeitet und die im Skill festgelegten Intents identifiziert und als im JSON-Format codiertes Textdokument an den Host, mit dem entsprechenden verarbeitenden Programm, sendet. In unserem Beispiel ist die Absicht, die “Temperatur” in der “Küche” abzufragen.
  • Auf dem Host empfängt das Programm das JSON-Dokument über eine HTTP-Anfrage, beziehungsweise wenn das Programm auf einer AWS-Lambda-Funktion basiert über den direkten Aufruf der Lambda-Funktion. Das Programm liest die übergebenen Absichten aus und verarbeitet diese entsprechend. In unserem Beispiel führt die Übergabe “Temperatur” und “Küche” zur Abfrage unserer Datenbank, mit dem Umweg über ein PHP-Skript per Request, nach dem letzten gespeicherten Temperaturwert in der Küche.
  • Die auf der Hostseite angefragten bzw. ermittelten Daten, in unserem Fall zum Beispiel eine “Temperatur” von “20,0” Grad Celsius in der “Küche“, werden wieder per Textdokument im JSON-Format an die Alexa Service Plattform zurückgesandt. Dabei ist zu beachten, der komplette Ausgabetext von Alexa muss als Antwort generiert werden.
  • Die Alexa Service Plattform empfängt die Antwort und gibt diese unter Verwendung der Text zu Sprache Funktion, über den Echo, dem Benutzer die Antwort aus. In unserem Fall könnte die Antwort lauten: “Die aktuelle Temperatur am Messort Küche beträgt 20,0 Grad Celsius”.

 

Für die Umsetzung dieser Alexa Anwendung verwende ich eine AWS Lambda Funktion in Python. Aus dieser greife ich über ein, auf meinem Webhostingpaket gespeichertes PHP Skript auf eine zugehörige MySQL Datenbank zu. Für diesen Weg habe ich mich entschieden, da die Nutzung der AWS Lambda Funktion nur nach Bedarf abgerechnet wird, und für mich somit günstiger als das bei Verwendung eines eigenen Backend notwendige Trusted-Zertifikat ist. Zudem bietet Amazon ein kostenloses Kontingent zum Testen des Services an. Zudem bietet Amazon ein kostenloses Kontingent zum Testen des Services an.

 

Demonstration

Folgendes Video zeigt die Verwendung eines Amazon Echo Dot mit dem hier vorgestellten Alexa Skill. Dabei rufe ich zuerst nur den Alexa Skill mit den verwendeten Auslösewörtern “Alexa” und “Zentral” ohne direkte Fragestellung auf. Alexa antwortet mit einer im Python Skill vorgefertigten Anweisung. Danach frage ich die zuletzt gespeicherte Temperatur, Luftfeuchtigkeit und Spannung für verschiedene Messorte mit den entsprechenden Begriffen ab. Durch eine Pause bei der Interaktion mit Alexa, gibt diese einen Hinweis zur Beendigung aus. Auch diese Textpassage ist in dem Python Skill vordefiniert. Eine wiederholte Abfrage, “Alexa frage Zentrale nach durchschnittlicher Temperatur in der Küche gestern”, in diesem Fall mit Auslöseworten und hinterlegten Intents, liefert als Antwort die durchschnittliche Temperatur an einem Messort für einen gewünschten Zeitraum. Die weitere Frage mit Auslöseworten und entdprechenden Intents liefert einen Differenzwert zurück.

 

 

Voraussetzung für die Umsetzung

Ein Alexa Echo oder Echo Dot wäre natürlich interessant, allerdings ist ein Testen auch auf der Alexa Service Plattform möglich. Was du allerdings unbedingt benötigst, ist ein kostenloser Amazon Developer Account um Zugriff auf die Developer Console zur Entwicklung des Alexa-Skill zu erhalten. Die Nutzung der AWS Lambda Funktion erhältst du über das Amazon-Web-Service Angebot. Damit du dein eigenes Amazon Echo zum Testen ohne große Probleme verwenden kannst, nutze bei der Registrierung die gleichen Daten wie die deines Amazon-Kontos, mit dem das Echo verknüpft ist.

Zur Umsetzung des hier vorgestellten Alexa Skill benötigen wir eine Datenquelle, in diesem Fall eine Datenbank mit entsprechend gespeicherten Werten der verwendeten Sensoren und ein vom Internet aus zugängliches PHP-Skript zur Bereitstellung der angefragten Daten. In meinem Beispiel greife ich auf die in den entsprechenden Beiträgen, zum Beispiel “DS18B20 Temperatursensor am ESP8266….” oder  “Temperatur-Sensor DS1820 am Raspberry Pi mit Python” mit der Erweiterung einer entsprechenden Datenbankanbindung verwendeten Datenquellen zurück.

 

Alexa Skill

Ersteinrichtung

Um mit der Erstellung beginnen zu können, melde dich auf der Developer Console an und starte über “Alexa Skills Kit” in der Registrierkarte “Alexa” die Funktion “Add a New Skill”.

Als Erstes geben wir die “Skill information” ein. Hierzu wählen wir den Skill Type “Custom Interaction Model” und die Sprache “German” aus. Unter Name gibst du die Bezeichnung des Skills ein, dieser wird bei Veröffentlichung im Alexa Skill Store angezeigt. Da wir dieses Skill nur für den Eigengebrauch nutzen, bleibt dieser in der Testphase und du musst dir keine allzu großen Gedanken wegen der Namensgebung machen. 😉 Außerdem kann man die Daten nachträglich immer noch ändern. Wichtiger ist die Eingabe bei Invocation Name, hier wird das Auslösewort, in diesem Fall “zentrale” eingegeben. Die Einstellung bei Global Fields – Audio Player, bleibt bei der Vorauswahl “No”.

Nach der Speicherung bekommen wir eine eindeutige Application Id, diese wird später zur Verbindung in unserer AWS Lambda Funktion benötigt.

 

Interaction Model

Im Intent-Schema legen wir die Interaktionsmöglichkeit mit Alexa fest. Da in diesem Beispiel verschiedene Messwerte abgefragt werden, allerdings die Örtlichkeiten der angebrachten Sensoren in meinem Fall unterschiedlich sind, habe ich die einzelnen Abfragen zum besseren Verständnis hierzu nach Sensortypen getrennt. Eine Zusammenfassung und Kürzung ist natürlich immer möglich.

Im Intent Schema legen wir die verschiedenen Funktionen zu den einzelnen gewünschten Abfragen fest.

  • “intent”: “temperaturAbfrage” – dient zur Abfrage der zuletzt gespeicherten Temperatur eines Messortes
  • “intent”: “luftfeuchtigkeitsAbfrage” – dient zur Abfrage der zuletzt gespeicherten Luftfeuchtigkeit eines Messortes
  • “intent”: “spannungsAbfrage” – dient zur Abfrage der zuletzt gespeicherten Spannung eines Messortes
  • “intent”: “durchschnittsAbfrage” – dient zur Abfrage eines Durchschnittswertes von einem Messort zu einer bestimmten Zeit
  • “intent”: “differenzAbfrage” – dient zur Abfrage eines Differenzwertes von einem Messort zu einer bestimmten Zeit

Neben den eigenen Intents, habe ich die folgenden zwei Alexa Standard-Intents in mein Skill eingebunden.

  • “intent”: “AMAZON.HelpIntent” – geben dem Benutzer einen Hilfetext
  • “intent”: “AMAZON.StopIntent” – lassen den Benutzer einen Vorgang abbrechen

In jeder der Funktionen definieren wir mindestens einen Platzhalter für die noch später definierten Satzvariationen. In der Funktion temperaturAbfrage ist dies “temp_ort”, der auf die entsprechende Liste der Custom Slot Types verweist. In dieser Liste werden alle gültigen Parameter für die Funktion aufgelistet. In diesem Fall ist unter dem definierten Slot “liste_temp_ort” folgender Eintrag hinterlegt.

Diese Liste kannst und solltest du entsprechend deiner Messorte und verwendeten Begrifflichkeiten erweitern. Zum Beispiel wohnzimmer, wohnraum, wohnstube usw.

Die weiteren einzelnen Type sind in meinem Beispiel:

Nun müssen wir nur noch die verschiedenen Satzvariationen mit den entsprechenden {Platzhaltern} unter Sample Utterances anlegen.

Die Sätze setzten sich aus den folgenden Einzelteilen zusammen, zuerst wird die zu verwendende Funktion benannt, danach kommt der dazugehörige Satz mit den einzelnen Platzhaltern. So wird mit dem Satz, “Temperatur in Küche” die Funktion “temperaturAbfrage” mit der gültigen Begrifflichkeit “Küche” aufgerufen.

Interessanter gestaltet sich zum Beispiel der Satz, “Alexa frage Zentrale nach Unterschied der Spannung in Flur von heute zu Vorwoche”. Neben den Auslöseworten “Alexa” und “Zentrale” werden der Backend-Funktion der Funktionsname “differenzAbfrage” und die Begrifflichkeiten “Spannung” für {differenzWert}, “Flur” für {differenzOrt} und “Vorwoche” für {differenzZeit}.

 

Configuration

Sobald nun Alexa unser Intent-Schema verwendet, sendet es die entscheidenden Daten per JSON-Dokument an den Host-Server unserer Anwendung. Da wir für dieses Beispiel AWS Lambda verwenden, müssen wir, wie im folgenden Abschnitt beschrieben, eine entsprechende Lambda-Funktion erstellen und die eindeutige ARN dieser Funktion unter Endpoint eintragen.

 

Test

Nach der Konfiguration gelangen wir zur Testseite. Zum Test ist wie oben schon erwähnt, kein eigener Echo oder Echo Dot notwendig und man kann das Skill über den bereitgestellten Simulator testen.

 

  • Alexa Reite in der Developer Console

 

Programmierung des benutzerdefinierten Skill

Nachdem du dich im Amazon Web Service angemeldet hast, musst du eine neue Lambda-Funktion einrichten. Achte bei der Region auf die vom Alexa Skill Kit geforderte Region Europe. Die notwendigen Schritte zur Erstellung einer Funktion habe ich in folgenden Slider zusammengefasst.

  • Auswahl von Lambda

Neben den Quellcode der Funktion musst du einen Namen sowie die Runtime zwingend festlegen. Als Runtime wähle für dieses Beispiel Python 2.7.

Danach folgt der Programmcode, den du durch nachstehenden Quellcode ersetzten kannst.

Der Einstiegspunkt ist wie bei allen Lambda-Funktionen:

am Ende im Bereich “#– Main handler –” des Programmcodes. Hier musst du in der if-Abfrage die Sternchen mit deiner Application Id des erstellten Alexa Skills ersetzen.

Die notwendigen Events bei Aufruf des Skills durch Alexa findest du im Bereich “#– Events –“. Hier ist für uns vor allem die if-Abfrage des eingehenden “intent” in folgender Funktion interessant und ggf. anzupassen, da in dieser Funktion auf die zur Datenermittlung notwendigen Funktionen verwiesen wird.

Wenn zum Beispiel die Anfrage zur “Temperatur in der Küche” eingeht, wird über das Alexa Skill der Intent “temperaturAbfrage” übergeben. Die Funktion ruft in diesem Fall folgende Funktion auf.

In dieser Funktion vergebe ich zuerst einen beliebigen card_title. Danach lege ich manuell fest, dass es sich um eine Temperaturabfrage handelt. Man könnte natürlich die Funktion für alle verwendeten Sensoren verwenden und den zugehörigen Intent auslesen. Siehe dir hierzu zum Beispiel einmal die Funktion get_differenzwert() an. Das Selbige gilt auch für die Werte zeitangabe und anforderung, diese sind notwendig für die Datenbankabfrage.

Die verwendete Zeichenkette “reprompt_text” bzw. “speech_output” beinhalten die Textausgaben, welche nach der Rückgabe an das Alexa Skill vom Amazon Echo ausgegeben werden.

Da nicht unbedingt alle verwendeten Begrifflichkeiten für den Messort so in der Datenbank abgespeichert sind, passe ich diese in der Funktion get_messort_code an bzw. gebe ein unbekannt zurück. Dies führt zu dem Hinweis, es ist kein Sensor vorhanden.

Die Request Anfrage zum PHP Skript findest du in der folgenden Funktion.

In der Zeichenkette “url” gibst du die Adresse zu deinem PHP-Skript ein. Damit Alexa den Sensorwert korrekt ausgeben bzw. aussprechen kann, bearbeite ich die vom Request übergebene Zeichenkette “wertAusTabelle” am Schluss der Funktion.

Die Definierung der Sprachausgabe bei Aufruf und Beendigung des Alexa Skills findest du im Bereich “# —- Functions that control the skill’s behavior —” in den beiden Funktionen.

Das PHP-Skript und die verwendete Tabellenstruktur

Das PHP-Skript zur gewünschten Datenbankabfrage könnte wie folgt aussehen.

Die Struktur, der von mir für dieses Projekt verwendete Tabelle in der Datenbank zeigt, folgende Skizze.

 

Fazit und Anmerkung

Die Entwicklung eines Alexa Skill für die Amazon Echo Plattform gestaltet sich relativ einfach. Und da die Nutzung des Skills keine Veröffentlichung im Alexa-Skill-Store voraussetzt, lässt sich die Anbindung der eigenen Sensoren somit gut umsetzten.

 

In diesem Beitrag verwende ich Affiliate Links zum Amazon Partnerprogramm. Für dich entstehen dadurch keine Mehrkosten.

Share on Facebook1Share on Google+0Tweet about this on Twitter0Pin on Pinterest1Share on LinkedIn0



Servus, ich bin Wolfgang.

Webworker - Maker - web & mobile Developer - Dobermann Besitzer.

Mit meinem über die Jahre gesammelten Wissen als Webworker möchte ich dir Hilfestellungen und Anregungen zur Nutzung der sich aus dem digital Lifestyle ergebenden Möglichkeiten und Notwendigkeiten geben.

Einen aktuellen Schwerpunkt auf meinem Blog bildet das Thema IoT im Zusammenspiel mit dem Raspberry Pi.

Ähnliche Artikel zum Thema

Oh, zu diesem Thema konnte leider kein Beitrag gefunden werden...


Hinterlasse einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Notwendige Felder sind mit * markiert.

6 Reaktionen (6 Kommentare)

  • Murat Bayram schrieb am 25. April 2017:

    Hi,

    ich habe durch Zufall deinen Artikel hier gefunden. Ich habe ähnliches vor und orientiere mich gerade an der Anleitung. Allerdings spuckt mir der Code Editor beim anlegen der Slots in die Suppe. Sobald ich bei einem der intents Anlege, will er sie auch für alle anderen. Einfaches Copy&Paste von deinem Beispiel ging aber ebenfalls nicht ohne Fehler, weil du intentes mehrfach aufrufst, was laut Code editor nicht erlaubt ist. Hast du ggf. Screenshots deiner Intents, Slot Types und des Codes?

    Des Weiteren ist mir nicht ganz klar wo du deine liste “temp_ort_liste” und “temp_ort” abgelegt hast.

    Grüße

    • Wolfgang schrieb am 25. April 2017:

      Hallo,
      wie Du schon bemerkt hast, bei der Anlage des Skills bzw. des Interaction Model ist kein Copy&Paste möglich, da Amazon bei der Eingabe eine Überprüfung durchführt. Daher muss jeder “intent” einzeln angelegt werden. Die Fehlermeldung kommt daher eher zustande, da bei einem Copy&Paste noch nicht alle notwendigen Daten eingetragen sind. Die “Listen” werden in den Custom Slot Types eingetragen.
      Viele Grüße

  • Klaus-D. Meier schrieb am 6. April 2017:

    Hallo Wolfgang,
    eine super Arbeit.
    Vielen Dank
    Klaus

    • Wolfgang schrieb am 7. April 2017:

      Hallo Klaus,
      vielen Dank für Deine positive Rückmeldung.
      Viele Grüße
      Wolfgang

  • Ulli schrieb am 5. April 2017:

    Hi Wolfgang,

    vor einigen Tagen ist Alexa bei mir eingezogen Eine einfache Wemo-Switch-Emulation mit einem ESP8266 habe ich schon gebaut. Nun will ich mehr!

    Deine Anleitung ist sehr ausführlich und das Ergebnis beeindruckend. Nun bin ich neben dem Umgang mit Amazon Echo auch noch Anfänger, was Python betrifft. Deshalb bleiben ein paar Fragen. Die wichtigsten:
    In welchem Kontext wird die Datenbankabfrage ausgführt? Auf dem Amazon-Service-Server, d.h. die Datenbank muss über eine öffentliche Adresse erreichbar sein, oder im Kontext des WLANs (direkt vom Echo-Modul), d.h. es reicht ein DB-Server im WLAN?

    Und

    Ist es möglich, statt der DB-Abfrage z.B. einen Web-Server per HTTP abzufragen oder gibt es dabei Hindernisse, die das Vorhaben prinzipiell unmöglich machen (dass ich noch nicht weiß, wie man das mit Python macht, gehört (hoffentlich) nicht in diese Kategorie :-)) )?

    Viele Grüße
    Ulli

    • Wolfgang schrieb am 5. April 2017:

      Hallo Ulli,
      vielen Dank für Deinen Kommentar. Am Anfang hatte ich das Gefühl, Alexa versteht mich überhaupt nicht 😀
      Doch mit der Zeit haben wir uns gut aneinander angepasst. Besonders nach den ersten Versuchen mit der Erstellung eines komplett eigenen Skills wurde mir die Funktionsweise erst wirklich bewußt.

      Die Datenbank muss über eine öffentliche Adresse zugänglich sein, da der Zugriff nicht von Deinem Echo erfolgt, sondern von der ASP (Alexa Service Plattform). Da die ASP per JSON kommuniziert, benötigst Du eine entsprechende Gegenstelle im öffentlichen Netz, die dringend per HTTPS erreichbar sein muss. Amazon bietet den Alexa Developers einen günstigen und einfach einzurichtenden Backend-Bereich auf seinem AWS Lambda an. Auf AWS Lambda stehen Dir, soweit ich mich erinnere, für die Alexa-Skills die Programmiersprachen Python 2.7, JAVA und Node JS zur Verfügung. Die Datenbank-Abfrage ist nicht notwendig, so könnte die Antwort einer Anfrage wie zum Beispiel “Alexa frage Zufallsgenerator nach einer Zufallszahl von 1 bis 100?” direkt in dem kleinen Programm erstellt werden. Eine Abfrage eines Web-Server per HTTP stellt kein Problem dar, da eine HTTPS-Verbindung nur zwischen dem ASP und zum Beispiel AWS notwendig ist.Für die Kommunikation zwischen Python und dem Internet ist das Modul “urllib” eine erste Anlaufstelle 😉 In meinem Beispiel greife ich auch über dieses Modul auf meinen “einfachen” Webspace zur Datenbankabfrage zu, da mir eine direkte Datenbankabfrage über Python außerhalb des AWS nicht möglich war.

      Ich hoffe, ich konnte Dir mit meiner Antwort behilflich sein.

      Viele Grüße
      Wolfgang