Seit dem Film Space Odyssey (Odyssee im Weltraum) und dem HAL9000 sind wohl viele von uns begeistert von dem Gedanken eine Unterhaltung mit einem Computer zu führen, ihm Fragen zu stellen und Informationen zu bekommen. Genau diese Voice Services sind zur Zeit auf dem Vormarsch. Amazon’s Alexa, Google Home, ivee oder Cubic.
Dies öffnet eine ganz neue Welt für Entwickler. In diesem Tutorial möchte ich euch anhand eines einfachen Beispiels die Entwicklung eines neuen Skills für Alexa beibringen.
In dieser Abbildung könnt ihr auf einen Blick, erkennen was ma dazu benötigt. Der Nutzer stellt Alexa die Frage „Alexa, was kann ich heute zu Abend essen?“. Diese Anfrage wird online in einem weiteren Service in Text umgesetzt und dann der passende Voice (Micro) Service ausgewählt. In diesem Fall ist es die HungerApp. Die Utterances (dt. Äußerungen) werden per Hand vordefiniert. Sie werden auf die Spracheingaben des Nutzers gemappt. Leider habe ich in der Beispielabbildung genau die Utterance, die der Nutzer verwendet, vergessen aufzuführen. In einer echten Liste stehen in der Regel jedoch weitaus mehr Utterances. Hier fehlt also mindestens noch „GetEssen sag mir was ich heute zu Abend essen kann“.
Das Alexa Voice Kit leitet den Request nun an einen – durch den Entwickler festgelegten Endpunkt – weiter. Entweder wird hier eine eigene Schnittstelle entwickeln oder einfach der Lambda Service von AWS verwenden. Letzteres wird in diesem Artiekl verwendet. Die Lambda-Funktion kann in Java, Pyhton oder NodeJS geschrieben werden. Im Code wird festgelegt was Alexa antworten soll und die Antwort in Textform zurückgegeben. Diese wird dann von Alexa Voice Service Device (also Echo, Dot oder sogar dem Rapsberry Pi) „ausgesprochen“.
Schritt 1 – Vorbereitung:
Du benötigst ein Account für https://developer.amazon.com/ und https://aws.amazon.com/.
In AWS wirst du gleich eine Lambda Funktion anlegen und in der Developer Console deinen Alexa Voice Skill erstellen.
Schritt 2 – Anlegen des Voice Skills
Nachdem du dich auf der „Developer Console“ eingeloggt hast – klick auf „Alexa“ im Menü.
Du hast nun die Möglichkeit zwischen „Alexa Skills Kit“ und „Alexa Voice Service“ zu wählen. Unter „Alexa Skills Kit“ kannst du neue Skills – also neue Sprach Apps – anlegen, genau das was wir in diesem Tutorial machen wollen. (Falls du allerdings irgendwann den Alexa Service in ein Gerät integrieren willst, kannst du das mit dem Alexa Voice Service machen.)
Klick „Alexa Skills Kit“.
In der Ecke rechts oben könnt ihr jetzt auf „Add new Skill“ klicken.
Es öffnet sich ein Formular zum Anlegen eines neuen Skills. Im ersten Schritt wirst du nach Skill Type, Language, Name und Invocation Name gefragt.
Invocate Name ist die sprachliche Bezeichnung durch die Alexa den Skill erkennt und aufruft. Wenn man also „Alexa starte meinen Skill“ sagt, wird die Anwendung gestartet. Der Name ist für die Bezeichnung im Alexa App Store. Language bedarf wohl keiner Erklärung. Bleibt der Skill Type: Es gibt 3 Types zur Auswahl. „Smart Home Skills“ für Anwendungen im Smart Home-Bereich, die beispielsweise Geräte steuern sollen, „Flash Briefing Skills“ für reine Nachrichten oder Kurz Informations Skills und schließlich „Custom Skills“ mit Nutzerinteraktion wie wir es für dieses Tutorial benötigen.
Klick dann auf „Next“ bzw. „Weiter“.
Schritt 3 – Intent Schema und Utterances
Nun wird zwar noch nicht los programmiert, trotzdem wird es spannend. Wir müssen unser Intent Schema und die Utterances festlegen. Utterances (engl. Äußerung) sind kurze manuell angelegte Sätze (mit und ohne Platzhaltern), durch die Alexa Sprachbefehle vordefiniert werden. Alles, was Alexa verstehen kann, bewegt sich im Raum der festgelegten Utterances. Es liegt also in eurer Hand, auf welche Varianten eines Satzes Alexa reagiert. Ein Beispiel für Utterances ist:
IntentUrlaub wohin kann ich reisen ?
IntentUrlaub wohin kann ich fliegen ?
IntentUrlaub wo kann ich urlaub machen ?
IntentUrlaub wohin kann ich verreisen ?
IntentUrlaub wo kann ich meinen Urlaub verbringen ?
IntentFlugAbfrage wie teuer ist es von {StartOrt} nach {ZielOrt} am {ReiseTag} zu fliegen ?
IntentFlugAbfrage wie teuer ist es am {ReiseTag} von {StartOrt} nach {ZielOrt} zu fliegen ?
…
Das erste Wort eines jeden Satzes ist der Intent Name. Nachdem der Alexa Service eine Äußerung zugeordnet hat, muss er zwei Dinge tun: Platzhalter (von nun an als Slots bezeichnet) herausfiltern und einen Request zu deinem WebService senden. Die gerade erwähnten Slots kann man auch im unteren Beispiel sehen. Es sind die Wörter, die von den geschweiften Klammern umgeben sind, also {ReiseTag}, {StartOrt} und {ZielOrt}. Das Intent Schema legt fest welche Intents es gibt und über welche Slots diese verfügen.
Es gibt Intents die ihr in jeder App haben müsst. Diese sind zum Beispiel:
AMAZON.HelpIntent
AMAZON.CancelIntent
Das Tolle an diesen Intents ist, dass ihr sie nur im Intent Schema angeben müsst, aber keine extra Utterances anlegen müsst. Alexa erkennt die Utterances für „Alexa, Stop“, „Hilfe“ usw.
AMAZON.EUROPE_CITY
). Im Falle, dass die gegebenen Slot Types nicht ausreichen, könnt ihr auch Custom Types anlegen. Ein Beispiel könnten TV Sender sein.
Beispiel:
{
"intents": [
{
"intent": "GetHoroscope",
"slots": [
{
"name": "Sign",
"type": "LIST_OF_SIGNS"
},
{
"name": "Date",
"type": "AMAZON.DATE"
}
]
}
]
}
Schritt 4 – Programming
Jetzt beginnt der Spass. Alexa fragt euch nun, an welchen HTTPS Server die Request vom Voice Service gesendet werden sollen. Wenn ihr nicht gerade Lust habt, euren eigenen HTTPS Server aufzusetzen, zu maintainen und zu bezahlen, dann nehmt ihr am besten den Lambda Service. Lambda erlaubt euch einen Micro Service in der AWS Umgebung zu entwickeln und laufen zu lassen. Super easy – super cool! Zur Wahl stehen NodeJS, Python und Java. Obwohl ich am liebsten alles in Java schreibe, habe ich mich hierbei für Python entschieden. Einfach weniger code.
Geht zunächst auf https://aws.amazon.com und loggt euch ein.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“142″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“163″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Klickt auf Mein Konto -> AWS Management Console.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“143″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“291″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Nun müsst ihr die Region zu Ireland umstellen. Diese ist momentan die einzige europäische Region welche über den Trigger für Alexa Skill Kit verfügt. Frankfurt geht also momentan nicht.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“144″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“209″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Dann wählt den Lambda Cloud Service und Klick „Create a Lambda Function“.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“145″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“269″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Wählt die alexa-skills-kit-color-expert-python blueprint und klick weiter.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“149″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“200″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Bei Configure triggers muss darauf geachtet werden, dass wie in der Abbildung, „Alexa Skill Kit“ ausgewählt ist. Klickt auf Next/Weiter.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“150″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“173″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Im nächsten Schritt kann die Funktion benannt und die Runtime ausgewählt werden. Für dieses Tutorial wähle ich Python. Falls genug Interesse besteht, werde ich auch erklären wie Alexa Skill development mit Java funktioniert.
Auch wenn es sehr verlockend ist – den Abschnitt „Lambda function code“ muss noch ignoriert werden.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“151″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“157″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Als Handler kann der Namen der Funktion angeben werden, die als Endpunkt verwendet werden soll. Hier landen also die HTTPS Requests nachdem sie von dem Alexa Skill eingeordnet wurde und der Request gebaut wurde. (Es wird als JSON erstellt, aber dazu später mehr). Die Auflösung des Handler Names ist folgender: <dateiname>.<funktionsname>. Für dieses Tutorial verwendet bitte den Standard Namen um Probleme zu vermeiden.
Bei der Role sollte zunächste „Choose an existing role“ gewählt werden. Bei Existing Role muss „lambda_basic_execution“ stehen. Falls dies nicht zur Auswahl steht, muss eine neu Custom Role erstellt werden.
In der Sektion „Advanced settings“ kann alles so bleiben wie es voreingestellt ist. Klickt also auf Weiter.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“152″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“364″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Fast geschafft. Nach einer kurzen Überprüfung der Angaben kann die Funktion durch klicken auf „Create function“ erstellt werden.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“153″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“280″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Theoretisch könnte man die Funktion nun innerhalb des Browser programmiert werden. Allerdings werdet ihr früher oder später Bibliotheken verwenden wollen. Daher bietet es sich an die Funktion erst einmal zu exportieren. Nach dem ihr „Export function“ angeklickt habt sollte ein Zip herunter geladen werden (reiseInfoFunktion.zip). Entpackt das Archie und schaut euch den entstanden Ordner an.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“154″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“124″,“typeof“:“foaf:Image“,“width“:“386″}}]]
Wie bereits erwähnt haben wir die Funktion exportiert damit es uns möglich ist Bibliotheken zu verwenden. Die fügt ihr folgendermaßen hinzu:
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“155″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“164″,“typeof“:“foaf:Image“,“width“:“480″}}]]
Stellt sicher das ihr pip installiert habt. Dann öffnet ein Terminal und navigiert zu dem Ordner in dem eure Funktion liegt. Falls er nicht in einem extra Ordner liegt sollten ihr einen erstellen und in diesen ordner navigieren. Führt dann den Befehlt „pip install <packagename> -t .“ aus. Der Parameter -t <dir> sorgt dafür, dass das Paket in das angegebene Verzeichnet installiert („Install packages into <dir>.“). Ich habe zum Beispiel „requests“ installiert und kann es nun wie gewohnt per import in python verwenden.
Jetzt kann es ans Programmieren gehen. Eure Python Datei heisst so, wie ihr es im Punkt „Lambda function handler and role“ bei handler angegeben habt (der Part links vom Punkt). Öffnet diese nun.
[[{„type“:“media“,“view_mode“:“media_large“,“fid“:“156″,“attributes“:{„alt“:““,“class“:“media-image“,“height“:“202″,“style“:“font-size: 13.008px;“,“typeof“:“foaf:Image“,“width“:“480″}}]]
Such die Funktion „lambda_handler“ (Erinnerung: Festgelegt duch Einstellung bei „Lambda function handler and role“). Hier kommen die Anfragen von eurem Alexa Skill an. Gehen wir den Code nun mal gemeinsam durch: Wir erhalten 2 Übergabewerte, von denen uns momentan eigentlicht nur der Erste, nämlich „event“, interessiert.
Zunächst eine Session gestartet. Diese dient dazu, dass sich der Skill während der Nutzerinteraktionen Dinge „merken“ kann. Zum Beispiel den Spielstand bei einem Quiz oder euren Namen. Im Beispiel script passiert in der Funktion on_session_started nichts.
Der Code erklärt sich eigentlich von selbst deswegen gehen wir nun exemplarisch eine Anfrage gemeinsam durch. Damit es spannend wird nehmen wir an, dass wir einen IntentRequest bekommen. Er enthält alle Informationen die wir zur „Beantwortung“ der Nutzer Anfrage benötigen. In Schritt 2 haben wir das Intent Schema festgelegt. Alle dort angegebenen Intents können Zustand von event[‚request‘][‚intent‘][’name‘] sein.
To be continued.