Spaces:
Sleeping
A newer version of the Gradio SDK is available: 6.22.0
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 fichiertab_*.pyimporte les fonctions depuiscore/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 : <type>(<scope>): <description>
- 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éebuild/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 :
- NLTK (punkt) — Word-level classique, découpe sur les espaces et la ponctuation
- SpaCy — Word-level plus intelligent (gère les contractions, abbréviations)
- BERT WordPiece — Subword : découpe les mots rares en sous-parties (préfixe
##) - 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 :
- Sentiment (DistilBERT SST-2) → Positif / Négatif avec score de confiance
- É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 :
- Les deux textes sont encodés en vecteurs d'embedding (384 dimensions) via
all-MiniLM-L6-v2 - On calcule la similarité cosinus entre les deux vecteurs (1 = identique, 0 = aucun rapport)
- 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
- Textes pré-remplis : Chaque onglet a un texte d'exemple par défaut → pas de champ vide
- Feedback immédiat : Un clic sur le bouton = résultat visible sans scroll
- Tabs autonomes : Chaque onglet est indépendant, on peut démontrer un seul module
- 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.
_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 :
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 :
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 :
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 :
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 :
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 :
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)
Settings → Entrer la clé Gemini (optionnel, les textes par défaut suffisent)
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
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
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
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
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 ( |
| 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 !