File size: 12,606 Bytes
93c5df6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | ---
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 <your-repo-url>
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**
|