--- title: Sentiment d'appels vocaux francais emoji: "🎙️" colorFrom: blue colorTo: purple sdk: gradio sdk_version: 5.50.0 python_version: 3.11 app_file: app.py suggested_hardware: cpu-basic preload_from_hub: - jonatasgrosman/wav2vec2-large-xlsr-53-french - cardiffnlp/twitter-xlm-roberta-base-sentiment --- # Détection de sentiment dans des appels vocaux français Projet individuel de **Deep Learning 2** : un pipeline de bout en bout qui reçoit un fichier audio, le transcrit en français, puis classe le sentiment en `positif`, `négatif` ou `neutre` avec un score de confiance. ## Architecture ```text WAV / MP3 -> validation + mono + 16 kHz + normalisation -> Wav2Vec 2.0 (ASR) -> transcription française -> XLM-RoBERTa fine-tuné (sentiment) -> positif / négatif / neutre + confiance ``` La même classe `SentimentCallPipeline` est utilisée par l'interface Gradio et l'API FastAPI. Cela évite que les deux interfaces divergent et garantit que le même prétraitement est appliqué partout. ## Choix des modèles et justification | Étape | Modèle | Justification | |---------------|-------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Transcription | [`jonatasgrosman/wav2vec2-large-xlsr-53-french`](https://huggingface.co/jonatasgrosman/wav2vec2-large-xlsr-53-french) | Wav2Vec 2.0 XLSR est spécifiquement fine-tuné pour le français et correspond au modèle proposé par l'énoncé. Il prend un signal mono de 16 kHz, d'où le prétraitement imposé. | | Sentiment | [`cardiffnlp/twitter-xlm-roberta-base-sentiment`](https://huggingface.co/cardiffnlp/twitter-xlm-roberta-base-sentiment) | XLM-RoBERTa est une variante de la famille BERT. Son fine-tuning fournit directement trois classes (négatif, neutre, positif) et prend en charge le français. | Les poids ne sont pas stockés dans Git : ils sont téléchargés une seule fois au premier appel via Hugging Face, puis mis en cache localement. Sur une machine avec GPU CUDA, PyTorch l'utilise automatiquement ; sinon l'inférence fonctionne sur CPU, plus lentement. Le décodage de la transcription est un décodage CTC glouton (`argmax`) réalisé dans le code. Il ne nécessite pas `pyctcdecode` : cette dépendance est réservée au décodage avec language model externe, qui n'est pas indispensable ici. `sentencepiece` et `protobuf` font partie des dépendances obligatoires : elles permettent de charger le tokenizer du modèle XLM-RoBERTa de sentiment. Le message Hugging Face concernant `hf_xet` est seulement une optimisation de téléchargement ; sans ce paquet, le téléchargement HTTP standard fonctionne normalement. ## Installation et reproduction Prérequis : Python 3.9 ou supérieur. Pour les fichiers MP3, installez aussi `ffmpeg` et rendez-le disponible dans le `PATH`. ```bash git clone cd DL_FINAL_EXAMEN python -m venv .venv ``` Sous Windows : ```powershell .venv\Scripts\Activate.ps1 pip install -r requirements.txt ``` Sous Linux/macOS : ```bash source .venv/bin/activate pip install -r requirements.txt ``` Vérifier les validations audio sans charger les modèles : ```bash pytest -q ``` ## Interface Gradio ```bash python app.py ``` Ouvrez l'URL affichée par Gradio dans un navigateur. L'utilisateur peut importer ou enregistrer un WAV/MP3. L'écran affiche volontairement la **transcription intermédiaire**, le sentiment final et la confiance, comme demandé dans l'énoncé. ## API REST Démarrer le serveur : ```bash uvicorn api:app --reload ``` Vérifier qu'il répond : ```bash curl http://127.0.0.1:8000/health ``` Prédire à partir d'un audio : ```bash curl -X POST "http://127.0.0.1:8000/predict" -F "file=@samples/positif.wav" ``` Réponse attendue : ```json { "transcription": "je suis très satisfait du service","sentiment": "positif","confidence": 0.9273 } ``` `POST /predict` renvoie `400` pour un format non supporté, un fichier vide, un audio silencieux ou un audio de plus de cinq minutes. Un échec de téléchargement/chargement du modèle est renvoyé en `503` plutôt que masqué par une erreur interne. ## Démonstration Le dossier [`samples/`](samples/) contient trois audios de démonstration, un par classe. Les phrases attendues sont documentées dans [`samples/README.md`](samples/README.md). Sous PowerShell, exécutez les trois commandes suivantes : ```bash curl -X POST "http://127.0.0.1:8000/predict" -F "file=@samples/positif.wav" curl -X POST "http://127.0.0.1:8000/predict" -F "file=@samples/negatif.wav" curl -X POST "http://127.0.0.1:8000/predict" -F "file=@samples/neutre.wav" ``` Les scores peuvent varier légèrement selon la version des bibliothèques et la qualité de l'enregistrement. La classe attendue est celle indiquée dans `samples/README.md`. ### Origine des audios de test Les fichiers `samples/positif.wav`, `samples/negatif.wav` et `samples/neutre.wav` **ne proviennent pas d'un site externe** : ils ont été créés localement par synthèse vocale Windows avec la voix française `Microsoft Hortense Desktop`. Ce choix rend la démonstration réutilisable, évite les problèmes de droit d'auteur et garantit qu'aucune donnée vocale de client n'est incluse dans le dépôt. Le script complet et commenté est disponible dans [`scripts/generate_demo_audios.ps1`](scripts/generate_demo_audios.ps1). Pour régénérer exactement les fichiers sous Windows, depuis la racine du projet : ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\generate_demo_audios.ps1 ``` Si la voix `Microsoft Hortense Desktop` n'est pas disponible, il faut l'ajouter dans les paramètres Windows (voix française), ou enregistrer les trois phrases indiquées dans `samples/README.md` avec un téléphone puis les exporter en WAV/MP3. ## Limites connues - La qualité de l'ASR diminue avec le bruit, les chevauchements de voix, les accents peu représentés dans les données d'entraînement et les appels téléphoniques fortement compressés. - Le classifieur a été fine-tuné sur des textes courts de type réseaux sociaux : une transcription erronée, l'ironie ou le contexte conversationnel peuvent conduire à une classe incorrecte. - Le score est la probabilité du modèle, pas une garantie de justesse ni une mesure de satisfaction métier calibrée. - Les fichiers longs sont refusés à cinq minutes pour protéger la mémoire et le temps de réponse. Pour un centre d'appels réel, il faut découper les conversations et ajouter l'identification des locuteurs. ## Bonus : Docker Le conteneur lance l'API FastAPI sur le port `8000`. Il installe aussi `ffmpeg`, nécessaire pour que les fichiers MP3 soient réellement pris en charge dans le conteneur. ```bash docker compose up --build ``` L'API sera accessible sur `http://127.0.0.1:8000`. Au premier appel de prédiction, le conteneur doit avoir accès à Internet pour télécharger les modèles. ## Bonus : déploiement public de la démo Le fichier `README.md` contient déjà la configuration d'un **Hugging Face Space Gradio** : `app.py` est l'interface publique, et les deux modèles sont préchargés lors du build pour éviter un premier clic très lent. 1. Créer un nouveau Space public sur Hugging Face et choisir le SDK **Gradio**. 2. Pousser tout ce dépôt dans le Space ; ne pas envoyer `.venv/` grâce au `.gitignore`. 3. Attendre la fin du build, puis ouvrir l'URL publique `https://-.hf.space`. 4. Tester un import WAV et un enregistrement microphone dans la démo publique. ## Structure du dépôt ```text . ├── app.py # interface Gradio ├── api.py # endpoint POST /predict ├── src/audio.py # validation et prétraitement 16 kHz/mono ├── src/pipeline.py # Wav2Vec2 -> XLM-RoBERTa ├── tests/ # tests unitaires de la couche audio ├── samples/ # trois audios et deux vidéos de démonstration ├── scripts/ # outil reproductible de génération des audios ├── requirements.txt └── Dockerfile ```