Liyew commited on
Commit
de46f3a
·
verified ·
1 Parent(s): 4535f71

Create app/outfit.py

Browse files
Files changed (1) hide show
  1. app/outfit.py +86 -0
app/outfit.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter
2
+ from pydantic import BaseModel
3
+ from typing import List
4
+ import requests
5
+ import json
6
+ import os
7
+
8
+ router = APIRouter(prefix="/outfit", tags=["Outfit"])
9
+
10
+ WARDROBE_API_URL = "https://wardrobestudio.net/wardrobe/items"
11
+ HF_API_URL = "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.1"
12
+ HF_TOKEN = os.getenv("HF_TOKEN") # Set in Hugging Face Secrets
13
+ HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"}
14
+
15
+ class Item(BaseModel):
16
+ id: str
17
+ label: str
18
+ image_url: str
19
+
20
+ class OutfitSuggestion(BaseModel):
21
+ day: str
22
+ items: List[Item]
23
+
24
+ def classify_with_clip(image_url: str) -> str:
25
+ return "jacket" if "jacket" in image_url.lower() else "clothing"
26
+
27
+ def get_llm_recommendation(items: List[dict], weather_forecast: List[str]) -> List[dict]:
28
+ prompt = f"""
29
+ You are a fashion stylist. Here is a user's wardrobe. Each item has a unique ID, label, and image:
30
+
31
+ {json.dumps(items, indent=2)}
32
+
33
+ 7-day forecast: {', '.join(weather_forecast)}.
34
+
35
+ Suggest 7 outfits (2–3 item ids per day) for the week. Respond as JSON:
36
+
37
+ [
38
+ {{"day": "Monday", "items": ["item1", "item3"]}},
39
+ ...
40
+ ]
41
+ """.strip()
42
+
43
+ response = requests.post(HF_API_URL, headers=HEADERS, json={"inputs": prompt})
44
+ response.raise_for_status()
45
+ result = response.json()
46
+
47
+ if isinstance(result, dict) and "error" in result:
48
+ raise RuntimeError(f"Hugging Face API error: {result['error']}")
49
+
50
+ generated_text = result[0].get("generated_text", "")
51
+ return json.loads(generated_text.split("```")[0].strip())
52
+
53
+ @router.get("/weekly", response_model=List[OutfitSuggestion])
54
+ async def generate_outfits():
55
+ try:
56
+ res = requests.get(WARDROBE_API_URL)
57
+ res.raise_for_status()
58
+ wardrobe = res.json()
59
+ except Exception as e:
60
+ return [{"day": "Error", "items": [{"id": "error", "label": "Wardrobe fetch failed", "image_url": ""}]}]
61
+
62
+ labeled_items = []
63
+ for idx, item in enumerate(wardrobe):
64
+ image_path = item.get("image_url")
65
+ image_url = f"https://wardrobestudio.net{image_path}"
66
+ label = classify_with_clip(image_url)
67
+ labeled_items.append({
68
+ "id": f"item{idx+1}",
69
+ "label": label,
70
+ "image_url": image_path
71
+ })
72
+
73
+ weather = ["sunny", "rainy", "cloudy", "cold", "warm", "hot", "windy"]
74
+
75
+ try:
76
+ outfits_raw = get_llm_recommendation(labeled_items, weather)
77
+ result = []
78
+ for entry in outfits_raw:
79
+ matched_items = [item for item in labeled_items if item["id"] in entry.get("items", [])]
80
+ result.append({
81
+ "day": entry.get("day", "Unknown"),
82
+ "items": matched_items
83
+ })
84
+ return result
85
+ except Exception as e:
86
+ return [{"day": "Error", "items": [{"id": "error", "label": f"LLM failed: {e}", "image_url": ""}]}]