Entwicklung von Alexa Skills

Einleitung

Sprachbediensysteme und digitale Assistenten setzen sich immer mehr durch und gewinnen an Bedeutung. Daher ist es sinnvoll, sich mit diesen Technologien zu beschäftigen und auseinanderzusetzen.

Alexa, der Sprachassistent von Amazon, kann mit sogenannten Alexa Skills um beliebige Funktionen erweitert werden. Dieser Beitrag soll anhand eines Beispiels einen kurzen Überblick über die Funktionsweise und die Entwicklung von Alexa Skills geben.

Als Beispiel soll ein einfaches Spiel mit dem Namen „Kopfrechnen üben“ dienen. Dem Nutzer werden Rechenaufgaben gestellt. Je nach Antwort wird die Aufgabe als „falsch“ oder „richtig“ gewertet. Es ist ebenfalls möglich, Aufgaben zu überspringen. Nach 10 Aufgaben wird dem Nutzer als Ergebnis mitgeteilt, wie viele richtige Antworten er oder sie geschafft hat.

Moderne Sprachbediensysteme

Für jedes Sprachbediensystem ist vor allem das Dialogdesign wichtig. Die Eingaben des Benutzers werden mit Hilfe eines Spracherkenners erfasst, wobei der Nutzer keine Befehle auswendig lernen soll, sondern die Möglichkeit haben soll, frei und natürlich mit dem System zu sprechen. Der Erkenner kann dabei sowohl lokal auf dem Gerät laufen als auch cloudbasiert über das Internet bereitgestellt werden. Im Fall von Alexa wird die sogenannte Wakeup Phrase („Alexa!“) lokal erkannt, alle weiteren Eingaben werden jedoch in die Cloud gesendet und dort von einem cloudbasierten Spracherkenner interpretiert.

Nach der Verarbeitung der Eingaben soll dem Nutzer ein sinnvolles und ebenfalls natürlich wirkendes Feedback gegeben werden. Dies geschieht mit Hilfe einer sogenannten TTS(Text To Speech)-Sprachausgabe. Die Sprachausgaben müssen dabei so gestaltet sein, dass der Nutzer bei der Bedienung der Anwendung im Dialog mit dem Sprachbediensystem steht und unterstützendes Feedback erhält. Er muss jederzeit wissen, was seine letzte Eingabe bewirkt hat und was das System als nächste Information von ihm erwartet. Je nach genutzter Hardware zur Kommunikation mit Alexa ist der Dialog entweder auf reine Sprachbedienung beschränkt (z.B. Echo Dot) oder kann durch grafische Anzeigen ergänzt werden (z.B. Echo Show).

Aufbau von Alexa Skills

Technisch bestehen Alexa Skills aus zwei Teilen: Interaktionsmodell und Service.

Mit Hilfe der Alexa Skills Kit Developer Console im Amazon Developer Portal modelliert der Entwickler die möglichen Eingaben für seinen Skill in Form eines sogenannten Interaktionsmodells. Basierend auf diesem Modell wird die Kommunikation mit dem Skill später auf einem Alexa Server für die Endgeräte bereitgestellt.

Außerdem werden in der Developer Console auch die Eigenschaften des Skills festgelegt. Jeder Alexa Skill verfügt neben einer eindeutigen ID außerdem über einen sogenannten Invocation Name. Mit diesem Namen kann der Skill aufgerufen werden. Beim eingangs beschriebenen Spiel wäre eine Eingabe dafür zum Beispiel “Alexa, starte Kopfrechnen üben“. Dafür muss der Skill vom Nutzer jedoch zuerst über den Amazon Alexa Skills Shop aktiviert werden. Die dort angezeigten Eigenschaften des Skills, zum Beispiel sein Name, eine Beschreibung und ein Icon, wurden im Vorfeld in der Developer Console angegeben.

Der Service hinter dem Skill steuert die Programmlogik, das Dialogverhalten und die Ausgaben. Er wird vom Entwickler in Form eines Webservice bereitgestellt. Die Kommunikation zwischen diesem Service und dem Alexa Server findet im JSON Format statt.

Eingaben mit Intents und Slots

Für jede Eingabe muss ein sogenannter Intent angelegt werden. Dieser kann als Custom Intent frei erstellt und konfiguriert werden. Für Eingaben wie zum Beispiel die Frage nach Hilfe, die in vielen verschiedenen Skills sinnvoll sein können, gibt es aber auch bereits von Amazon vorgefertigte Intents. Für jeden Intent müssen möglichst viele Beispieleingaben genannt werden, die der User sagen könnte, wenn er genau diesen Intent sprechen will. Damit wird eine möglichst natürlich klingende Kommunikation mit dem System unterstützt. Auch die bereits vorgefertigten Intents kann man mit eigenen Eingabebeispielen erweitern und so auf den eigenen Dialog zuschneiden.

Wenn nicht nur die Intention des Nutzers relevant ist, sondern auch seine konkrete Eingabe, können Intents mit Slots kombiniert werden. Für jeden Slot kann ein Datentyp, z.B. freier Text, Zahlen oder europäische Städte, oder auch eine feste Anzahl von vorgegebenen Auswahlmöglichkeiten angegeben werden.

Für den Beispielskill wurden zwei Custom Intents angelegt: Der AnswerIntent mit dem Slot Answer vom Typ AMAZON.NUMBER nimmt die Ergebnisse der Rechnungen entgegen. Einige mögliche Eingaben, die zur Erkennung dieses Intents führen, können in der Abbildung abgelesen werden. Der Platzhalter {Answer} steht dabei für die Platzierung des Slots. Es ist durch das erste Eingabebeispiel in der Liste auch möglich, nur mit einer Zahl ohne zusätzliche Worte zu antworten. Der DontKnowIntent signalisiert den Wunsch, eine Aufgabe zu überspringen, und enthält Eingaben wie „ich weiß es nicht“, „keine Ahnung“, oder „bitte Aufgabe überspringen“. Alle weiteren verwendeten Intents sind von Amazon bereits vorgefertigt und dienen zur allgemeinen Dialogsteuerung, z.B. um den Skill neu zu starten.

Nach Fertigstellung der Modellierung muss mit Hilfe der Developer Console ein Build des Interaktionsmodells durchgeführt werden.

Service als AWS Lambda Funktion

Der Service zur Verarbeitung der Intents kann im Prinzip ein beliebiger Webservice sein, der HTTPS unterstützt und mit den JSON-Daten des Alexa Servers umgehen kann. Zur Vereinfachung der Serviceseite von Alexa Skills gibt es auch die Möglichkeit, eine AWS Lambda Funktion zu nutzen. Dieser Weg wurde für das Beispiel gewählt.

AWS steht für Amazon Web Services. Neben vielen anderen Services wird hier die Möglichkeit geboten, mit einer sogenannten AWS Lambda Funktion einen Endpunkt für einen Service anzubieten. Diese Funktion kann speziell für die Zusammenarbeit mit dem Alexa Skills Kit konfiguriert werden. Hierfür verbindet man Alexa Skill und AWS Lambda Funktion wechselseitig, indem man einerseits in der AWS Lambda Funktion die ID des Skills als Trigger angibt, andererseits den Skill in der Alexa Skills Kit Developer Console für die Nutzung mit AWS konfiguriert und die eindeutige Adresse der AWS Lambda Funktion, die sogenannte ARN (Amazon Resource Name), dort hinterlegt.

Der Code für den Service kann in einer von vielen Programmier- und Skriptsprachen geschrieben werden, z.B. in Java, Python, JavaScript (Node.js), oder C#.  Für das Beispielprogramm wurde Java gewählt. In der AWS Developer Console, dem Webinterface von AWS, kann das Programm in diesem Fall als JAR hochgeladen werden und man kann angeben, welche Klasse als Handler Anfragen entgegennimmt. Diese Klasse muss von einer abstrakten Klasse abgeleitet werden, auf die im weiteren Text noch näher eingegangen wird. Für andere Sprachen, wie z.B. JavaScript, ist es auch möglich, den Code direkt in der AWS Developer Konsole zu schreiben.

Implementierung des Service

Als API zur Kommunikation mit dem Alexa Server muss die Alexa Skills Kit Library für Java verwendet werden, die per Maven eingebunden werden kann. Ebenso wird Maven verwendet, um das JAR-File für den AWS Upload zu bauen.

Die API beinhaltet u.a. den SpeechletRequestStreamHandler, von dem die Klasse abgeleitet werden muss, die als Einsprungspunkt für die AWS Lambda Funktion dient. Ein weiterer wichtiger Bestandteil ist das Interface Speechlet. Die Klasse, die Speechlet implementiert, ist das eigentliche Programm hinter dem Skill. Sie wird vom Handler instanziiert und mit den bereits aufbereiteten Daten vom Alexa Server versorgt. Ein manuelles Parsen der JSON-Nachrichten ist nicht nötig.

Dialogführung und Prompting

Alle Nutzeranfragen kommen über die Methoden onLaunch und onIntent des Speechlets an. Dabei wird onLaunch beim initialen Start eines Dialogs ohne gleichzeitige Erkennung eines Intents verwendet, in allen anderen Fällen wird onIntent aufgerufen.

public SpeechletResponse onLaunch(LaunchRequest request, Session session)

public SpeechletResponse onIntent(IntentRequest request, Session session)

Im IntentRequest können der erkannte Intent und ggf. auch Slotinhalte ausgelesen werden. Diese Daten kann das Programm verwenden, um seine Dialoglogik entsprechend abzuarbeiten, die zum Beispiel als Statemachine implementiert sein kann. So kann eine passende Rückantwort an den Nutzer ermittelt werden und das Programm kann auf zu erwartende weitere Eingaben vorbereitet werden. onIntent könnte beispielsweise folgendermaßen aussehen:

Dialog dialog = new Dialog();
Intent intent = request.getIntent();

if ("AMAZON.StartOverIntent".equals(intent.getName()) || session.isNew()) {
       dialog.setSession(session, true);
       return dialog.startGame();
} else if ("AnswerIntent".equals(intent.getName())) {
       // question answered
       dialog.setSession(session, false);
       return dialog.questionAnswered(intent.getSlot("Answer"));
} else if ("DontKnowIntent".equals(intent.getName())) {
       // question skipped
       dialog.setSession(session, false);
       return dialog.questionSkipped();
} else if ("AMAZON.HelpIntent".equals(intent.getName())) {
       return dialog.help();
} else if ("AMAZON.CancelIntent".equals(intent.getName())) {
       return dialog.cancel();
} else if ("AMAZON.StopIntent".equals(intent.getName())) {
       return dialog.cancel();
} else {
       throw new SpeechletException("Unrecognized intent: " + intent.getName());
}

Der Parameter Session kann und sollte dabei für das Sessionhandling verwendet werden. An der Session können beliebige Daten hinterlegt werden, die bei der nächsten Eingabe des Nutzers wieder mitgesendet werden. Das Programm selber sollte keine Daten z.B. in Membervariablen vorhalten und bei einem erneuten Aufruf wiederverwenden, da mit AWS nicht sichergestellt ist, dass derselbe Nutzer immer wieder mit derselben Instanz des Programms kommuniziert. Daher muss das Programm jederzeit mit allen möglichen Eingaben zurechtkommen und sich basierend auf den Daten in der Session konfigurieren. Pro Nutzer wird dabei die selbe Session vom Start des Skills durch den Nutzer bis zum Ende des Dialogs durch das Programm verwendet. Wird der Skill ein weiteres Mal gestartet, wird eine neue Session erzeugt.

Wenn die Verarbeitung der aktuellen Eingabe abgeschlossen ist und die Sessiondaten entsprechend aktualisiert wurden, kann der Rückgabewert vom Typ SpeechletResponse genutzt werden, um dem Nutzer akustisch und ggf. visuell Feedback zu geben. Dafür gibt es in der SpeechletResponse u.a. die Felder OutputSpeech und Card.

OutputSpeech enthält den Text für die Sprachausgabe per TTS, den sogenannten Prompt. Dieser kann entweder ein Freitext sein oder in SSML (Speech Synthesis Markup Language) verfasst werden. SSML ist ein XML-basierter Standard, mit dem man Sprachausgaben sehr detailliert steuern kann und z.B. Pausen, Betonungen oder Phoneme verwenden kann. Um eine natürliche Ausgabe zu erhalten, kann man für jede Systemreaktion mehrere Prompts definieren und per Zufallsgenerator aus diesen auswählen.

public static final String[] QUESTION_PROMPTS = new String[]{

       "Was ist <say-as interpret-as="cardinal">%s</say-as> %s <say-as interpret-as="cardinal">%s</say-as>?",
       "Wieviel ist <say-as interpret-as="cardinal">%s</say-as> %s <say-as interpret-as="cardinal">%s</say-as>?",
       "Was ergibt <say-as interpret-as="cardinal">%s</say-as> %s <say-as interpret-as="cardinal">%s</say-as>?"
    };

...

questionPrompt = String.format(Prompts.QUESTION_PROMPTS[randomizer.nextInt(RANDOM_PROMPT_COUNT)], task.getFirst(), getSymbolPrompt(task), task.getSecond());

...

SsmlOutputSpeech speech = new SsmlOutputSpeech();

speech.setSsml("&lt;speak&gt;" + prefixPrompt + " " + questionPrompt + "&lt;/speak&gt;");

...

return SpeechletResponse.newAskResponse(speech, reprompt, card);

Die optionale Card kann einen auf kompatiblen Geräten darstellbaren Bildschirminhalt beschreiben, bei dem man Überschrift, Fließtext und eine Grafik integrieren kann.

Außerdem kann über die SpeechletResponse gesteuert werden, ob der Dialog beendet werden soll oder nicht. Beim Beenden des Dialogs würde sich das Alexa Gerät nach der Ausgabe deaktivieren. Wenn der Dialog aufrechterhalten werden soll, würde das Gerät aktiv bleiben, den Spracherkenner für eine gewisse Zeit offenhalten und auf weitere Eingaben warten.

Testen und Veröffentlichen des Skills

Der Skill ist auf jedem Amazon Gerät, dass mit dem im Developer Portal genutzten Account verbunden ist, automatisch aktiviert. Außerdem gibt es im Alexa Skills Kit die Möglichkeit, den Skill für Testzwecke mit Texteingaben zu verwenden. Dies ist sehr praktisch zur Fehleranalyse und erlaubt einen etwas tieferen Einblick in den Ablauf der Kommunikation, da das JSON für Anfrage und Rückantwort in der Weboberfläche angezeigt wird.

Wenn man sich entschließt, den eigenen Skill im Alexa Skills Shop zu veröffentlichen, muss der Skill von Amazon vorgegebene Kriterien erfüllen. Er durchläuft einen Zertifizierungsprozess und wird nach erfolgreicher Annahme im Alexa Skills Shop freigeschaltet, so dass ihn alle Nutzer für ihr Alexa Gerät aktivieren können, sofern ihre eingestellte Sprache vom Skill unterstützt wird.

Fazit

Alexa Skills zur Erweiterung von Amazon Alexa lassen sich in wenigen Schritten erstellen. Es ist dabei jedoch wichtig, auf ein gutes und natürliches Dialogdesign zu achten, um die Erwartungen der Nutzer zu erfüllen und keine Frustration z.B. durch nicht verstandene Eingaben aufkommen zu lassen. Die für die Entwicklung zur Verfügung gestellten Tools und auch die Fähigkeiten der angebotenen Endgeräte werden ständig weiterentwickelt, wirken aber bereits ausgereift und sind gut nutzbar.

Quellen

https://developer.amazon.com/de/docs/ask-overviews/build-skills-with-the-alexa-skills-kit.html

https://developer.amazon.com/alexa-skills-kit/tutorials

https://aws.amazon.com/de/documentation/lambda/

https://github.com/alexa?language=java

https://www.w3.org/TR/speech-synthesis11/

Von |2018-05-27T19:19:55+00:0026. Mai 2018|Apps, Java, Programmierung, teck*talk, Tutorials|Kommentare deaktiviert für Entwicklung von Alexa Skills

Über den Autor:

Nina Pralle
Software-Entwicklerin bei eck*cellent IT