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()) @router.get("/weekly", response_model=List[OutfitSuggestion]) 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": ""}]}]