| | """API controllers for request handling and validation.""" |
| |
|
| | import asyncio |
| | from fastapi import HTTPException |
| |
|
| | from app.core.logging import logger |
| | from app.services.base import InferenceService |
| | from app.api.models import ImageRequest, PredictionResponse |
| |
|
| |
|
| | class PredictionController: |
| | """Controller for prediction endpoints.""" |
| |
|
| | @staticmethod |
| | async def predict( |
| | request: ImageRequest, |
| | service: InferenceService |
| | ) -> PredictionResponse: |
| | """Run inference using the configured service.""" |
| | try: |
| | if not service or not service.is_loaded: |
| | raise HTTPException(503, "Service not available") |
| |
|
| | if not request.image.mediaType.startswith('image/'): |
| | raise HTTPException(400, f"Invalid media type: {request.image.mediaType}") |
| |
|
| | return await asyncio.to_thread(service.predict, request) |
| |
|
| | except HTTPException: |
| | raise |
| | except ValueError as e: |
| | logger.error(f"Invalid input: {e}") |
| | raise HTTPException(400, str(e)) |
| | except Exception as e: |
| | logger.error(f"Prediction failed: {e}") |
| | raise HTTPException(500, "Internal server error") |
| |
|