Download main.py from dpratapx/restaurant-inspector-api-dev: direct link, hf CLI and curl.
- Browser
- Download file 4.74 kB
-
https://huggingface.co/spaces/dpratapx/restaurant-inspector-api-dev/resolve/main/main.py
- Command line
-
hf download hf://spaces/dpratapx/restaurant-inspector-api-dev/main.py
-
curl -L -o main.py https://huggingface.co/spaces/dpratapx/restaurant-inspector-api-dev/resolve/main/main.py
4.74 kB
| """ | |
| Restaurant Inspector API. | |
| Analyzes restaurant reviews and provides scores for various aspects. | |
| """ | |
| from datetime import datetime | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel, Field | |
| from transformers import pipeline | |
| # Initialize FastAPI app | |
| app = FastAPI( | |
| title="Restaurant Inspector", | |
| description="AI-powered restaurant review aspect analyzer", | |
| version="1.0.0", | |
| ) | |
| # Aspect names mapping | |
| ASPECT_NAMES = ["FOOD", "SERVICE", "HYGIENE", "PARKING", "CLEANLINESS"] | |
| # Load model at startup (once!) | |
| print("🚀 Loading model...") | |
| try: | |
| classifier = pipeline( | |
| "text-classification", | |
| model="dpratapx/restaurant-inspector", | |
| device=-1, # CPU mode | |
| top_k=None, # Return all scores | |
| ) | |
| print("✅ Model loaded successfully!") | |
| except Exception as e: | |
| print(f"❌ Error loading model: {e}") | |
| print("⚠️ Make sure you've run 'python train.py' first!") | |
| classifier = None | |
| # Request/Response models | |
| class ReviewRequest(BaseModel): | |
| """Request model for review analysis.""" | |
| text: str = Field( | |
| ..., | |
| min_length=10, | |
| max_length=1000, | |
| description="Restaurant review text to analyze", | |
| examples=["Great food but terrible parking and dirty bathrooms"], | |
| ) | |
| class AspectScores(BaseModel): | |
| """Aspect scores model.""" | |
| FOOD: float = Field(..., ge=0.0, le=1.0, description="Food quality score (0-1)") | |
| SERVICE: float = Field(..., ge=0.0, le=1.0, description="Service quality score (0-1)") | |
| HYGIENE: float = Field(..., ge=0.0, le=1.0, description="Hygiene score (0-1)") | |
| PARKING: float = Field(..., ge=0.0, le=1.0, description="Parking availability score (0-1)") | |
| CLEANLINESS: float = Field(..., ge=0.0, le=1.0, description="Cleanliness score (0-1)") | |
| class AnalysisResponse(BaseModel): | |
| """Response model for review analysis.""" | |
| review: str = Field(..., description="Original review text") | |
| scores: AspectScores = Field(..., description="Aspect scores") | |
| timestamp: str = Field(..., description="Analysis timestamp (ISO 8601)") | |
| # API Endpoints | |
| async def root(): | |
| """Root endpoint with API information.""" | |
| return { | |
| "message": "Restaurant Inspector API", | |
| "version": "1.0.0", | |
| "endpoints": { | |
| "POST /analyze": "Analyze a restaurant review", | |
| "GET /health": "Health check", | |
| "GET /docs": "API documentation", | |
| }, | |
| } | |
| async def health_check(): | |
| """Health check endpoint.""" | |
| model_status = "ready" if classifier is not None else "not_loaded" | |
| return { | |
| "status": "healthy" if model_status == "ready" else "degraded", | |
| "model": model_status, | |
| "timestamp": datetime.utcnow().isoformat(), | |
| } | |
| async def analyze_review(request: ReviewRequest): | |
| """ | |
| Analyze a restaurant review and return aspect scores. | |
| Args: | |
| request: ReviewRequest with review text | |
| Returns: | |
| AnalysisResponse with scores for each aspect | |
| Raises: | |
| HTTPException: If model not loaded or analysis fails | |
| """ | |
| if classifier is None: | |
| raise HTTPException( | |
| status_code=503, | |
| detail="Model not loaded. Please run 'python train.py' first.", | |
| ) | |
| try: | |
| # Get predictions | |
| results = classifier(request.text) | |
| # Parse scores - results is a list of lists of dicts | |
| # Format: [[{'label': 'LABEL_0', 'score': 0.9}, ...]] | |
| scores_dict = {} | |
| if isinstance(results[0], list): | |
| # top_k=None returns list of all labels with scores | |
| for item in results[0]: | |
| label_idx = int(item["label"].split("_")[1]) | |
| if 0 <= label_idx < len(ASPECT_NAMES): | |
| aspect_name = ASPECT_NAMES[label_idx] | |
| scores_dict[aspect_name] = round(item["score"], 3) | |
| else: | |
| # Fallback for different pipeline output format | |
| for i, aspect_name in enumerate(ASPECT_NAMES): | |
| scores_dict[aspect_name] = 0.5 # Default score | |
| # Ensure all aspects are present | |
| for aspect in ASPECT_NAMES: | |
| if aspect not in scores_dict: | |
| scores_dict[aspect] = 0.5 | |
| return AnalysisResponse( | |
| review=request.text, | |
| scores=AspectScores(**scores_dict), | |
| timestamp=datetime.utcnow().isoformat(), | |
| ) | |
| except Exception as e: | |
| raise HTTPException( | |
| status_code=500, | |
| detail=f"Analysis failed: {str(e)}", | |
| ) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=8000) | |