dpratapx's picture
Add Streamlit admin dashboard and normalize database with restaurants table
93c5df6
|
Raw
History Blame Contribute Delete
12.6 kB
metadata
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:

  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

uvicorn main:app --reload

Server runs at: http://localhost:8000

API Documentation

πŸ§ͺ 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

  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 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

  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

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

🀝 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