Paquets & Modules
Les modules sont les compétences de Léon, c'est grâce à eux que Léon est capable de faire des choses en fonction de ce que vous lui demandez. Dans cette section vous allez en savoir plus à ce sujet.
#
PaquetsLes paquets contiennent une infinité de modules. Un paquet n'est ni plus ni moins qu'un dossier contenant des modules, vous pouvez les considérer comme étant une catégorie de modules.
Ex. le paquet Checker contient des modules tels que le Is It Down car ce paquet inclut les modules ayant pour but la "vérification".
La liste complète des paquets est disponible ici.
#
Structure des dossiersLes paquets sont listés dans le répertoire packages
. Prenons le paquet Video Downloader comme exemple.
Notez que le nom du paquet doit être en minuscule et en anglais.
packages/videodownloader
: nom du paquet.packages/videodownloader/config/config.json
: configuration du paquet. Il contient la configuration de tous ses modules.packages/videodownloader/config/config.sample.json
: exemple de fichier de configuration. Ce fichier est copié pendant l'installation afin de générer le fichier ci-dessus.packages/videodownloader/data/answers
: dossier contenant la traduction des réponses de chaque module.packages/videodownloader/data/db
: dossier contenant la base de donnée du paquet.packages/videodownloader/data/expressions
: dossier contenant le jeux de données de compréhension de chaque module. Ces jeux de données sont utilisés pour entraîner le modèle de compréhension.packages/videodownloader/test
: dossier contenant les tests de chaque module.packages/videodownloader/README.md
: fichier contenant les objectifs du paquet et de ses modules.packages/videodownloader/__init__.py
: fichier vide permettant de charger le paquet comme un paquet Python.packages/videodownloader/version.txt
: fichier contenant la version du paquet.packages/videodownloader/youtube.py
: module YouTube.
Chaque paquet :
- À sa propre version.
- À sa propre configuration (pour chaque module).
- À son propre jeux de données (pour chaque module).
- À ses propres tests (pour chaque module).
#
Gestion des versions- Les paquets de Léon respectent le SemVer.
- Chaque nouveau module incrémente le nombre de version MINEUR du paquet (ex. 1.0.0 -> 1.1.0).
- À chaque fois qu'un nombre de version MAJEUR ou MINEUR est incrémenté, alors le nombre MINEUR de la version du projet est incrémenté également (ex. 1.0.0 -> 2.0.0 | 1.1.0 -> 1.1.0).
- À chaque fois qu'un nombre de version CORRECTIF d'un paquet est incrémenté, alors le nombre CORRECTIF du projet est incrémenté également (ex. 1.0.0 -> 1.0.1 -> 1.0.1).
#
ModulesLes modules sont les compétences de Léon. Ils contiennent une ou plusieurs action(s) afin d'accomplir une tâche spécifique.
Quand Léon comprend ce que vous lui dites, il :
- Appel une action de module.
- Fait le job.
- Vous retourne le résultat de l'éxécution.
Chaque module à son propre objectif et sa propre configuration. N'hésitez pas à parcourir la liste des paquets afin de comprendre leur buts.
Aujourd'hui, les modules sont écrits en Python mais à l'avenir ils pourraient supportés d'autres langages grâce aux connecteurs.
#
ConfigurationPrenons à nouveau le paquet Video Downloader comme exemple.
packages/videodownloader/config/config.json
Dans chaque fichier de configuration de paquet, vous pouvez ajouter autant de nouvelles clés / valeur que vous souhaitez lors de la création d'un module.
Dans cette exemple, les clés api_key
et playlist_id
ont été ajoutées à la configuration du module YouTube.
Ceci permet au module de sélectionner ces valeurs dans le but de requêter l'API YouTube.
Pour accèder à ces propriétés, vous pouvez utiliser la fonction utils.config(key).
Les options sont utilisées lorsqu'il y a besoin d'une intéraction entre un module et le noyau.
Options are used when it needs interaction between a module and the core. Elles peuvent par exemple être utilisées pour le synchroniseur.
Astuce
N'hésitez pas à jeter un œil aux autres modules afin d'avoir une meilleure compréhension.
#
Jeux de données et traductionsPour vous répondre et vous comprendre, Léon a besoin de ses jeux de données et traductions.
En effet, ses jeux de données sont divisés en deux parties : les expressions et les réponses.
- Chaque module a ses propres expressions et réponses.
- Chacun de ces jeux de données a ses propres traductions.
- Les traductions sont représentées par le nom de fichier de ces jeux de données, tels que
en.json
,fr.json
, etc.
#
ExpressionsLes expressions sont les données utilisées afin d'entraîner la compréhension de Léon. Lorsque vous exécutez le script d'entraînement, toutes les expressions de chaque module sont parcourues et génèrent le classifieur.
Les expressions sont contenues dans une action de module. C'est comme ça que Léon comprend quelle action il doit faire.
Notez que chaque expression de chaque action de module a sa propre confiance (précision).
Ex. les expressions françaises du module Who Am I appartiennent au paquet Leon. Ces expressions sont contenues dans l'action
run
.
#
FallbacksMalgré les expressions que vous avez écrit, il se peut que Léon ne les comprend toujours pas. C'est là que les fallbacks entrent en jeu.
Dans le fichier core/langs.json, vous pouvez trouver la liste des langues supportées avec plusieurs propriétés :
short
: le code court de la langue.min_confidence
: la confiance (précision) minimum de la compréhension de Léon. Si cette confiance est plus petite que celle définie, alors Léon vous répond qu'il n'est pas sûr de ce que vous lui dites.fallbacks
: force la sélection d'un module. Utilisez la cléwords
afin de déterminer avec quels mots vous souhaitez que Léon sélectionne un module en particulier. Et utilisez les cléspackage
,module
etaction
pour définir quel action de module devrait être exécuté en fonction des mots donnés.
#
RéponsesLes réponses sont les données utilisées par Léon qui permettent de vous fournir les résultats couplés aux sorties des modules.
Ex. une partie des réponses françaises du module Greeting appartenant au paquet Leon.
#
HTMLIl est possible d'utiliser de l'HTML dans vos réponses.
Ex. une partie des réponses françaises du module GitHub appartenant au paquet Trend.
#
Créer un moduleAstuce
- La création d'un module est l'une des meilleures façons de contribuer à Léon ! Avant toute chose, assurez-vous de prendre connaissance de ce document ❤️
- Par exemple, vous pouvez imaginer créer un module to-do liste (bien que celui-ci existe déjà). Faites un tour sur la roadmap pour voir ce qu'il y a de prévu.
- N'hésitez pas à ouvrir une issue si vous avez la moindre question.
Chaque module est inclus dans un paquet (ex. packages/{NOM DU PAQUET}/{NOM DU MODULE}.py
).
#
ÉtapesVoici les étapes basiques pour créer un module. Pour ces étapes, nous prendrons un module tweets grabber en tant qu'exemple.
#
1. Définir le ou les objectif(s)- Je veux créer un module tweets grabber. Quand je dis ou lorsque j'écris :
- Je veux que léon me donne mes 5 derniers tweets avec les statistiques de chaque.
- Il semblerait que ce module ne correspond pas à un paquet (catégorie) existant. Alors je crée le paquet Twitter en créant le dossier
packages/twitter
. - Pour ce faire, je m'assure de suivre la structure des dossiers d'un paquet et que cette structure contienne les fichiers requis.
Astuce
Si votre module est plus avancé et doit comprendre plusieurs objectifs, alors n'hésitez pas à créer plusieurs actions.
#
2. Nommer votre module- Je choisis de nommer mon module
Tweets Grabber
.
#
3. Écrire le code- Afin de requêter l'API de Twitter, j'ai besoin des identifiants API. Alors je renseigne les clés de l'API Twitter dans le fichier
packages/twitter/config/config.json
que j'ai précédemment créé à l'étape 1. - De plus, je crée le fichier
packages/twitter/tweetsgrabber.py
, définis la ou les action(s) de mon module puis j'écris mon code. - Pendant que j'écris le code, j'édite
server/src/query-object.sample.json
depuis le répertoire racine du projet, j'utilise cette commande :
#
4. Écrire les tests- Maintenant que je suis satisfait avec mon module, je crée le fichier
packages/twitter/test/tweetsgrabber.spec.js
. - J'écris les tests de mon module dans ce fichier.
#
5. Expliquer comment utiliser- Dans le fichier
packages/twitter/README.md
, j'ajoute une courte description expliquant l'objectif de mon module. - J'explique brièvement comment mon module s'utilise (quelle phrases nous pouvons utiliser, si on doit / peut configurer certaines choses, etc..
#
6. Partager- Je partage mon module au monde entier en contribuant.
#
Actions (fonctions de module)Dans le fichier du module, vous devez ajouter une action (fonction) qui sera le point d'entrée de l'exécution. Une action prend la chaîne de caractères d'entrée (query) et les entités comme paramètres.
Quand vous avez seulement une action dans votre module, le nom d'action utilisé est généralement run
:
Quand vous avez plusieurs actions dans votre module :
Astuce
N'oubliez pas que Léon sait quelle action il doit exécuter grâce aux expressions que vous définissez.
#
Convention de nommageLe nom de fichier d'un module doit uniquement contenir des lettres minuscules et doit être nommé en anglais.
Ex. le nom de fichier du module Meaning of Life :
meaningoflife.py
Les noms d'actions doivent utiliser le snakecase (lettres minuscules et `` seulement) et doit être nommés en anglais.
Ex. les actions du module To-Do List :
create_list
,add_todo
,complete_todo
, etc.
#
Objet de demandeChaque fois que vous communiquer avec Léon, il va créer un fichier d'objet de demande temporaire avec les propriétés suivantes :
lang
: code (court) de la langue utilisée.package
: nom du paquet utilisé.module
: nom du module utilisé.action
: nom de l'action utilisée.query
: votre phrase.entities
: un tableau d'entités que Léon a extrait de votre phrase. Une entité peut être ce que vous voulez en fonction de ce que vous définissez (entité personnalisée) ou elle peut être une entité intégrée comme une durée dans le temps, un nombre, un nom de domaine, etc.
Le fichier server/src/query-object.sample.json est présent pour que vous puissiez exécuter et tester le comportement du code de votre module à la volée pendant sa création. Modifiez le en fonction des propriétés de votre module.
#
EntitésLes entités sont des morceaux que Léon extrait des phrases. Ces entités sont partagées à vos actions afin que vous puissiez les manipuler pour donner plus de sens à vos modules.
Il y a différents types d'entités, ceux-ci sont listés ci-dessous :
#
Entités intégréesLes entités intégrées sont celles déjà inclues dans Léon. Léon extrait automatiquement ces entités depuis vos phrases.
La liste complète est disponible ici.
Astuce
N'hésitez pas à consulter des exemples afin de comprendre comment ces entités sont utilisées. Ceux-ci sont des exemples parfaits :
Comme vous voyez, vous pouvez itérer sur les entités pour récupérer les informations dont vous avez besoin (nom de domaines, dates, vos propres entités, etc.).
#
Entités personnaliséesLes entités personnalisées sont celles que vous définissez vous-même en fonction de vos cas d'utilisations. Vous pouvez créer vos propres entités dans les fichiers de langues situés dans : packages/{NOM DU PAQUET}/data/expressions/{FICHIER DE LANGUE}.json
. Dans ce fichier, les entités personnalisées sont inclues dans les propriétés d'actions au même niveau que les expressions.
Elles sont représentées par un tableau d'objets :
Comme vous pouvez le voir, une entité personnalisée comprend un type
, un name
et plus en fonction de son type.
Ex. consultez les entités de l'action create_list du module To-Do List.
Les entités personnalisées ont deux types listés ci-dessous :
#
Entités réduitesLes entités réduites vous permettent de tronquer des parties de la phrase pour extraire le texte qui vous intéresse. Ceci se fait à l'aide des conditions :
{ "type": "between", "from": [], "to": [] }
{ "type": "after", "from": "" }
{ "type": "after_first", "from": "" }
{ "type": "after_last", "from": "" }
{ "type": "before", "to": "" }
{ "type": "before_first", "to": "" }
{ "type": "before_last", "to": "" }
Afin d'illustrer tout ça, admettons que nous créons un module To-Do List. Pour ce faire, nous allons définir une entité personnalisée list
.
Lorsque nous avons les phrases suivantes :
Nous voulons extraire le texte courses
afin de l'associer à notre entité list
. Nous utilisons la condition after
pour récupérer ce qu'il y a après de
ou nommée
:
Dans le fichier module packages/{PACKAGE NAME}/todolist.py
:
Astuce
Vous pouvez jeter un œil au réel module To-Do List du paquet Calendar.
#
Entités expressions régulièresLes entités expressions régulières vous permettent de récupérer les parties d'une phrase via des expressions régulières.
Disons que nous créons un module Color Picker. Pour ce faire, nous allons définir une entité expression régulière color
.
Lorsque nous avons la phrase suivante :
Nous voulons extraire les chaînes de caractères rouge
et bleu
afin de les associer à des entités color
. Nous utilisons une expression régulière pour récupérer ces couleurs :
Dans le fichier module (packages/{PACKAGE NAME}/colorpicker.py
):
#
Données persistentesLéon utilise TinyDB pour gérer les bases de données des paquets. Chaque paquet peut voir sa propre base de données et cette base de données est gérée par les modules.
Pour plus d'informations, veuillez vous référer à :
- La fonction utils.db().
- La documentation TinyDB.
- L'exemple du module YouTube.
#
Installer des paquets Python tiersLéon tourne dans un environnement virtuel afin d'assurer que les paquets / dépendances du projet ne soient pas en conflit avec ceux installés sur votre système.
Afin d'installer les paquets tiers, veuillez suivre les étapes suivantes :
- Ouvrez votre terminal au dossier
bridges/python
. - Exécutez
pipenv install {NOM DU PAQUET}=={VERSION DU PAQUET}
. Notez qu'il doit y avoir une version spécifique du paquet. - Importez le nouveau paquet installé dans le fichier du module requis via
import {NOM DU PAQUET}
.
{NOM DU PAQUET}
et {VERSION DU PAQUET}
sont des placeholders. N'oubliez pas de les remplacer par le nom et la version du paquet que vous souhaitez installer.
#
SortiesTous les modules font quelque chose, et les sorties permettent au noyau de comprendre ce qu'un module a fait et de connaître l'état de l'exécution du module. C'est grâce aux sorties que Léon sait ce qu'il doit faire ensuite.
Le noyau comprend deux types de sorties :
inter
, qui sont les sorties intermédiaires. Vous pouvez avoir autant de sorties intermédiaires que vous souhaitez.end
, qui sont les sorties finales.. Vous devez uniquement avoir une sortie finale, elle permet à Léon de savoir que l'exécution du module est terminée.
Les sorties sont représentées par la fonction utils.output().
#
Tester un module#
À la voléePour tester le comportement de votre module pendant que vous êtes en train de le créer, vous pouvez utiliser la commande suivante depuis le dossier racine du projet :
Par exemple, pour le module Is It Down le fichier d'objet de demande pourrait ressembler à ceci :
Astuce
N'oubliez pas de jeter un œil à cette liste pour voir comment les entités sont formatées.
#
Bout en bout (fonctionnel)Les modules ont leur propre tests. Ils sont représentés par un fichier unique pour chaque module que vous pouvez trouver ici : packages/{NOM DU PAQUET}/test/{NOM DU MODULE}.spec.js
.
Comme vous pouvez le constater, JavaScript est utilisé pour tester les modules parce que le noyau est écrit en JavaScript et nous utilisons les tests de bout en bout (fonctionnels) en exécutant une query au NLU. Puis le cerveau de Léon est exécuté et retourne la sortie. C'est cette sortie, particulièrement les codes qui ont été interprétés par votre module que vous devez considérer.
Léon utilise Jest comme framework de test.
Voici deux exemples de tests du module Is It Down :
Ces tests peuvent être trouvés dans packages/checker/test/isitdown.spec.js
Une fois que vous avez terminé d'écrire vos tests, vous pouvez exécuter la commande suivante pour les exécuter :
#
Fonctions utilesLes fonctions utilitaires sont disponibles dans bridges/python/utils.py.
Pour utiliser ces fonctions, n'oubliez pas d'importer le module Python utils au début de votre module Léon :
Astuce
Vous pouvez également contribuer en améliorant ces fonctions ou en ajoutant de nouvelles afin de rendre la création de modules encore meilleure.
#
getqueryobj()Retourne l'objet de demande.
#
translate(key, d = { })Sélectionne aléatoirement une réponse du module depuis le fichier packages/{PACKAGE NAME}/data/answers/{LANG}.json
grâce à la clé donnée. Aussi, cette fonction permet l'interpolation via l'objet de données donné et retourne la réponse sous forme de chaîne de caractères.
key
: clé de réponse du module pour sélectionner la bonne chaîne de caractères.d
: objet de données pour effectuer l'interpolation de chaîne de caractères.
#
output(type, code, speech = '')Communique les données du module vers le noyau.
type
(inter|end): type de sortie afin d'informer le noyau si l'exécution du module est terminée ou non. Le typeend
doit apparaître une fois.code
: code de sortie fournissant une information additionnel quant au type de sortie. Habituellement utilisé pour les tests de modules.speech
: réponse sous forme de chaîne de caractères.
#
http(method, url, headers = None)Envoie une requête HTTP avec l'agent utilisateur Leon/{NUMÉRO DE VERSION}
. La librairie Python Request est utilisée.
method
: méthode HTTP.url
: URL à requêter.headers
: en-têtes HTTP.
#
config(key)Récupére la configuration du module depuis le fichier packages/{PACKAGE NAME}/config/config.json
.
key
:clé de configuration du module.
#
createdldir()Crée le dossier de téléchargements du module courant. Lorsque Léon a besoin de télécharger un contenu, ce dernier est sauvegardé dans : downloads/{NOM DU PAQUET}/{NOM DU MODULE}
.
#
db(dbtype = 'tinydb')Crée une base de données dédiée d'un paquet.
dbtype
(tinydb): type de la base de données. Aujourd'hui seulement TinyDB est supporté.