Spaces:
Sleeping
Sleeping
| """ | |
| CalorieCLIP API for FitGenie backend. | |
| POST /predict { "image": "<base64>" } -> { "calories": 342 } | |
| GET /health -> { "status": "ok" } | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, Header, HTTPException | |
| from pydantic import BaseModel, Field | |
| from model_core import decode_base64_image, load_models, predict_calories | |
| API_KEY = os.getenv("CALORIE_CLIP_API_KEY", "").strip() | |
| def _require_api_key(x_api_key: str | None) -> None: | |
| if not API_KEY: | |
| return | |
| if x_api_key != API_KEY: | |
| raise HTTPException(status_code=401, detail="Invalid API key") | |
| async def lifespan(_: FastAPI): | |
| load_models() | |
| yield | |
| app = FastAPI(title="FitGenie CalorieCLIP", version="1.1.0", lifespan=lifespan) | |
| class PredictRequest(BaseModel): | |
| image: str = Field(..., description="Base64-encoded food photo") | |
| def root() -> dict[str, str]: | |
| return {"service": "FitGenie CalorieCLIP", "endpoints": "/health, /predict"} | |
| def health() -> dict[str, str]: | |
| return {"status": "ok", "model": "CalorieCLIP"} | |
| def predict( | |
| req: PredictRequest, | |
| x_api_key: str | None = Header(default=None, alias="X-API-Key"), | |
| ) -> dict[str, int]: | |
| _require_api_key(x_api_key) | |
| try: | |
| image = decode_base64_image(req.image) | |
| except ValueError as exc: | |
| raise HTTPException(status_code=400, detail=str(exc)) from exc | |
| return {"calories": predict_calories(image)} | |