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 for hosted Postgres)
- 2GB+ RAM for model training
1. Clone Repository
git clone <your-repo-url>
cd resturant-inspector-server
2. Create Virtual Environment
python -m venv venv
# Windows PowerShell:
.\venv\Scripts\Activate.ps1
# Linux/Mac:
source venv/bin/activate
3. Install Dependencies
pip install sqlalchemy alembic psycopg2-binary datasets transformers torch scikit-learn python-dotenv fastapi uvicorn
4. Configure Database
Create .env file:
DATABASE_URL=postgresql://user:password@host/database
5. Run Migrations
alembic upgrade head
π― Annotation Workflow
Step 1: Bootstrap Reviews
Load Yelp reviews into database:
$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:
$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:
# 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:
$env:PYTHONPATH='.'
python scripts/train.py
This will:
- Load 200 approved annotations from database
- Split into 120 train / 40 val / 40 test
- Fine-tune DistilBERT (3 epochs)
- Evaluate on test set
- Save model to
models/aspect-classifier/ - Log metrics to
training_runstable
Training time: ~10-15 minutes (CPU) or ~2 minutes (GPU)
π Running the API Server
Start FastAPI Server
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
curl -X POST "http://localhost:8000/analyze" \
-H "Content-Type: application/json" \
-d '{"text": "Amazing biryani but terrible parking and dirty bathrooms"}'
Expected Response
{
"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
# One-command setup and launch (Windows)
.\start_dashboard.ps1
Or manually:
# 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
- View Annotations β Filter and browse AI predictions
- Approve/Reject β Update annotation status in database
- Train Model β Run
python scripts/train.pyin terminal - 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 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
$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
$env:PYTHONPATH='.'
python scripts/approve_annotations.py --summary
Output:
=== Annotation Status Summary ===
approved: 200
draft: 100
TOTAL: 300 (66.7% approved)
Approve More Annotations
python scripts/approve_annotations.py --approve-count 50 --reviewer "your_name"
π Deploying to Production
Option 1: Render
- Push to GitHub
- Create new Web Service on Render
- Connect your repository
- Set environment variable:
DATABASE_URL - Build command:
pip install -r requirements.txt - Start command:
uvicorn main:app --host 0.0.0.0 --port $PORT
Option 2: Docker
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:
# Windows PowerShell
$env:PYTHONPATH='.'
# Linux/Mac
export PYTHONPATH=.
Database connection fails
Check .env file exists and DATABASE_URL is correct:
echo $env:DATABASE_URL # Windows
echo $DATABASE_URL # Linux/Mac
Training runs out of memory
Reduce batch size in scripts/train.py:
per_device_train_batch_size=4, # default is 8
π Additional Resources
- 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
- Fork the repository
- Create feature branch:
git checkout -b feature/new-aspect - Commit changes:
git commit -am 'Add new aspect' - Push:
git push origin feature/new-aspect - 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
- Fork the repository
- Create a feature branch
- Make your changes
- Run linting:
ruff check --fix . - Format code:
ruff format . - 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