API_RAG / app.py
Aghode91's picture
rag
f3350ab
Raw
History Blame Contribute Delete
1.91 kB
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)