Spaces:
Sleeping
Sleeping
| """ | |
| Prediction endpoints. | |
| POST /predict/file - Upload image file | |
| POST /predict/url - Predict from image URL | |
| POST /predict/base64 - Predict from base64 image | |
| """ | |
| from fastapi import APIRouter, UploadFile, File, HTTPException, Query | |
| from backend.app.schemas.predict import ( | |
| PredictResponse, | |
| PredictURLRequest, | |
| PredictBase64Request, | |
| PredictionItem, | |
| BreedInfo, | |
| ) | |
| from backend.app.services.inference import inference_service | |
| from backend.app.services.image_loader import ( | |
| load_image_from_upload, | |
| load_image_from_url, | |
| load_image_from_base64, | |
| ) | |
| from backend.app.services.breed_info import breed_info_service | |
| from backend.app.core.logging import logger | |
| router = APIRouter(prefix="/predict", tags=["Prediction"]) | |
| def _build_response(result: dict) -> PredictResponse: | |
| """Build a PredictResponse from inference result dict.""" | |
| # Get breed info | |
| breed_info = None | |
| breed_summary = breed_info_service.get_breed_summary(result['predicted_breed']) | |
| if breed_summary: | |
| breed_info = BreedInfo(**breed_summary) | |
| return PredictResponse( | |
| predicted_breed=result['predicted_breed'], | |
| confidence=result['confidence'], | |
| top_k=[PredictionItem(**item) for item in result['top_k']], | |
| breed_info=breed_info, | |
| model_version=result.get('model_version', 'v1.0'), | |
| inference_time_ms=result['inference_time_ms'], | |
| warning=result.get('warning'), | |
| ) | |
| async def predict_file( | |
| file: UploadFile = File(...), | |
| top_k: int = Query(default=3, ge=1, le=10), | |
| ): | |
| """Predict breed from uploaded image file.""" | |
| try: | |
| contents = await file.read() | |
| image = load_image_from_upload(contents) | |
| result = inference_service.predict(image, top_k=top_k) | |
| return _build_response(result) | |
| except ValueError as e: | |
| raise HTTPException(status_code=400, detail=str(e)) | |
| except Exception as e: | |
| logger.error(f"Prediction error: {e}") | |
| raise HTTPException(status_code=500, detail="Prediction failed") | |
| async def predict_url(request: PredictURLRequest): | |
| """Predict breed from image URL.""" | |
| try: | |
| image = load_image_from_url(request.url) | |
| result = inference_service.predict(image, top_k=request.top_k) | |
| return _build_response(result) | |
| except ValueError as e: | |
| raise HTTPException(status_code=400, detail=str(e)) | |
| except Exception as e: | |
| logger.error(f"Prediction error: {e}") | |
| raise HTTPException(status_code=500, detail="Prediction failed") | |
| async def predict_base64(request: PredictBase64Request): | |
| """Predict breed from base64-encoded image.""" | |
| try: | |
| image = load_image_from_base64(request.image) | |
| result = inference_service.predict(image, top_k=request.top_k) | |
| return _build_response(result) | |
| except ValueError as e: | |
| raise HTTPException(status_code=400, detail=str(e)) | |
| except Exception as e: | |
| logger.error(f"Prediction error: {e}") | |
| raise HTTPException(status_code=500, detail="Prediction failed") | |