Alexa Skill: Endpoint basato su Azure Function

Alexa Skill: Endpoint basato su Azure Function

Sviluppare una Skill per Alexa e’ (relativamente) semplice grazie all’interfaccia intuitiva offerta dal portale Amazon Developer Services. Il grosso scoglio che ho trovato durante la primissima prova e’ stato l’utilizzo di NodeJS a me totalmente oscuro come linguaggio. Fortunatamente tra StackOverflow ed una serie di ricerche in Google l’esperimento e’ andato a buon fine.

In quel momento sono sorte le prime domande a cui trovare una risposta:

  • Se volessi fare del codice di backend più spinto come piace a me per Alexa?
  • Se volessi integrare del codice che vive nell’ecosistema Azure Cloud?

La risposta -di per se molto intuitiva- e’ stata la mia amata Azure Function e per farlo servono pochissimi passaggi. Ora cercherò di riportare tutti i passaggi in modo chiaro ed ordinato

IMPORTANTE: I prerequisiti per questo articolo sono i seguenti.

  • Essere in possesso di un account su Azure
  • Essere in possesso di un account su AWS & Amazon Developer Service
  • Sapere creare una Azure Function e pubblicarla
  • Sapere i concetti base legati al mondo Alexa/Alexa Skill

Azure: New Function

Per potere utilizzare una Azure Function come Endpoint della nostra Alexa Skill dobbiamo crearla. Come primo punto al vostro progetto dovete aggiungere tramite Nuget il seguente pacchetto: Alexa.NET

Dopo avere effettuato questo passaggio dovete definire la vostra Function nel seguente modo:

Aggiunta delle using necessarie

1
2
3
4
using Alexa.NET;
using Alexa.NET.Request;
using Alexa.NET.Request.Type;
using Alexa.NET.Response;

Dichiarazione della Function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[FunctionName("AlexaSkillTest")]
public async Task<IActionResult> Run(
	[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
	ILogger log)
{
	string json = await req.ReadAsStringAsync();
	var skillRequest = JsonConvert.DeserializeObject<SkillRequest>(json);
	var result = await ProcessRequest(skillRequest, log);
	return result;
}

Analisi richiesta della Skill Il seguente codice (privato ovviamente delle parti sviluppate nello specifico) e’ un ottimo punto di partenza per cominciare a capire i dati forniti dalla skill alla nostra function e fornire un ritorno alla Skill (e di conseguenza all’utente)

 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
31
32
33
34
35
36
private async Task<IActionResult> ProcessRequest(SkillRequest skillRequest, ILogger log)
{
	var requestType = skillRequest.GetRequestType();

	SkillResponse response = null;
	if (requestType == typeof(LaunchRequest))
	{
		response = ResponseBuilder.Tell("I'm the LaunchRequest");
		response.Response.ShouldEndSession = false;
	}
	else if (requestType == typeof(IntentRequest))
	{
		var intentRequest = skillRequest.Request as IntentRequest;

		switch (intentRequest.Intent.Name)
		{
			case "TestFirstIntent":
				{
					response = ResponseBuilder.Tell("I'm the TestFirstIntent");
					break;
				}
			case "TestSecondIntent":
				{
					response = ResponseBuilder.TellWithReprompt( ... );
					break;
				}
		}
		response.Response.ShouldEndSession = false;
	}
	else if (requestType == typeof(SessionEndedRequest))
	{
		response = ResponseBuilder.Tell("See you next time!");
		response.Response.ShouldEndSession = true;
	}
	return new OkObjectResult(response);
}

Chiamata: ResponseBuilder.TellWithReprompt Come avrete notato ho privato di parametri la chiamata a ResponseBuilder.TellWithReprompt in quanto preferisco darvi le firme presenti al momento e lasciare decidere voi quale e’ più adatta alle vostre esigenze:

1
2
3
4
5
6
public static SkillResponse TellWithReprompt(Speech speechResponse, Reprompt reprompt, Session sessionAttributes);
public static SkillResponse TellWithReprompt(Speech speechResponse, Reprompt reprompt);
public static SkillResponse TellWithReprompt(string speechResponse, Reprompt reprompt);
public static SkillResponse TellWithReprompt(IOutputSpeech speechResponse, Reprompt reprompt);
public static SkillResponse TellWithReprompt(IOutputSpeech speechResponse, Reprompt reprompt, Session sessionAttributes);
public static SkillResponse TellWithReprompt(string speechResponse, Reprompt reprompt, Session sessionAttributes);

Vi invito caldamente a guardare la classe ResponseBuilder per visionare tutte le firme offerte per lo sviluppo della skill.

Ora vi consiglio di pubblicare la skill in modo da avere il vostro EndPoint da poterlo poi testare dal portale Amazon.

Alexa: Create Skill

Entrando nel portale Amazon Developer Services troverete il pulsante Create Skill e dalle opzioni proposte dovrete selezionare:

Choose a model to add to your skill: There are many ways to start building a skill. You can design your own custom model or start with a pre-built model. Pre-built models are interaction models that contain a package of intents and utterances that you can add to your skill.

  • Custom: Design a unique experience for your users. A custom model enables you to create all of your skill’s interactions.

Choose a method to host your skill’s backend resources: You can provision your own backend resources or you can have Alexa host them for you. If you decide to have Alexa host your skill, you’ll get access to our code editor, which will allow you to deploy code directly to AWS Lambda from the developer console.

  • Provision your own: Provision your own endpoint and backend resources for your skill. This is recommended for skills that have significant data transfer requirements. You will not gain access to the console’s code editor.

Ora dobbiamo solamente attenere il tempo tecnico per la creazione dalla skill su Amazon

Alexa: Configurazione ENDPOINT

Ora manca l’ultimo passaggio fondamentale per fare parlare la Skill e la nostra Azure Function. Per farlo dobbiamo configurare l’EndPoint e per farlo dobbbiamo andare nella sezione apposita chiamata “Endpoint” e la possiamo trovare nella colonna di sinistra nel menu.

The Endpoint will receive POST requests when a user interacts with your Alexa Skill. The request body contains parameters that your service can use to perform logic and generate a JSON-formatted response. Learn more about AWS Lambda endpoints here. You can host your own HTTPS web service endpoint as long as the service meets the requirements described here.

A questo punto ci viene chiesto in prima battuta quale filone di endpoint vogliamo utilizzare

  • AWS Lambda ARN (Recommended)
  • HTTPS

Nel nostro caso la scelta ricadrà su HTTPS

Nella casella di testo Default Region dovrete mettere l’url della Azure Function appena pubblicata. Il menu a tendina sotttostante propone la scelta tra tre diverse opzioni:

  • My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority
  • My development endpoint has a certificate from a trusted certificate authority
  • I will upload a self-signed certificate in X 509 format

La voce da scegliere sara’ My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority

Qualora la vostra Skill sara’ a livello globale/mondiale (cosa che vi auguro perché significa che vi state divertendo con un progetto bello grosso) avrete la possibilita’ di distribuire gli endpoint a livello geografico (anche solamente per la vicinanza al database e riduzione dei tempi di risposta)

  • North America (Optional)
  • Europe and India (Optional)
  • Far East (Optional)

Una volta salvato il vostro endpoint potrete effettuare una simulazione di comunicazione tramite il tab test

Alexa: Test della Skill

In questa fase vi consiglio due punti molto rapidamente che rientrano in parte nei presupposti indicati in testa

  • Associate un Application Insight alla vostra Azure Function e monitorate il tutto con Live stream (anche perche e’ molto figo da vedere)
  • Per la fase di sviluppo/debug cambiate l’endpoint utilizzando ngrok sulla vostra macchina

Ora non mi resta che augurarvi buon divertimento perdendovi nel Cloud!