Lo scopo di questo progetto è quello di riuscire ad interpretare il linguaggio naturale in termini di estrazione delle entità da una frase, che rappresentano le intenzioni di un soggetto in seguito all’espressione di un comando. Questa funzionalità sarà poi riutilizzabile per interpretare anche dei comandi vocali.

Per fare ciò ci siamo appoggiati ai servizi offerti da Microsoft Azure. In particolare Azure una famiglia di servizi cloud con API REST ed SDK delle librerie client disponibili per aiutare a integrare l’intelligenza cognitiva nelle applicazioni. Tali servizi sono detti cognitive services e il catalogo dei servizi offerti è suddiviso in 5 categorie:

  • Visione
  • Sintesi vocale
  • Lingua
  • Decisione
  • Ricerca

Quello che a noi interessa è il servizio lingua, in particolare Azure Luis.

AZURE LUIS

LUIS (Language Understanding) è un servizio di intelligenza artificiale conversazionale basato sul cloud che applica l’intelligenza di Machine Learning al testo in linguaggio naturale per prevedere il significato generale ed estrarre informazioni pertinenti e dettagliate.

Per testare questo servizio abbiamo deciso di creare un caso d’uso realistico da poter testare. Abbiamo deciso di simulare la prenotazione di una sede tramite comando vocale.
Quindi ad esempio dalla frase “prenota la sede di Erbusco per il 15 dicembre” quali sono le entità da estrarre?

Prima di tutto serve capire in che modo è strutturato LUIS. Per far si che il testo venga interpretato correttamente è necessario definire degli intents (finalità, intenti) e delle entities (entità).

Un’entità è usata come una variabile in algebra. Viene utilizzato per acquisire e trasmettere informazioni importanti. Gli intenti, invece, sono il modo in cui LUIS determina ciò che un utente vuole fare.

Nel nostro caso abbiamo creato 3 intenti: prenota, elimina e sposta.
Successivamente abbiamo aggiunto delle entità già fatte che fanno riferimento agli eventi di un calendario in quanto ci è d’aiuto con le date. Inoltre abbiamo creato un’entità lista con all’interno tutte le sedi Sme.Up in modo che vengano sempre riconosciute.

Di seguito troviamo un esempio dell’intent prenota: 

Come possiamo notare la frase viene riconosciuta come un’entità “phrase” che a sua volta è composta da un’azione, da una sede e da una data. Queste tre entità dunque compongono un comando vocale base che abbiamo definito noi all’interno della sezione entità.

Come possiamo notare l’elemento “place” ha una features “Sedi”. Si tratta di una lista che può essere creata dal portale LUIS e contiene tutte le sedi Sme.UP.

La data a sua volta ha una certa complessità in quanto può essere di 3 tipi: il, dal, al. Questa distinzione è stata creata per facilitare l’interpretazione del comando “sposta” in quanto sono necessarie due date.

INTEGRAZIONE LUIS 

Una volta definite le entità, gli intenti e effettuato il training del modello possiamo iniziare a effettuare dei test. 

Per poter fare dei test all’interno di Sme.Up abbiamo dovuto configurare lo script LOA38.  Infatti tale script serve ad indicare a Sme.UP verso chi richiedere (o inviare) i dati e come deve inviare (o riceverli).

In seguito ad un’analisi sulla varietà di operazioni che è possibile effettuare con LUIS e la diversità di input richiesti per ogni operazione, abbiamo deciso di “nascondere” la complessità delle chiamate a LUIS dietro una piccola API creata con Node.js, che semplifica la comunicazione tra AS/400 e il portale LUIS di Microsoft Azure. 

In seguito a questa stratificazione è ora possibile effettuare 3 operazioni principali,

Dopo un’analisi è emerso che per un funzionamento base è necessario definire 3 chiamate:

  1. Chiamata per aggiornare o creare da nuovo un’entità. Serve per poter modificare ed effettuare il training del modello con nuove informazioni aggiuntive nel caso si volesse migliorare il modello (ad esempio potrebbe essere necessaria l’aggiunta di una nuova sede nell’elenco sedi). 
  2. Chiamata per eliminare un’entità, utile in caso l’entità sia stata aggiunta per errore o non sia più necessaria. Anche in seguito a questa chiamata viene effettuato il training del modello.
  3. Chiamata per l’interpretazione del comando. Si tratta della chiamata principale in quanto da qui otterremo il json con all’interno tutte le informazioni principali.

Di seguito un esempio di configurazione del LOA38:

::SEZ Cod="M04" Txt="Aggiunta nuove entità"
::A38.CLSSEZ Class="com.smeup.wscspi.httpdelegate.HttpDelegatePlugin" Log="Yes" Url="https://node-luis-service.azurewebsites.net/[a38.app_id]/[a38.version_id]/create_list" HttpMode="POST" HttpAuth="none" CntGrp="com.smeup" CntArt="WSCSPI-httpdelegate" CntVer="1.8.0"
::A38.CNFSEZ Name="HttpDebug" Value="true"

::SUB Cod="001" Txt="Info"
::A38.SUBMET Value="GetModel" Txt="Informazioni modelli"
::A38.SUBVAR Name="Content-Type" Txt="Type" TpVar="Hea" DftVal="application/json"
::A38.SUBVAR Name="Ocp-Apim-Subscription-Key" Txt="Token di autenticazione" TpVar="Hea"
::A38.SUBVAR Name="app_id" Txt="ID Applicazione" TpVar="Int"
::A38.SUBVAR Name="version_id" Txt="ID modello" TpVar="Int"
::A38.SUBVAR Name="json" Txt="Lista" TpVar="Int"

In questo caso richiamiamo l’endpoint per creare una nuova entità di tipo lista. Per effettuare questa chiamata sarà necessario specificare nell’url l’app id e il version id, reperibili dal portale Luis.
Nell’header della richiesta andremo ad inserire la “subscriprion key” per verificare che esista un account con una sottoscrizione valida e anche il “content-type” che di default è settato a “application/json”, infatti nel body poi andremo ad inserire un JSON. In quest’ultimo dovremo specificare il nome della lista e poi gli elementi della lista.

{
  name: "Sedi test",
  sublists: [
    {
      canonicalForm: "Erbusco"
    },
    {
      canonicalForm: "Parma"
    },
  ],
}

Come possiamo inoltre notare dall’URL della chiamata ci accorgiamo che in realtà ci stiamo appoggiando a una piccola applicazione web Node.js che espone degli endpoint per interfacciarsi a Azure. Così facendo possiamo automatizzare dei processi ogni volta che viene effettuata la chiamata. 
Un esempio è la pulizia del json di risposta dell’API che estrae le entità da una frase. Infatti grazie a Node.js abbiamo creato una piccola funzione che collegata all’API rende molto più “leggero” e leggibile il json di risposta. 

Vediamo quindi quali sono gli endpoint esposti per potersi interfacciare a LUIS:

  • GET https://node-luis-service.azurewebsites.net/list – Lettura di tutte le entità di tipo lista presenti su LUIS
  • GET https://node-luis-service.azurewebsites.net/[app_id]/[subscription_key]/entity?phrase=… – Estrazione entità da una frase
  • POST https://node-luis-service.azurewebsites.net/[app_id]/[version_id]/lists – Creazione di una nuova entità di tipo lista
  • PUT https://node-luis-service.azurewebsites.net/[app_id]/[version_id]/update_list/[list_id] – Modifica di una lista
  • GET https://node-luis-service.azurewebsites.net/[app_id]/[version_id]/delete_list/[list_id] – Eliminare una lista

SCHEDA PER TESTARE SERVIZIO

Per testare il servizio è necessario un semplice campo testuale. Inserendo la frase desiderata riceveremo come output un json con all’interno la topIntent e le varie entità che compongono la frase.

API Node.js con Azure App Service

Per caricare un’app su Azure App Service per prima cosa bisogna installare un’estensione per Visual Studio Code, chiamata Azure App Service.

I passi successivi sono:

Nota: Noi abbiamo caricato l’app su una machina Linux, quindi i passaggi successivi servono per caricare su Linux, per windows ci sono dei passaggi aggiuntivi.

  • Accedere al portale Microsoft Azure
  • Dopo l’accesso premere sulla sulla seconda icona nella finestra APP SERVICE
  • Scegliere la directory ( app ) da caricare
  • Scegliere Create new Web App
  • Immettere un nome univoco per l’app
  • Scegliere una versione di Node.Js (noi abbiamo usata la versione LTS)
  • Selezionare Yes al messaggio:
  • Selezionare Yes al messaggio seguente sotto indicato per assicurarsi che il deployment delle modifiche venga fatto sull’app giusta