Spaces:
Sleeping
Sleeping
from fastapi import APIRouter | |
from pydantic import BaseModel | |
from typing import List | |
import requests | |
import json | |
import os | |
router = APIRouter(prefix="/outfit", tags=["Outfit"]) | |
WARDROBE_API_URL = "https://wardrobestudio.net/wardrobe/items" | |
HF_API_URL = "https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.1" | |
HF_TOKEN = os.getenv("HF_TOKEN") # Set in Hugging Face Secrets | |
HEADERS = {"Authorization": f"Bearer {HF_TOKEN}"} | |
class Item(BaseModel): | |
id: str | |
label: str | |
image_url: str | |
class OutfitSuggestion(BaseModel): | |
day: str | |
items: List[Item] | |
def classify_with_clip(image_url: str) -> str: | |
return "jacket" if "jacket" in image_url.lower() else "clothing" | |
def get_llm_recommendation(items: List[dict], weather_forecast: List[str]) -> List[dict]: | |
prompt = f""" | |
You are a fashion stylist. Here is a user's wardrobe. Each item has a unique ID, label, and image: | |
{json.dumps(items, indent=2)} | |
7-day forecast: {', '.join(weather_forecast)}. | |
Suggest 7 outfits (2–3 item ids per day) for the week. Respond as JSON: | |
[ | |
{{"day": "Monday", "items": ["item1", "item3"]}}, | |
... | |
] | |
""".strip() | |
response = requests.post(HF_API_URL, headers=HEADERS, json={"inputs": prompt}) | |
response.raise_for_status() | |
result = response.json() | |
if isinstance(result, dict) and "error" in result: | |
raise RuntimeError(f"Hugging Face API error: {result['error']}") | |
generated_text = result[0].get("generated_text", "") | |
return json.loads(generated_text.split("```")[0].strip()) | |
async def generate_outfits(): | |
try: | |
res = requests.get(WARDROBE_API_URL) | |
res.raise_for_status() | |
wardrobe = res.json() | |
except Exception as e: | |
return [{"day": "Error", "items": [{"id": "error", "label": "Wardrobe fetch failed", "image_url": ""}]}] | |
labeled_items = [] | |
for idx, item in enumerate(wardrobe): | |
image_path = item.get("image_url") | |
image_url = f"https://wardrobestudio.net{image_path}" | |
label = classify_with_clip(image_url) | |
labeled_items.append({ | |
"id": f"item{idx+1}", | |
"label": label, | |
"image_url": image_path | |
}) | |
weather = ["sunny", "rainy", "cloudy", "cold", "warm", "hot", "windy"] | |
try: | |
outfits_raw = get_llm_recommendation(labeled_items, weather) | |
result = [] | |
for entry in outfits_raw: | |
matched_items = [item for item in labeled_items if item["id"] in entry.get("items", [])] | |
result.append({ | |
"day": entry.get("day", "Unknown"), | |
"items": matched_items | |
}) | |
return result | |
except Exception as e: | |
return [{"day": "Error", "items": [{"id": "error", "label": f"LLM failed: {e}", "image_url": ""}]}] | |