Vous êtes sur la page 1sur 28

Rapport de stage 2ème année

Luc Domingo

Sujet :
Améliorer l’accessibilité des outils de traitements du langage développés par
LIAAD
Durée : 8 Juin 2019 — 25 Août 2019

Remerciements

Je remercie mon maître de stage Monsieur Alípio Mário Guedes Jorge, Professeur associé au
Département de la Science de l’Informatique de l’Université de Science de Porto et coordinateur
de LIAAD.

Je tiens aussi à remercier Monsieur Arian Pasquali, Chercheur associé à LIAAD


Sommaire
1 Introduction 2

2 Contexte du Stage 2
2.1 Présentation succincte du Laboratoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2 Méthodologie et Environnement de travail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.3 Les outils développés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

3 Une accessibilité intuitive et interactive 3


3.1 Modèle préexistant et innovation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.2 Conception d’un premier site web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3.3 Mise en place d’une application full-stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.4 Nouvelle idée d’approche intuitive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

4 Vers une intégration plus facile 10


4.1 Modèle de Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2 Mise en application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.3 Première implémentation en ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

5 Construction d’un modèle plus réaliste 12


5.1 Idée générale et Solution proposée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5.2 Implémentation avec Kubernetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.3 Implémentation avec Docker swarm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.4 Retour vers le passé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

6 Amélioration et Perspectives 18

7 Conclusion 19

8 Annexes 20
8.A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
8.B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
8.C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
8.D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
8.E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.G . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.H . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
8.I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

9 Références Bibliographiques 27

1
1 Introduction
Le traitement du langage naturel (TLN) est une discipline visant à modéliser et reproduire par le biais d’algorithmes la
capacité humaine à créer et interpréter des énoncés linguistiques pour communiquer. LIAAD ( Laboratory of Artificial
Intelligence and Decision Support ) est un laboratoire de recherche développant des outils de TLN recouvrant certains
domaines de l’Intelligence Artificielle. Les projets développés impliquent des technologies différentes et l’accessibilité
est compromise par cette diversité. Ainsi l’appréhension et l’utilisation des outils conçus peut s’avérer laborieuse. Le
travail réalisé lors de ce stage s’appuie sur différents niveau d’accessibilité. Ces niveaux sont intriquement liés au besoin
de l’utilisateur et peuvent être classés en fonction de leur abstraction. Premièrement, nous pouvons travailler sur
l’appréhension des outils développés via la création d’applications web interactives par exemple. Ce niveau s’adresse à
des utilisateurs cherchant à mieux comprendre le travail et les enjeux du laboratoire. Cependant, de nombreux outils
peuvent être utilisés dans des projets extérieurs ou liés à LIAAD. Cela nécessite de travailler sur un nouveau modèle
d’accessibilité. Il est nécessaire de fournir une intégration simple des outils, en outre c’est à ce niveau qu’interviennent
des technologies comme Docker. Enfin certains utilisateurs travaillent directement au niveau du code source reproduisant
alors l’environnement exact employé lors du développement. Durant le stage, le travail effectué ce situe principalement
sur les deux premiers niveaux présentés.
Dans un premier temps, je vais rapidement décrire le contexte de mon stage pour que le lecteur puisse appréhender une
vue globale. Puis, je vais débuter la présentation de mon travail. Je commencerai à exposer les approches intuitives
des outils de LIAAD via des applications web. Par la suite j’exposerai le travail réalisé avec Docker et les systèmes que
j’ai mis en place pour déployer les applications. Enfin, je me retournerai sur mon travail pour essayer d’avoir un regard
critique et d’exposer les améliorations potentielles.
Je suis désolé par avance d’avoir garder certain mots en anglais par faute ne n’avoir trouvé une traduction satisfaisante
en français.

2 Contexte du Stage
2.1 Présentation succincte du Laboratoire
Comme évoqué précédemment LIAAD est un laboratoire de recherche et développement situé à Porto. Il est associé à
l’INESC TEC, un laboratoire pluridisciplinaire. Par conséquent, les champs de recherches sont hétéroclites parmi eux la
science de l’informatique, les systèmes de réseaux intelligents, puissance et énergie, ... Cependant LIAAD concentre ses
recherches sur le data mining, l’analyse des données et leur modélisation statistique dans le but de fournir un support
de décision.

2.2 Méthodologie et Environnement de travail


J’ai eu l’opportunité durant ce stage d’être encadré par deux chercheurs. Ils ont su apporter des réponses techniques
et des conseils avisés à mes agissements. Suite à une panne de mon ordinateur personnel et la perte d’une semaine de
travail ils ont eu l’amabilité de me prêter un ordinateur pour que je puisse débuter mes tâches. J’avais à ma disposition
une salle commune à d’autres étudiants de l’université. En effet, j’ai passé la majorité de mon temps de travail au
département d’informatique de l’université des sciences. Par conséquent, j’ai pu échanger avec d’autres professeurs que
mes encadrants. En particulier, le laboratoire reçut la visite du Dr.Havasi1 venant du MIT, une experte en TLN, et
j’eus l’opportunité de lui présenter mon projet.
Je fus en contact permanent par mail avec mes encadrants et je les voyais plusieurs fois par semaine à la suite de
réunions pour faire le bilan sur mon travail.
Tout les codes sources du travail réalisé et exposé durant ce rapport sont disponibles sur des répertoires associés a
mon compte Github 2 . Pour la plupart des projets j’ai rédigé une documentation la plus claire possible. Cela paraît
1 lien vers sa page wikipédia : https://en.wikipedia.org/wiki/Catherine_Havasi
2 https://github.com/LucDomingo

2
absolument naturel cependant ce n’était pas un exercice auquel j’étais accoutumé. Pourtant l’importance de bonne
documentations est cruciale pour l’amélioration continue et l’appropriation d’un projet.

2.3 Les outils développés


Concrètement, le laboratoire ce consacre majoritairement au traitement du langage naturel. Ainsi, nous pouvons citer
dans les projets les plus conséquents, des extracteurs de mot clés, extracteurs d’entités nommés (nom commun et nom
propre) , analyseurs de sentiments, résumeur temporel, ... Tout au long de ce rapport je ferai référence à ces outils dont
je connais l’usage mais que je n’ai absolument pas implémenté. A l’exception de PAMPO [1] un extracteur d’entités
nommés à partir d’un texte en Portugais duquel j’ai implémenter une partie de l’algorithme. Cette section du stage
est difficilement intégrable ailleurs car c’est l’unique fois où j’ai du me pencher sur les notions d’Intelligence Artificielle.
Globalement, l’algorithme se décompose en deux phases distinctes. Une première phase correspondant à la génération
des candidats. Le but de ce processus est d’identifier un maximum de bons candidats grâce à une base de données non-
exhaustives composée en autre des "stop words"(noms les plus utilisés), prépositions 3 , noms de famille commun, titres
(président, ministre, ...). Cette partie de l’algorithme était déjà réalisée en python en s’appuyant sur les expressions
régulières, voir le module python-pcre [2]. Mon travail consista à la mise en oeuvre de la seconde phase, la sélection
d’entités. Nous travaillons à partir des candidats pré-sélectionnés de la phase 1. Il s’agit de réaliser un étiquetage des
mots en fonctions de leur nature grammaticale. Ainsi, nous pouvons éliminer les expressions ne contenant pas au moins
un nom 4 . L’étiquetage est réalisé grâce au module spaCy [3] qui propose des réseaux de neurones pré-entraînés pour
de nombreux langages comprenant le portugais. Au préalable cet algorithme avait été implémenté en R [4] par certains
chercheurs, un langage plus adapté aux statistiques et à la gestion des données. Ainsi de manière empirique il était
possible de comparer les résultats des deux implémentations.
Il existe d’autres outils que j’utilise sans connaître leur implémentations. Citons YAKE! [5] un extracteur de mots clé,
Contamehistorias [6] un framework de résumé temporel et d’autres outils sur lesquels je reviendrai plus tard.
Ainsi après cette légère digression, je pus entamer le véritable sujet de mon stage. Il est important de noter qu’une
grande partie des outils est seulement disponible sous forme de code source. Ainsi, certains utilisent des versions de
python ou de R différentes. Il y avait donc un travail d’homogénéisation à réaliser.

3 Une accessibilité intuitive et interactive


3.1 Modèle préexistant et innovation
La majorité des outils conçus dispose du même modèle d’accessibilité. En effet, chaque projet possède un site web.
Ce dernier présente dans les grandes lignes le fonctionnement de chacun d’eux et fait référence à chacun des articles
scientifiques à la base de la théorie. De plus, il propose une interface ludique pour tester l’outil en ligne. Enfin il
présente les personnes intervenues dans la mise en oeuvre de l’ensemble du projet.
D’autre part chacun des outils dispose d’un répertoire Github, où est stocké une documentation et bien entendu le code
source. Ce modèle assez simple présente des avantages pour les développeurs qui ont simplement à créer un site web
et pousser le code dans un répertoire. Cependant, il est trop décentralisé, et ne permet pas une intégration facile des
modèles et une vue d’ensemble des travaux réalisés par le laboratoire.

3 pour sélectionner les noms composés


4 "au moins" car l’algorithme peut sélectionner les noms composés

3
3.2 Conception d’un premier site web
Dans la continuité de la politique d’accessibilité de LIAAD et après avoir fini l’implémentation de PAMPO (voir 2.3), j’ai
donc commencé la réalisation d’un site web pour présenter l’outil. Au vu de l’implémentation en Python de PAMPO, le
choix des technologies à utiliser s’est orienté vers Flask [7]. C’est un framework de développement web écrit en Python
compatible WSGI. Pour comparer avec Django [8] 5 il a l’avantage d’être plus minimaliste et simple d’apprentissage.
Je me réfère à plusieurs témoignages y compris celui de mon deuxième encadrants Mr.Pasquali. Ainsi dans un soucis
de productivité et d’efficacité j’ai privilégié Flask. De plus il dispose d’un moteur de template assez facile d’utilisation
Jinja [9]. J’ai découvert ces deux outils et appris les bases me permettant de construire l’application. Cela ne fait
absolument pas de moi un expert en la matière , certe Flask est minimaliste mais il existe une multitude de modules
complémentaires. Pour illustrer le fonctionnement global de l’application, je vous propose d’analyser certaine portion
du code.

Figure 1: Arborescence du projet

J’ai volontairement illustré l’arborescence avec les fichiers les plus essentiels. Nous allons en étudier certains. Un
dossier de base est static. Celui-ci contient tout les fichiers CSS et Javascript responsable de l’affichage de notre site.
D’ailleurs, j’ai utilisé Bootstrap pour garantir un site responsive design, c’est-à-dire ajustant l’affichage en fonction de
l’appareil de l’utilisateur ( tablette, mobile, ...).
Dans app.py est défini l’application et les routes. Étant donné la longueur du code j’ai préféré ne pas l’incorporer en
annexes pour faciliter la lecture.

5 un autre framework de développement web écrit en python

4
Voici donc une portion représentative du code :
1 from flask import Flask , render_template , request
2 import pampo
3 app = Flask ( __name__ ) # Cr é ation d une instance pour la classe Flask
4
5 @app . route ( ’/ ’) # route () , un d é corateur d é clenche l app en fonction de l url
6 def index () :
7 return r e nd er _ te mp l at e ( ’ index . html ’) # la methode r en d er _t e mp la t e ()
8 # retourne une template situ é e
9 # dans le dossier templates
10 @app . route ( ’/ home ’)
11 def home () :
12 return r e nd er _ te mp l at e ( ’ index . html ’)
13 @app . route ( ’/ about ’)
14 def about () :
15 return r e nd er _ te mp l at e ( ’ about . html ’)

Ce fichier est essentiel c’est lui qui définit le comportement du serveur en fonction de la route interrogée. Les fichiers
contenus dans templates sont les fichiers html générés grâce à Jinja. Ce dernier permet notamment d’éviter la répli-
cation de code et de récupérer des variables transférées par l’application. Tous les fichiers spécifiques à PAMPO sont
dans le dossier Pampo. Comme je l’ai évoqué précédemment le travail que j’ai fait sur l’implémentation de cet outil
est minime et je préfère ne pas m’étaler dessus car il n’est pas en rapport avec le reste de mon stage. Ce qu’il faut
retenir c’est que le serveur utilise les fonctionnalités de PAMPO. Les autres fichiers sont en relation avec Heroku [10].
Celui-ci est une plateforme en tant que service6 permettant de déployer nos applications en ligne . L’utilisateur reçoit
une machine virtuelle dotée déjà d’un système d’exploitation7 ainsi nous sommes uniquement responsable de la gestion
des données et des logiciels d’applications. Toutes les applications sur la plateforme fonctionnent grâce à des dynos.
Ce sont des conteneurs Linux comparable aux conteneurs de Docker. Mais le gros avantage d’Heroku réside dans le
déploiement des applications qui repose sur git. Au préalable il est nécessaire de configurer le fichier Procfile. Il permet
de déclarer quelle commande sera exécutée pour démarrer l’application. Dans notre cas, il suffit d’écrire :

1 web : gunicorn app : app

Cette ligne précise que le processus lancé sera de type web8 , c’est à dire qu’il bénéficiera d’un routage des requêtes
HTTP venant de l’extérieur et donc a fortiori d’une url pour y accéder. Gunicorn semble être un bon choix dans
notre cas car c’est un serveur WSGI HTTP Unix et de plus il est recommandé par le guide de déploiement. Le fichier
requirements spécifie les bibliothèques que doit installer notre dyno pour faire fonctionner le serveur et PAMPO. Enfin
il suffit de pousser le code sur un répertoire git :
1 git add .
2 git commit -m " Demo "
3 git push heroku master
4 heroku open

Vous pouvez si vous le désirez accéder au site web via https://safe-basin-21244.herokuapp.com/. Heroku propose
beaucoup d’extension pour la majeure partie payante, il en va de même si l’application consomme trop de ressources
CPU ou d’espace mémoire. Cependant, pour des projets de cette envergure c’est une solution productive et gratuite.
L’ensemble du code est disponible sur Github 9 . J’ai réalisé ce projet seul, néanmoins des indications sur les technologies
à utiliser m’ont été procurées.

6 Paas:"Platform as a service".
7 Depuis Heroku-18 c’est ubuntu 18.04 qui est utilisé.
8 Il existe aussi des processus de type worker, par exemple pour réaliser des tâches de calcul ou pour instancier une base de donnée
9 https://github.com/LucDomingo/pampo_demo

5
3.3 Mise en place d’une application full-stack
Le travail réalisé par LIAAD est trop décentralisé et il est difficile pour un utilisateur d’avoir une vue d’ensemble
des projets. Une partie des codes sources est disponible sur Github, une autre partie sur Gitlab et chacun des outils
disposent d’un site web.
L’idée du projet suivant est assez simple; développer une seule application web qui regroupe tout les projets. Une fois la
problématique posée, il faut définir les exigences du projet. L’interface doit permettre de tester de manière interactive
et ludique chacun des outils et doit proposer le lien vers leur site web respectif. En d’autres termes, les utilisateurs
pourront rentrer certains paramètres (texte, date, ...) et recevoir la prédiction de l’algorithme du modèle choisi. De plus
nous devons construire une application avec une importante longévité. Pour cela, il faut garantir une intégration et une
maintenance simple. Désormais, nous pouvons esquisser une architecture qui s’apparente à une application full-stack
classique :

Figure 2: Architecture globale

6
La base de donnée n’est pas réellement nécessaire. En effet l’idée est de pouvoir générer une url spécifique à chaque
résultat. Ainsi, les utilisateurs peuvent échanger leur résultat via l’url générée. Les algorithmes sont déterministes,
pour une entrée spécifique le résultat sera identique. L’idée est qu’une entrée peut entraîner un résultat inattendu et
ainsi le garder en mémoire permet potentiellement d’en faire une étude de cas.
À présent, nous pouvons choisir les technologies à employer. Pour le serveur l’idéal serait de choisir comme langage
Python étant donné que la majorité des outils de LIAAD sont codés en Python. Ici encore nous pouvons utiliser Flask
pour les même raisons qu’évoquées précédemment. Pour la base de donnée, par préférence j’ai opté pour MongoDB
[11]. Python possède une bibliothèque nommée PyMongo [12] pour interagir avec ce genre de base de donnée. Pour le
moment, les codes source des outils sont stockés dans un répertoire auquel le serveur a accès.
Nous pouvons étudier le fonctionnement de ce dernier. Il contient deux routes. La première permet de recevoir les
données d’entrée des utilisateurs et d’interroger le modèle correspondant afin de retourner la prédiction de celui-ci. De
plus nous stockons dans la base de donnée le résultat associé à ces données d’entrée. Plus tard, si les même données
sont saisies pour le modèle correspondant alors il suffit de récupérer le résultat dans la base de donnée. Cette démarche
sous-entend l’hypothèse que le temps d’accès à la base Mongo est inférieur à utiliser le modèle. La seconde route
est déclenchée lorsque l’utilisateur demande un permalien, c’est-à-dire un lien correspondant à un résultat particulier.
Imaginons qu’un chercheur teste un modèle avec des données précises et qu’il veuilles partager le résultat, il lui suffira
d’envoyer le lien généré. Je ne rentre pas plus en détail dans le code car il est semblable à celui du site de PAMPO mis
à part les interactions avec la base de donnée.

Pour le front-end le choix est plus difficile. Effectivement, il va falloir présenter les résultats sous une forme plus
originale que pour le site de PAMPO , ce qui sous-entend un usage plus poussé de Javascript. Logiquement, j’ai du
faire usage d’un framework adapté. L’éventail est large. Mais aiguillé par Mr.Pasquali, j’ai opté pour ReactJS [13]. Je
ne peux pas faire de comparaison avec d’autres frameworks comme AngularJS [14] ou EmberJS [15] car je n’ai jamais
travaillé avec. Néanmoins, je trouve l’approche de ReactJS intéressante. En effet, il travaille à partir de composants.
Conceptuellement, les composants sont comme des fonctions JavaScript. Ils acceptent des entrées quelconques (appelées
« props ») et renvoient des éléments React décrivant ce qui doit apparaître à l’écran 10 . Cette démarche permet d’avoir
une implémentation très modulaire. La composition permet d’isoler des caractéristiques des éléments de l’interface,
comme leur comportement. L’isolation permet une intégration plus facile. Comme gestionnaire de paquet j’ai opté pour
npm [16] , dans un soucis de rendement car je connaissais déjà son fonctionnement. La démarche la plus difficile à mon
sens fut d’établir une architecture pour le front-end. Sur ce point là il me semble indispensable de signaler que je me
suis inspirer de nombreux projets déjà disponibles sur le web. J’ai regardé et étudié plusieurs d’entre eux pour aboutir
à une implémentation qui collait le plus possible au cahier des charges. Cependant j’ai dû adapter et chercher certaines
solutions par moi-même. Ainsi après réflexion, je suis parvenu à cette architecture pour le front-end, voir figure 3.

10 extrait du site web de ReactJS [13]

7
Figure 3: Architecture globale du front-end

Cette présentation globale est peu précise je le conçois, mais a le mérite de présenter et segmenter les bases du
front-end. Ainsi détaillons chacun des blocs. Le premier assure le routage des url demandées vers les bons com-
posants. Il y a deux possibilités l’url a un un format simple de type "/nom_de_l’outil", soit elle est de la forme
"/nom_de_l’outil/:slug". Dans le premier cas, il sera nécessaire de faire appel au back-end pour prédire le résultat.
Dans le second, le slug identifie un résultat enregistré dans la base de donnée et le bloc 1 peut directement faire une
requête au back-end pour le récupérer. Le bloc suivant concerne tout les fichiers définissant les composants déterminant
l’affichage. J’entends par là , les composants du menu, du bas de page,les formulaires d’entrée,... et le composant
spécifique au modèle demandé. Un exemple du code de PAMPO est disponible en annexe 8A.
Ce fichier est en fait un modèle de construction pour ajouter un nouvel outil. Dès lors, il est relativement simple
pour des personnes extérieures de rajouter au front-end un modèle. Les autres fichiers appartenant au bloc2 n’ont pas
d’intérêt particulier ils décrivent le comportement des boutons, panneaux, menu, ...
Désormais nous devons étudier le dernier bloc. Le fichier principal est Model.js, une partie de son code est commenté
en annexe 8B. Maintenant que nous avons vu dans les grandes lignes le fonctionnement du projet, analysons ses points
positifs et négatifs. Pour ajouter un nouveau modèle à l’application, il y a quelques étapes:

• Copier le code source du modèle dans le répertoire du serveur et rajouter quelques lignes de codes pour que celui-ci
puisse calculer les prédictions.
• Rajouter un fichier au front-end semblable au modèle de celui présenté précédemment.
Ces étapes ne nécessite aucune connaissance particulière en ReactJS, de plus les lignes de code sont dépendantes du
modèle et n’imposent pas la connaissance entière du projet. C’est un avantage qui garantit une intégration et une
maintenance simple de l’application. Cependant, cela nécessite que les outils soient programmés sous la même version
de Python que celle du serveur. De plus toutes les bibliothèques spécifiques à un modèle doivent être installées sur
celui-ci. Cet inconvénient majeur sera réglé plus tard au cours du stage.

8
3.4 Nouvelle idée d’approche intuitive
Toujours dans la recherche de rendre accessible les projets du laboratoire j’ai eu l’idée de développer une extension
pour Google Chrome s’appuyant sur l’extracteur de mot clé YAKE!. Le principe est simple, l’extension permet de
sur-ligner sur une page web les mots clés retournés par l’algorithme. Il y a deux paramètres la couleur de sur-lignage et
le nombre de mot clés à extraire. Pour construire cette application il est nécessaire de créer certains fichiers spécifiques
aux extensions Google Chrome. Commençons avec background.js qui permet d’interagir avec l’API de Chrome. En
effet, il permet la gestion des évènements, par exemple la navigation sur une nouvelle page, effacement de marque-page,
changement d’onglet,... En résumé ce script tourne en arrière plan comme son nom l’indique et nous permet de traiter
des évènements. Le fichier content.js permet d’intéragir avec le DOM. Enfin, popup.js permet de définir l’interface avec
l’utilisateur. Tous ces scripts peuvent communiquer au moyen de messages. Voici la structure de l’extension :

Figure 4: Extension Google Chrome utilisant YAKE!

9
Je pense qu’il est nécessaire de détailler certains aspects. Le localstorage est un espace de mémoire fourni par le
navigateur, dans notre cas nous y enregistrons le nombre de mots clés et la couleur de sur-lignage choisie par l’utilisateur.
Le background est en écoute de message rentrant ainsi, popup lui envois un message lui notifiant qu’il peut désormais
lire les entrées utilisateur. Il fait ensuite la requête à l’API REST de YAKE!. Plusieurs points sont à éclaircir. Cette
API, je l’ai mise en place grâce à Heroku mais son implémentation sera expliquée dans une partie du rapport plus
propice. Ce qu’il faut retenir, c’est simplement que en entrée l’API demande le nombre de mots clés à extraire et une
url pour récupérer le texte contenu sur la page web. Cette dernière n’est autre que l’url où l’utilisateur se trouve lorqu’il
utilise l’extension. C’est pour cela qu’il faut passer par le background car celui-ci peut intéragir avec l’API de Chrome
et récupérer cette url. Une fois les mots clés recueillis, le background les envois au content. C’est lui qui se charge de
les sur-ligner. Vous pouvez trouver en annexe 8I une capture d’écran illustrant l’utilisation de l’extension.

4 Vers une intégration plus facile


4.1 Modèle de Base
La grande diversité des outils et par conséquent de leurs technologies sous-jacente représente un obstacle pour une
utilisation et une intégration simple. J’ai assez fait durer le suspense, évidemment Docker [17] semble être l’outil idéal
pour résoudre certains de ces problèmes. En effet il permet de créer des applications isolées dans des conteneurs incluant
toutes leurs dépendances et bibliothèques.
L’idée est de construire un conteneur pour chacun des projets de LIAAD. Celui-ci sera accessible via un ou plusieurs
ports sous forme d’API REST. Donc il sera facile pour un utilisateur simplement en faisant des requêtes HTTP de
récupérer les prédictions des algorithmes. Étudions la structure et les fichiers nécessaires au déploiement :

Figure 5: Projet Docker de PAMPO

Le dossier webapp définit l’API. Le fichier app.py est simplement une application Flask avec une route qui une fois
interrogée, utilise l’algorithme de PAMPO et retourne la réponse. De plus chacun des projets disposent d’une route
donnant accès à leur documentation Swagger [18]. À présent nous pouvons étudier le Dockerfile qui indique les étapes
à suivre pour construire le conteneur (voir annexe 8C). Comme indiqué dans la documentation, ce fichier doit être le
plus concis possible pour améliorer les performances d’exécution.

10
4.2 Mise en application
J’ai donc effectué ce travail de conteneurisation sur les trois outils, PAMPO, YAKE!, Contamehistorias. J’ai suivi le
même modèle de construction pour les trois (figure 5). Je pense qu’il était attendu de ma part d’établir des règles
d’uniformisation. C’est pour cela que les trois projets ont la même structure. C’est d’ailleurs en cherchant des outils
pouvant m’aider que j’ai découvert Cookiecutter [19]. C’est une bibliothèque Python qui permet de créer des templates
pour nos projets. Les noms des dossiers et des fichiers sont paramétrables, ainsi la création d’un nouveau projet est
simplifiée et automatisée.
Certains projets de LIAAD sont en R et ne seront pas nécessairement implémentés en Python dans le futur. Mais le
modèle utilisé reste valable. Il suffira juste de constuire une API REST qui utilise par exemple Plumber [20]. Je n’ai
pas eut l’occasion d’effectuer une conteneurisation avec un outil programmé en R.

4.3 Première implémentation en ligne


Pour faciliter l’utilisation de ces API c’est-à-dire éviter de devoir installer docker et de construire localement chacun
des conteneurs, j’ai utilisé Heroku pour les rendre publiques. Le déploiement est assez simple. En effet il y différentes
méthodes, soit la construction du conteneur est effectuée par Heroku, soit on passe par Docker Hub [21] . Ce dernier est
une plate-forme de partage d’images de conteneurs. Le fonctionnement est semblable à Github. Il suffit d’utiliser push
ou pull pour pousser en ligne ou récupérer une image. Je vais détailler en quelques lignes un déploiement classique :
1 heroku container : login # Connexion au Docker - Hub de Heroku
2 docker tag pampo_docker registry . heroku . com / ancient - crag -40137/ web # Renommage de notre image ,
registry . heroku . com est le r é pertoire sur docker - hub , ancient - crag -40137 est le nom de notre
application et web le type de dyno
3 docker push registry . heroku . com / ancient - crag -40137/ web # On pousse l ’ image sur le r é pertoire docker
hub .
4 heroku container : release web -- app ancient - crag -40137 # Mise à jour de l ’ application

Petit détail concernant le Dockerfile, c’est Heroku qui décide quel port sera exposé par le conteneur, ainsi il faut écrire
EXPOSE $PORT. Le port est ici une variable d’environnement déterminée par Heroku.
J’ai réalisé ce travail pour les trois outils que j’avais au préalable conteneurisés. Les documentations Swagger sont
disponibles aux url suivante :
• Pampo : https://ancient-crag-40137.herokuapp.com/apidocs/
• Contamehistorias : https://desolate-ocean-90460.herokuapp.com/apidocs/
• YAKE! : https://serene-sands-13924.herokuapp.com/apidocs/

Le nom des applications est aléatoire cependant il peut être modifié. L’API REST de YAKE! sur Heroku est celle
utilisée par l’extension Google Chrome.
L’avantage d’un déploiement comme celui-ci est sa simplicité. Cependant étant donnée qu’il est basé sur l’offre gratuite
de Heroku, il est contraint à des restrictions d’activité (550h par mois sur l’ensemble des dynos). De plus, Heroku donne
la possibilité d’utiliser 5 dynos gratuitement, ce qui ne permet pas d’ajouter de nombreux outils. Cette solution est
donc temporaire et ne peux pas passer à l’échelle, d’une part si le nombre d’utilisateurs augmente et d’autre part si le
nombre d’outil est supérieur à 5.

11
5 Construction d’un modèle plus réaliste
5.1 Idée générale et Solution proposée
Nous pouvons mettre en place de nombreux procédés pour combler les inconvénients du déploiement précédent. Pre-
mièrement nous pourrions utiliser un proxy inverse pour rediriger toutes les requêtes des utilisateurs. En d’autre termes
les utilisateurs interrogent une route avec la même racine et indique en paramètre de l’url le modèle choisi. Ainsi, nous
gagnons en simplicité pour l’utilisateur, il y a seulement un point d’accès. De plus, cela permet de centraliser les requêtes
pour avoir une meilleure gestion du trafic rentrant 11 . Enfin, la plus-part de ces serveurs disposent d’algorithmes de
répartitions des charges permettant d’ajuster la charge de travail des serveurs du back-end en fonction de leur disponi-
bilité par exemple. Souvent, ces serveurs qui travaillent en arrière plan sont organisés sous forme de cluster. Dans notre
cas, ces derniers hébergent les instances de conteneurs fonctionnant comme des API REST.
Nous pouvons esquisser l’architecture de base d’un tel déploiement :

Figure 6

Par conséquent, une des tâches suivantes est de trouver un système d’orchestration des conteneurs. De plus, il faut
un hébergeur capable de fournir des ressources pour former un cluster. Les avantages de former une grappe de serveurs
sont multiples. Cela permet une meilleure disponibilité grâce justement à une bonne gestion de la charges de travail.
Le cluster garantit aussi la scalabilité, c’est-à-dire une capacité d’adaptation en fonction de la variation d’utilisateurs.
Ces notions nous les retrouvons aussi dans l’informatique en nuage 12 . J’ai donc choisi de développer mon application
sur un hébergeur cloud.
N’ayant jamais utilisé ces technologies je me suis tourné vers Google Cloud Platform [21], car l’offre gratuite me paraissait
bonne. J’avais un accès total à toutes les fonctionnalités avec un crédit initial de 400 euros et aucun engagement.
J’ai été sincèrement surpris par les fonctionnalités et les possibilités offertes par l’informatique en nuage. Le déploiement
11 Par exemple cela facilite la mise en place d’un pare-feu
12 Cloud Computing

12
et l’arrêt des services est quasi-instantané et accompli simplement grâce à une invite de commande ou directement via une
interface web classique. L’allocation et la désallocation des ressources est rapide et simple. J’ai réellement l’impression
de n’avoir utilisé qu’une partie infime du potentiel énorme de cette technologie. Après avoir fait des recherches, j’ai pu
comprendre quelles étaient les briques de base d’un tel système; l’informatique distribué, un réseau haut débit, et des
plate-formes efficaces pour les machines virtuelles. Cependant, la vérité est qu’il me reste beaucoup de zones d’ombres
à éclaircir. Heureusement, celles-ci n’empêchent pas la réalisation de mes prochains projets.
Pour le proxy inverse, après quelques recherches les deux les plus utilisés du marché semble être Apache [22] et Nginx
[23]. J’ai choisi le second car il est réellement dédié à cette tâche contrairement à Apache qui est un serveur web
"général". Certaines fonctionnalités de ce dernier me seront donc inutiles.

5.2 Implémentation avec Kubernetes


Comme indiqué dans le titre cette première implémentation s’appuie sur Kubernetes [24]. C’est une plate-forme open-
source de gestion de services conteneurisés sous Docker. Le gros avantage d’utiliser Google Cloud c’est qu’il fournit un
environnement prêt à l’emploi pour le déploiement d’applications en conteneur; Kubernetes Engine. Cela nous évite
de configurer tout le plan de contrôle de Kubernetes. En effet, sans aller dans les détails son fonctionnement peut être
décrit comme une relation maître esclave. Le maître Kubernetes contient l’API par laquelle le développeur peut agir
sur le cluster, par exemple créer de nouveaux services, allouer des ressources,... Par conséquent, le maître supervise
les noeuds esclaves grâce au daemons kubelet présent sur chacun d’eux. Ce dernier assure les instructions venant
du maître, il est donc responsable de l’état d’exécution de chacun des conteneurs présent sur les noeuds. Le dernier
élément indispensable est kube-proxy, c’est un proxy s’exécutant sur chaque noeud qui se charge des services réseaux ,
par exemple le routage des requêtes rentrantes,... Tout ceci représente la structure fondamentale de Kubernetes.
Cependant l’API interagit avec des objets propres à Kubernetes qu’il convient de décrire.
Un pod est la plus petite unité déployable. C’est lui qui encapsule le conteneur Docker. Il dispose d’une adresse IP
unique sur le noeud. Plusieurs pods de la même instance conteneurisée peuvent s’exécuter en même temps, c’est un
paramètres que l’on peut ajuster dynamiquement et qui permet de veiller à la disponibilité de nos services.
Un service est un moyen de définir une politique d’accès pour nos pods. Les pods ont une durée d’exécution finie et
comme nous l’avons vu plus haut plusieurs pods peuvent être l’hôte de la même application conteneurisée. Ainsi si un
pods du back-end "meurt", alors il faut que les pods du front-end puisse garder une trace de l’adresse ip à laquelle se
connecter (exemple repris de la documentation). Chaque pods hébergeant la même instance dispose du même service.
Ces derniers peuvent être de nature différentes, ils peuvent exposer les pods aux autres pods du cluster mais aussi au
monde extérieur.
Il y a d’autres objets conceptuel que j’expliquerai au cours de mon implémentation. A ce stade nous pouvons rassembler
tous ces éléments sur un schéma (voir fig7) . Donc si nous récapitulons, dans notre cas nous avons trois applications
qui sont nos trois outils conteneurisés sous forme d’API REST. Les images correspondantes sont récupérées depuis
Docker-hub. Pour instancier les pods correspondant, nous utilisons la commande kubectl qui permet d’intéragir avec
L’API du maître Kubernetes. Elle prend en argument un fichier .yaml. Vous pouvez trouver en annexe 8D la structure
d’un fichier de déploiement de pods. On déploie de la même façon le serveur Nginx conteneurisé. Pour ce faire je me
suis appuyé sur un très bon tutoriel13 présent sur Github .

13 https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md

13
Figure 7: Exemple de cluster à deux noeuds

Désormais il faut indiquer en créant des services comment exposer nos applications. Les services correspondant aux
pods des outils sont de type clusterIP. Autrement dit ils sont accessible via une adresse ip interne au cluster et un
port. De plus lors de la création d’un service un autre type d’objet est généré les endpoints. Ils répertorient de manière
dynamiques tous les couples ip_pods/ports associés à un service. Cependant, Kube-proxy entretient aussi une table
associant un nom de service à son couple ip_service:port. Imaginons un pods1 du service1 essaie de communiquer
avec un autre pods2 du service2 . Le message est d’abord routé jusqu’au service2 grâce à la table ip, puis service2
regarde son endpoint et sélectionne un pod. C’est d’ailleurs à ce moment là que nous pouvons faire de l’équilibrage de
charge. Si un service à le choix entre plusieurs pods, nous pouvons définir une politique d’accès en round robin par
exemple. Pour mieux comprendre, le code de déploiement d’un service est disponible en annexe 8E. Le service Nginx
est de type loadBalancer, il est exposé à l’extérieur du cluster, par conséquent accessible via une adresse ip et un port.
Cependant, il faut créer un Ingress qui va gérer l’accès aux services internes en fonction des routes demandées. Afin
de mieux discerner le fonctionnement, le code du déploiement de l’Ingress est disponible en annexe 8F. Finalement,
le cluster est atteignable par l’extérieur via une adresse ip et un port ( en l’occurence 80 ). Ainsi l’utilisateur peut
indiquer dans la route le service interne qu’il souhaite joindre et le contrôleur Nginx redirigera sa requête correctement.
Pareillement à la partie 4, la documentation Swagger des outils est disponible, la route est de la forme <adresse ip
externe nginx>:80/<nom_outil>/apidocs/. Ayant épuisé mes crédits je n’ai plus d’accès gratuit au cluster.
Ce déploiement est assez basique et nécessiterait certaines améliorations. Nous en parlerons partie 7. Comme dit
en introduction, nous avons gagné en scalabilité. Un service peut être arrêté, démarré très simplement via juste une
commande kubectl. Je ne l’ai pas précisé mais nous pouvons ajuster les ressources14 allouées de manière dynamique.
L’ajout d’un nouvel outil est assez simple. Supposons que la version conteneurisée soit disponible sur Docker-hub. Il
suffit de créer un nouveau déploiement et un nouveau service pour cet outil. Or chacun des outils suit le même modèle
(voir les annexes). Enfin il faut rajouter une règle de routage dans le contrôleur Ingress.

14 Mémoire et CPU

14
5.3 Implémentation avec Docker swarm
En plus de l’implémentation avec Kubernetes, j’ai décidé de reprendre la structure générale (voir figure 6), mais d’utiliser
Docker Swarm [26]. Je pensais qu’il ne fallait pas seulement se baser sur une technologie pour prendre une décision. Pour
être sincère, depuis que j’avais commencé à conteneuriser les outils j’étais en totale autonomie. Ce qui me permettais
d’être libre sur mes choix. Mon but étant de proposer plusieurs solutions différentes pour avoir un support de décision
plus large pour le laboratoire. Je savais juste que LIAAD disposait de plusieurs serveurs, et qu’il avait développé
certains projets déjà sur le cloud computing.
Mais revenons à Docker-Swarm. Pour faire le développement je me suis appuyé sur Google Compute Engine. C’est un
service payant, j’ai donc utilisé les crédits gratuits que j’ai pu obtenir suite à mon inscription 15 . Il fournit une machine
virtuelle nue. C’est un service IaaS16 , ainsi nous choisissons le système d’exploitation et d’autres paramètres comme la
mémoire.
Désormais nous pouvons explorer grossièrement le fonctionnement de Docker-Swarm. L’architecture se compose de
deux types de noeuds les managers et les workers. Toutes les interactions avec le cluster se font via l’intermédiaire des
managers. J’entends par là, création et arrêt de services par exemple. Comme pour Kubernetes il est possible de gérer
le nombre de répliques de containers s’exécutant pour un service ainsi que les ressources qui leurs sont allouées. En
résumé les noeuds managers assurent que les commandes utilisateurs soient exécutées, ils sont responsable de la gestion
et de l’orchestration des services au seins du cluster. Les workers reçoivent et exécutent des tâches distribuées par les
managers.
Désormais, il faut donc créer ses noeuds, pour faire simple j’ai utilisé un cluster avec un seul noeud manager et deux
workers. Une fois cette tâche finie, nous initialisons un swarm sur le noeud que l’on choisi comme manager. Puis, nous
forçons les deux autres noeuds à rejoindre le swarm en tant que workers. A présent, il faut réfléchir au déploiement
de nos services et comment les faire communiquer. Le procédé utilisé par Docker-swarm est différent de Kubernetes,
nous utilisons un overlay network (voir figure 8). Comme nous l’avons vu Kubernetes considère que chaque noeud à
son propre réseau docker. Ainsi le routage se fait entre les hôtes d’une machine à l’autre et d’un conteneur à l’autre.
Mais Docker-Swarm utilise le protocole VXLAN, qui permet de tunneler le trafic d’un host à l’autre, en encapsulant les
trames Ethernet dans des paquets IP. Des mécanismes complexes gèrent les résolutions ARP et DNS. Ainsi des services
n’appartenant pas au même noeuds peuvent communiquer comme s’ils appartenaient au même réseau local. Pour le
développeur il suffit d’une seule commande pour créer ce type de réseau. Je ne rentre pas plus dans les détails car
je n’en sais pas plus, mais cela m’a suffit à comprendre le fonctionnement global de la communication entre différents
services. Par la suite, nous déployons les services. Il faut configurer le serveur Nginx comme le faisait automatiquement
Kubernetes via les règles Ingress et le rendre accessible à l’extérieur du cluster. Pour ce faire, nous modifions son fichier
de configuration principal. Toutes les étapes sont détaillées en annexe 8G.
Les outils ainsi que leurs documentations sont donc accessible via des API REST sur le port 80 exposé à l’extérieur par
le serveur Nginx. Pour ajouter un nouvel outil, il suffit de créer un nouveau service (docker service create) et de mettre
à jour le fichier de configuration de Nginx pour y ajouter une route supplémentaire. Si la demande est trop importante
sur une API en particulier nous pouvons lui allouer plus de ressources. Si le système global nécessite plus de ressources,
il suffit de rajouter un noeud.
Cette solution allie simplicité dans l’ajout de service et élasticité. C’est en grande partie grâce à des outils comme
docker-swarm et l’informatique en nuage qui abstraient nombre de tâches s’exécutant en arrière-plan.

15 J’ai réalisé l’implémentation de Docker Swarm et Kubernetes plus ou moins en parallèle


16 Infrastructure as a service

15
Figure 8

5.4 Retour vers le passé


Au vu des technologies découvertes, j’ai pu repenser l’implémentation du site web en ReactJS. Pour rappel, il nécessite
un environnement avec un back-end Flask, une base MongoDB. Pour ce qui est du front-end, les fichiers peuvent être
servis soit directement par le serveur Flask soit par Serve [27], un serveur dédié à rendre des fichiers statiques. Ainsi,
nous pouvons imaginer une architecture à deux ou trois conteneurs Docker. Un pour chaque service. Le client demande
l’index du site. Le proxy inverse renvoi la requête sur le service du front-end. Celui-ci répond. Enfin si le client demande
une prédictions à un modèle, alors il interroge une route différente. Elle est redirigée vers le serveur Flask. Celui-ci
interroge les API REST des modèles en interne. Selon Kubernetes ou Docker Swarm les méthode d’exposition change
comme nous l’avons vu. Finalement, le client reçoit les prédictions du modèle. Les étapes sont résumées figure 9. De
la même manières que pour les outils de TLN j’ai rajouté ses services dans mes deux implémentations.

16
Figure 9

Malheureusement, le site n’est plus accessible de cette façon, mes crédits étant épuisés sur Google Cloud Platform.
Mais de la même façon que les API REST des outils , j’ai déployé le site sur Heroku. C’est une solution temporaire.
Par contre, la mise en place fut plus compliquée. Je m’explique. Pour éviter de déployer trois dynos supplémentaires, ce
qui m’était d’ailleurs impossible sur mon compte actuel limité à cinq, j’ai utilisé un seul conteneur. J’ai donc rassemblé
tous les services. Le serveur Flask rend l’index du site, les fichier Javascript et CSS, interroge les API REST des outils
déployées sur Heroku, et interagit avec la base de donnée. Le code du Dockerfile est disponible en annexe 8H. Le site
est accessible à l’adresse : https://vast-refuge-73742.herokuapp.com17

17 Les outils nlp-microservices sont en cours de mise à jour au moment ou j’écris ce rapport, et donc non fonctionnels.

17
6 Amélioration et Perspectives
Sur l’ensemble de mon travail de nombreux points peuvent être améliorés. Je vais surtout me concentrer sur les parties
utilisant Docker comme base. Néanmoins, il y a certainement des points à améliorer dans l’architecture du site en
ReactJS, pour rendre l’application plus accessible.
Concernant les projets sur Docker-Swarm et Kubernetes, le port accessible est 80 et les requêtes sont de type HTTP.
Il existe des manières pour migrer vers le port 443 et HTTPS. Par exemple, pour Kubernetes, l’Ingress permet d’avoir
une terminaison TLS. Le principe est de créer un secret qui est un objet spécifique à Kubernetes permettant de stocker
des données sensibles. Dans notre cas, il faudrait y stocker la clé privée et le certificat à utiliser pour TLS. L’utilité
d’une telle action peut être critiquée, mais nous pouvons imaginer qu’à long terme, les clients voudront que les données
qu’ils envoient et reçoivent soient chiffrées.
L’objectif futur est bien-sûr de rajouter d’autres outils et de construire une plate-forme plus conséquente. Nous pouvons
imaginer mettre en place des outils de monitoring sur le Cluster. Par exemple Prometheus que l’on peut intégrer comme
service dans le swarm. Il va permettre de récupérer des métriques comme le nombre de requêtes par exemple et de
tracer des graphes d’évolution temporelle. Cela permet d’avoir une meilleure vue globale sur l’état de notre cluster.
De plus, j’avais commencé à réfléchir à un système pour perfectionner l’automatisation de certaines tâches sur les
clusters. Le but étant d’arriver à une intégration et un déploiement continu. Il existe un outil adapté à cet objectif,
Jenkins [28]. En outre, il permet d’automatiser certaines tâches au travers de pipelines. Je n’ai pas eut le temps de
mettre en place un tel système, mais ma pensée de base peut s’illustrer (figure 10).

Figure 10

18
Détaillons les différentes étapes :

• 1) Les codes sources sont mis à jour sur Github par les développeurs.
• 2) Chaque commit déclenche Jenkins.
• 3) Jenkins construit une nouvelle image Docker et la pousse sur un répertoire, par exemple sur Docker-Hub

• 4) Jenkins alerte Kubernetes que l’image a été mise à jour


• 5) Kubernetes récupère la dernière version de l’image
• 6) Kubernetes met à jour les déploiements utilisant la nouvelle image
Un tel système permet de gagner en temps d’intégration et de déploiement.

7 Conclusion
L’ensemble de mon travail vise à améliorer l’accessibilité des outils du laboratoire. Comme évoqué durant l’introduction
celle-ci peut se décomposer en plusieurs niveaux de services. En effet, les utilisateurs peuvent découvrir et appréhender
le travail réalisé par LIAAD grâce à des sites web intéractifs. Ils ont la possibilité de tester les outils, ,d’enregistrer les
prédictions des algorithmes, d’accéder aux papiers de recherche ainsi qu’aux codes sources. J’ai donc dans cet objectif
déployé deux applications web.
Si d’autres utilisateurs veulent faire usage des outils et les intégrer dans l’une de leur application. Ils peuvent se procurer
l’image des conteneurs des outils sur Docker-hub qui sont sous forme d’API REST. Ils ont aussi la possibilité d’intéragir
directement avec ces API via internet car elles sont publiques et temporairement déployées sur Heroku. Un exemple
concret d’utilisation est l’extension Google Chrome YAKE!.
Par ailleurs mon travail me poussa à explorer les solutions d’actualité pour déployer des application conséquentes en ligne
. Ces solutions s’appuient sur l’informatique en nuage et des systèmes d’orchestration de conteneurs. Les avantages
sont nombreux. Parmi eux nous pouvons citer le déploiement et arrêt des services à la demande et l’allocation et
désallocation rapide des ressources. Ainsi les charges de travail peuvent être contrôlées. Par exemple, si une API est
très sollicitée, il est possible de lui allouer plus de ressources et si cela ne suffit pas de créer une nouvelle machine
virtuelle pour joindre le cluster.
Ces avantages considérables laissent entrevoir des perspectives d’ajout de nouveaux modèles grâce au redimensionnement
facile de notre application. Le laboratoire peut décider de déployer l’application finale sur un hébergeur cloud ou sur
leurs serveurs.
Les améliorations peuvent se situer au niveau d’un déploiement et d’une intégration continue grâce à des systèmes
d’automatisation simplifiant le travail du développeur.
Tout le long, je me suis évertué à simplifier l’accessibilité pour les utilisateurs tout en essayant de faciliter le travail du
développeur. Tous ces efforts visent à garantir une application avec une forte longévité.

19
8 Annexes
8.A
1 const apiUrl = () = > ‘$ { API_ROOT }/ predict / pampo ‘ // route sp é cifique à PAMPO pour le back - end
2
3 const title = " Pampo " ; // titre du mod è le
4
5 var bib_article = " @article { Rocha2016PAMPOUP ,\ n "
6 + " title ={ PAMPO : using pattern matching and pos - tagging for effective Named Entities
recognition in Portuguese } ,\ n "
7 + " author ={ Concei ç {\~ a } o Rocha and Al {\ ’ i } pio M {\ ’ a } rio Jorge and Roberta Sionara and Paula
Brito and Carlos Pimenta and Solange Oliveira Rezende } ,\ n "
8 + " journal ={ CoRR } ,\ n "
9 + " year ={2016} ,\ n "
10 + " volume ={ abs /1612.09535} ,\ n "
11 + " } " ; // utilis é pour citer le papier scientifique
12 const bibliography = parseString ( bib_article ) ;
13 const description = (
14 < span >
15 < span >
16 The method , named PAMPO ( PAttern Matching and POs tagging based algorithm for NER ) , ...
17 </ span >
18 < br / >
19 <a href = " https :// safe - basin -21244. herokuapp . com / home " target = " _blank " rel = " noopener noreferrer "
>
20 { ’ ’} Demo website { ’ ’}
21 </a >
22 < br / >
23 <a href = " https :// github . com / LIAAD / py - pampo " target = " _blank " rel = " noopener noreferrer " >{ ’ ’}
Github { ’ ’ } </a >
24 < br / >
25 < pre style ={{ fontSize : " 0.8 em " }} >
26 { bib_article }
27 </ pre >
28 </ span >
29 ) // description avec lien vers le code source et le site sp é cique à l ’ outil
30
31 const fields = [
32 { name : " tabs " , type : " TABS2 " , input : " opt_pampo " }
33 ] // ce sont les champs d é finissant le formulaire d ’ entr é e , ici PAMPO utilise TABS2 , ces composants
sont d é fini dans un autre fichier
34
35 const Output = ({ responseData }) = > {
36 ...
37 return (...)
38 } // Ici on d é finit l ’ affichage des r é sultats ( responseData )
39
40 const modelProps = { apiUrl , title , description , fields , Outout } // ce sont les propri é t é s qui d é
finissent le mod è le
41
42 export default withRouter ( props = > < Model {... props } {... modelProps }/ >)
43 // Model h é ritera des props et des propri é t é s du mod è le , withRouter permet de connecter le composant
Model au routeur . Plus de d é tail dans la suite .

retour au texte

20
8.B
1 class Model extends React . Component {
2 constructor ( props ) {
3 super ( props ) ;
4 const { requestData , responseData } = props ;
5 // H é ritage des propri é t é s
6 this . state = {
7 ...
8 requestData : requestData ,
9 responseData : responseData
10 }; // variables internes et g é r é es par le composant
11 this . runModel = this . runModel . bind ( this )
12 }
13 runModel ( inputs ) {
14 const { selectedModel , apiUrl } = this . props // on r é cup è re l ’ url et le nom du mod è le
15 fetch ( apiUrl ( inputs ) , { // requ ê te asynchrone
16 method : ’ POST ’ ,
17 headers : {
18 ’ Accept ’: ’ application / json ’ ,
19 ’ Content - Type ’: ’ application / json ’ ,
20 },
21 body : JSON . stringify ( inputs )
22 }) . then (( response ) = > {
23 return response . json () ;
24 }) . then (( json ) = > {
25 // Si la r é ponse contient un slug on redirige l ’ utilisateur sur le bon permalien
26
27 const newPath = ‘/ $ { selectedModel } ‘
28 const location = {
29 pathname : newPath ,
30 state : { requestData : inputs , responseData : json }
31 }
32 // On utilise ‘ history . push ‘ , c ’ est ici que sert withRouter , qui permet à Model d ’ utiliser
cette m é thode . C ’ est le lien entre le bloc 3 et 1.
33 this . props . history . push ( location ) ; // Le bloc 1 re ç oit les entr é es et les sorties pour un mod
è le donn é . Il peut mettre à jour l ’ affichage .
34 }) . catch (( error ) = > {
35 ...
36 }) ;
37 }
38 ...
39 }
40 export default Model

retour au texte

21
8.C
1 FROM library / python :3.7.1 - alpine # L ’ avantage d ’ une distribution Alpine est sa l é g è ret é compar é par
example à Debian
2
3 RUN apk update && apk upgrade && \
4 apk add --no - cache bash git && \ # Installation de git
5 apk add build - base # Equivalent de apt - get install build - essential
6
7 RUN apk add pcre - dev # Indispensable pour la biblioth è que PCRE ( regex ) de python
8 RUN pip install -- upgrade pip # Installation de pip
9
10 RUN pip install -r requirements . txt # Installation de toutes les biblioth è ques requises
11 RUN pip install git + https :// github . com / LIAAD / py - pampo . git # Installation de PAMPO depuis github
12 RUN pip install gunicorn
13
14 ADD ./ webapp / opt / webapp / # Copie de tous les fichiers n é cessaires au serveur
15 WORKDIR / opt / webapp # / opt / webapp est d é finit comme r é pertoire de travail
16
17 EXPOSE 8000 # Port expos é par le conteneur
18 CMD gunicorn -- bind 0.0.0.0:8000 wsgi # Commande pour lancer le serveur

retour au texte

8.D
1 # pampo . yaml
2 apiVersion : apps / v1 # version de l ’ API utilis é e
3 kind : Deployment # Indique qu ’ on veut d é ployer des pods
4 metadata :
5 name : pypampo # nom du d é ploiement
6 spec :
7 replicas : 2 # nombres d ’ instances du pods en ex é cution d é sir é es
8 template :
9 metadata :
10 labels :
11 app : pypampo # é tiquette des pods
12 spec :
13 containers : # Conteneur s ’ ex é cutant dans les 2 pods
14 - name : pypampo # nom du conteneur
15 image : 329719/ pypampo # image r é cup é r é e depuis Docker - hub
16 ports :
17 - containerPort : 8000 # Correspond au port expos é dans le Dockerfile
18 ---
19 # On d é ploie sur le cluster avec la commande : kubectl create -f pampo . yaml
20 # on r é p è te la m ê me proc é dure pour les autres conteneurs

retour au texte

22
8.E
1 # d é ploiement des services associ é s aux pods pr é c é dents
2 # pampo_svc . yaml
3 apiVersion : v1
4 kind : Service
5 metadata :
6 name : pypamposvc # nom du service
7 spec :
8 ports :
9 - port : 8000 # port sur lequel le service est accessible
10 protocol : TCP
11 targetPort : 8000 # port sur lequel l ’ application s ’ ex é cute sur les pods
12 selector :
13 app : pypampo # s é lectionne les pods cor respon dants
14 ---
15 # Cr é ation du service avec la commande : kubectl create -f pampo_svc . yaml
16 # ... de m ê me pour les autres outils

retour au texte

8.F
1 # Ici j ’ ai pris l ’ exemple qu ’ il y a deux services sur le cluster , un pour PAMPO et l ’ autre pour
Contamehistorias
2 apiVersion : extensions / v1beta1
3 kind : Ingress # D é ploiement de type Ingress
4 metadata :
5 annotations :
6 kubernetes . io / ingress . class : nginx # Notre Ingress contr ô leur est de classe nginx
7 nginx . ingress . kubernetes . io / cors - allow - methods : " PUT , GET , POST , OPTIONS " # m é thodes autoris é e
8 nginx . ingress . kubernetes . io / use - regex : " true " # Utiliser le regex pour les routes
9 nginx . ingress . kubernetes . io / rewrite - target : / $2 # on re é crit le chemin en r é cup é rant la variable
regex en deuxi è me position sur la route
10 name : ingress - resource
11 spec :
12 rules :
13 - http :
14 paths :
15 - path : / c o n t a m e h i s t o r i a s (/| $ ) (.*) # Si la route demand é e est de cette forme ; / c o n t a m e h i s t o r i a s
/{ $2 = n ’ importe quelles chaines de charact è res }
16 backend :
17 serviceName : c o n t a m e h i s t o r i a s s v c # alors nous redirigeons vers le service associ é
18 servicePort : 8000 # et sur le port du service , voir annexe 9 E
19 - path : / pampo (/| $ ) (.*)
20 backend :
21 serviceName : pypamposvc
22 servicePort : 8000

retour au texte

23
8.G
1 # 1) Cr é ation des noeuds , l ’ option -d permet de pr é ciser que l ’ on fait appel à Google Cloud Engine ,
par d é faut c ’ est ubuntu 16.04 qui est choisi comme syst è me d ’ exploitation .
2 docker - machine create swarm - manager -d google -- google - project LIAAD_tools
3 docker - machine create swarm - worker -1 -d google -- google - project LIAAD_tools
4 docker - machine create swarm - worker -2 -d google -- google - project LIAAD_tools
5 # ------------------------------------------------------------------
6 # 2) Initia lisati on du Swarm sur le noeud manager . La commande " eval " permet de configurer le shell
pour communiquer avec swarm - manager .
7 eval $ ( docker - machine env swarm - manager ) ;
8 docker swarm init ;
9 # ------------------------------------------------------------------
10 # 3) Les autres noeuds joignent le swarm en tant que worker . Le < token > et < manager_ip > nous sont
donn é s lors de l ’é tape pr é c é dente . Ce sont des param è tres choisis par Docker .
11 eval $ ( docker - machine env swarm - worker -1) ;
12 docker swarm join -- token < token > < manager_ip >:2377;
13 eval $ ( docker - machine env swarm - worker -2) ;
14 docker swarm join -- token < token > < manager_ip >:2377;
15 # ------------------------------------------------------------------
16 # 4) Cr é ation du r é seau de communication de nos services .
17 docker network create -d overlay my_network
18 # ------------------------------------------------------------------
19 # 5) Chacun de noeuds doit disposer du fichier de configuration de Nginx . L ’ explication arrivera l ’
une des é tapes suivantes . Le port 22 est ouvert sur chacune des machines . Le fichier est cr é e sur
chacun des noeuds puis le fichier local nginx . conf est copi é dedans .
20 docker - machine ssh < node_name > " touch / home / docker - user / nginx . conf "
21 docker - machine scp nginx . conf < node_name >:/ home / docker - user / nginx . conf
22 # ------------------------------------------------------------------
23 # 6) Cr é ation des services associ é s aux outils . Nous pr é cisons le port sur lequel ils sont joignable
via -- publish target . Les services appartiennent au r é seau cr é e pr é c é demment gr â ce à -- network .
Enfin , l ’ image est charg é e depuis le r é pertoire 329719 sur Docker - hub .
24 docker service create -- name c o n t a m e h i s t o r i a s -- replicas 2 -- publish target =8000 -- network my_network
329719/ c o n t a m e h i s t o r i a s ;
25 docker service create -- name pypampo -- replicas 2 -- publish target =8000 -- network my_network 329719/
pypampo ;
26 # ------------------------------------------------------------------
27 # 7) Cr é ation du service associ é au serveur nginx . Le port 80 est expos é hors du swarm gr â ce à --
publish published =80 . De m ê me chacun des services internes peut joindre le serveur via le port
80 , target =80. Il appartient au r é seau my_network . Enfin , il y a le montage du fichier de
configuration situ é sur chacun des noeuds et celui situ é dans le conteneur de nginx . Il est n é
cessaire que chacun des noeuds dispose du fichiers car nous ne pouvons pr é supposer o ù le
conteneur de nginx s ’ ex é cutera .
28 docker service create -- name nginx -- replicas 1 \
29 -- publish published =80 , target =80 -- network my_network \
30 -- mount type = bind , src =/ home / docker - user / nginx . conf , dst =/ etc / nginx / nginx . conf nginx \

retour au texte

24
8.H
1 FROM ubuntu : latest # Image construite à partir de celle d ’ Ubuntu
2 # Installation de packages utiles
3 RUN apt - get update
4 RUN apt - get install -y python3 .7 # Python pour le serveur back - end
5 RUN apt - get install -y python3 - lxml
6 RUN apt - get install -y python3 - pip
7 RUN apt - get install -y wget
8 # -----------------------------------------------------------
9 # Installation de la base de donn é es MONGODB
10 RUN mkdir -p / data / db
11 RUN wget - qO - https :// www . mongodb . org / static / pgp / server -4.2. asc | apt - key add -
12 RUN echo " deb [ arch = amd64 ] https :// repo . mongodb . org / apt / ubuntu bionic / mongodb - org /4.2 multiverse " |
tee / etc / apt / sources . list . d / mongodb - org -4.2. list
13 RUN apt - get update
14 RUN D EB IA N _F RO N TE N D = nonint eracti ve apt - get install -y mongodb - org
15 RUN apt - get install -y mongodb - server
16 # -----------------------------------------------------------
17 COPY / demo / demo # Copie des fichiers du Front - end
18 # Installation des biblioth è ques du serveur
19 ENV P YT HO N _P AC K AG E S = " \
20 bson \
21 flask \
22 flask_cors \
23 gevent \
24 pymongo \
25 werkzeug \
26 nltk \
27 pytz \
28 lxml \
29 "
30 RUN pip3 install --no - cache - dir $ P Y T H O N _ P A C K A G E S
31 RUN pip3 install gunicorn
32 # -----------------------------------------------------------
33 COPY app . py app . py # Fichier de configuration du serveur
34 COPY utils . py utils . py
35 COPY lauch . sh lauch . sh
36 EXPOSE $PORT # Heroku choisi le port
37 CMD ./ lauch . sh $PORT # Commande ex é cut é e lors de l ’ instanciation du conteneur
38 # ----------------------
39 # lauch . sh
40 # mongod & # Lancement de la base de donn é e
41 # python3 app . py $1 # Lancement du serveur
42 # ----------------------

retour au texte

25
8.I

retour au texte

26
9 Références Bibliographiques
[1] C.Rocha,A.M.Jorge,P.Brinto,C.Pimenta,R.A.Sionara,S.O.Rezende "PAMPO: using pattern matching and pos-tagging
for effective named entities recognition in portuguese"/ https://arxiv.org/pdf/1612.09535.pdf
[2] python-pcre,"Python bindings for PCRE regex engine."/ https://github.com/awahlig/python-pcre
[3] spaCy,"Industrial-Strength Natural Language Processing"/ https://spacy.io/
[4] R language, https://www.r-project.org/about.html

[5] Campos R., Mangaravite V., Pasquali A., Jorge A.M., Nunes C., and Jatowt A. (2018). YAKE! Collection-
independent Automatic Keyword Extractor. In: Pasi G., Piwowarski B., Azzopardi L., Hanbury A. (eds). Advances in
Information Retrieval. ECIR 2018 (Grenoble, France. March 26 – 29). Lecture Notes in Computer Science, vol 10772,
pp. 806 - 810. pdf
[6] Pasquali A., Mangaravite V., Campos R., Jorge A.M., Jatowt A. (2019) Interactive System for Automatically Gen-
erating Temporal Narratives. In Advances in Information Retrieval. ECIR 2019. Lecture Notes in Computer Science,
vol 11438. Springer, Cham
[7] Flask Documentation, https://flask.palletsprojects.com/en/1.1.x/

[8] Django Documentation, https://docs.djangoproject.com/en/2.2/

[9] Jinja2 Template Documentation , https://jinja.palletsprojects.com/en/2.10.x/templates/

[10] Heroku website, https://www.heroku.com/


[11] Site français de MongoDB, https://www.mongodb.com/fr
[12] PyMongo 3.9.0 Documentation, https://api.mongodb.com/python/current/
[13] Site français de ReactJS, https://fr.reactjs.org/
[14] AngularJS website, https://angularjs.org/
[15] EmberJS website, https://emberjs.com/
[16] npmjs website, https://www.npmjs.com/
[17] Docker Documentation, https://docs.docker.com/
[18] Swagger Documentation, https://swagger.io/docs/
[19] Cookiecutter Documentation, https://cookiecutter.readthedocs.io/en/latest
[20] Plumber Documentation, https://www.rplumber.io/
[21] Docker hub website, https://hub.docker.com/
[22] Apache official website, http://httpd.apache.org/
[23] Nginx official website, https://www.nginx.com/
[24] Site web français de GCP , https://cloud.google.com/
[25] Documentation officielle de Kubernetes , https://kubernetes.io/fr/docs/tutorials/kubernetes-basics/
[26] Docker-swarm Documentation , https://docs.docker.com/engine/swarm/
[27] npm serve package , https://www.npmjs.com/package/serve
[28] Jenkins website , https://jenkins.io/

27