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