AIML e teoria dei chatbot – Seconda parte

AI, INTELLIGENZA ARTIFICIALE, TUTORIAL

AIML

Quando si parla di intelligenza artificiale, si fa riferimento alla scienza che studia sistemi  in grado di simulare il pensiero umano, ovvero di  risolvere problemi con un approccio tipico di un essere umano e di agire autonomamente su categorie di  problemi normalmente molto difficili da affrontare per le macchine. Questa definizione lascia intendere che in realtà l’AI non è una una scienza relegata ad un contesto ristretto di tecnologie, ma abbraccia diverse tecniche e conoscenze  necessarie per raggiungere l’obiettivo enunciato.

In merito, qualche tempo fa, avevo scritto un articolo, in cui cercavo di spiegare proprio questo concetto; ad ogni modo mi risoffermo sul tema, perché deve essere  chiaro che parlare di  IA, non significa parlare esclusivamente di reti neurali. L’area dell’IA, ad esempio,  che si occupa dello studio dell’interazione uomo-macchina attraverso il linguaggio naturale (NLP) è una delle più interessanti ed in merito sono stati utilizzati approcci diversi per risolvere le complessità legate alla lingua, quali ad esempio la disambiguazione dei concetti espressi o la contestualizzazione di parole legate i problemi di polisemia della lingua; in merito possiamo sicuramente annoverare tecniche basate su reti neurali ricorsive RNN o su algoritmi in grado di valutare statisticamente le ricorrenze delle parole; a questo tipo di tecniche, si affiancano anche metodi più tradizionali basati su linguaggi specializzati nella  modellazione della lingua naturale. Tra i più diffusi possiamo sicuramente annoverare  l’AIML che sarà oggetto di studio di questo articolo.

Che cosa è L’AIML

L’AIML (Artificial intelligence markup language)  è  un linguaggio XML compliant, ideato da Richard S. Wallace per facilitare la scrittura di regole al fine di modellizzare un sistema in grado di intrattenere dialoghi in linguaggio naturale. L’AIML viene spesso utilizzato per la creazione di CHATBOT e devo dire che per lo scopo è  uno strumento efficace, ma solo nel caso in cui si voglia realizzare un sistema in grado di rispondere, esclusivamente a domande in un contesto definito,  accettando il limite di un livello di auto apprendimento praticamente nullo. Prima di infilarci, pertanto,  in esempi e strutture AIML  cerchiamo di  capirne la filosofia e comprenderne le regole generali.

Come funziona

L’AIML funziona grazie ad un meccanismo di stimolo e risposta. La risposta verrà restituita  solo se esisterà nei files di configurazione una regola in grado di “intercettare” lo stimolo o domanda. Essendo L’AIML un markup language XML compliant è ovvio immaginare, pertanto, che la struttura delle regole sarà costruita attraverso l’uso di tag. Tra i  più importanti abbiamo:

  • <aiml>: è il tag che apre e chiude un document AIML
  • <category>: è il blocco base ed racchiude la singola regola
  • <pattern>: racchiude un pattern semplice che corrisponde a cosa dice o scrive un utente
  • <template>: racchiude la risposta ad un input utente

Una configurazione AIML sarà costituita in generale da strutture di conoscenza elementari <category> in ognuna delle quali sarà sempre presente l’elemento <pattern> ed il <template>. D’ora in avanti, pertanto, chiameremo questa struttura semplicemente categoria.

Esempio di categoria:

<category>
<pattern> TESTO </pattern>
<template> TESTO </template>
</category>

Sintassi AIML tag

Come in altri markup language anche nell’AIML  i tag sono sempre delimitati da “<” e “>”  ed in generale nella struttura formale di un contesto ci sarà sempre un tag di apertura ed un tag di chiusura :

<tag> informazione </tag>

Solo in alcuni casi, dove tra i tag  non dovrà essere inserita un’informazione, si potrà scrivere direttamente in forma abbreviata qualcosa del genere:

<tag/>

Cerchiamo di capire la struttura di una configurazione AIML attraverso un primo esempio :

Esempio 1

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<aiml>

<category>
<pattern>chi sei</pattern>
<template>sono un assistente virtuale</template>
</category>

</aiml>

In questo esempio alla domanda : chi sei  il sistema risponderà -> sono un assistente virtuale. Ovviamente il sistema non sarà in grado di rispondere ad  input diversi da quello configurato. Se scrivessi ad esempio : tu chi sei  –> il sistema non sarà in grado di rispondere. Come risolvere  questo primo problema? Banalmente introducendo il concetto di wildcard di cui  riporto  un’immagine che ne spiega bene l’uso evidenziando altresì i livelli di priorità che introducono le stesse durante la fase di matching dell’input.

 

In altre parole HELLO * avrà meno priorità ad esempio di HELLO THERE che avrà meno priorità di HELLO #

Riscriviamo l’esempio

Esempio 2

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<aiml>
<category> <pattern>* chi sei</pattern> <template>sono un assistente virtuale</template> </category> </aiml>

in questo caso se scrivessi chi sei non otterrei risposta mentre otterrei risposta a:  tu chi sei oppure ma chi sei.  Se volessi usare una sola regola per intercettare i due casi, basterà usare la wildcard #

Esempio 3

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<aiml>

<category>
<pattern># chi sei</pattern>
<template>sono un assistente virtuale</template>
</category>

</aiml>

La wildcard # infatti come descritto nella figura precedente identifica zero o più parole a differenza di * che identifica una o più parole.

Esempi di pattern AIML validi 

<pattern>*</pattern>
<pattern>HOW ARE YOU</pattern>
<pattern>How are you</pattern>
<pattern>HoW aRe YoU</pattern> -- AIML patterns sono case invariant
<pattern><set>color</set></pattern>
<pattern><SET>COLOR</SET></pattern> <pattern>I LIKE <set>color</set></pattern> <pattern>_ THANK YOU</pattern> <pattern>_ MUSIC *</pattern> <pattern># MUSIC #</pattern> <pattern>I LIKE # MUSIC</pattern>
<pattern>_ * _ * _</pattern> regola potenzialmente valida anche se senza significato

Esempi di pattern AIML non validi 

<pattern></pattern> Pattern senza contenuto non sono validi
<pattern>How are you?</pattern> -- Pattern con punti di punteggiatura non sono validi
<pattern>I LIKE*</pattern> -- wildcard devono essere sempre separati dalla spazio
<pattern><set>*</set></pattern> -- nei set non posso essere usati wildcard
<pattern>_*_*_</pattern> -- le wildcard dovrebbero avere spazi che li separano

Lista TAG AIML

Iniziamo a fissare la lista dei tag AIML più importanti, che via via impareremo ad usare.

<aiml> Definisce l’inizio e la fine di un documento AIML
<category> Definisce l’unità di conoscenza AIML
<pattern> Definisce il pattern utente che sarà valutato
<template> Definisce il risultato ad un input
<star> Identifica in template l’elemento wildcard del pattern
<srai> Identifica un sinonimo o alias
<random> Utilizzato per creare risposte random
<li> Elemento in risposte multiple usato insieme al  tag random o in condition
<set> Tag per configurare il valore di nuove  variabili 
<get> Tag per ottenere il valore di una variabile
<that> Consente di contestualizzare le risposte in base al contesto della risposta precedente
<topic> Definisce un context 
<think> Esegue dei tag AIML senza fornire risposte agli stimoli. Usato per settare variabili. 
<condition> Tag usato per creare delle risposte condizionate 

Struttura base: <pattern> e <template>

Proviamo ad approfondire le strutture AIML disponibili iniziando da quella base <pattern> e <template>

<?xml version="1.0" encoding="UTF-8"?> <aiml version="1.0"> 

<category>
<pattern>CIAO</pattern>
<template>Buon giorno.</template>
</category>

<category>
<pattern>*</pattern>
<template>Cosa vuoi dire?</template>
</category>

</aiml>

L’esempio, appena descritto è in grado di rispondere al saluto “CIAO” ed a qualunque altro stimolo con la risposta cosa vuoi dire? proviamo a migliorarne la dinamicità utilizzando un nuovo tag <srai> che ci consentirà di gestire i sinonimi

<?xml version="1.0" encoding="UTF-8"?> 
<aiml version="1.0">

<category>
<pattern>CIAO</pattern>
<template>Buon giorno.</template>
</category>
<category>

<pattern>SALVE</pattern>
<template><srai>CIAO</srai></template>
</category>
<category>

<pattern>BUON GIORNO</pattern>
<template><srai>CIAO</srai></template>
</category>

<category>
<pattern>*</pattern>
<template>Cosa vuoi dire?</template>
</category>

</aiml>

L’elemento <srai> può essere  usato solo all’interno di un elemento <template> ed introduce  una ricorsione. In questo caso, quando lo stimolo è «salve» o «buon giorno», si va a produrre la stessa risposta che si avrebbe con lo stimolo «ciao». Le risposte agli stimoli, come intuito,  posso essere composte anche da strutture complesse e quindi non necessariamente solo testo. Iniziamo in tal senso a comprendere l’uso del tag  <star>. Il tag <star> indica l’elemento che “matcha” la  wildcard o un <set> nel pattern. Proviamo a capire il  tag con degli esempi.

<category> 
<pattern>Salve</pattern>
<template>Salve, come ti chiami?</template>
</category>

<category>
<pattern>Il mio nome è *</pattern>
<template>Piacere di conoscerti <star/> </template>
</category>

L’esempio  introduce un semplice concetto di domanda e risposta; in tal caso il tipico dialogo potrebbe essere qualcosa del tipo :

Utente: Salve
Bot: Salve, come ti chiami?
Utente: il mio nome è Domenico
Bot: Piacere di conoscerti Domenico

In pratica con lo <star/> intercettiamo il  valore corrispondente alla prima wildcard. Complichiamo un pò l’esempio:

<category> 
<pattern>Salve</pattern>
<template>Salve, come ti chiami?</template>
</category>

<category>
<pattern>Il mio nome è  *  ed il mio cognome è *</pattern>
<template>Piacere di conoscerti <star index=1> <star index=2> </template>
</category>

In questo ultimo caso il dialogo risultante sarà qualcosa del tipo:

Utente: Salve

Bot: Salve, come ti chiami?

Utente: il mio nome è Domenico e dil mio cognome è Soriano

Bot: Piacere di conoscerti Domenico Soriano

Facciamo qualche altro esempio usando il tag <srai>

<category> 
<pattern>DIMMI *</pattern>
<template><star/></template>
</category>
in questo esempio il sistema sarà in grado di rispondere a stimoli del tipo :
utente : dimmi ciao
bot: ciao
utente: dimmi ti voglio bene
bot: ti voglio bene
estendiamo la struttura con lo <srai>
<category> 
<pattern>DIMMI *</pattern>
<template><star/></template>
</category>

<category>
<pattern>GENTILMENTE DIMMI *</pattern>
<template><srai>DIMMI <star/></srai></template>
</category>
in tal caso l’utente potrà chiedere qualcosa del tipo:
utente: gentilmente dimmi ti voglio bene
questo input verrà trasformato in
-> dimmi ti voglio bene
che richiamerà il primo blocco il cui pattern è DIMMI *, il bot continuerà a rispondere:
bot: ti voglio bene
 
NB: il tag <sr> è una semplificazione di <srai><star/></srai>.

Categoria con  variabili

In una category è possibile dichiarare e leggere delle variabili , attraverso l’uso degli  elementi set e get. Le variabili dichiarate in questo modo hanno valore globale e se si tenta di leggere una variabile non ancora dichiarata, si ottiene la stringa «unknown», nel caso contrario  si ottiene l’ultimo valore configurato.

<category> 
<pattern>MI CHIAMO *</pattern>
<template>Ciao <set name="nome"><star/></set>, come va?</template>
</category>

nell’esempio precedente se l’utente scrivesse Mi chiamo Domenico la variabile name=”nome” verrebbe valorizzata con il contenuto di <star> che sappiamo essere in tal caso il valore intercettato dallo * nel nostro caso Domenico.

MI CHIAMO *  -> MI CHIAMO DOMENICO 

<category> 
<pattern>TI RICORDI DI ME</pattern>
<template> <get name="nome"/>, come potrei dimenticarmi di te!</template>
</category>
In questo secondo esempio con il get sono in grado di prendere il valore configurato precedentemente, ovviamente nel caso in cui l’utente dicesse TI RICORDI DI ME prima di presentarsi  il bot risponderebbe:
unknown  come potrei dimenticarmi di te!
che non è ovviamente una buona risposta. Questo problema può essere risolto in vari modi quello più semplice è di intercettare questo caso e rispondere adeguatamente, definendo una sorta di struttura condizionale, con l’aiuto di srai:

<category>
<pattern>TI RICORDI DI ME</pattern>
<template><srai>TIRICORDIDIME <get name="nome"/></template>
</category>

<category>
<pattern>TIRICORDIDIME UNKNOWN</pattern>
<template>No, non mi ricordo.</template>
</category>

<category>
<pattern>TIRICORDIDIME *</pattern>
<template><get name="nome"/>, come potrei dimenticarmi di te!</template>
</category>

Con l’esempio precedente si intuisce che, nel momento in cui l’utente farà la domanda ti ricordi di me, il sistema risponderà trasformando il responso  in<srai>TIRICORDIDIME <get name=”nome”/> per cui se la variabile name=”nome” sarà  valorizzata verrà via <srai> invocata la categoria con pattern TIRICORDIDIME * altrimenti la categoria TIRICORDIDIME UNKNOWN in accordo anche all’ordine delle priorità delle wildcard.

AIML e teoria dei chatbot – Terza parte >>

Se vuoi farmi qualche richiesta o contattarmi per un aiuto riempi il seguente form