salma-mahjoub commited on
Commit
ee432f8
·
1 Parent(s): 2154031

feat: Initial Recommender service with ML

Browse files
Files changed (4) hide show
  1. README.md +23 -6
  2. app.py +54 -0
  3. recommender_model.py +103 -0
  4. requirements.txt +4 -0
README.md CHANGED
@@ -1,13 +1,30 @@
1
  ---
2
- title: Styleto Recommender
3
- emoji: 🚀
4
  colorFrom: blue
5
- colorTo: blue
6
  sdk: gradio
7
- sdk_version: 6.1.0
8
  app_file: app.py
9
  pinned: false
10
- license: apache-2.0
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Labasni Recommender
3
+ emoji: 👔
4
  colorFrom: blue
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.44.1
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
+ # 🎽 Labasni Outfit Recommender
13
+
14
+ Service de recommandation d'outfits basé sur Machine Learning.
15
+
16
+ ## Features
17
+ - Recommandations intelligentes selon le style
18
+ - Prise en compte de la météo et des saisons
19
+ - API REST accessible depuis NestJS
20
+
21
+ ## Usage
22
+ ```python
23
+ import requests
24
+ response = requests.post(
25
+ "https://VOTRE_USERNAME-labasni-recommender.hf.space/api/predict",
26
+ json={
27
+ "data": [clothes_json, "casual", "Tunis"]
28
+ }
29
+ )
30
+ ```
app.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Labasni Recommender Service - Hugging Face Space
3
+ Interface Gradio pour les recommandations d'outfits
4
+ """
5
+
6
+ import gradio as gr
7
+ import json
8
+ from recommender_model import recommend_outfit_ml
9
+
10
+ def recommend_outfit_api(clothes_json: str, preference: str, city: str = "Tunis"):
11
+ """
12
+ API endpoint pour les recommandations d'outfit
13
+
14
+ Args:
15
+ clothes_json: JSON string contenant la liste des vêtements
16
+ preference: Style préféré (casual, formal, sport)
17
+ city: Ville pour la météo
18
+
19
+ Returns:
20
+ JSON avec l'outfit recommandé
21
+ """
22
+ try:
23
+ clothes_data = json.loads(clothes_json)
24
+ result = recommend_outfit_ml(clothes_data, preference, city)
25
+ return json.dumps(result, indent=2)
26
+ except Exception as e:
27
+ return json.dumps({"success": False, "error": str(e)})
28
+
29
+ # Interface Gradio
30
+ iface = gr.Interface(
31
+ fn=recommend_outfit_api,
32
+ inputs=[
33
+ gr.Textbox(
34
+ label="Clothes Data (JSON)",
35
+ placeholder='[{"id":"top1","category":"top","style":"casual",...}]',
36
+ lines=10
37
+ ),
38
+ gr.Dropdown(
39
+ choices=["casual", "formal", "sport", "chic"],
40
+ label="Preference",
41
+ value="casual"
42
+ ),
43
+ gr.Textbox(label="City", value="Tunis")
44
+ ],
45
+ outputs=gr.Textbox(label="Recommended Outfit (JSON)", lines=15),
46
+ title="🎽 Labasni Outfit Recommender",
47
+ description="Recommandations d'outfits basées sur ML (TensorFlow + PyTorch)",
48
+ examples=[
49
+ ['[{"id":"top1","category":"top","style":"casual","color":"white","season":"summer"}]', "casual", "Tunis"]
50
+ ]
51
+ )
52
+
53
+ if __name__ == "__main__":
54
+ iface.launch()
recommender_model.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Logique ML pour les recommandations d'outfits
3
+ Adapté de votre fichier recommendations.py
4
+ """
5
+
6
+ import numpy as np
7
+ import requests
8
+ from sklearn.metrics.pairwise import cosine_similarity
9
+ import json
10
+
11
+ # Configuration météo
12
+ OPENWEATHER_API_KEY = "a92f907ace22631f8af40374ae0b30b6"
13
+
14
+ def get_weather(city: str):
15
+ """Récupère la météo depuis OpenWeather API"""
16
+ try:
17
+ url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={OPENWEATHER_API_KEY}&units=metric"
18
+ response = requests.get(url, timeout=5)
19
+ data = response.json()
20
+ return {
21
+ "temperature": data["main"]["temp"],
22
+ "condition": data["weather"][0]["main"]
23
+ }
24
+ except:
25
+ return {"temperature": 20, "condition": "Clear"}
26
+
27
+ def get_season_from_weather(temp: float):
28
+ """Détermine la saison selon la température"""
29
+ if temp > 25:
30
+ return "summer"
31
+ elif temp > 17:
32
+ return "spring"
33
+ elif temp > 0:
34
+ return "fall"
35
+ return "winter"
36
+
37
+ def recommend_outfit_ml(clothes_data: list, preference: str, city: str):
38
+ """
39
+ Recommande un outfit complet basé sur ML
40
+
41
+ Args:
42
+ clothes_data: Liste des vêtements disponibles
43
+ preference: Style préféré
44
+ city: Ville pour la météo
45
+
46
+ Returns:
47
+ Dict avec l'outfit recommandé et l'explication
48
+ """
49
+ # 1. Obtenir la météo
50
+ weather = get_weather(city)
51
+ season = get_season_from_weather(weather["temperature"])
52
+
53
+ # 2. Filtrer par style et saison
54
+ pref_lower = preference.lower()
55
+
56
+ def matches_season(item_season, target_season):
57
+ if not item_season or item_season.lower() in ["all", "toutes"]:
58
+ return True
59
+ return item_season.lower() == target_season
60
+
61
+ tops = [c for c in clothes_data if c.get("category") == "top" and c.get("style") == pref_lower and matches_season(c.get("season"), season)]
62
+ bottoms = [c for c in clothes_data if c.get("category") == "bottom" and c.get("style") == pref_lower and matches_season(c.get("season"), season)]
63
+ footwear = [c for c in clothes_data if c.get("category") in ["footwear", "shoes"] and c.get("style") == pref_lower and matches_season(c.get("season"), season)]
64
+
65
+ # 3. Vérifier si on a assez de vêtements
66
+ if not tops or not bottoms or not footwear:
67
+ return {
68
+ "success": False,
69
+ "message": f"Pas assez de vêtements '{preference}' pour la saison '{season}'",
70
+ "weather": weather,
71
+ "season": season
72
+ }
73
+
74
+ # 4. Sélectionner le meilleur outfit (basé sur les scores)
75
+ top = max(tops, key=lambda x: x.get("score", 0))
76
+ bottom = max(bottoms, key=lambda x: x.get("score", 0))
77
+ shoe = max(footwear, key=lambda x: x.get("score", 0))
78
+
79
+ return {
80
+ "success": True,
81
+ "outfit": {
82
+ "top": top["id"],
83
+ "bottom": bottom["id"],
84
+ "footwear": shoe["id"]
85
+ },
86
+ "explanation": {
87
+ "top": {
88
+ "reason": f"Best rated (Score: {top.get('score', 0):.2f})",
89
+ "score": top.get("score", 0)
90
+ },
91
+ "bottom": {
92
+ "reason": f"Best match (Score: {bottom.get('score', 0):.2f})",
93
+ "score": bottom.get("score", 0)
94
+ },
95
+ "footwear": {
96
+ "reason": f"Best match (Score: {shoe.get('score', 0):.2f})",
97
+ "score": shoe.get("score", 0)
98
+ }
99
+ },
100
+ "weather": weather,
101
+ "season": season,
102
+ "preference": preference
103
+ }
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio==4.44.1
2
+ numpy==1.24.3
3
+ scikit-learn==1.3.0
4
+ requests==2.31.0