Skip to content

Reconnaissance vocale (expert)

Paul Guyot edited this page Apr 29, 2024 · 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

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 pour cette partie, le reste se faisant directement sur le lapin.

Sur desktop, récupérer le code source de pynab avec git (git clone https://github.com/nabaztag2018/pynab), puis tout se passe dans le répertoire asr.

git clone https://github.com/nabaztag2018/pynab
cd 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 <airquality> dans la règle <control> :

public <control> =
    <noise> +
    | [ <euh> ] ( <weather> | <airquality> | <8ball> | <surprise> | <taichi> | <carot> | <clock> ) [ <euh> ];

Et on ajoute la règle suivante :

<airquality> =
    air
    | [ <giveme> la ] qualité de l'air [ <date> ]
    | [ <giveme> le ] taux de CO2 [ <date> ]
    | quelle est la qualité de l'air [<date>] [ dehors | à l'extérieur ]
    | quel est le taux de CO2 [<date>] [ 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é [<date>]
    ;

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 avec le paramètre fr 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.

bash adapt-model.sh fr

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 lapin, de le décompresser 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 spécialisé de la même manière.

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](aujourd'hui)
  - est-ce que je peux aller dehors ou c'est trop pollué
  - c'est pas un peu pollué [date:snips/datetime](aujourd'hui)

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")