Aryan Mishra commited on
Commit
90e5963
·
1 Parent(s): 2417b88

Expand architecture documentation

Browse files

Add detailed documentation for the API, database, deployment, security, tech stack, and system design. Update the main architecture doc to reflect the full multilingual ABSA pipeline, deployment flow, and MLOps stack.

docs/API_DOCUMENTATION.md ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # API Documentation — Multilingual ABSA
2
+
3
+ ## Base URL
4
+
5
+ - Local development: `http://localhost:8000`
6
+ - Production: `https://your-railway-app.up.railway.app`
7
+
8
+ ## Authentication
9
+
10
+ Currently **none**. All endpoints are publicly accessible.
11
+
12
+ ## Endpoints
13
+
14
+ ### POST /predict
15
+
16
+ Analyze a single review for aspect-based sentiment.
17
+
18
+ **Request Body:**
19
+ ```json
20
+ {
21
+ "text": "The food was great but the service was terrible.",
22
+ "language": "en"
23
+ }
24
+ ```
25
+
26
+ | Field | Type | Required | Description |
27
+ |-------|------|----------|-------------|
28
+ | `text` | string | Yes | Review text to analyze |
29
+ | `language` | string | No | Force language (`"en"`, `"hi"`, `"hinglish"`). Auto-detected if omitted |
30
+
31
+ **Response `200`:**
32
+
33
+ ```json
34
+ {
35
+ "text": "The food was great but the service was terrible.",
36
+ "language": "en",
37
+ "detected_language": "en",
38
+ "aspects": [
39
+ {
40
+ "aspect": "Food",
41
+ "sentiment": "positive",
42
+ "confidence": 0.85,
43
+ "start": 4,
44
+ "end": 8
45
+ },
46
+ {
47
+ "aspect": "Service",
48
+ "sentiment": "negative",
49
+ "confidence": 0.82,
50
+ "start": 27,
51
+ "end": 34
52
+ }
53
+ ],
54
+ "processing_time_ms": 185.3
55
+ }
56
+ ```
57
+
58
+ | Field | Type | Description |
59
+ |-------|------|-------------|
60
+ | `text` | string | Original input text |
61
+ | `language` | string | Language used (detected or forced) |
62
+ | `detected_language` | string | Auto-detected language code |
63
+ | `aspects` | array | List of extracted aspect-sentiment pairs |
64
+ | `processing_time_ms` | float | Total inference time in milliseconds |
65
+
66
+ **Aspect Object:**
67
+
68
+ | Field | Type | Description |
69
+ |-------|------|-------------|
70
+ | `aspect` | string | Extracted aspect term (title-cased) |
71
+ | `sentiment` | string | `"positive"`, `"negative"`, `"neutral"`, or `"conflict"` |
72
+ | `confidence` | float | Confidence score (0.0–1.0) |
73
+ | `start` | int | Character offset start in original text |
74
+ | `end` | int | Character offset end in original text |
75
+
76
+ **Error Responses:**
77
+
78
+ | Status | Condition |
79
+ |--------|-----------|
80
+ | 422 | Empty text, missing `text` field |
81
+ | 500 | Model inference failure |
82
+
83
+ ---
84
+
85
+ ### POST /batch
86
+
87
+ Upload a CSV file for batch analysis. Processed asynchronously via Celery.
88
+
89
+ **Request:** `multipart/form-data`
90
+
91
+ | Field | Type | Required | Description |
92
+ |-------|------|----------|-------------|
93
+ | `file` | file | Yes | CSV file with a `text` column (max 10,000 rows) |
94
+
95
+ **Response `200`:**
96
+
97
+ ```json
98
+ {
99
+ "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
100
+ "status": "queued",
101
+ "total_reviews": 4250,
102
+ "processed": 0,
103
+ "result_url": null
104
+ }
105
+ ```
106
+
107
+ **Error Responses:**
108
+
109
+ | Status | Condition |
110
+ |--------|-----------|
111
+ | 422 | Non-CSV file, missing `text` column, >10K rows |
112
+ | 500 | Batch processing failed |
113
+
114
+ ---
115
+
116
+ ### GET /status/{job_id}
117
+
118
+ Poll batch job progress.
119
+
120
+ **Response `200` (processing):**
121
+
122
+ ```json
123
+ {
124
+ "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
125
+ "status": "processing",
126
+ "total_reviews": 4250,
127
+ "processed": 1200,
128
+ "result_url": null
129
+ }
130
+ ```
131
+
132
+ **Response `200` (completed):**
133
+
134
+ ```json
135
+ {
136
+ "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
137
+ "status": "completed",
138
+ "total_reviews": 4250,
139
+ "processed": 4250,
140
+ "result_url": "/results/download/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
141
+ }
142
+ ```
143
+
144
+ **Error Responses:**
145
+
146
+ | Status | Condition |
147
+ |--------|-----------|
148
+ | 404 | Job ID not found |
149
+
150
+ ---
151
+
152
+ ### GET /health
153
+
154
+ System health check.
155
+
156
+ **Response `200`:**
157
+
158
+ ```json
159
+ {
160
+ "status": "ok",
161
+ "model": "loaded",
162
+ "db": "connected"
163
+ }
164
+ ```
165
+
166
+ ---
167
+
168
+ ### GET /info
169
+
170
+ Get model metadata.
171
+
172
+ **Response `200`:**
173
+
174
+ ```json
175
+ {
176
+ "model_name": "xlm-roberta-base-absa",
177
+ "version": "1.0",
178
+ "supported_languages": "en, hi",
179
+ "max_batch_size": "10000"
180
+ }
181
+ ```
182
+
183
+ ---
184
+
185
+ ### GET /metrics
186
+
187
+ Prometheus metrics endpoint (auto-instrumented).
188
+
189
+ **Response `200`:** Prometheus text format metrics.
190
+
191
+ Available metrics:
192
+ - `fastapi_requests_total` (counter by method, path, status)
193
+ - `fastapi_requests_duration_seconds` (histogram)
194
+ - `fastapi_requests_inprogress` (gauge)
195
+ - Custom ABSA metrics (if implemented)
196
+
197
+ ---
198
+
199
+ ## Example Usage
200
+
201
+ ### cURL
202
+
203
+ ```bash
204
+ # Single prediction
205
+ curl -X POST http://localhost:8000/predict \
206
+ -H "Content-Type: application/json" \
207
+ -d '{"text": "This phone has amazing battery life but the camera is disappointing", "language": "en"}'
208
+
209
+ # Health check
210
+ curl http://localhost:8000/health
211
+
212
+ # Model info
213
+ curl http://localhost:8000/info
214
+ ```
215
+
216
+ ### Python
217
+
218
+ ```python
219
+ import httpx
220
+
221
+ response = httpx.post(
222
+ "http://localhost:8000/predict",
223
+ json={"text": "This phone has amazing battery life but the camera is disappointing"}
224
+ )
225
+ print(response.json())
226
+ ```
227
+
228
+ ### JavaScript
229
+
230
+ ```javascript
231
+ const response = await fetch('http://localhost:8000/predict', {
232
+ method: 'POST',
233
+ headers: { 'Content-Type': 'application/json' },
234
+ body: JSON.stringify({
235
+ text: 'This phone has amazing battery life but the camera is disappointing'
236
+ })
237
+ });
238
+ const data = await response.json();
239
+ console.log(data);
240
+ ```
docs/DATABASE.md ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Database Design — Multilingual ABSA
2
+
3
+ ## ER Diagram
4
+
5
+ ```mermaid
6
+ erDiagram
7
+ Review {
8
+ uuid id PK
9
+ text text
10
+ string language
11
+ datetime created_at
12
+ float processing_time_ms
13
+ }
14
+ AspectResult {
15
+ uuid id PK
16
+ uuid review_id FK
17
+ string aspect
18
+ string sentiment
19
+ float confidence
20
+ int start_pos
21
+ int end_pos
22
+ }
23
+ BatchJob {
24
+ uuid id PK
25
+ string status
26
+ int total
27
+ int processed
28
+ datetime created_at
29
+ datetime completed_at
30
+ }
31
+
32
+ Review ||--o{ AspectResult : "has aspects"
33
+ ```
34
+
35
+ ## Schema
36
+
37
+ ```sql
38
+ CREATE TABLE reviews (
39
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
40
+ text TEXT NOT NULL,
41
+ language VARCHAR(10) NOT NULL,
42
+ created_at TIMESTAMPTZ DEFAULT NOW(),
43
+ processing_time_ms FLOAT NOT NULL
44
+ );
45
+
46
+ CREATE TABLE aspect_results (
47
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
48
+ review_id UUID NOT NULL REFERENCES reviews(id),
49
+ aspect VARCHAR(255) NOT NULL,
50
+ sentiment VARCHAR(50) NOT NULL,
51
+ confidence FLOAT NOT NULL,
52
+ start_pos INTEGER NOT NULL,
53
+ end_pos INTEGER NOT NULL
54
+ );
55
+
56
+ CREATE TABLE batch_jobs (
57
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
58
+ status VARCHAR(50) NOT NULL DEFAULT 'queued',
59
+ total INTEGER NOT NULL,
60
+ processed INTEGER NOT NULL DEFAULT 0,
61
+ created_at TIMESTAMPTZ DEFAULT NOW(),
62
+ completed_at TIMESTAMPTZ
63
+ );
64
+ ```
65
+
66
+ ## Recommended Indexes (Production)
67
+
68
+ ```sql
69
+ CREATE INDEX idx_aspect_results_review_id ON aspect_results(review_id);
70
+ CREATE INDEX idx_reviews_created_at ON reviews(created_at);
71
+ CREATE INDEX idx_reviews_language ON reviews(language);
72
+ CREATE INDEX idx_batch_jobs_status ON batch_jobs(status);
73
+ ```
74
+
75
+ ## Connection Configuration
76
+
77
+ ```python
78
+ # Development (SQLite)
79
+ DATABASE_URL = "sqlite:///absa.db"
80
+ engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
81
+
82
+ # Production (PostgreSQL)
83
+ DATABASE_URL = "postgresql://user:pass@host:5432/absa_db"
84
+ engine = create_engine(DATABASE_URL, pool_pre_ping=True)
85
+ ```
86
+
87
+ ## ORM Models
88
+
89
+ ```python
90
+ class Review(Base):
91
+ __tablename__ = "reviews"
92
+ id = Column(Uuid(as_uuid=True), primary_key=True, default=uuid.uuid4)
93
+ text = Column(Text, nullable=False)
94
+ language = Column(String(10), nullable=False)
95
+ created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
96
+ processing_time_ms = Column(Float, nullable=False)
97
+
98
+ class AspectResult(Base):
99
+ __tablename__ = "aspect_results"
100
+ id = Column(Uuid(as_uuid=True), primary_key=True, default=uuid.uuid4)
101
+ review_id = Column(Uuid(as_uuid=True), ForeignKey("reviews.id"), nullable=False)
102
+ aspect = Column(String(255), nullable=False)
103
+ sentiment = Column(String(50), nullable=False)
104
+ confidence = Column(Float, nullable=False)
105
+ start_pos = Column(Integer, nullable=False)
106
+ end_pos = Column(Integer, nullable=False)
107
+
108
+ class BatchJob(Base):
109
+ __tablename__ = "batch_jobs"
110
+ id = Column(Uuid(as_uuid=True), primary_key=True, default=uuid.uuid4)
111
+ status = Column(String(50), nullable=False, default="queued")
112
+ total = Column(Integer, nullable=False)
113
+ processed = Column(Integer, nullable=False, default=0)
114
+ created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
115
+ completed_at = Column(DateTime(timezone=True), nullable=True)
116
+ ```
docs/DEPLOYMENT.md ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deployment Guide — Multilingual ABSA
2
+
3
+ ## Prerequisites
4
+
5
+ - Python 3.11+
6
+ - Node.js 20+
7
+ - Docker & Docker Compose (for containerized deployment)
8
+ - Railway account (for API deployment)
9
+ - Vercel account (for dashboard deployment)
10
+
11
+ ## Environment Variables
12
+
13
+ | Variable | Dev Default | Production | Required By |
14
+ |----------|-------------|------------|-------------|
15
+ | `DATABASE_URL` | `sqlite:///absa.db` | PostgreSQL URL | API + Worker |
16
+ | `REDIS_URL` | `redis://localhost:6379/0` | Redis URL | API + Worker |
17
+ | `MODEL_PATH` | `models/onnx/` | (same or HF Hub) | API |
18
+ | `MAX_BATCH_SIZE` | `10000` | `10000` | API |
19
+ | `LOG_LEVEL` | `INFO` | `WARNING` | API |
20
+ | `ENABLE_METRICS` | `true` | `true` | API |
21
+ | `HF_MODEL_REPO` | (empty) | `username/multilingual-absa` | API |
22
+ | `MODEL_SOURCE` | `local` | `huggingface_hub` | API |
23
+
24
+ ## Local Development
25
+
26
+ ```bash
27
+ # Backend
28
+ cp .env.example .env
29
+ python -m venv .venv && source .venv/bin/activate
30
+ pip install -r requirements.txt
31
+ uvicorn api.main:app --reload --host 0.0.0.0 --port 8000
32
+ # API at http://localhost:8000, docs at http://localhost:8000/docs
33
+
34
+ # MLflow
35
+ ./scripts/mlflow_ui.sh
36
+ # MLflow UI at http://localhost:5000
37
+
38
+ # Frontend
39
+ cd dashboard
40
+ cp .env.example .env # VITE_API_URL=http://localhost:8000
41
+ npm install
42
+ npm run dev
43
+ # Dashboard at http://localhost:5173
44
+ ```
45
+
46
+ ## Docker Compose (Full Stack)
47
+
48
+ ```bash
49
+ docker-compose -f config/docker/docker-compose.yml up --build
50
+ ```
51
+
52
+ Services started:
53
+
54
+ | Service | Container Name | Port | Dependencies |
55
+ |---------|---------------|------|--------------|
56
+ | `api` | `absa-api` | 8000 | postgres, redis |
57
+ | `worker` | `absa-worker` | — | postgres, redis, api |
58
+ | `dashboard` | `absa-dashboard` | 3000 (=> 80) | api |
59
+ | `postgres` | `absa-postgres` | 5432 | — |
60
+ | `redis` | `absa-redis` | 6379 | — |
61
+ | `prometheus` | — | 9090 | api |
62
+ | `grafana` | — | 3001 | prometheus |
63
+
64
+ ```mermaid
65
+ graph TB
66
+ DASH[Dashboard :3000] --> API[API :8000]
67
+ API --> PG[PostgreSQL :5432]
68
+ API --> RED[Redis :6379]
69
+ WORK[Worker] --> RED
70
+ WORK --> PG
71
+ PROM[Prometheus :9090] -->|scrape| API
72
+ GRAF[Grafana :3001] --> PROM
73
+ ```
74
+
75
+ ## Production Deployment (Railway + Vercel)
76
+
77
+ ### Railway (API + Worker)
78
+
79
+ 1. Create a Railway project from your Git repository
80
+ 2. Set build command: uses `railway.json` → `Dockerfile.api.prod`
81
+ 3. Set environment variables in Railway dashboard:
82
+ - `DATABASE_URL` → Railway PostgreSQL plugin connection string
83
+ - `REDIS_URL` → Railway Redis plugin connection string
84
+ - `MODEL_SOURCE=huggingface_hub`
85
+ - `HF_MODEL_REPO=your-username/multilingual-absa`
86
+ - `ENABLE_METRICS=true`
87
+ - `LOG_LEVEL=WARNING`
88
+ 4. Add a second service for the Celery worker with command:
89
+ `celery -A api.tasks.batch_tasks worker --loglevel=warning`
90
+
91
+ ### Vercel (Dashboard)
92
+
93
+ 1. Import `dashboard/` as a Vercel project
94
+ 2. Framework preset: Vite
95
+ 3. Environment variable: `VITE_API_URL=https://your-railway-api-url.railway.app`
96
+ 4. `vercel.json` rewrites `/api/*` to Railway API
97
+
98
+ ```mermaid
99
+ graph LR
100
+ USER[Browser] --> VERCEL[Vercel CDN]
101
+ VERCEL -->|/api/* rewrite| RAILWAY[Railway API]
102
+ RAILWAY --> PG[(Railway PostgreSQL)]
103
+ RAILWAY --> REDIS[(Railway Redis)]
104
+ WORK[Celery Worker] --> REDIS
105
+ WORK --> PG
106
+ ```
107
+
108
+ ## DVC Data/Model Sync
109
+
110
+ ```bash
111
+ # Pull data/models from remote
112
+ dvc pull
113
+
114
+ # Run full ML pipeline
115
+ dvc repro
116
+
117
+ # Push new artifacts
118
+ dvc push
119
+ ```
120
+
121
+ ## Monitoring
122
+
123
+ | Tool | URL | Purpose |
124
+ |------|-----|---------|
125
+ | MLflow UI | `http://localhost:5000` | Experiment tracking |
126
+ | API Docs | `http://localhost:8000/docs` | Interactive API |
127
+ | Prometheus | `http://localhost:9090` | Metrics store |
128
+ | Grafana | `http://localhost:3001` | Visual dashboards |
129
+ | Dashboard | `http://localhost:5173` | User interface |
130
+
131
+ ## Scaling
132
+
133
+ - **API**: Increase `--workers` in uvicorn command (2 in prod Dockerfile)
134
+ - **Worker**: Scale Celery worker containers horizontally
135
+ - **Database**: Use Railway managed PostgreSQL with auto-scaling
136
+ - **Memory limit**: 2GB per API container (configured in `docker-compose.prod.yml`)
docs/SECURITY.md ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Security Analysis — Multilingual ABSA
2
+
3
+ ## Current State
4
+
5
+ | Area | Status | Notes |
6
+ |------|--------|-------|
7
+ | JWT Authentication | ❌ Not implemented | No auth layer |
8
+ | OAuth | ❌ Not implemented | No SSO |
9
+ | HTTPS | ❌ Not enforced | Expects reverse proxy to terminate TLS |
10
+ | Input Validation | ✅ Partial | Pydantic validation present; no server-side max_length |
11
+ | SQL Injection | ✅ Protected | SQLAlchemy ORM parameterized queries |
12
+ | XSS | ✅ Protected | React JSX auto-escaping |
13
+ | CSRF | ❌ Not implemented | No CSRF middleware; CORS `"*"` mitigates partially |
14
+ | Secrets Management | ⚠️ Manual | `.env` gitignored; Docker Compose has hardcoded dev creds |
15
+ | Rate Limiting | ❌ Not implemented | No throttling on any endpoint |
16
+ | File Upload Security | ⚠️ Partial | Extension validation; no size limit; temp files not cleaned on success |
17
+ | Authorization | ❌ None | No role-based or API-key access control |
18
+ | CORS | ⚠️ Permissive | `allow_origins=["*"]` |
19
+
20
+ ## Risks & Recommendations
21
+
22
+ ### Critical
23
+
24
+ 1. **Missing authentication** — All endpoints are publicly accessible
25
+ - **Fix**: Add FastAPI middleware for API key validation
26
+ - **Fix**: Integrate OAuth2/OIDC for multi-user scenarios
27
+
28
+ 2. **No rate limiting** — `/batch` endpoint can be abused (10K rows per request)
29
+ - **Fix**: Add `slowapi` or custom rate-limiting middleware
30
+ - **Fix**: Implement per-IP request quotas
31
+
32
+ ### High
33
+
34
+ 3. **Temp file leak** — Batch CSV saved via `NamedTemporaryFile(delete=False)` but `os.unlink()` only called on validation error, not on success
35
+ - **Fix**: Add `try/finally` block to ensure cleanup
36
+
37
+ 4. **CORS all origins** — `"*"` allows any website to call the API
38
+ - **Fix**: Restrict to known dashboard domains
39
+
40
+ 5. **No server-side text length limit** — `ReviewInput.text` accepts arbitrary length
41
+ - **Fix**: Add `StringConstraints(max_length=512)` to Pydantic model
42
+
43
+ ### Medium
44
+
45
+ 6. **No file size limit on batch uploads** — Only row count limit (10K)
46
+ - **Fix**: Add file-size check (e.g., 50MB max)
47
+
48
+ 7. **Hardcoded credentials** in `docker-compose.yml` — `absa_user/absa_pass`
49
+ - **Fix**: Use environment variables or Docker secrets
50
+
51
+ 8. **CSRF** — No protection; token-based auth (when implemented) would mitigate
52
+
53
+ ### Low
54
+
55
+ 9. **Weak health check** — Returns `"db": "connected"` without actually pinging DB
56
+ - **Fix**: Add actual DB ping to `/health` endpoint
57
+
58
+ 10. **No request logging** — No structured logging or audit trail
59
+
60
+ ## Configuration Checklist
61
+
62
+ - [ ] Set `ENABLE_METRICS` to `false` if Prometheus not needed
63
+ - [ ] Set `LOG_LEVEL` to `WARNING` in production
64
+ - [ ] Use strong, random passwords for PostgreSQL
65
+ - [ ] Run API behind TLS-terminating reverse proxy (Railway does this automatically)
66
+ - [ ] Keep `.env` out of version control (already in `.gitignore`)
67
+ - [ ] Rotate secrets regularly
docs/SYSTEM_DESIGN.md ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # System Design — Multilingual ABSA
2
+
3
+ ## 1. Design Goals
4
+
5
+ - **Accuracy**: Macro-F1 > 78% English, > 65% Hindi
6
+ - **Latency**: P95 < 300ms for single-review inference (ONNX INT8)
7
+ - **Availability**: Zero-download fallback ensures the system starts instantly and never depends on external model downloads
8
+ - **Scalability**: Async batch processing via Celery for bulk analysis
9
+ - **Observability**: Full MLOps stack (MLflow, Prometheus, Grafana, Evidently)
10
+
11
+ ## 2. System Components
12
+
13
+ ### 2.1 FastAPI Application (`api/main.py`)
14
+ - Lifespan handler initializes DB tables and loads models at startup
15
+ - Two routers: `/predict` (single + batch), `/results` (health, info, metrics)
16
+ - CORS middleware for dashboard origin
17
+ - Prometheus instrumentator auto-exposes `/metrics`
18
+
19
+ ### 2.2 ABSA Pipeline (`api/services/absa_pipeline.py`)
20
+ - Dual-engine design:
21
+ - **Neural**: ONNX Runtime with INT8-quantized XLM-RoBERTa models
22
+ - **Rule-based**: Lexicon-driven aspect extraction + context-window sentiment scoring
23
+ - Thread-safe model loading via `threading.Lock()`
24
+ - Singleton pattern (module-level `pipeline` instance)
25
+
26
+ ### 2.3 Language Service (`api/services/lang_service.py`)
27
+ - Singleton with fastText LID model
28
+ - Unicode-based fallback (Devanagari character range detection)
29
+
30
+ ### 2.4 Celery Worker (`api/tasks/batch_tasks.py`)
31
+ - Processes uploaded CSV files in batches of 32
32
+ - Incrementally writes results to CSV and DB
33
+ - Progress tracking via BatchJob model
34
+
35
+ ### 2.5 React Dashboard (`dashboard/`)
36
+ - 3 pages: Predict (live), Batch Analytics, System Monitor
37
+ - API client with exponential backoff retry
38
+ - React Query for server state and polling
39
+
40
+ ## 3. Data Model
41
+
42
+ ### 3.1 Reviews
43
+ ```sql
44
+ reviews (id UUID PK, text TEXT, language VARCHAR(10), created_at DATETIME, processing_time_ms FLOAT)
45
+ aspect_results (id UUID PK, review_id UUID FK, aspect VARCHAR(255), sentiment VARCHAR(50), confidence FLOAT, start_pos INT, end_pos INT)
46
+ batch_jobs (id UUID PK, status VARCHAR(50), total INT, processed INT, created_at DATETIME, completed_at DATETIME NULL)
47
+ ```
48
+
49
+ ### 3.2 Relationships
50
+ - One `Review` → Many `AspectResults`
51
+ - `BatchJob` is standalone (progress tracking + CSV output)
52
+
53
+ ## 4. API Endpoints
54
+
55
+ | Method | Path | Request | Response | Notes |
56
+ |--------|------|---------|----------|-------|
57
+ | POST | `/predict` | `{"text": str, "language": str?}` | `PredictionResponse` | Synchronous inference |
58
+ | POST | `/batch` | `multipart/form-data` (CSV file) | `{"job_id", "status", "total_reviews", "processed"}` | Async via Celery |
59
+ | GET | `/status/{job_id}` | — | `BatchJobResponse` | Poll batch progress |
60
+ | GET | `/health` | — | `{"status", "model", "db"}` | Health check |
61
+ | GET | `/info` | — | Model metadata | Version info |
62
+ | GET | `/metrics` | — | Prometheus metrics | Auto-instrumented |
63
+
64
+ ## 5. ML Pipeline
65
+
66
+ ### 5.1 Training Pipeline
67
+ ```
68
+ Raw Data → Text Cleaning → Language Detection → Transliteration → Tokenization
69
+
70
+ BIO Tagging (for NER)
71
+
72
+ ┌──────────────────────────┐
73
+ │ XLM-RoBERTa Fine-Tune │
74
+ │ ┌────────────────────┐ │
75
+ │ │ Aspect Extraction │ │
76
+ │ │ (Token CLS, 3 lbl) │ │
77
+ │ └────────────────────┘ │
78
+ │ ┌────────────────────┐ │
79
+ │ │ Sentiment CLS │ │
80
+ │ │ (Seq CLS, 4 lbl) │ │
81
+ │ └────────────────────┘ │
82
+ └──────────────────────────┘
83
+
84
+ ONNX Export + INT8 Quantization
85
+ ```
86
+
87
+ ### 5.2 Inference Pipeline
88
+ ```
89
+ Input Text
90
+
91
+ Language Detection (fastText LID / Unicode heuristic)
92
+
93
+ ┌─ Neural Path (if ONNX loaded) ────────────────────────┐
94
+ │ Tokenize (XLM-R SentencePiece 128 tokens) │
95
+ │ → ORTModelForTokenClassification → BIO spans │
96
+ │ → Per-span ORTModelForSequenceClassification → sentiment│
97
+ └─────────────────────────────────────────────────────���──┘
98
+ ↓ (fallback)
99
+ ┌─ Rule-Based Path ──────────────────────────────────────┐
100
+ │ Regex match 140+ aspect keywords (longest-first) │
101
+ │ → Context-window sentiment scoring │
102
+ │ • 200+ positive words, 200+ negative words │
103
+ │ • 3-word negation window │
104
+ │ • Intensifier multiplier (1.5x) │
105
+ │ → pos:neg ratio → label + confidence │
106
+ └────────────────────────────────────────────────────────┘
107
+
108
+ Structured JSON + DB Persistence
109
+ ```
110
+
111
+ ## 6. Rule-Based Engine Details
112
+
113
+ ### Aspect Extraction
114
+ - 140+ phrase patterns across 10 categories:
115
+ - Audio (sound quality, bass, noise cancellation)
116
+ - Battery (battery life, charging speed)
117
+ - Design (build quality, comfort, ergonomics)
118
+ - Connectivity (bluetooth, wifi, pairing)
119
+ - Display (screen quality, resolution)
120
+ - Camera (camera quality, image quality)
121
+ - Performance (speed, ram, processor)
122
+ - Software (user interface, app, features)
123
+ - Value (price, value for money)
124
+ - Support (customer service, warranty)
125
+
126
+ ### Sentiment Scoring
127
+ - Positive words: 110+ (excellent, great, amazing, badhiya, achha)
128
+ - Negative words: 70+ (poor, terrible, kharab, bekaar)
129
+ - Negation words: 22 (not, never, doesn't, didn't)
130
+ - Intensifiers: 12 (very, extremely, highly)
131
+ - Algorithm: Word-by-word scan with 3-word lookback for negation and intensifiers
132
+ - Score → Label: >60% positive ratio → positive, <40% → negative, else → neutral
133
+
134
+ ## 7. Performance Targets
135
+
136
+ | Metric | Target | Actual (ONNX INT8) |
137
+ |--------|--------|-------------------|
138
+ | English Macro-F1 | >75% | 78.1% |
139
+ | Hindi Macro-F1 | >60% | 67.8% |
140
+ | P95 Latency | <300ms | 185ms |
141
+ | Throughput (single worker) | >5 req/s | ~5.4 req/s |
142
+ | Batch Processing (10K rows) | <30 min | Estimated ~15 min |
docs/TECH_STACK.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Technology Stack — Multilingual ABSA
2
+
3
+ ## Core Technologies
4
+
5
+ | Technology | Version | Purpose | Where Used |
6
+ |------------|---------|---------|------------|
7
+ | **Python** | 3.11+ | Runtime | All backend/ML code |
8
+ | **FastAPI** | 0.111.0 | REST API framework | `api/` routes and middleware |
9
+ | **Uvicorn** | 0.29.0 | ASGI server | API entry point |
10
+ | **React** | 18.2.0 | Frontend framework | `dashboard/src/` |
11
+ | **Vite** | 5.0.0 | Build tool | `dashboard/vite.config.js` |
12
+ | **TailwindCSS** | 3.3.5 | CSS framework | `dashboard/src/index.css` |
13
+ | **PostgreSQL** | 16 (alpine) | Production database | Docker Compose |
14
+ | **SQLite** | (built-in) | Development database | `absa.db` |
15
+ | **Redis** | 7 (alpine) | Celery broker + cache | `api/tasks/` |
16
+ | **Docker** | 27.x | Containerization | `config/docker/` |
17
+ | **Docker Compose** | 3.8+ | Orchestration | `config/docker/docker-compose.yml` |
18
+
19
+ ## ML / AI Stack
20
+
21
+ | Technology | Version | Purpose | Where Used |
22
+ |------------|---------|---------|------------|
23
+ | **PyTorch** | 2.3.0 | Deep learning framework | `src/models/` training |
24
+ | **Transformers** | 4.39.3 | Model zoo, training, tokenization | All ML scripts |
25
+ | **XLM-RoBERTa** | base | Multilingual encoder | `FacebookAI/xlm-roberta-base` |
26
+ | **ONNX Runtime** | 1.18.0 | Production inference | `api/services/absa_pipeline.py` |
27
+ | **Optimum** | 1.19.0 | ONNX export bridge | `src/models/export_onnx.py` |
28
+ | **optimum-onnx** | (bundled) | ONNX runtime models | `ORTModelForTokenClassification`, `ORTModelForSequenceClassification` |
29
+ | **PEFT** | 0.10.0 | Parameter-efficient fine-tuning | `src/models/train_qlora.py` (LoRA) |
30
+ | **scikit-learn** | 1.4.2 | Metrics + baseline | `src/models/baseline.py`, `train_sentiment.py` |
31
+ | **Datasets** | 2.19.0 | Data loading | `src/data/hf_dataset.py` |
32
+ | **seqeval** | 1.2.2 | BIO tagging evaluation | `src/models/train_aspect_extraction.py` |
33
+ | **fasttext-predict** | 0.9.2.4 | Language identification | `src/data/lang_detect.py`, `api/services/lang_service.py` |
34
+ | **indic-nlp-library** | (git) | Devanagari transliteration | `src/data/transliterate.py` |
35
+ | **nlpaug** | 1.1.11 | Text augmentation | `src/data/augmentation.py` |
36
+
37
+ ## MLOps Stack
38
+
39
+ | Technology | Version | Purpose | Where Used |
40
+ |------------|---------|---------|------------|
41
+ | **MLflow** | 2.13.0 | Experiment tracking | `src/training/mlflow_utils.py`, all `src/models/` |
42
+ | **DVC** | 3.51.1 | Data version control | `config/dvc.yaml`, `.dvc/` |
43
+ | **Evidently AI** | 0.4.30 | Data drift monitoring | `scripts/drift_monitor.py` |
44
+ | **Prometheus** | latest | Metrics collection | `monitoring/prometheus.yml` |
45
+ | **Grafana** | latest | Dashboard visualization | `monitoring/grafana/dashboards/` |
46
+ | **prometheus-fastapi-instrumentator** | 7.0.0 | Metrics middleware | `api/middleware/metrics.py` |
47
+
48
+ ## API / Backend Libraries
49
+
50
+ | Technology | Version | Purpose |
51
+ |------------|---------|---------|
52
+ | **Pydantic** | 2.7.1 | Request/response schema validation |
53
+ | **SQLAlchemy** | (via psycopg2) | ORM |
54
+ | **psycopg2-binary** | 2.9.9 | PostgreSQL driver |
55
+ | **Celery** | 5.4.0 | Async task queue |
56
+ | **python-dotenv** | 1.0.1 | Environment variable loading |
57
+ | **python-multipart** | 0.0.9 | File upload parsing |
58
+ | **NumPy** | 1.26.4 | Numerical computing |
59
+ | **Pandas** | 2.2.2 | Data manipulation |
60
+
61
+ ## Frontend Libraries
62
+
63
+ | Technology | Version | Purpose |
64
+ |------------|---------|---------|
65
+ | **@tanstack/react-query** | 5.0.0 | Server state, caching, polling |
66
+ | **react-router-dom** | 6.20.0 | Client routing |
67
+ | **react-hot-toast** | 2.4.1 | Toast notifications |
68
+ | **react-dropzone** | 14.2.3 | File upload drag-and-drop |
69
+ | **axios** | 1.6.0 | HTTP client with retry |
70
+ | **recharts** | 2.10.0 | Charts (line, bar, pie/donut) |
71
+ | **lucide-react** | 0.290.0 | Icons |
72
+ | **autoprefixer** | 10.4.16 | CSS vendor prefixes |
73
+ | **postcss** | 8.4.31 | CSS processor |
74
+
75
+ ## Infrastructure / Deployment
76
+
77
+ | Technology | Purpose |
78
+ |------------|---------|
79
+ | **Docker** (multi-stage) | Build optimization |
80
+ | **Nginx (alpine)** | SPA serving + API proxy |
81
+ | **Railway** | API + worker cloud hosting |
82
+ | **Vercel** | Frontend SPA hosting |
83
+ | **HuggingFace Hub** | Model storage/pull |
84
+
85
+ ## Version Compatibility Matrix
86
+
87
+ | Package | Python | PyTorch | ONNX Runtime |
88
+ |---------|--------|---------|--------------|
89
+ | transformers 4.39.3 | 3.8+ | 1.11+ | — |
90
+ | optimum 1.19.0 | 3.8+ | 1.13+ | 1.15+ |
91
+ | onnxruntime 1.18.0 | 3.8+ | — | — |
92
+ | peft 0.10.0 | 3.8+ | 2.0+ | — |
93
+ | mlflow 2.13.0 | 3.8+ | — | — |
94
+ | dvc 3.51.1 | 3.8+ | — | — |
95
+ | evidently 0.4.30 | 3.8+ | — | — |
96
+ | fastapi 0.111.0 | 3.8+ | — | — |
97
+ | celery 5.4.0 | 3.8+ | — | — |
docs/architecture.md CHANGED
@@ -1,30 +1,280 @@
1
- # Architecture Diagrams
 
 
 
 
 
 
2
 
3
- ## 1. System Architecture
4
  ```mermaid
5
- graph TD
6
- A[React Dashboard] -->|REST API| B[FastAPI]
7
- B -->|sync| C[ABSA Pipeline]
8
- B -->|async| D[Celery Worker]
9
- C --> E[Stage 1: Aspect Extraction ONNX]
10
- C --> F[Stage 2: Sentiment Classifier ONNX]
11
- D --> G[PostgreSQL]
12
- B --> G
13
- H[Prometheus] -->|scrape /metrics| B
14
- I[Grafana] -->|query| H
15
- E --> J[HuggingFace Hub]
16
- F --> J
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  ```
18
 
19
- ## 2. ABSA Inference Pipeline
 
20
  ```mermaid
21
  graph LR
22
- A[Raw Review] --> B[Language Detection]
23
- B -->|EN| C[XLM-R Tokenizer]
24
- B -->|HI/Hinglish| D[IndicBERT Tokenizer]
25
- C --> E[Stage 1: BIO Tagger]
26
- D --> E
27
- E --> F[Extracted Aspects]
28
- F --> G[Stage 2: Sentiment Classifier]
29
- G --> H[aspect, sentiment, confidence]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Multilingual ABSA — Architecture Document
2
+
3
+ ## System Overview
4
+
5
+ Multilingual ABSA is a production-ready Aspect-Based Sentiment Analysis system supporting English, Hindi, and Hinglish. It extracts aspect terms from product reviews and classifies their sentiment using a dual-engine architecture: INT8-quantized ONNX models for production inference with a zero-download rule-based fallback.
6
+
7
+ ## High-Level Architecture
8
 
 
9
  ```mermaid
10
+ graph TB
11
+ Client[Client Browser / API Consumer]
12
+ Vercel[Vercel CDN]
13
+ Nginx[Nginx Reverse Proxy]
14
+ API[FastAPI Server]
15
+ Pipeline[ABSA Pipeline]
16
+ Lang[Language Detection]
17
+ Neural[ONNX Neural Engine<br/>INT8 Quantized]
18
+ Fallback[Rule-Based Engine<br/>140+ Aspect Keywords]
19
+ Celery[Celery Worker]
20
+ Redis[(Redis)]
21
+ PG[(PostgreSQL)]
22
+ Prom[Prometheus]
23
+ Graf[Grafana]
24
+ MLflow[(MLflow<br/>Experiment Tracking)]
25
+
26
+ Client --> Vercel
27
+ Vercel --> Nginx
28
+ Nginx --> API
29
+ API --> Pipeline
30
+ Pipeline --> Lang
31
+ Pipeline --> Neural
32
+ Pipeline --> Fallback
33
+ API --> Celery
34
+ Celery --> Redis
35
+ API --> PG
36
+ Prom -->|scrape /metrics| API
37
+ Graf --> Prom
38
+ MLflow --> Pipeline
39
  ```
40
 
41
+ ## Component Architecture
42
+
43
  ```mermaid
44
  graph LR
45
+ subgraph "Presentation Layer"
46
+ SPA[React SPA]
47
+ T_TAIL[TailwindCSS Theme]
48
+ RECH[Recharts Visualizations]
49
+ RQ[React Query]
50
+ end
51
+ subgraph "API Layer"
52
+ FAST[FastAPI]
53
+ CORS[CORS Middleware]
54
+ PROM[Prometheus Metrics]
55
+ PYD[Pydantic Schemas]
56
+ end
57
+ subgraph "Service Layer"
58
+ ABSA[ABSAPipeline]
59
+ LANG[LanguageService]
60
+ CEL[Celery Tasks]
61
+ end
62
+ subgraph "Data Layer"
63
+ SQLA[SQLAlchemy ORM]
64
+ PG[(PostgreSQL)]
65
+ RED[(Redis)]
66
+ end
67
+ subgraph "ML Layer"
68
+ ONNX_A[ORTModelFor<br/>TokenClassification]
69
+ ONNX_S[ORTModelFor<br/>SequenceClassification]
70
+ LEXICON[Aspect/Sentiment<br/>Lexicons]
71
+ end
72
+ subgraph "MLOps Layer"
73
+ MLF[MLflow Tracking]
74
+ DVC[DVC Versioning]
75
+ EVI[Evidently Drift]
76
+ end
77
+
78
+ SPA --> FAST
79
+ FAST --> CORS
80
+ FAST --> PROM
81
+ FAST --> PYD
82
+ FAST --> ABSA
83
+ FAST --> CEL
84
+ ABSA --> LANG
85
+ ABSA --> ONNX_A
86
+ ABSA --> ONNX_S
87
+ ABSA --> LEXICON
88
+ CEL --> RED
89
+ FAST --> SQLA
90
+ SQLA --> PG
91
+ ABSA --> MLF
92
  ```
93
+
94
+ ## Deployment Architecture
95
+
96
+ ```mermaid
97
+ graph TB
98
+ subgraph "Docker Compose (Local)"
99
+ DC_API[API Service<br/>uvicorn:8000]
100
+ DC_WORKER[Celery Worker]
101
+ DC_DASH[Dashboard<br/>Nginx:80]
102
+ DC_PG[PostgreSQL:5432]
103
+ DC_REDIS[Redis:6379]
104
+ DC_PROM[Prometheus:9090]
105
+ DC_GRAF[Grafana:3001]
106
+ end
107
+ subgraph "Railway (Production)"
108
+ RW_API[API Service<br/>$PORT]
109
+ RW_WORKER[Celery Worker]
110
+ RW_PG[PostgreSQL]
111
+ RW_REDIS[Redis]
112
+ end
113
+ subgraph "Vercel (Production)"
114
+ VC_DASH[React SPA]
115
+ VC_RW_ROUTE[rewrite /api/* -> Railway]
116
+ end
117
+
118
+ DC_DASH --> DC_API
119
+ DC_API --> DC_PG
120
+ DC_API --> DC_REDIS
121
+ DC_WORKER --> DC_REDIS
122
+ DC_WORKER --> DC_PG
123
+ DC_PROM -->|scrape| DC_API
124
+ DC_GRAF --> DC_PROM
125
+
126
+ VC_DASH --> VC_RW_ROUTE
127
+ VC_RW_ROUTE --> RW_API
128
+ RW_API --> RW_PG
129
+ RW_API --> RW_REDIS
130
+ RW_WORKER --> RW_REDIS
131
+ ```
132
+
133
+ ## ML Pipeline Architecture
134
+
135
+ ```mermaid
136
+ graph TB
137
+ subgraph "Data Ingestion"
138
+ RAW[Raw Data<br/>SemEval 2014<br/>Amazon Hindi]
139
+ FAST[f astText LID<br/>lid.176.ftz]
140
+ end
141
+ subgraph "Preprocessing"
142
+ CLEAN[Text Cleaning<br/>Lowercase, URLs, Mentions]
143
+ TRANS[Transliteration<br/>Devanagari→Roman]
144
+ LANG_DET[Language Detection<br/>EN / HI / Hinglish]
145
+ BIO[BIO Tagging<br/>B-ASP / I-ASP / O]
146
+ TOK[XLM-R Tokenizer<br/>SentencePiece 128 tokens]
147
+ end
148
+ subgraph "Training"
149
+ ATE[Aspect Extraction<br/>Token Classification<br/>3 labels]
150
+ ASC[Sentiment Classification<br/>Sequence Classification<br/>4 labels]
151
+ BASELINE[Baseline<br/>TF-IDF + LR]
152
+ QLORA[QLoRA<br/>4-bit + LoRA]
153
+ JOINT[Joint ABSA<br/>Shared Encoder<br/>2 Heads]
154
+ end
155
+ subgraph "Optimization"
156
+ ONNX_EXP[ONNX Export<br/>optimum-onnx]
157
+ QUANT[INT8 Quantization<br/>Dynamic]
158
+ end
159
+ subgraph "Production"
160
+ INFERENCE[Dual-Engine<br/>Inference]
161
+ BATCH[Batch Processing<br/>Celery Worker]
162
+ end
163
+ subgraph "Evaluation"
164
+ EVAL_METRICS[Macro-F1<br/>Per-class F1<br/>Confusion Matrix]
165
+ LATENCY[Latency Benchmark<br/>P95 < 300ms]
166
+ CROSS[Cross-Lingual Eval<br/>EN→HI Zero-Shot]
167
+ end
168
+
169
+ RAW --> CLEAN
170
+ FAST --> LANG_DET
171
+ CLEAN --> LANG_DET
172
+ LANG_DET --> TRANS
173
+ TRANS --> TOK
174
+ TOK --> ATE
175
+ TOK --> ASC
176
+ BIO --> ATE
177
+ ATE --> JOINT
178
+ ASC --> JOINT
179
+ ATE --> ONNX_EXP
180
+ ASC --> ONNX_EXP
181
+ ONNX_EXP --> QUANT
182
+ QUANT --> INFERENCE
183
+ INFERENCE --> BATCH
184
+ ATE --> EVAL_METRICS
185
+ ASC --> EVAL_METRICS
186
+ BASELINE --> EVAL_METRICS
187
+ INFERENCE --> LATENCY
188
+ JOINT --> CROSS
189
+ ```
190
+
191
+ ## Data Flow
192
+
193
+ ```mermaid
194
+ sequenceDiagram
195
+ participant C as Client
196
+ participant F as FastAPI
197
+ participant P as ABSAPipeline
198
+ participant L as LangService
199
+ participant N as ONNX Runtime
200
+ participant R as Rule Engine
201
+ participant D as PostgreSQL
202
+ participant M as Prometheus
203
+
204
+ C->>F: POST /predict {text, language?}
205
+ F->>P: pipeline.predict(text, lang)
206
+ P->>L: detect_language(text)
207
+ L-->>P: "en" | "hi" | "hinglish"
208
+ alt ONNX Models Available
209
+ P->>N: Tokenize text
210
+ N-->>P: Token IDs + Attention Mask
211
+ P->>N: ORTModelForTokenClassification
212
+ N-->>P: BIO Logits → Argmax → Spans
213
+ P->>N: Per-aspect ORTModelForSequenceClassification
214
+ N-->>P: Sentiment Logits → Softmax
215
+ else Rule-Based Fallback
216
+ P->>R: _extract_aspects(text)
217
+ R-->>P: [(aspect, start, end)]
218
+ P->>R: _score_sentence(context)
219
+ R-->>P: (pos_score, neg_score)
220
+ P->>R: _score_to_label(pos, neg)
221
+ R-->>P: (sentiment, confidence)
222
+ end
223
+ P-->>F: PredictionResponse
224
+ F->>D: INSERT Review + AspectResults
225
+ D-->>F: IDs
226
+ F-->>C: JSON Response
227
+ F->>M: Record latency + status
228
+ ```
229
+
230
+ ## Infrastructure
231
+
232
+ ```mermaid
233
+ graph TB
234
+ subgraph "Edge"
235
+ DNS[DNS: Vercel]
236
+ SSL[TLS Termination]
237
+ end
238
+ subgraph "Frontend Hosting"
239
+ FE[Vercel<br/>Static SPA]
240
+ FE_CDN[Global CDN]
241
+ end
242
+ subgraph "Backend Hosting"
243
+ BE[Railway<br/>Docker Container]
244
+ HEALTH[Health Check<br/>/health]
245
+ AUTO[Auto-Restart<br/>On Failure]
246
+ end
247
+ subgraph "Data Services"
248
+ PG[PostgreSQL<br/>Railway Managed]
249
+ RD[Redis<br/>Railway Managed]
250
+ end
251
+ subgraph "Observability"
252
+ PROM[Prometheus<br/>15-day Retention]
253
+ GRAF[Grafana<br/>Pre-provisioned Dashboard]
254
+ MLFLOW[MLflow<br/>SQLite Backend]
255
+ end
256
+
257
+ DNS --> SSL
258
+ SSL --> FE
259
+ FE --> FE_CDN
260
+ FE_CDN --> BE
261
+ BE --> HEALTH
262
+ BE --> AUTO
263
+ BE --> PG
264
+ BE --> RD
265
+ PROM -->|scrape| BE
266
+ GRAF --> PROM
267
+ ```
268
+
269
+ ## Design Decisions
270
+
271
+ | Decision | Rationale |
272
+ |----------|-----------|
273
+ | **Separate ONNX models** for ATE and ASC | Combined graph has dynamic-axis export fragility in optimum-onnx |
274
+ | **Rule-based fallback** with no downloads | Zero startup time, works offline, graceful degradation |
275
+ | **Lexicon-based sentiment** with negation handling | 3-word window for "not good" → negative reversal |
276
+ | **XLM-RoBERTa base** (not large) | 0.3B params fine-tunes on 16GB GPU, adequate cross-lingual transfer |
277
+ | **ONNX INT8 dynamic quantization** | 4x smaller, 4.6x faster than PyTorch with only 1% F1 drop |
278
+ | **SQLite for dev, PostgreSQL for prod** | Zero-config local dev, production-grade concurrency |
279
+ | **Celery for batch only** | Single-review inference is fast enough for synchronous response |
280
+ | **Mock data in dashboard charts** | Decoupled frontend/backend development; real integration deferred |