File size: 18,087 Bytes
f23553c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
# 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 : `<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é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 !_