Spaces:
Sleeping
Sleeping
Commit ·
987a859
1
Parent(s): 87b7096
Fix: Update Gradio 6.x API endpoint configuration
Browse files
app.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
| 1 |
"""
|
| 2 |
Labasni Recommender Service - Hugging Face Space
|
| 3 |
Interface Gradio pour les recommandations d'outfits
|
| 4 |
-
Version corrigée avec api_name="predict"
|
| 5 |
"""
|
| 6 |
|
| 7 |
import gradio as gr
|
|
@@ -21,114 +20,47 @@ def recommend_outfit_api(clothes_json: str, preference: str, city: str = "Tunis"
|
|
| 21 |
JSON avec l'outfit recommandé
|
| 22 |
"""
|
| 23 |
try:
|
| 24 |
-
#
|
| 25 |
-
print(f"📥 Received request: preference={preference}, city={city}")
|
| 26 |
-
print(f"📦 Clothes data length: {len(clothes_json)}")
|
| 27 |
-
|
| 28 |
-
# Parser le JSON des vêtements
|
| 29 |
clothes_data = json.loads(clothes_json)
|
| 30 |
-
print(f"✅ Parsed {len(clothes_data)} clothes items")
|
| 31 |
|
| 32 |
# Appeler le modèle ML
|
| 33 |
result = recommend_outfit_ml(clothes_data, preference, city)
|
| 34 |
-
print(f"✅ Model returned: success={result.get('success')}")
|
| 35 |
|
| 36 |
-
# Retourner le résultat en JSON
|
| 37 |
return json.dumps(result, indent=2)
|
| 38 |
-
|
| 39 |
-
except json.JSONDecodeError as e:
|
| 40 |
-
error_msg = f"Invalid JSON format: {str(e)}"
|
| 41 |
-
print(f"❌ {error_msg}")
|
| 42 |
-
return json.dumps({"success": False, "error": error_msg})
|
| 43 |
-
|
| 44 |
except Exception as e:
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
return json.dumps({"success": False, "error": error_msg})
|
| 48 |
|
| 49 |
-
#
|
| 50 |
-
#
|
| 51 |
demo = gr.Interface(
|
| 52 |
fn=recommend_outfit_api,
|
| 53 |
inputs=[
|
| 54 |
gr.Textbox(
|
| 55 |
label="Clothes Data (JSON)",
|
| 56 |
-
placeholder='[{"id":"top1","category":"top","style":"casual",
|
| 57 |
-
lines=10
|
| 58 |
-
info="Liste des vêtements au format JSON"
|
| 59 |
),
|
| 60 |
gr.Dropdown(
|
| 61 |
choices=["casual", "formal", "sport", "chic"],
|
| 62 |
label="Preference",
|
| 63 |
-
value="casual"
|
| 64 |
-
info="Style d'outfit souhaité"
|
| 65 |
),
|
| 66 |
-
gr.Textbox(
|
| 67 |
-
label="City",
|
| 68 |
-
value="Tunis",
|
| 69 |
-
info="Ville pour la météo"
|
| 70 |
-
)
|
| 71 |
],
|
| 72 |
-
outputs=gr.Textbox(
|
| 73 |
-
label="Recommended Outfit (JSON)",
|
| 74 |
-
lines=15,
|
| 75 |
-
show_copy_button=True
|
| 76 |
-
),
|
| 77 |
title="🎽 Labasni Outfit Recommender",
|
| 78 |
-
description=""
|
| 79 |
-
Recommandations d'outfits basées sur Machine Learning.
|
| 80 |
-
|
| 81 |
-
**Fonctionnalités:**
|
| 82 |
-
- 🤖 Algorithme ML intelligent (ResNet50 + Scikit-learn)
|
| 83 |
-
- 🌤️ Prise en compte de la météo réelle
|
| 84 |
-
- 🎨 Compatibilité des couleurs et styles
|
| 85 |
-
- 📊 Scoring basé sur l'historique
|
| 86 |
-
|
| 87 |
-
**Usage API:**
|
| 88 |
-
```bash
|
| 89 |
-
curl -X POST https://salma-mahjoub-styleto-recommender.hf.space/api/predict \\
|
| 90 |
-
-H "Content-Type: application/json" \\
|
| 91 |
-
-d '{"data": [CLOTHES_JSON, "casual", "Tunis"]}'
|
| 92 |
-
```
|
| 93 |
-
""",
|
| 94 |
examples=[
|
| 95 |
[
|
| 96 |
-
|
| 97 |
-
'[{"id":"top1","category":"top","style":"casual","color":"white","season":"summer","score":0.8,"imageURL":"https://example.com/top.jpg"},{"id":"bottom1","category":"bottom","style":"casual","color":"blue","season":"summer","score":0.7,"imageURL":"https://example.com/bottom.jpg"},{"id":"shoe1","category":"footwear","style":"casual","color":"black","season":"summer","score":0.9,"imageURL":"https://example.com/shoes.jpg"}]',
|
| 98 |
"casual",
|
| 99 |
"Tunis"
|
| 100 |
-
],
|
| 101 |
-
[
|
| 102 |
-
# Exemple 2: Outfit formel d'hiver
|
| 103 |
-
'[{"id":"shirt1","category":"top","style":"formal","color":"white","season":"winter","score":0.9,"imageURL":"https://example.com/shirt.jpg"},{"id":"pants1","category":"bottom","style":"formal","color":"black","season":"winter","score":0.8,"imageURL":"https://example.com/pants.jpg"},{"id":"dress_shoes","category":"footwear","style":"formal","color":"black","season":"winter","score":0.95,"imageURL":"https://example.com/dress_shoes.jpg"}]',
|
| 104 |
-
"formal",
|
| 105 |
-
"Paris"
|
| 106 |
-
],
|
| 107 |
-
[
|
| 108 |
-
# Exemple 3: Outfit sport
|
| 109 |
-
'[{"id":"tshirt1","category":"top","style":"sport","color":"red","season":"all","score":0.75,"imageURL":"https://example.com/tshirt.jpg"},{"id":"shorts1","category":"bottom","style":"sport","color":"black","season":"summer","score":0.8,"imageURL":"https://example.com/shorts.jpg"},{"id":"sneakers1","category":"footwear","style":"sport","color":"white","season":"all","score":0.9,"imageURL":"https://example.com/sneakers.jpg"}]',
|
| 110 |
-
"sport",
|
| 111 |
-
"New York"
|
| 112 |
]
|
| 113 |
],
|
| 114 |
-
|
| 115 |
-
api_name="predict",
|
| 116 |
-
|
| 117 |
-
# Options supplémentaires
|
| 118 |
-
allow_flagging="never", # Désactiver le flagging
|
| 119 |
-
theme=gr.themes.Soft(), # Theme moderne
|
| 120 |
)
|
| 121 |
|
| 122 |
-
#
|
| 123 |
-
#
|
| 124 |
-
# - Pas besoin d'appeler demo.launch()
|
| 125 |
-
# - Le Space démarre automatiquement
|
| 126 |
-
|
| 127 |
-
# Pour le développement local (optionnel):
|
| 128 |
-
if __name__ == "__main__":
|
| 129 |
-
# Lancement local pour tester
|
| 130 |
-
demo.launch(
|
| 131 |
-
server_name="0.0.0.0",
|
| 132 |
-
server_port=7860,
|
| 133 |
-
share=False
|
| 134 |
-
)
|
|
|
|
| 1 |
"""
|
| 2 |
Labasni Recommender Service - Hugging Face Space
|
| 3 |
Interface Gradio pour les recommandations d'outfits
|
|
|
|
| 4 |
"""
|
| 5 |
|
| 6 |
import gradio as gr
|
|
|
|
| 20 |
JSON avec l'outfit recommandé
|
| 21 |
"""
|
| 22 |
try:
|
| 23 |
+
# Parser le JSON
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
clothes_data = json.loads(clothes_json)
|
|
|
|
| 25 |
|
| 26 |
# Appeler le modèle ML
|
| 27 |
result = recommend_outfit_ml(clothes_data, preference, city)
|
|
|
|
| 28 |
|
| 29 |
+
# Retourner le résultat en JSON
|
| 30 |
return json.dumps(result, indent=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
except Exception as e:
|
| 32 |
+
# Retourner l'erreur en JSON
|
| 33 |
+
return json.dumps({"success": False, "error": str(e)})
|
|
|
|
| 34 |
|
| 35 |
+
# Interface Gradio avec api_name explicite
|
| 36 |
+
# La variable DOIT s'appeler 'demo' pour Hugging Face Spaces
|
| 37 |
demo = gr.Interface(
|
| 38 |
fn=recommend_outfit_api,
|
| 39 |
inputs=[
|
| 40 |
gr.Textbox(
|
| 41 |
label="Clothes Data (JSON)",
|
| 42 |
+
placeholder='[{"id":"top1","category":"top","style":"casual",...}]',
|
| 43 |
+
lines=10
|
|
|
|
| 44 |
),
|
| 45 |
gr.Dropdown(
|
| 46 |
choices=["casual", "formal", "sport", "chic"],
|
| 47 |
label="Preference",
|
| 48 |
+
value="casual"
|
|
|
|
| 49 |
),
|
| 50 |
+
gr.Textbox(label="City", value="Tunis")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
],
|
| 52 |
+
outputs=gr.Textbox(label="Recommended Outfit (JSON)", lines=15), # Removed show_copy_button
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
title="🎽 Labasni Outfit Recommender",
|
| 54 |
+
description="Recommandations d'outfits basées sur ML (TensorFlow + PyTorch)",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
examples=[
|
| 56 |
[
|
| 57 |
+
'[{"id":"top1","category":"top","style":"casual","color":"white","season":"summer","score":0.8,"imageURL":"https://example.com/top.jpg"},{"id":"bot1","category":"bottom","style":"casual","color":"blue","season":"summer","score":0.7,"imageURL":"https://example.com/bottom.jpg"},{"id":"shoe1","category":"footwear","style":"casual","color":"black","season":"summer","score":0.9,"imageURL":"https://example.com/shoes.jpg"}]',
|
|
|
|
| 58 |
"casual",
|
| 59 |
"Tunis"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
]
|
| 61 |
],
|
| 62 |
+
api_name="predict" # CRUCIAL pour exposer l'endpoint /api/predict
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
)
|
| 64 |
|
| 65 |
+
# Pour Hugging Face Spaces, l'interface est automatiquement détectée et lancée
|
| 66 |
+
# Pas besoin d'appeler demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|