Spaces:
Paused
Paused
File size: 1,906 Bytes
f3350ab | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | from contextlib import asynccontextmanager
from pathlib import Path
from typing import List, Optional
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
from ingest import CHROMA_DIR, build_index
from retriever import recommend
VALID_FORMULATIONS = {"vegan", "clean", "bio"}
VALID_ORIGINS = {"french"}
VALID_PRODUCT_TYPES = {
"moisturizer", "serum", "cleanser", "toner",
"mask", "oil", "sunscreen", "exfoliant", "eye_care",
}
VALID_PRICE_BANDS = {"budget", "mid", "premium", "any"}
@asynccontextmanager
async def lifespan(app: FastAPI):
if not CHROMA_DIR.exists() or not any(CHROMA_DIR.iterdir()):
build_index()
yield
app = FastAPI(title="Product Recommendation API", lifespan=lifespan)
class Preferences(BaseModel):
formulation: List[str] = [] # ex: ["vegan", "clean"]
origin: List[str] = [] # ex: ["french"]
product_type: Optional[str] = None # ex: "serum"
price_band: Optional[str] = None # "budget" | "mid" | "premium" | "any"
class RecommendationInput(BaseModel):
skin_type: str # "oily" | "dry" | "normal"
acne: bool
preferences: Preferences
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/recommend")
def recommend_endpoint(payload: RecommendationInput):
prefs = payload.preferences.model_dump()
prefs["formulation"] = [f for f in prefs["formulation"] if f in VALID_FORMULATIONS]
prefs["origin"] = [o for o in prefs["origin"] if o in VALID_ORIGINS]
if prefs.get("product_type") not in VALID_PRODUCT_TYPES:
prefs["product_type"] = None
if prefs.get("price_band") not in VALID_PRICE_BANDS:
prefs["price_band"] = None
return recommend(
skin_type=payload.skin_type,
acne=payload.acne,
preferences=prefs,
)
if __name__ == "__main__":
uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=False)
|