# DeepText Studio — Guide de Présentation > **Projet** : Multi-Task NLP Toolkit · ISEN M1 S8 > **Auteur** : Maxime Demeulemeester > **Date** : Mars 2026 --- ## 1. Présentation Générale **DeepText Studio** est une application web qui regroupe **5 modules de NLP** (Natural Language Processing) dans une interface unique construite avec **Gradio**. L'idée est de proposer un **toolkit interactif** où l'on peut explorer différentes tâches du traitement du langage naturel sans écrire de code — tout se fait via une interface web avec des onglets dédiés. ### Les 5 modules | # | Onglet | Ce que ça fait | Modèle utilisé | |---|--------|----------------|-----------------| | 1 | **Tokenization** | Compare 4 méthodes de découpage de texte en tokens | NLTK punkt, SpaCy, BERT WordPiece, GPT-2 BPE | | 2 | **Sentiment Analysis** | Détecte le sentiment (positif/négatif) + les émotions | DistilBERT SST-2 + DistilRoBERTa emotions | | 3 | **Semantic Similarity** | Mesure la distance sémantique entre 2 textes | sentence-transformers/all-MiniLM-L6-v2 | | 4 | **Zero-Shot Classification** | Classe un texte dans des catégories libres (sans entraînement) | facebook/bart-large-mnli | | 5 | **NER (Innovation)** | Extrait les entités nommées (personnes, lieux, organisations) | dslim/bert-base-NER | **+ un onglet Settings** pour configurer une clé API Gemini qui permet de générer du texte aléatoire dans chaque module. --- ## 2. Stack Technique | Composant | Technologie | Rôle | |-----------|-------------|------| | Framework UI | **Gradio 4.x** | Interface web multi-onglets | | Backend | **Python 3.10+** | Logique NLP | | Modèles NLP | **HuggingFace Transformers** | Pipelines pré-entraînés | | Embeddings | **sentence-transformers** | Encodage sémantique des phrases | | Tokeniseurs classiques | **NLTK** + **SpaCy** | Tokenisation word-level | | Deep Learning | **PyTorch** | Backend des modèles Transformers | | API externe | **Google Gemini** | Génération de texte aléatoire | | Déploiement | **FastAPI** + **Vercel** (via `api/index.py`) | Serverless | --- ## 3. Architecture du Projet ``` DeepText Studio/ ├── app.py ← Point d'entrée (lance l'app Gradio) ├── requirements.txt ← Dépendances Python ├── api/ │ └── index.py ← Entry point Vercel (FastAPI + Gradio monté) ├── core/ ← Logique métier pure (pas de Gradio ici) │ ├── tokenizer.py ← 4 méthodes de tokenisation │ ├── sentiment.py ← Pipeline sentiment + émotions │ ├── similarity.py ← Cosine similarity sur embeddings │ ├── zero_shot.py ← Classification zero-shot BART │ ├── innovation.py ← NER avec BERT-base-NER │ └── settings.py ← Gestion clé API Gemini + génération de texte ├── ui/ ← Interface Gradio (composants visuels) │ ├── theme.py ← Thème dark futuriste + CSS custom │ ├── tab_tokenizer.py ← UI onglet tokenisation │ ├── tab_sentiment.py ← UI onglet sentiment │ ├── tab_similarity.py ← UI onglet similarité │ ├── tab_zero_shot.py ← UI onglet zero-shot │ ├── tab_innovation.py ← UI onglet NER │ └── tab_settings.py ← UI onglet paramètres └── build/ ← Fichiers de planification et suivi ├── plan.md ← Plan de développement par phases ├── agent.md ← Contexte IA inter-phases └── claude.md ← Instructions pour les agents IA ``` ### Principe de séparation `core/` vs `ui/` Le projet suit un pattern **MVC simplifié** : - **`core/`** contient toute la logique métier (appels aux modèles, calculs). Aucune dépendance à Gradio. - **`ui/`** contient uniquement les composants d'interface. Chaque fichier `tab_*.py` importe les fonctions depuis `core/` et les branche sur des boutons Gradio. Cela permet de : - Tester la logique indépendamment de l'UI - Réutiliser le core dans un autre contexte (API, CLI, etc.) - Garder le code lisible et maintenable --- ## 4. Méthodologie de Développement ### 4.1 Planification par Phases Le développement a été structuré en **8 phases séquentielles**, chacune correspondant à une branche Git : | Phase | Branche | Contenu | Tags | |-------|---------|---------|------| | **P0** | `setup/init` | Scaffold du projet, structure de dossiers, requirements | `v0.1-scaffold` | | **P1** | `feature/tokenization` | Module tokenisation (4 méthodes) | `v0.2-tokenization` | | **P2** | `feature/sentiment` | Module sentiment + émotions | `v0.3-sentiment` | | **P3** | `feature/similarity` | Module similarité sémantique | `v0.4-similarity` | | **P4** | `feature/zero-shot` | Module classification zero-shot | `v0.5-zero-shot` | | **P5** | `feature/innovation` | Module NER (feature innovante) | `v0.6-innovation` | | **P6** | `ui/theme-polish` | Thème dark futuriste, CSS, polish | `v0.7-themed` | | **P7** | `release/v1.0` | Tests, nettoyage, documentation | `v1.0-release` | ### 4.2 Convention de commits Format : `(): ` - Types : `init`, `feat`, `fix`, `style`, `docs`, `test`, `chore`, `release` - Scopes : `token`, `sentiment`, `sim`, `zs`, `ner`, `ui`, `app` ### 4.3 Fichiers de suivi IA Le projet utilise trois fichiers de pilotage pour les agents IA : - **`build/plan.md`** : Le plan de développement complet avec chaque étape détaillée - **`build/agent.md`** : L'état du projet (version, phase active, décisions prises, problèmes) - **`build/claude.md`** : Les règles de code, style UI, et conventions à respecter Ces fichiers permettent de maintenir la cohérence du projet quand on utilise un LLM pour coder. --- ## 5. Détail Technique par Module ### 5.1 Tokenization (Tab 1) **Objectif** : Montrer la différence entre tokenisation word-level et subword. **4 méthodes comparées :** 1. **NLTK (punkt)** — Word-level classique, découpe sur les espaces et la ponctuation 2. **SpaCy** — Word-level plus intelligent (gère les contractions, abbréviations) 3. **BERT WordPiece** — Subword : découpe les mots rares en sous-parties (préfixe `##`) 4. **GPT-2 BPE** — Byte Pair Encoding : subword basé sur la fréquence des paires d'octets (préfixe `Ġ`) **Point intéressant à expliquer en démo** : Pour le mot "unprecedented", NLTK et SpaCy gardent le mot entier, mais BERT le découpe en `un`, `##pre`, `##ce`, `##dent`, `##ed` — ça montre comment les Transformers gèrent les mots hors vocabulaire. **Lazy loading** : Les modèles ne sont chargés qu'au premier clic (pas au démarrage de l'app). ### 5.2 Sentiment Analysis (Tab 2) **Objectif** : Analyser la tonalité d'un texte. **Deux analyses combinées :** 1. **Sentiment** (DistilBERT SST-2) → Positif / Négatif avec score de confiance 2. **Émotions** (DistilRoBERTa j-hartmann) → 7 émotions : joy, anger, fear, sadness, surprise, disgust, neutral — classées par score décroissant **Point intéressant** : On utilise `top_k=None` pour obtenir TOUTES les émotions avec leur score, pas juste la dominante. Ça permet d'afficher un tableau complet avec barres de progression. ### 5.3 Semantic Similarity (Tab 3) **Objectif** : Mesurer à quel point deux textes disent "la même chose". **Comment ça marche :** 1. Les deux textes sont encodés en **vecteurs d'embedding** (384 dimensions) via `all-MiniLM-L6-v2` 2. On calcule la **similarité cosinus** entre les deux vecteurs (1 = identique, 0 = aucun rapport) 3. Le résultat est affiché avec une **interprétation** (Very Similar / Moderately / Slightly / Not Similar) **Point intéressant** : "The cat is sitting on the mat" vs "A kitten is resting on the rug" → score élevé car le modèle comprend que chat ≈ chaton, tapis ≈ natte, assis ≈ se repose. ### 5.4 Zero-Shot Classification (Tab 4) **Objectif** : Classer un texte dans des catégories arbitraires sans ré-entraîner le modèle. **Comment ça marche :** - Le modèle **BART-large-MNLI** est entraîné sur le Natural Language Inference (NLI) - Pour chaque catégorie, il évalue l'hypothèse "This text is about {category}" et donne un score - L'utilisateur peut entrer n'importe quelles catégories séparées par des virgules **Point intéressant** : Le modèle fait ~1.6 GB — c'est le plus gros du projet. Il est capable de classifier dans des catégories jamais vues grâce au transfer learning. ### 5.5 NER - Innovation (Tab 5) **Objectif** : Extraire les entités nommées d'un texte. **4 types d'entités détectées :** - **PER** (Person) : Elon Musk, Barack Obama - **ORG** (Organization) : NASA, Tesla, SpaceX - **LOC** (Location) : Washington, Tokyo, Paris - **MISC** (Miscellaneous) : European, FIFA World Cup **Choix de l'innovation** : La NER est complémentaire aux autres modules — elle montre une compréhension structurelle du texte (qui, où, quelle organisation) plutôt que sémantique (sentiment, similarité). **Modèle** : `dslim/bert-base-NER` avec `aggregation_strategy="simple"` pour fusionner les sous-tokens en entités complètes. ### 5.6 Settings (Tab 6) **Objectif** : Permettre la configuration d'une clé API Gemini. **Fonctionnalités :** - Sauvegarde sécurisée de la clé API (champ password) - Test de connexion automatique à l'API - Une fois configurée, un bouton "Generate with Gemini" apparaît dans chaque onglet pour générer du texte aléatoire adapté au module (texte simple, paires de phrases, texte riche en entités, catégories...) --- ## 6. Choix de Design (UI/UX) ### Thème Dark Futuriste - **Fond** : Noir profond `#0a0a0f` → Bleu nuit `#0d1117` - **Accents** : Cyan néon `#00f0ff` + Violet électrique `#a855f7` - **Texte** : Blanc `#e6edf3` - **Police** : Inter (UI) + JetBrains Mono (code/tokens) - **Effets** : Bordures subtiles, glow cyan au focus, animation fadeIn sur les onglets. ### Principes UX appliqués 1. **Textes pré-remplis** : Chaque onglet a un texte d'exemple par défaut → pas de champ vide 2. **Feedback immédiat** : Un clic sur le bouton = résultat visible sans scroll 3. **Tabs autonomes** : Chaque onglet est indépendant, on peut démontrer un seul module 4. **Responsive** : CSS adaptatif pour tablette et mobile --- ## 7. Difficultés Rencontrées & Solutions ### 7.1 Taille des modèles **Problème** : Les modèles Transformers sont volumineux (BART-large-MNLI = ~1.6 GB). Le premier chargement est lent et consomme beaucoup de RAM. **Solution** : **Lazy loading** — chaque modèle est stocké dans une variable globale `_pipeline = None` et n'est chargé qu'au premier appel de la fonction. Ça évite de charger les 5 modèles au démarrage. ```python _sentiment_pipeline = None def _get_sentiment_pipeline(): global _sentiment_pipeline if _sentiment_pipeline is None: _sentiment_pipeline = pipeline("sentiment-analysis", model="...") return _sentiment_pipeline ``` ### 7.2 Tokenisation SpaCy — modèle manquant **Problème** : SpaCy nécessite un modèle de langue téléchargé séparément (`fr_core_news_sm` ou `en_core_web_sm`). Sans ça, l'app crash. **Solution** : Fallback automatique — on essaie d'abord le modèle français, puis l'anglais, et si aucun n'est trouvé, on télécharge automatiquement : ```python for model in ("fr_core_news_sm", "en_core_web_sm"): try: _spacy_nlp = spacy.load(model) return _spacy_nlp except OSError: continue # Auto-download si aucun trouvé subprocess.run(["python", "-m", "spacy", "download", "fr_core_news_sm"]) ``` ### 7.3 NLTK punkt — téléchargement silencieux **Problème** : NLTK a besoin du tokenizer `punkt_tab` mais ne le télécharge pas tout seul. **Solution** : Vérification + téléchargement automatique au chargement du module : ```python try: nltk.data.find("tokenizers/punkt_tab") except LookupError: nltk.download("punkt_tab", quiet=True) ``` ### 7.4 Warnings des modèles Transformers **Problème** : Les modèles HuggingFace affichent des warnings "UNEXPECTED keys" dans la console, ce qui peut être confus. **Solution** : Suppression des warnings dans `app.py` : ```python import warnings, logging warnings.filterwarnings("ignore", message=".*UNEXPECTED.*") logging.getLogger("transformers.modeling_utils").setLevel(logging.ERROR) ``` ### 7.5 SSR (Server-Side Rendering) de Gradio **Problème** : Le mode SSR de Gradio posait des problèmes de compatibilité lors du déploiement. **Solution** : Désactivation explicite du SSR dans `app.py` : ```python app.launch(ssr_mode=False) ``` ### 7.6 Déploiement Vercel (Serverless) **Problème** : Gradio est conçu pour tourner en tant que serveur persistant, pas en serverless. **Solution** : Création de `api/index.py` qui monte l'app Gradio sur **FastAPI**, compatible avec le runtime serverless de Vercel : ```python app = FastAPI() app = gr.mount_gradio_app(app, demo, path="/") ``` ### 7.7 NER — Tokens fragmentés **Problème** : Le modèle NER retourne des entités fragmentées en sous-tokens (ex: "Elon" et "Musk" séparés). **Solution** : Utilisation de `aggregation_strategy="simple"` dans le pipeline pour fusionner automatiquement les sous-tokens en entités complètes. ### 7.8 Émotions — Format de retour variable **Problème** : Le pipeline d'émotions avec `top_k=None` retourne tantôt une liste simple, tantôt une liste de listes selon la version de Transformers. **Solution** : Double vérification du format : ```python if emo_result and isinstance(emo_result[0], list): emo_raw = emo_result[0] else: emo_raw = emo_result ``` --- ## 8. Ce qu'on peut montrer en Démo ### Scénario de démo recommandé (5-10 min) 1. **Settings** → Entrer la clé Gemini (optionnel, les textes par défaut suffisent) 2. **Tokenization** → Montrer le texte par défaut, cliquer "Tokenize" - Comparer NLTK vs BERT → expliquer word-level vs subword - Montrer que GPT-2 BPE gère différemment de BERT WordPiece 3. **Sentiment** → Tester avec une phrase positive puis une négative - Montrer les 7 émotions détectées - Changer le texte et relancer pour voir la différence 4. **Similarity** → Garder l'exemple par défaut (cat/kitten) - Montrer le score élevé (~0.8+) - Changer un texte pour quelque chose sans rapport → score bas 5. **Zero-Shot** → Le texte SpaceX par défaut - Montrer que "Technology" et "Science" scorent le plus haut - Changer les catégories pour des choses farfelues → le modèle s'adapte 6. **NER** → Le texte avec Elon Musk, NASA, Washington - Montrer l'extraction des entités avec leur type - Expliquer PER / ORG / LOC / MISC ### Questions potentielles du jury et réponses | Question | Réponse | |----------|---------| | Pourquoi Gradio et pas Flask/Streamlit ? | Gradio est imposé par le sujet, mais il est idéal pour les démos ML : composants pré-construits, multi-tabs, déploiement facile | | Pourquoi ces modèles spécifiques ? | Bon compromis taille/performance. DistilBERT est léger (~260 MB), MiniLM est ultra-compact (~90 MB). Seul BART est gros (~1.6 GB) mais c'est le standard pour le zero-shot | | Comment gérez-vous la performance ? | Lazy loading des modèles + cache HuggingFace local. Premier appel lent, ensuite instantané | | Pourquoi NER comme innovation ? | Complémentaire aux autres modules (analyse structurelle vs sémantique), bonne démo visuelle, modèle performant et léger | | Le projet tourne-t-il sur GPU ? | Auto-détection CPU/GPU. En démo locale, CPU suffit car les modèles sont optimisés (DistilBERT, MiniLM) | | Comment fonctionne le zero-shot ? | BART est entraîné sur le NLI (textual entailment). Pour chaque catégorie, il teste l'hypothèse "This text is about {category}" | | Quel est le rôle de Gemini ? | Uniquement pour la génération de texte aléatoire (bouton "Generate"). Les analyses NLP sont 100% locales avec les modèles HuggingFace | --- ## 9. Résumé des Technologies et Concepts Clés ### Concepts NLP à connaître - **Tokenisation** : Découpage du texte en unités (tokens). Word-level = mots entiers, Subword = sous-parties de mots - **WordPiece** (BERT) : Algorithme qui découpe les mots rares en sous-tokens fréquents (préfixe `##`) - **BPE** (GPT-2) : Byte Pair Encoding — fusionne itérativement les paires de caractères les plus fréquentes - **Sentiment Analysis** : Classification binaire (positif/négatif) ou multi-classes (émotions) - **Embeddings** : Représentation vectorielle dense d'un texte (ici 384 dimensions) - **Cosine Similarity** : Mesure de l'angle entre deux vecteurs (1 = même direction = même sens) - **Zero-Shot** : Capacité d'un modèle à classifier dans des catégories jamais vues pendant l'entraînement - **NLI (Natural Language Inference)** : Tâche consistant à déterminer si une hypothèse est impliquée par une prémisse - **NER (Named Entity Recognition)** : Identification et classification des entités nommées dans un texte - **Transfer Learning** : Réutilisation d'un modèle pré-entraîné pour une tâche différente - **Lazy Loading** : Chargement différé d'une ressource au moment où elle est réellement nécessaire ### Bibliothèques utilisées | Bibliothèque | Version | Usage | |---------------|---------|-------| | `gradio` | ≥ 4.0 | Interface web | | `transformers` | latest | Pipelines NLP (sentiment, NER, zero-shot) | | `torch` | latest | Backend PyTorch pour les modèles | | `sentence-transformers` | latest | Embeddings de phrases | | `spacy` | latest | Tokenisation word-level | | `nltk` | latest | Tokenisation word-level (punkt) | | `scipy` | latest | Calcul de distance cosinus | | `google-genai` | latest | API Gemini pour génération de texte | | `fastapi` | latest | Montage Gradio pour Vercel | | `uvicorn` | latest | Serveur ASGI | --- > _Bonne présentation !_