1. IntroduzioneIl progetto è open-source e ha lo scopo di testare le funzionalità di Natural Language Understanding di Rasa e dei moduli NVIDIA NeMo (integrati nelle ultime versioni di NVIDIA Riva per la gestione di assistenti virtuali). Lo scopo del progetto è stato quello di testare alcune funzionalità delle librerie messe in open-source da NVIDIA e verificarne l'integrabilità di servizi esterni come Rasa NLU. Scrivo questa discussione per mostrarvi un opportunità di creare in maniera semplice e veloce un proprio assistente virtuale (un pò come Alexa o Siri ma fatte da voi utilizzando modelli di Automatic Speech Recognition, Text-To-Speech e Natural Language Processing). I moduli sono stati tutti testati singolarmente e lo scopo ultimo del progetto, da come si può vedere dalla repository che posterò, è quella di evitare il parallelismo GPU (questo ha fatto si che si possa riadattare il bot in sistemi free-GPU e integrare i moduli in Arduino o altri hardware isolated systems a basso costo (perchè siamo poveri)).
Questo progetto è universitario, data dalla magistrale di Informatica dell'Alma Mater Studiorum per il progetto di Natural Language Processing. Devo dire che mi sono divertito e non poco a creare e testare i moduli per poi integrarli in una architettura ad-hoc di tipo client-server.
Importante: Capire come siano fatti i modelli utilizzati NON è necessario al fine di aggiornare o implementare nuovi funzionalità di Alysia (si, è il nome dell'assistente).
2. Indice
La presentazione del progetto è divisa in varie sezioni:
- ASR: Automatic Speech Recognition, per la sintetizzazione vocale in uno spettrogramma mel e la conversione in un testo scritto.
- NLP: Nello specifico andremo ad utilizzare Rasa per il Natural Language Understanding, basato su un orientamento ad intent come in dialogflow e sistema autonomo di actions che, dopo un rapido test di applicabilità, abbiamo deciso di non utilizzare data l'inefficienza delle performance in runtime (sono stati sostituiti con funzioni scratch implementate come API all'interno di un semplice server Flask). Sono stati integrati moduli NLP di NVIDIA NeMo per la gestione di contenuti su Wikipedia.
- TTS: Text-To-Speech, in cui si passa dal testo alla codifica di uno spettrogramma mel per poi alla generazione sonora all'interno di un file audio da riprodurre (rappresenta la voce del nostro assistente).
3. ASR
Da come si può vedere nella prima immagine, i moduli di Automatic Speech Recognition sono stati presi da un modello Quartznet 15x5. Esso rappresenta un modello allo stato dell'arte attuale (superando anche Megatron e altri modelli derivati). Ha un WER di circa il 4% su dataset noti come LibriSpeech e ha una velocità di trascrizione elevata (riuscendo a supportare anche testi molto lunghi con margini di errore minimi).
Esso è formato da una rete neurale in cui si hanno:
- Convolutional Layer seguita da 15 blocchi ripetuti 5 volte
- Ogni blocco è formato da:
- 1D depth-wise convolution layer (in cui ogni canale ha un valore del kernel differente)
- Pointwise convolution layer con dimensione 1x1 del kernel su vari canali paralleli
- Layer di normalizzazione per evitare ripetizioni (Rimuove ad esempio ripetizioni come AAAAAANNNIMAAL in ANIMAL)
- ReLu layer che applica la funzione di ReLu sull'output
- Modulo CTC loss per la gestione dell'associazione testuale
Sono consapevole che è difficile capire come sia fatta una rete frutto di una ricerca moderna in un campo complesso come il Natural Language Processing, per chi vuole sapere di più su questo modello, me lo faccia sapere nei commenti, cosi al massimo possono anche darvi un mio notebook con un implementazione basata su tensorflow.
4. NLP/NLU
Questa parte non fa altro che prendere un valore testuale e processarlo logicamente per poter generare una risposta ad una domanda. Vi sono due parti:
- Rasa NLU: Rappresenta un modello orientato ad intent in cui non si fa altro che processare la domanda, verificare quale sia l'intent (associazione tra la struttura della domanda con un suo significato semantico) e restituirlo al server per compiere la procedura correlata. In alternativa è possibile integrare un Rasa Server in grado di computare le procedure direttamente nell'intent-system e restituire la risposta sottoforma di messaggio JSON.
- NeMo NLP: Abbiamo creato un semplice scraper che processa dei testi all'interno di wikipedia in associazione ai termini utilizzati ad una domanda, successivamente abbiamo creato un input in formato JSON che sia conforme alla struttura di SQuAD 2.0 su cui è allenato un modello QAModel fornito da NeMo NVIDIA stesso nelle sue collezioni NLP. L'output è una risposta inerente alla domanda con un margine di precisione testato e visibile all'interno delle valutazioni nella documentazione ufficiale del progetto (vedere la repositry GitHub per maggiori info). Un esempio può essere "Search how old is John Cena?" e la risposta è 44. Abbiamo utilizzato Wikipedia come banca dati poichè open-source, siete liberi di modificarlo a vostro piacimento per integrarlo con piattaforme più mirate (modificando ovviamente anche lo scraper).
5. TTS
Questa parte ci ha creato non pochi problemi, soprattutto per l'assenza di un sistema con GPU. I moduli di TTS utilizzano per default CUDA X. Per chi non lo sapesse, è una libreria basata sulla parallelizzazione di sottoprocessi in grado di definire un ottimizzazione delle performance, per usarla si ha l'obbligo di una GPU o una TPU. In assenza di ciò, i moduli server-side crashano, per questo motivo all'interno del progetto troverete la classe con i moduli TTS di NeMo che non verranno utilizzati, si ha comunque possibilità di integrarli se avete GPU NVIDIA in vostro possesso. In alternativa, si può utilizzare un modulo di WebSpeech API di Javascript compatibili con i modelli integrati (per capirci, quelli che si trovano nei vecchi Mac intel-based).
Fatto sta che abbiamo testato:
- FastSpeech: Generatore di spettrogrammi a partire da un input testuale. Rappresentato da sotto-moduli in grado di predirne la durata e il picco dello spettrogramma per ogni lettera scandita all'interno del testo, secondo un approccio parallelo.
- HiFiGAN: Esso è un modello GAN (Generative Adversarial Network) in grado di trasformare uno spettrogramma (quello del FastSpeech definito prima) in voce. Nello specifico esso è un modello composto da un generatore e due discriminatori (multi-scale e multi-period).
Non mi soffermo molto su questi modelli, vi rilascio alle loro ricerche nelle referenze sottostanti per capirne meglio la struttura.
6. Architettura
In conclusione possiamo sintetizzare l'architettura nei seguenti punti:
- Flask Server: Ha la funzionalità di gestire le actions in seguito alle specifiche degli intent, richiamare i moduli di ASR e TTS ed inoltrare le request al server Rasa.
- Rasa Server: Ha la funzione di definire il servizio di intent per associare una semantica alle domande
- ASR: Modello Quartznet15x5 di NVIDIA NeMo per la sintetizzazione vocale
- TTS: Modello di FastSpeech + HiFiGAN per la conversione vocale di un testo
- QAModel: Modello NLP di NeMo in grado di dare una risposta logica basata sullo scraping di Wikipedia
- Database MongoDB: Immagazzina le informazioni necessarie per la gestione di entità logiche.
7. Riferimenti
Repository: https://github.com/kode-git/NeMo-virtual-assistant
Ogni riferimento è interno alla documentazione nel folder ./doc