--- title: Restaurant Inspector API emoji: ๐Ÿฝ๏ธ colorFrom: blue colorTo: green sdk: docker pinned: false --- # ๐Ÿฝ๏ธ Restaurant Inspector **Production-grade NLP annotation workflow and aspect-based sentiment analysis** for restaurant reviews. Extracts structured insights across 5 dimensions using DistilBERT with a **human-in-the-loop annotation pipeline**. ## ๐Ÿš€ Features - **Multi-Aspect Sentiment**: 4-state labeling (positive/negative/mixed/not_mentioned) for 5 aspects - **Annotation Workflow**: Draft โ†’ Review โ†’ Approve with full audit trails - **Database-Backed**: PostgreSQL schema with SQLAlchemy ORM + Alembic migrations - **Trained Model**: DistilBERT fine-tuned on 200 professionally approved annotations - **Production-Ready**: FastAPI inference server with logged metrics - **Reproducible**: Version-controlled schema and training pipeline ## ๐Ÿง  Technology Stack - **Model**: DistilBERT-base-uncased (66M parameters, fine-tuned) - **Database**: PostgreSQL (Neon hosted) with SQLAlchemy 2.0 + Alembic - **ML Framework**: Hugging Face Transformers + PyTorch - **API Framework**: FastAPI + Uvicorn - **Data Source**: Yelp Polarity dataset (Hugging Face Datasets) - **Python**: 3.11+ ## ๏ฟฝ Aspect Analysis The model scores reviews across 5 dimensions with 4-state sentiment: | Aspect | States | Description | |--------|--------|-------------| | ๐Ÿ• **Food** | โœ… Positive / โŒ Negative / โš–๏ธ Mixed / โž– Not Mentioned | Quality, taste, freshness | | ๐Ÿ‘ฅ **Service** | โœ… Positive / โŒ Negative / โš–๏ธ Mixed / โž– Not Mentioned | Staff, speed, attentiveness | | ๐Ÿงผ **Hygiene** | โœ… Positive / โŒ Negative / โš–๏ธ Mixed / โž– Not Mentioned | Cleanliness, sanitation | | ๐Ÿ…ฟ๏ธ **Parking** | โœ… Positive / โŒ Negative / โš–๏ธ Mixed / โž– Not Mentioned | Availability, convenience | | โœจ **Cleanliness** | โœ… Positive / โŒ Negative / โš–๏ธ Mixed / โž– Not Mentioned | Ambiance, maintenance | ## ๐Ÿ“ฆ Installation ### Prerequisites - Python 3.11+ - PostgreSQL database (we use [Neon](https://neon.tech) for hosted Postgres) - 2GB+ RAM for model training ### 1. Clone Repository ```bash git clone cd resturant-inspector-server ``` ### 2. Create Virtual Environment ```bash python -m venv venv # Windows PowerShell: .\venv\Scripts\Activate.ps1 # Linux/Mac: source venv/bin/activate ``` ### 3. Install Dependencies ```bash pip install sqlalchemy alembic psycopg2-binary datasets transformers torch scikit-learn python-dotenv fastapi uvicorn ``` ### 4. Configure Database Create `.env` file: ```env DATABASE_URL=postgresql://user:password@host/database ``` ### 5. Run Migrations ```bash alembic upgrade head ``` ## ๐ŸŽฏ Annotation Workflow ### Step 1: Bootstrap Reviews Load Yelp reviews into database: ```bash $env:PYTHONPATH='.' # Windows PowerShell python scripts/bootstrap_reviews.py --count 300 ``` Result: 300 reviews in `reviews` table ### Step 2: Generate Draft Annotations Create heuristic labels using keyword rules: ```bash $env:PYTHONPATH='.' python scripts/generate_draft_annotations.py --limit 300 --annotator "data_analyst_v1" ``` Result: 300 draft annotations with `status='draft'` ### Step 3: Approve Annotations Review and approve annotations for training: ```bash # View current status $env:PYTHONPATH='.' python scripts/approve_annotations.py --summary # Approve first 200 drafts python scripts/approve_annotations.py --approve-count 200 --reviewer "senior_analyst_v1" ``` Result: 200 annotations marked `status='approved'` ### Step 4: Train Model Train DistilBERT on approved annotations: ```bash $env:PYTHONPATH='.' python scripts/train.py ``` This will: 1. Load 200 approved annotations from database 2. Split into 120 train / 40 val / 40 test 3. Fine-tune DistilBERT (3 epochs) 4. Evaluate on test set 5. Save model to `models/aspect-classifier/` 6. Log metrics to `training_runs` table **Training time**: ~10-15 minutes (CPU) or ~2 minutes (GPU) ## ๐Ÿƒ Running the API Server ### Start FastAPI Server ```bash uvicorn main:app --reload ``` Server runs at: http://localhost:8000 ### API Documentation - **Swagger UI**: http://localhost:8000/docs - **ReDoc**: http://localhost:8000/redoc ## ๐Ÿงช Testing the API ### Using curl ```bash curl -X POST "http://localhost:8000/analyze" \ -H "Content-Type: application/json" \ -d '{"text": "Amazing biryani but terrible parking and dirty bathrooms"}' ``` ### Expected Response ```json { "food": "positive", "service": "not_mentioned", "hygiene": "negative", "parking": "negative", "cleanliness": "negative" } ``` ## ๐ŸŽจ Streamlit Admin Dashboard **NEW!** Visual annotation management and monitoring tool for internal use. ### Quick Start ```bash # One-command setup and launch (Windows) .\start_dashboard.ps1 ``` Or manually: ```bash # Install Streamlit dependencies pip install streamlit pandas plotly # Apply latest migrations (includes restaurants table) alembic upgrade head # Start dashboard streamlit run streamlit_app/Home.py ``` Opens at: **http://localhost:8501** ### Pages - **๐Ÿ  Home**: System overview with quick stats and navigation - **Annotations.py**: Review and approve AI-generated labels - Filter by restaurant, status, date, aspect - View AI predictions for all 5 aspects - Approve/reject individual annotations - Real-time status updates - **Training.py**: Monitor model performance - Training run history with metrics (F1, Precision, Recall) - Performance trend charts over time - Training data quality statistics ### Database Structure The dashboard uses a **normalized database** with proper foreign key relationships: ``` restaurants (master table) โ”œโ”€โ”€ id, name, address, phone โ””โ”€โ”€ Referenced by reviews.restaurant_id reviews โ”œโ”€โ”€ restaurant_id โ†’ restaurants.id โ””โ”€โ”€ Review text + metadata review_annotations โ”œโ”€โ”€ review_id โ†’ reviews.id โ””โ”€โ”€ Aspect labels + approval status ``` Current restaurant: **Niloufer** (Hyderabad, India) ### Workflow 1. **View Annotations** โ†’ Filter and browse AI predictions 2. **Approve/Reject** โ†’ Update annotation status in database 3. **Train Model** โ†’ Run `python scripts/train.py` in terminal 4. **View Results** โ†’ Check Training page for metrics ### Use Cases - **Client Demo**: Show professional annotation workflow with visual UI - **Quality Control**: Manual review of model predictions - **Data Curation**: Approve high-quality training data before model training - **Progress Tracking**: Monitor annotation counts and training runs **Note**: Streamlit runs locally for demos. FastAPI is deployed to Hugging Face Spaces for production inference. See [`streamlit_app/README.md`](streamlit_app/README.md) for detailed usage guide. --- ## ๐Ÿ“Š Model Performance **Current Model** (trained on 200 approved samples): ``` Training samples: 120 Validation: 40 Test: 40 Test Precision: 9.2% Test Recall: 77.1% Test F1: 16.5% ``` **Why low precision?** - Small dataset (200 samples total) - Class imbalance (most reviews don't mention all aspects) - Heuristic labels contain noise **Improvement roadmap**: - Approve 500+ annotations โ†’ F1 > 40% - Tune per-aspect decision thresholds - Try RoBERTa or ALBERT ## ๐Ÿ“ Project Structure ``` resturant-inspector-server/ โ”œโ”€โ”€ alembic/ # Database migrations โ”‚ โ”œโ”€โ”€ versions/ โ”‚ โ”‚ โ”œโ”€โ”€ 20260323_0001_*.py # Initial schema โ”‚ โ”‚ โ””โ”€โ”€ 5eed963bbc03_*.py # Training runs table โ”‚ โ””โ”€โ”€ env.py โ”œโ”€โ”€ app/ โ”‚ โ”œโ”€โ”€ db/ โ”‚ โ”‚ โ”œโ”€โ”€ models.py # Review, ReviewAnnotation, TrainingRun โ”‚ โ”‚ โ”œโ”€โ”€ enums.py # AspectState, AnnotationStatus, LabelSource โ”‚ โ”‚ โ”œโ”€โ”€ session.py # Database session factory โ”‚ โ”‚ โ””โ”€โ”€ base.py โ”‚ โ””โ”€โ”€ core/ โ”‚ โ””โ”€โ”€ labeling.py # Heuristic labeling logic โ”œโ”€โ”€ scripts/ โ”‚ โ”œโ”€โ”€ bootstrap_reviews.py # Load Yelp data โ”‚ โ”œโ”€โ”€ generate_draft_annotations.py # Create draft labels โ”‚ โ”œโ”€โ”€ approve_annotations.py # Approve workflow โ”‚ โ””โ”€โ”€ train.py # Train DistilBERT โ”œโ”€โ”€ models/ โ”‚ โ””โ”€โ”€ aspect-classifier/ # Trained model outputs โ”‚ โ”œโ”€โ”€ model.safetensors โ”‚ โ”œโ”€โ”€ config.json โ”‚ โ”œโ”€โ”€ tokenizer.json โ”‚ โ””โ”€โ”€ metadata.json โ”œโ”€โ”€ .env # DATABASE_URL โ”œโ”€โ”€ alembic.ini โ”œโ”€โ”€ PROJECT_STATUS.md # Detailed project documentation โ””โ”€โ”€ README.md ``` ## ๐Ÿ—„๏ธ Database Schema ### `reviews` Stores raw review text from external sources ### `review_annotations` Aspect-level annotations with audit trails - **States**: draft โ†’ reviewed โ†’ approved โ†’ rejected - **Sources**: heuristic, manual, heuristic_reviewed - **Tracks**: annotator_name, reviewer_name, timestamps, confidence ### `training_runs` Logs all model training runs with metrics ## ๐Ÿ› ๏ธ Development Commands ### View Training History ```bash $env:PYTHONPATH='.' .\venv\Scripts\python -c "from app.db.session import SessionLocal; from app.db.models import TrainingRun; s = SessionLocal(); [print(f'Run {r.id}: F1={r.test_f1:.4f}') for r in s.query(TrainingRun).all()]; s.close()" ``` ### Check Annotation Status ```bash $env:PYTHONPATH='.' python scripts/approve_annotations.py --summary ``` Output: ``` === Annotation Status Summary === approved: 200 draft: 100 TOTAL: 300 (66.7% approved) ``` ### Approve More Annotations ```bash python scripts/approve_annotations.py --approve-count 50 --reviewer "your_name" ``` ## ๐Ÿš€ Deploying to Production ### Option 1: Render 1. Push to GitHub 2. Create new Web Service on Render 3. Connect your repository 4. Set environment variable: `DATABASE_URL` 5. Build command: `pip install -r requirements.txt` 6. Start command: `uvicorn main:app --host 0.0.0.0 --port $PORT` ### Option 2: Docker ```dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ``` ## ๐Ÿ”ง Troubleshooting ### ModuleNotFoundError: No module named 'app' Set PYTHONPATH before running scripts: ```powershell # Windows PowerShell $env:PYTHONPATH='.' # Linux/Mac export PYTHONPATH=. ``` ### Database connection fails Check `.env` file exists and `DATABASE_URL` is correct: ```bash echo $env:DATABASE_URL # Windows echo $DATABASE_URL # Linux/Mac ``` ### Training runs out of memory Reduce batch size in `scripts/train.py`: ```python per_device_train_batch_size=4, # default is 8 ``` ## ๐Ÿ“š Additional Resources - **[PROJECT_STATUS.md](PROJECT_STATUS.md)** - Detailed project overview and client responses - **Alembic Docs**: https://alembic.sqlalchemy.org/ - **Hugging Face Transformers**: https://huggingface.co/docs/transformers - **FastAPI Docs**: https://fastapi.tiangolo.com/ ## ๐Ÿค Contributing 1. Fork the repository 2. Create feature branch: `git checkout -b feature/new-aspect` 3. Commit changes: `git commit -am 'Add new aspect'` 4. Push: `git push origin feature/new-aspect` 5. Submit Pull Request ## ๐Ÿ“„ License [Add license info] ## ๐Ÿ‘ค Contact **Project**: Restaurant Inspector **Database**: Neon Postgres **Model**: DistilBERT (Hugging Face) --- **Built with** Python โ€ข PostgreSQL โ€ข Transformers โ€ข PyTorch โ€ข FastAPI - **PARKING**: parking, no space - **CLEANLINESS**: clean, messy, well-maintained ## ๐Ÿ“ Project Structure ``` resturant-inspector-server/ โ”œโ”€โ”€ pyproject.toml # Dependencies โ”œโ”€โ”€ train.py # Training script โ”œโ”€โ”€ main.py # FastAPI application โ”œโ”€โ”€ README.md # This file โ”œโ”€โ”€ .gitignore # Git ignore rules โ”œโ”€โ”€ venv/ # Virtual environment (not committed) โ””โ”€โ”€ model/ # Trained model (generated, not committed) โ”œโ”€โ”€ config.json โ”œโ”€โ”€ model.safetensors โ””โ”€โ”€ tokenizer files ``` ## ๐Ÿค Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Run linting: `ruff check --fix .` 5. Format code: `ruff format .` 6. Submit a pull request ## ๐Ÿ“„ License MIT License ## ๐Ÿ™ Acknowledgments - Hugging Face for Transformers library - Yelp for the dataset - FastAPI team for the framework ## ๐Ÿ“ž Support For issues or questions, please open a GitHub issue. --- **Built with โค๏ธ using Python, FastAPI, and DistilBERT**