ASI-Engineer commited on
Commit
50d8f40
·
verified ·
1 Parent(s): 584dcd9

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. .env.example +3 -0
  2. HF_DEPLOYMENT.md +168 -0
  3. QUICK_DEPLOY.md +139 -0
  4. app.py +109 -9
  5. src/Dockerfile +3 -3
  6. test_deployment.sh +166 -0
.env.example CHANGED
@@ -28,6 +28,9 @@ API_PORT=8000
28
  # Mode debug (True/False)
29
  DEBUG=False
30
 
 
 
 
31
  # ===== LOGGING =====
32
  # Niveau de log (DEBUG, INFO, WARNING, ERROR)
33
  LOG_LEVEL=INFO
 
28
  # Mode debug (True/False)
29
  DEBUG=False
30
 
31
+ # Activer l'interface Gradio
32
+ GRADIO_ENABLED=True
33
+
34
  # ===== LOGGING =====
35
  # Niveau de log (DEBUG, INFO, WARNING, ERROR)
36
  LOG_LEVEL=INFO
HF_DEPLOYMENT.md ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Déploiement sur HuggingFace Spaces
2
+
3
+ ## Architecture déployée
4
+
5
+ L'application lance **2 services simultanément** :
6
+
7
+ 1. **FastAPI** (port 8000) : API REST complète
8
+ 2. **Gradio** (port 7860) : Interface web interactive
9
+
10
+ ## URLs d'accès
11
+
12
+ Sur HuggingFace Spaces, l'application sera accessible à :
13
+
14
+ - **Interface Gradio** : `https://votre-space.hf.space/` (port public 7860)
15
+ - **API FastAPI** : Accessible en interne via `http://localhost:8000`
16
+
17
+ ⚠️ **Note importante** : HuggingFace Spaces n'expose publiquement que le port 7860 (Gradio). L'API FastAPI est accessible uniquement en interne ou via l'interface Gradio.
18
+
19
+ ## Configuration requise sur HF Spaces
20
+
21
+ ### 1. Variables d'environnement (Secrets)
22
+
23
+ Dans les paramètres de votre Space, configurez ces secrets :
24
+
25
+ ```bash
26
+ API_KEY=votre-clé-api-production
27
+ DEBUG=false
28
+ LOG_LEVEL=INFO
29
+ GRADIO_ENABLED=true
30
+ ```
31
+
32
+ ### 2. Fichiers nécessaires
33
+
34
+ Ces fichiers doivent être présents dans le repository :
35
+
36
+ ```
37
+ .
38
+ ├── app.py # Lance FastAPI + Gradio
39
+ ├── api.py # Code FastAPI
40
+ ├── db_models.py # Modèles BDD (optionnel sur HF)
41
+ ├── pyproject.toml # Dépendances Poetry
42
+ ├── poetry.lock # Lock des versions
43
+ ├── README.md # Documentation + metadata HF
44
+ └── src/
45
+ ├── __init__.py
46
+ ├── auth.py
47
+ ├── config.py
48
+ ├── gradio_ui.py # Interface Gradio
49
+ ├── logger.py
50
+ ├── models.py
51
+ ├── preprocessing.py
52
+ ├── rate_limit.py
53
+ └── schemas.py
54
+ ```
55
+
56
+ ### 3. Metadata HF dans README.md
57
+
58
+ Assurez-vous que le header YAML dans `README.md` contient :
59
+
60
+ ```yaml
61
+ ---
62
+ title: Employee Turnover Prediction API
63
+ emoji: 🚀
64
+ colorFrom: blue
65
+ colorTo: green
66
+ sdk: gradio
67
+ sdk_version: "5.9.1"
68
+ app_file: app.py
69
+ pinned: false
70
+ ---
71
+ ```
72
+
73
+ ## Comment l'application démarre
74
+
75
+ 1. `app.py` démarre FastAPI sur le port 8000 (background)
76
+ 2. Attend que FastAPI soit opérationnel (health check)
77
+ 3. Lance Gradio sur le port 7860 (foreground)
78
+ 4. Les deux services communiquent en interne
79
+
80
+ ## Test local
81
+
82
+ Pour tester localement avant déploiement :
83
+
84
+ ```bash
85
+ # Activer l'environnement virtuel
86
+ source .venv/bin/activate
87
+
88
+ # Lancer l'application
89
+ python app.py
90
+ ```
91
+
92
+ Puis accédez à :
93
+ - Gradio : http://localhost:7860
94
+ - FastAPI : http://localhost:8000/docs
95
+
96
+ ## Utilisation de l'API depuis l'extérieur
97
+
98
+ ### Option 1 : Via l'interface Gradio (recommandé)
99
+
100
+ Utilisez l'interface web directement sur `https://votre-space.hf.space/`
101
+
102
+ ### Option 2 : Via l'API Gradio (pour scripts externes)
103
+
104
+ Gradio expose automatiquement une API pour ses fonctions :
105
+
106
+ ```python
107
+ from gradio_client import Client
108
+
109
+ client = Client("https://votre-space.hf.space/")
110
+ result = client.predict(
111
+ nombre_participation_pee=0,
112
+ nb_formations_suivies=2,
113
+ # ... autres paramètres
114
+ api_name="/predict"
115
+ )
116
+ print(result)
117
+ ```
118
+
119
+ ### Option 3 : FastAPI (uniquement en local ou si proxy configuré)
120
+
121
+ L'API FastAPI n'est pas directement accessible depuis l'extérieur sur HF Spaces.
122
+
123
+ ## Dépannage
124
+
125
+ ### Le Space ne démarre pas
126
+
127
+ 1. Vérifiez les logs dans l'onglet "Logs" de HF Spaces
128
+ 2. Vérifiez que `pyproject.toml` et `poetry.lock` sont à jour
129
+ 3. Vérifiez que toutes les dépendances sont installables
130
+
131
+ ### FastAPI ne démarre pas
132
+
133
+ - Vérifiez que `uvicorn` est dans les dépendances
134
+ - Vérifiez les logs pour les erreurs de port
135
+ - Assurez-vous que le modèle est bien téléchargeable depuis HF Hub
136
+
137
+ ### Gradio ne répond pas
138
+
139
+ - Vérifiez que le port 7860 n'est pas bloqué
140
+ - Vérifiez que `sdk: gradio` est bien dans le README
141
+ - Vérifiez que `app_file: app.py` pointe vers le bon fichier
142
+
143
+ ## Logs et monitoring
144
+
145
+ Les logs sont visibles dans l'onglet "Logs" de HF Spaces. Format :
146
+
147
+ ```
148
+ 2026-01-12 03:22:01,905 - INFO - 🚀 Démarrage de l'application complète
149
+ 2026-01-12 03:22:02,256 - INFO - [FastAPI] Application startup complete
150
+ 2026-01-12 03:22:04,855 - INFO - ✅ FastAPI démarré et opérationnel
151
+ 2026-01-12 03:22:06,717 - INFO - 🌐 Lancement du serveur sur 0.0.0.0:7860...
152
+ ```
153
+
154
+ ## Mise à jour du déploiement
155
+
156
+ Pour mettre à jour l'application :
157
+
158
+ 1. Committez vos changements sur GitHub
159
+ 2. HF Spaces se synchronise automatiquement
160
+ 3. Le Space redémarre avec les nouveaux fichiers
161
+ 4. Vérifiez les logs pour confirmer le bon démarrage
162
+
163
+ ## Support
164
+
165
+ En cas de problème :
166
+ 1. Consultez les logs HF Spaces
167
+ 2. Testez localement avec `python app.py`
168
+ 3. Vérifiez la documentation : https://huggingface.co/docs/hub/spaces
QUICK_DEPLOY.md ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Guide de déploiement rapide sur HuggingFace Spaces
2
+
3
+ ## ✅ Prérequis
4
+
5
+ Votre application est maintenant configurée pour déployer **FastAPI + Gradio** ensemble.
6
+
7
+ ## 🚀 Déploiement en 3 étapes
8
+
9
+ ### Étape 1 : Tester localement
10
+
11
+ ```bash
12
+ # Lancer le script de test
13
+ ./test_deployment.sh
14
+ ```
15
+
16
+ Si tous les tests passent ✅, passez à l'étape 2.
17
+
18
+ ### Étape 2 : Commiter les changements
19
+
20
+ ```bash
21
+ # Voir les fichiers modifiés
22
+ git status
23
+
24
+ # Ajouter tous les fichiers
25
+ git add app.py src/Dockerfile HF_DEPLOYMENT.md test_deployment.sh QUICK_DEPLOY.md
26
+
27
+ # Commiter
28
+ git commit -m "Deploy: FastAPI + Gradio on HuggingFace Spaces"
29
+
30
+ # Pousser sur GitHub
31
+ git push origin main
32
+ ```
33
+
34
+ ### Étape 3 : Synchroniser HuggingFace Spaces
35
+
36
+ HuggingFace Spaces se synchronise automatiquement avec votre repo GitHub.
37
+
38
+ 1. Allez sur https://huggingface.co/spaces/votre-username/votre-space
39
+ 2. Cliquez sur l'onglet **"Settings"**
40
+ 3. Dans "Repository", vérifiez que le lien GitHub est configuré
41
+ 4. Le Space va se rebuilder automatiquement
42
+ 5. Vérifiez les logs dans l'onglet **"Logs"**
43
+
44
+ ## 📋 Checklist de vérification
45
+
46
+ - [ ] Les tests locaux passent (`./test_deployment.sh`)
47
+ - [ ] Le fichier `README.md` contient le header YAML avec `sdk: gradio`
48
+ - [ ] Les dépendances sont à jour dans `pyproject.toml`
49
+ - [ ] Les secrets sont configurés sur HF Spaces (API_KEY, DEBUG, etc.)
50
+ - [ ] Le repository GitHub est synchronisé
51
+
52
+ ## 🔍 Vérification après déploiement
53
+
54
+ Une fois le Space déployé, vérifiez :
55
+
56
+ 1. **Interface Gradio** : Accédez à `https://votre-space.hf.space/`
57
+ - Testez une prédiction unitaire
58
+ - Testez une prédiction batch
59
+
60
+ 2. **Logs** : Consultez les logs sur HF Spaces
61
+ ```
62
+ ✅ Recherchez ces messages :
63
+ - "🚀 Démarrage de l'application complète"
64
+ - "[FastAPI] Application startup complete"
65
+ - "✅ FastAPI démarré et opérationnel"
66
+ - "🌐 Lancement du serveur sur 0.0.0.0:7860"
67
+ ```
68
+
69
+ 3. **API interne** : L'API FastAPI tourne en interne (non accessible publiquement)
70
+
71
+ ## ⚠️ Problèmes courants
72
+
73
+ ### Le Space ne démarre pas
74
+
75
+ **Symptômes** : Le Space affiche "Building" indéfiniment ou erreur au démarrage
76
+
77
+ **Solutions** :
78
+ 1. Vérifiez les logs HF Spaces
79
+ 2. Vérifiez que `pyproject.toml` et `poetry.lock` sont synchronisés
80
+ 3. Vérifiez que toutes les dépendances sont installables
81
+ 4. Essayez de rebuilder manuellement : Settings → Factory reboot
82
+
83
+ ### FastAPI ne démarre pas
84
+
85
+ **Symptômes** : Dans les logs, erreur au démarrage de uvicorn
86
+
87
+ **Solutions** :
88
+ 1. Vérifiez que `uvicorn` est dans `pyproject.toml`
89
+ 2. Vérifiez que `api.py` est bien copié (voir `src/Dockerfile`)
90
+ 3. Vérifiez que le modèle est téléchargeable depuis HF Hub
91
+
92
+ ### Gradio ne répond pas
93
+
94
+ **Symptômes** : "502 Bad Gateway" ou page blanche
95
+
96
+ **Solutions** :
97
+ 1. Vérifiez que `sdk: gradio` est dans le header YAML du README
98
+ 2. Vérifiez que `app_file: app.py` pointe vers le bon fichier
99
+ 3. Attendez 2-3 minutes (le premier démarrage est long)
100
+
101
+ ### "API not found" dans l'interface
102
+
103
+ **Symptômes** : L'interface s'affiche mais les prédictions échouent
104
+
105
+ **Solutions** :
106
+ 1. Vérifiez que FastAPI a bien démarré (logs)
107
+ 2. Vérifiez que le port 8000 n'est pas bloqué
108
+ 3. Augmentez le temps d'attente dans `app.py` (ligne avec `sleep(5)`)
109
+
110
+ ## 🔄 Mise à jour du Space
111
+
112
+ Pour mettre à jour votre Space après modification :
113
+
114
+ ```bash
115
+ # 1. Modifier vos fichiers
116
+ # 2. Commiter
117
+ git add .
118
+ git commit -m "Update: description des changements"
119
+ git push origin main
120
+
121
+ # 3. HF Spaces se met à jour automatiquement (1-2 minutes)
122
+ ```
123
+
124
+ ## 📞 Support
125
+
126
+ - Documentation HF : https://huggingface.co/docs/hub/spaces
127
+ - Documentation Gradio : https://gradio.app/docs/
128
+ - Documentation FastAPI : https://fastapi.tiangolo.com/
129
+
130
+ ## 🎉 Vous êtes prêt !
131
+
132
+ Votre application est maintenant prête à être déployée avec :
133
+ - ✅ API REST complète (FastAPI)
134
+ - ✅ Interface web interactive (Gradio)
135
+ - ✅ Prédictions unitaires et batch
136
+ - ✅ Documentation automatique
137
+ - ✅ Monitoring et logs
138
+
139
+ Bon déploiement ! 🚀
app.py CHANGED
@@ -1,12 +1,16 @@
1
  #!/usr/bin/env python3
2
  """
3
- App Gradio pour Hugging Face Spaces.
4
 
5
- Lance l'interface Gradio pour la prédiction de turnover.
6
  """
7
  import sys
8
  import os
9
  import logging
 
 
 
 
10
 
11
  # Configurer le logging avant toute chose
12
  logging.basicConfig(
@@ -22,20 +26,116 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
22
 
23
  from src.config import get_settings # noqa: E402
24
 
25
- if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
26
  try:
27
- settings = get_settings()
28
- if not settings.GRADIO_ENABLED:
29
- logger.info("Gradio désactivée (GRADIO_ENABLED=False) - arrêt.")
30
- sys.exit(0)
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
- logger.info("🚀 Démarrage de l'application Gradio...")
 
 
 
 
 
 
 
 
 
 
 
 
33
  from src.gradio_ui import launch_standalone
34
 
35
  launch_standalone()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  except KeyboardInterrupt:
37
  logger.info("⏹️ Application arrêtée par l'utilisateur")
38
- sys.exit(0)
39
  except Exception as e:
40
  logger.error(f"❌ Erreur fatale: {e}", exc_info=True)
 
41
  sys.exit(1)
 
1
  #!/usr/bin/env python3
2
  """
3
+ App pour Hugging Face Spaces.
4
 
5
+ Lance FastAPI (port 8000) et Gradio (port 7860) simultanément.
6
  """
7
  import sys
8
  import os
9
  import logging
10
+ import subprocess
11
+ import time
12
+ import signal
13
+ from threading import Thread
14
 
15
  # Configurer le logging avant toute chose
16
  logging.basicConfig(
 
26
 
27
  from src.config import get_settings # noqa: E402
28
 
29
+
30
+ # Variables globales pour les processus
31
+ fastapi_process = None
32
+ gradio_thread = None
33
+
34
+
35
+ def start_fastapi():
36
+ """Lance le serveur FastAPI en subprocess."""
37
+ global fastapi_process
38
+ logger.info("🚀 Démarrage de FastAPI sur port 8000...")
39
+
40
  try:
41
+ fastapi_process = subprocess.Popen(
42
+ [
43
+ sys.executable,
44
+ "-m",
45
+ "uvicorn",
46
+ "api:app",
47
+ "--host",
48
+ "0.0.0.0",
49
+ "--port",
50
+ "8000",
51
+ ],
52
+ stdout=subprocess.PIPE,
53
+ stderr=subprocess.STDOUT,
54
+ text=True,
55
+ bufsize=1,
56
+ )
57
 
58
+ # Logger la sortie de FastAPI
59
+ for line in iter(fastapi_process.stdout.readline, ""):
60
+ if line:
61
+ logger.info(f"[FastAPI] {line.rstrip()}")
62
+
63
+ except Exception as e:
64
+ logger.error(f"❌ Erreur démarrage FastAPI: {e}", exc_info=True)
65
+
66
+
67
+ def start_gradio():
68
+ """Lance l'interface Gradio."""
69
+ logger.info("🎨 Démarrage de Gradio sur port 7860...")
70
+ try:
71
  from src.gradio_ui import launch_standalone
72
 
73
  launch_standalone()
74
+ except Exception as e:
75
+ logger.error(f"❌ Erreur démarrage Gradio: {e}", exc_info=True)
76
+
77
+
78
+ def cleanup(signum=None, frame=None):
79
+ """Nettoie les processus avant de quitter."""
80
+ logger.info("🛑 Arrêt des services...")
81
+
82
+ if fastapi_process:
83
+ logger.info("Arrêt de FastAPI...")
84
+ fastapi_process.terminate()
85
+ try:
86
+ fastapi_process.wait(timeout=5)
87
+ except subprocess.TimeoutExpired:
88
+ logger.warning("FastAPI ne répond pas, forçage de l'arrêt...")
89
+ fastapi_process.kill()
90
+
91
+ logger.info("✅ Arrêt propre effectué")
92
+ sys.exit(0)
93
+
94
+
95
+ if __name__ == "__main__":
96
+ try:
97
+ settings = get_settings()
98
+
99
+ # Installer les handlers de signaux
100
+ signal.signal(signal.SIGINT, cleanup)
101
+ signal.signal(signal.SIGTERM, cleanup)
102
+
103
+ logger.info("=" * 60)
104
+ logger.info("🚀 Démarrage de l'application complète")
105
+ logger.info(" - FastAPI sur http://0.0.0.0:8000")
106
+ logger.info(" - Gradio sur http://0.0.0.0:7860")
107
+ logger.info("=" * 60)
108
+
109
+ # Lancer FastAPI en thread séparé
110
+ fastapi_thread = Thread(target=start_fastapi, daemon=True)
111
+ fastapi_thread.start()
112
+
113
+ # Attendre que FastAPI démarre
114
+ logger.info("⏳ Attente du démarrage de FastAPI...")
115
+ time.sleep(5)
116
+
117
+ # Vérifier que FastAPI est démarré
118
+ import requests
119
+
120
+ for i in range(10):
121
+ try:
122
+ response = requests.get("http://localhost:8000/health", timeout=2)
123
+ if response.status_code == 200:
124
+ logger.info("✅ FastAPI démarré et opérationnel")
125
+ break
126
+ except Exception:
127
+ logger.info(f"⏳ Tentative {i + 1}/10 de connexion à FastAPI...")
128
+ time.sleep(2)
129
+ else:
130
+ logger.warning("⚠️ FastAPI ne répond pas, mais on continue...")
131
+
132
+ # Lancer Gradio (bloquant - dans le thread principal)
133
+ start_gradio()
134
+
135
  except KeyboardInterrupt:
136
  logger.info("⏹️ Application arrêtée par l'utilisateur")
137
+ cleanup()
138
  except Exception as e:
139
  logger.error(f"❌ Erreur fatale: {e}", exc_info=True)
140
+ cleanup()
141
  sys.exit(1)
src/Dockerfile CHANGED
@@ -21,15 +21,15 @@ RUN poetry install --no-dev --no-interaction --no-ansi
21
 
22
  # Copier le code de l'application
23
  COPY app.py .
 
24
  COPY db_models.py .
25
  COPY src/ ./src/
26
- COPY .env.example .env
27
 
28
  # Créer le dossier logs
29
  RUN mkdir -p logs
30
 
31
- # Exposer le port (7860 = Gradio par défaut sur HuggingFace Spaces)
32
- EXPOSE 7860
33
 
34
  # Variables d'environnement par défaut
35
  ENV DEBUG=false
 
21
 
22
  # Copier le code de l'application
23
  COPY app.py .
24
+ COPY api.py .
25
  COPY db_models.py .
26
  COPY src/ ./src/
 
27
 
28
  # Créer le dossier logs
29
  RUN mkdir -p logs
30
 
31
+ # Exposer les ports (7860 = Gradio, 8000 = FastAPI)
32
+ EXPOSE 7860 8000
33
 
34
  # Variables d'environnement par défaut
35
  ENV DEBUG=false
test_deployment.sh ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Script de test avant déploiement sur HuggingFace Spaces
3
+ # Vérifie que FastAPI et Gradio fonctionnent correctement ensemble
4
+
5
+ set -e
6
+
7
+ echo "=========================================="
8
+ echo "🧪 Test de l'application avant déploiement"
9
+ echo "=========================================="
10
+
11
+ # Couleurs
12
+ RED='\033[0;31m'
13
+ GREEN='\033[0;32m'
14
+ YELLOW='\033[1;33m'
15
+ NC='\033[0m' # No Color
16
+
17
+ # Fonction de nettoyage
18
+ cleanup() {
19
+ echo -e "\n${YELLOW}🧹 Nettoyage...${NC}"
20
+ pkill -f "python app.py" 2>/dev/null || true
21
+ pkill -f "uvicorn api:app" 2>/dev/null || true
22
+ sleep 2
23
+ }
24
+
25
+ # Nettoyer avant de commencer
26
+ cleanup
27
+
28
+ # Trap pour nettoyer en cas d'interruption
29
+ trap cleanup EXIT INT TERM
30
+
31
+ echo -e "\n${YELLOW}1️⃣ Démarrage de l'application...${NC}"
32
+
33
+ # Chercher l'environnement virtuel
34
+ if [ -d ".venv" ]; then
35
+ PYTHON=".venv/bin/python"
36
+ elif [ -d "venv" ]; then
37
+ PYTHON="venv/bin/python"
38
+ else
39
+ PYTHON="python3"
40
+ fi
41
+
42
+ echo -e "${YELLOW} Using Python: $PYTHON${NC}"
43
+ $PYTHON app.py > /tmp/app_test.log 2>&1 &
44
+ APP_PID=$!
45
+
46
+ # Attendre le démarrage
47
+ echo -e "${YELLOW}⏳ Attente du démarrage (20s)...${NC}"
48
+ sleep 20
49
+
50
+ # Vérifier que le processus tourne
51
+ if ! ps -p $APP_PID > /dev/null; then
52
+ echo -e "${RED}❌ L'application a crashé au démarrage${NC}"
53
+ echo -e "\n${YELLOW}Logs:${NC}"
54
+ tail -30 /tmp/app_test.log
55
+ exit 1
56
+ fi
57
+
58
+ echo -e "${GREEN}✅ Application démarrée${NC}"
59
+
60
+ # Test 1: Health check FastAPI
61
+ echo -e "\n${YELLOW}2️⃣ Test health check FastAPI (port 8000)...${NC}"
62
+ if curl -s -f http://localhost:8000/health > /dev/null; then
63
+ echo -e "${GREEN}✅ FastAPI répond${NC}"
64
+ curl -s http://localhost:8000/health | python3 -m json.tool 2>/dev/null || echo "{}"
65
+ else
66
+ echo -e "${RED}❌ FastAPI ne répond pas${NC}"
67
+ tail -30 /tmp/app_test.log
68
+ exit 1
69
+ fi
70
+
71
+ # Test 2: Gradio home
72
+ echo -e "\n${YELLOW}3️⃣ Test interface Gradio (port 7860)...${NC}"
73
+ if curl -s -f http://localhost:7860/ > /dev/null; then
74
+ echo -e "${GREEN}✅ Gradio répond${NC}"
75
+ else
76
+ echo -e "${RED}❌ Gradio ne répond pas${NC}"
77
+ tail -30 /tmp/app_test.log
78
+ exit 1
79
+ fi
80
+
81
+ # Test 3: Prédiction API
82
+ echo -e "\n${YELLOW}4️⃣ Test prédiction via API FastAPI...${NC}"
83
+
84
+ # Récupérer la clé API depuis .env ou utiliser la clé par défaut
85
+ if [ -f ".env" ]; then
86
+ API_KEY=$(grep "^API_KEY=" .env | cut -d'=' -f2)
87
+ else
88
+ API_KEY="dev-key-change-me-in-production"
89
+ fi
90
+
91
+ RESPONSE=$(curl -s -X POST http://localhost:8000/predict \
92
+ -H "Content-Type: application/json" \
93
+ -H "X-API-Key: $API_KEY" \
94
+ -d '{
95
+ "nombre_participation_pee": 0,
96
+ "nb_formations_suivies": 2,
97
+ "nombre_employee_sous_responsabilite": 1,
98
+ "distance_domicile_travail": 15,
99
+ "niveau_education": 3,
100
+ "domaine_etude": "Infra & Cloud",
101
+ "ayant_enfants": "Y",
102
+ "frequence_deplacement": "Occasionnel",
103
+ "annees_depuis_la_derniere_promotion": 2,
104
+ "annes_sous_responsable_actuel": 5,
105
+ "satisfaction_employee_environnement": 3,
106
+ "note_evaluation_precedente": 4,
107
+ "niveau_hierarchique_poste": 2,
108
+ "satisfaction_employee_nature_travail": 3,
109
+ "satisfaction_employee_equipe": 3,
110
+ "satisfaction_employee_equilibre_pro_perso": 2,
111
+ "note_evaluation_actuelle": 4,
112
+ "heure_supplementaires": "Non",
113
+ "augementation_salaire_precedente": 5.5,
114
+ "age": 35,
115
+ "genre": "M",
116
+ "revenu_mensuel": 4500.0,
117
+ "statut_marital": "Marié(e)",
118
+ "departement": "Commercial",
119
+ "poste": "Manager",
120
+ "nombre_experiences_precedentes": 3,
121
+ "nombre_heures_travailless": 80,
122
+ "annee_experience_totale": 10,
123
+ "annees_dans_l_entreprise": 5,
124
+ "annees_dans_le_poste_actuel": 2
125
+ }')
126
+
127
+ if echo "$RESPONSE" | grep -q "prediction"; then
128
+ echo -e "${GREEN}✅ Prédiction réussie${NC}"
129
+ echo "$RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$RESPONSE"
130
+ else
131
+ echo -e "${RED}❌ Erreur lors de la prédiction${NC}"
132
+ echo "$RESPONSE"
133
+ exit 1
134
+ fi
135
+
136
+ # Test 4: Documentation Swagger
137
+ echo -e "\n${YELLOW}5️⃣ Test documentation Swagger...${NC}"
138
+ if curl -s -f http://localhost:8000/docs > /dev/null; then
139
+ echo -e "${GREEN}✅ Documentation accessible${NC}"
140
+ else
141
+ echo -e "${RED}❌ Documentation non accessible${NC}"
142
+ exit 1
143
+ fi
144
+
145
+ # Résumé final
146
+ echo -e "\n=========================================="
147
+ echo -e "${GREEN}✅ TOUS LES TESTS SONT PASSÉS !${NC}"
148
+ echo -e "=========================================="
149
+ echo ""
150
+ echo "L'application est prête pour le déploiement sur HuggingFace Spaces."
151
+ echo ""
152
+ echo "Prochaines étapes :"
153
+ echo "1. Committez vos changements : git add . && git commit -m 'Deploy FastAPI + Gradio'"
154
+ echo "2. Poussez sur GitHub : git push origin main"
155
+ echo "3. HF Spaces se synchronisera automatiquement"
156
+ echo "4. Vérifiez les logs sur https://huggingface.co/spaces/votre-username/votre-space/logs"
157
+ echo ""
158
+ echo "URLs attendues sur HF Spaces :"
159
+ echo " - Interface : https://votre-space.hf.space/"
160
+ echo " - API interne : http://localhost:8000 (non publique)"
161
+ echo ""
162
+
163
+ # Nettoyer
164
+ cleanup
165
+
166
+ exit 0