Skip to content

Reconnaissance vocale (expert)

Enero edited this page Dec 6, 2019 · 11 revisions

Pour déclencher un nouveau service comme la qualité de l’air par la voix, il est nécessaire : d’adapter le modèle de reconnaissance vocale (ASR) afin de lui permettre de reconnaître les nouvelles phrases ; de définir les phrases possibles pour le modèle de NLU (Natural Language Understanding) ; de modifier le code du service (ici nabairqualityd.py) pour répondre aux commandes vocales.

Adapter le modèle de reconnaissance vocale (en français)

L’adaptation du modèle de reconnaissance vocale est relativement rapide et pourrait éventuellement se faire directement sur le Pi Zero (?). Dans ce tutoriel, nous allons utiliser Docker sur desktop.

Récupérer le code source de pynab avec git, puis tout se passe dans le répertoire asr.

Il s’agit de modifier le fichier nabaztag-grammar-fr.jsgf pour adapter la grammaire aux nouvelles commandes, et éventuellement de compléter le fichier dict-fr-nabaztag.ipa pour ajouter les nouveaux mots.

Ici, on modifie le début de nabaztag-grammar-fr.jsgf pour ajouter dans la règle :

public = + | [ ] ( | | <8ball> | | | | ) [ ];

Et on ajoute la règle suivante :

= air | [ la ] qualité de l'air [ ] | [ le ] taux de CO2 [ ] | quelle est la qualité de l'air [] [ dehors | à l'extérieur ] | quel est le taux de CO2 [] [ dehors | à l'extérieur ] | est-ce que je peux aller [ dehors | à l'extérieur ] ou c'est trop pollué | c'est pas un peu pollué [] ;

Il faut également ajouter les nouveaux mots dans le lexique dict-fr-nabaztag.ipa. On peut récupérer les prononciations dans un dictionnaire beaucoup plus complet à cette adresse : https://github.com/pguyot/zamia-speech/tree/master/data/src/dicts

Par exemple il nous faut les nouveaux mots suivants :

ou;u pas;pa peu;pø pollué;pɔlɥe trop;tʁo

Ensuite, on lance le script adapt-model.sh qui fait tout le boulot, en s’appuyant sur zamia-speech. S’il manque des mots dans le lexique, le script échouera et il est possible de les rajouter et de le relancer.

Au final, ce script génère le modèle sous une forme compressée (en .tar.xz). Il s’agit ensuite de le copier sur le Pi dans /opt/kaldi/model puis de modifier la configuration dans nabd/asr.py pour utiliser ce nouveau modèle.

Le modèle de reconnaissance vocale en anglais est actuellement (novembre 2019) non spécialisé, et ne nécessite pas d’adaptation. Cependant, la performance serait sans doute meilleure si on l’adaptait comme le modèle en français.

Ajouter les nouvelles commandes au modèle NLU

Il s’agit de créer des fichiers intent_*.yaml pour chaque langue dans nabairqualityd/nlu/. Ces fichiers sont compilés par le script d’installation.

Le fichier pour le français est le suivant (il reprend grossièrement la grammaire du modèle Kaldi) :


type: intent name: airquality_forecast utterances:

  • air
  • donne-moi la qualité de l'air
  • qualité de l'air
  • quelle est la qualité de l'air date:snips/datetime
  • est-ce que je peux aller dehors ou c'est trop pollué
  • c'est pas un peu pollué date:snips/datetime

Tous les fichiers intent sont combinés en un modèle unique, chargé par nabd. Pour mettre à jour ce modèle :

cd /home/pi/pynab

venv/bin/python -m snips_nlu generate-dataset en */nlu/intent_en.yaml > nabd/nlu/nlu_dataset_en.json

rm -rf nabd/nlu/engine_fr

venv/bin/snips-nlu train nabd/nlu/nlu_dataset_fr.json nabd/nlu/engine_fr

venv/bin/python -m snips_nlu generate-dataset fr */nlu/intent_fr.yaml > nabd/nlu/nlu_dataset_fr.json

rm -rf nabd/nlu/engine_en

venv/bin/snips-nlu train nabd/nlu/nlu_dataset_en.json nabd/nlu/engine_en

Il faut ensuite redémarrer nabd pour qu’il charge les nouveaux modèles (ASR & NLU).

sudo service nabd restart

Modifier le code du service pour répondre aux commandes vocales

Il suffit d’ajouter une fonction process_nabd_packet qui traite les paquets de type "asr_event" avec la bonne valeur dans ["nlu"]["intent"].

async def process_nabd_packet(self, packet): if ( packet["type"] == "asr_event" and packet["nlu"]["intent"] == "airquality_forecast" ): now = datetime.datetime.now(datetime.timezone.utc) expiration = now + datetime.timedelta(minutes=1) self.perform(expiration, "today")

Clone this wiki locally