Spaces:
Runtime error
Runtime error
File size: 24,714 Bytes
c35b57d | 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 | # Slides 14A & 14B β Backend & Deployment Architecture (Expanded 6-Slide Version)
All claims verified against: `api.py`, `core_ai.py`, `Dockerfile`, `requirements.txt`.
---
---
# PART A: BACKEND ARCHITECTURE (3 Slides)
---
## Slide 14A-1: Framework & Server Choice
### Slide Title:
> **Why FastAPI + Uvicorn?**
### Visual Layout:
**Full-width comparison table (centered on slide):**
| Criteria | Flask | Django | FastAPI β
|
|:---|:---|:---|:---|
| Request Handling | Synchronous (WSGI) | Synchronous (WSGI) | **Asynchronous (ASGI)** |
| Data Validation | Manual / WTForms | Django Forms | **Built-in Pydantic** |
| API Documentation | Manual / Swagger plugin | Django REST Framework | **Auto-generated Swagger** |
| Startup Overhead | Minimal | Heavy (ORM, admin, templates) | **Minimal** |
| Best For | Simple web apps | Full-stack web apps | **Pure REST APIs** |
**Below the table, a small block quote:**
> FastAPI delivers the performance of Node.js with the simplicity of Python.
*Caption: Figure 14A-1 β Framework comparison for API-only backend services.*
---
### π€ Speaking Script
> "Before diving into our backend, let me briefly explain why we chose FastAPI as our web framework.
>
> We evaluated three Python frameworks: Flask, Django, and FastAPI. Flask is lightweight but synchronous β each incoming request blocks a thread until it completes, which limits concurrency. Django is a full-stack framework that includes an ORM, an admin panel, and a template engine β all unnecessary overhead when building a pure REST API.
>
> We selected **FastAPI** because it is built specifically for API services. It runs on the **ASGI standard** using the **Uvicorn** server, which means it uses an asynchronous event loop to handle requests concurrently without blocking. This is critical for our use case, where a single analysis request may take over a second while the AI models process the text.
>
> FastAPI also gives us two things for free: **Pydantic-based input validation**, which rejects malformed requests before they reach our code, and **automatic Swagger documentation**, which generates a live, interactive API reference at the `/docs` endpoint. We didn't have to write a single line of documentation code."
---
### π‘ Jury Q&A
**Q: Can't Flask also handle async with libraries like gevent or asyncio?**
> "Technically yes, but it requires bolting on external libraries and rewriting request handlers. FastAPI is async-native β every route handler supports `async def` out of the box, and the underlying Starlette framework handles the event loop. It's a cleaner, more maintainable approach."
**Q: What is the difference between WSGI and ASGI?**
> "WSGI β Web Server Gateway Interface β processes one request per thread synchronously. ASGI β Asynchronous Server Gateway Interface β uses an event loop and can process many requests concurrently on a single thread. ASGI is especially beneficial when requests involve I/O-bound operations like database queries or API calls."
---
---
## Slide 14A-2: Request Pipeline & Validation
### Slide Title:
> **Request Pipeline: From Client to AI**
### Visual Layout:
**A horizontal flow diagram (left-to-right, full width):**
```
ββββββββββ ββββββββββββββ ββββββββββββββ ββββββββββββββ ββββββββββββ
β Client ββββββΆβ CORS ββββββΆβ Request ββββββΆβ Pydantic ββββββΆβ Route β
βRequest β β Middleware β β Logger β β Validation β β Handler β
ββββββββββ βallow_all(*)β βmethod,path β β42 ints, β β/analyze β
ββββββββββββββ βstatus, ms β βtextβ₯1 char β ββββββββββββ
ββββββββββββββ ββββββββββββββ
```
**Below the diagram, 3 compact code snippets side by side:**
**Snippet 1 β CORS Middleware:**
```python
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
)
```
**Snippet 2 β Request Logger (custom):**
```python
@app.middleware("http")
async def log_requests(request, call_next):
start = time.time()
response = await call_next(request)
ms = int((time.time()-start)*1000)
logger.info(f"{request.method} {request.url.path} {response.status_code} {ms}ms")
```
**Snippet 3 β Pydantic Schema:**
```python
class AnalyzeRequest(BaseModel):
text: str = Field(..., min_length=1)
survey_answers: list[int] = Field(..., min_items=42, max_items=42)
user_id: int | None = None
```
*Caption: Figure 14A-2 β Every request passes through 3 layers before reaching business logic.*
---
### π€ Speaking Script
> "Let me walk you through exactly what happens when a request hits our backend.
>
> Every HTTP request passes through **three middleware layers** before reaching our route handlers.
>
> First, the **CORS middleware**. Because our Flutter mobile app and web app send requests from different domains, the browser enforces Cross-Origin Resource Sharing restrictions. We configure the middleware to accept requests from all origins using `allow_origins=['*']`. This is intentional for our use case β the API is a public service consumed by multiple clients.
>
> Second, our **custom request logging middleware**. This intercepts every request, records the start time, waits for the response, then logs the HTTP method, URL path, response status code, and execution time in milliseconds. This gives us complete visibility into which endpoints are slow and which are failing. For example, we can see that the `/analyze` endpoint typically takes 1,200 milliseconds while `/checkin` takes under 50 milliseconds.
>
> Third, **Pydantic validation**. Each endpoint defines a strict schema. Our `AnalyzeRequest` schema, for instance, requires the `text` field to have at least one character and the `survey_answers` field to contain exactly 42 integers. If a client sends 41 answers or an empty text string, FastAPI automatically returns a **422 Unprocessable Entity** error with a detailed message explaining which field failed validation. Our AI models and database are never exposed to invalid input."
---
### π‘ Jury Q&A
**Q: Why `allow_origins=["*"]`? Isn't that a security risk?**
> "For a backend that serves a mobile app, CORS is irrelevant β mobile HTTP clients don't enforce CORS policies. CORS only applies to browser-based requests. Since we also have a web client, we set it to `*` for simplicity. In a production environment with sensitive data, we would whitelist specific domains."
**Q: How does the request logger help in production?**
> "It acts as our primary observability tool. If a user reports slow performance, we can check the server logs to see exactly which endpoint was called, how long it took, and what status code was returned. We log duration in milliseconds, so we can identify if the bottleneck is the AI model, the database, or the network."
**Q: What happens if someone sends survey_answers with values outside 0β3?**
> "The Pydantic schema enforces the array length but not individual value ranges at the schema level. However, the values are shifted by +1 and then passed through a StandardScaler that was fitted on the training data distribution. Out-of-range values would produce unusual scaled features, but the model would still return a probability distribution. For stricter enforcement, we could add per-element value constraints."
---
---
## Slide 14A-3: Database Architecture & Resilience
### Slide Title:
> **Database: Schema, Pooling & Graceful Degradation**
### Visual Layout:
**Left Column (50%) β Simplified schema diagram:**
```
βββββββββββββββββββββββ βββββββββββββββββββββββββββ
β users β β journal_entries β
β id (PK) β β id (PK) β
β name β β user_id (FK β users) β
β email (Unique, Idx)β β content (TEXT) β
β password (SHA-256) β β created_at β
β created_at β β updated_at β
βββββββββββββββββββββββ βββββββββββββββββββββββββββ
βββββββββββββββββββββββ βββββββββββββββββββββββββββ
β checkins β β analyses β
β id (PK) β β id (PK) β
β user_id (Idx) β β user_id (Idx) β
β mood, sleep, energyβ β clinical_scoring (JSON)β
β created_at β β text/survey/fused (JSONβ
βββββββββββββββββββββββ β severity, cause β
β suicidal_flag (BOOL) β
β text_input_hash (SHA) β
β created_at β
βββββββββββββββββββββββββββ
```
**Right Column (50%) β Bullet points:**
* **4 Tables:** `users`, `journal_entries`, `checkins`, `analyses`
* **Password Security:** SHA-256 hashing before storage
* **Composite Indexes:** `(user_id, created_at)` on both `analyses` and `checkins` for fast time-series queries
* **Deduplication:** `text_input_hash` (SHA-256 of journal text) prevents duplicate analysis records
* **Audit Trail:** `analyses` stores raw text, individual model scores (text + survey), fused scores, severity, cause, and suicidal flag β complete forensic record of every assessment
**Bottom strip β Resilience callout box:**
> π‘οΈ **Graceful Degradation:** If the database is unreachable at startup, the server starts anyway (8-second async timeout). If a DB write fails during analysis, the API still returns AI results to the user.
*Caption: Figure 14A-3 β PostgreSQL schema with resilience and audit trail design.*
---
### π€ Speaking Script
> "Now let's look at our database architecture.
>
> We use **Supabase PostgreSQL** as our cloud database, managed through **SQLAlchemy ORM**. The schema consists of four tables.
>
> The **users** table stores authentication data β name, email, and password. Passwords are hashed using **SHA-256** before storage. We never store plaintext passwords.
>
> The **journal_entries** table stores the user's journal text with timestamps. The **checkins** table stores daily mood, sleep, and energy metrics.
>
> The most important table is **analyses**. This is our complete audit trail. Every time a user submits an assessment, we store: the raw text input, a SHA-256 hash of that text for deduplication, the individual text model scores, the individual survey model scores, the fused scores, the detected severity level, the root cause category, and the suicidal flag. This means we can reconstruct exactly how any assessment was computed β which is essential for clinical credibility and debugging.
>
> We also define **composite indexes** on `(user_id, created_at)` for both the `analyses` and `checkins` tables. These indexes optimize the time-series queries that power our mood trend charts on the mobile app.
>
> Finally, our database layer is designed for **graceful degradation**. During server startup, table creation is wrapped in an 8-second async timeout. If the database is unreachable β for example, during a Supabase maintenance window β the server starts anyway and logs a warning. And during normal operation, if a database write fails after an analysis, we catch the exception and still return the AI results to the user. We prioritize the user experience over data persistence."
---
### π‘ Jury Q&A
**Q: Why SHA-256 for passwords instead of bcrypt or argon2?**
> "This is a valid critique. SHA-256 is a fast hash, which makes it more vulnerable to brute-force attacks compared to bcrypt, which is intentionally slow. For a production system handling sensitive health data, we would upgrade to bcrypt or argon2id. SHA-256 was chosen for this prototype to keep dependencies minimal, but we acknowledge it's not best practice for password storage."
**Q: Why store raw text in the analyses table? Isn't that a privacy concern?**
> "We store the raw text for two reasons: debugging and clinical audit. If the model produces an unexpected result, we need to see exactly what text was analyzed. In a production deployment subject to HIPAA or GDPR, we would encrypt the text_input column at rest and implement data retention policies. For our prototype, we prioritize diagnostic transparency."
**Q: What is the `text_input_hash` column used for?**
> "Deduplication. If a user accidentally submits the same journal text twice β for example by double-tapping the submit button β we can detect the duplicate by comparing the SHA-256 hash of the new text against existing hashes for that user. This prevents inflating the analysis history with identical records."
**Q: In the database schema, why are results (scores) stored as JSON instead of separate columns or tables?**
> "Storing scores directly as JSON (in `clinical_scoring`, `text_scores`, `survey_scores`, and `fused_scores`) provides three main advantages:
> 1. **Schema Flexibility:** If we add new mental health subscales, conditions, or dimensions to our machine learning models in the future, we don't have to run database migrations or alter the PostgreSQL table layout. The JSON columns naturally adapt to any new keys.
> 2. **Performance (Single-Row Retrieval):** We can retrieve the entire multi-dimensional assessment profile in a single database read without performing relational table JOINs across a separate scores table.
> 3. **Loose Coupling:** It keeps the database layer decoupled from the ML models. The database is a simple persistence store, and JSON maps directly to the Python dictionaries returned by the prediction pipeline. Since PostgreSQL natively supports JSON indexing and query path extraction (using `->>` operators), we retain full querying and filtering power."
---
---
---
# PART B: DEPLOYMENT ARCHITECTURE (3 Slides)
---
## Slide 14B-1: Client Deployment: Web (Netlify) & Mobile (APK)
### Slide Title:
> **Reaching Users Everywhere: Web & Mobile Platforms**
### Visual Layout:
**Two Feature Cards side-by-side (50% / 50% split):**
```
ββββββββββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββββββ
β π FLUTTER WEB APP β β π± ANDROID MOBILE APK β
ββββββββββββββββββββββββββββββββββββββββββββ€ ββββββββββββββββββββββββββββββββββββββββββββ€
β β’ Compiled using Flutter Web β β β’ Packaged into a ready-to-install β
β β’ Deployed on Netlify's high-speed CDN β β Android Application Package (APK) β
β β’ Zero-installation instant access β β β’ Runs natively on mobile devices β
β β’ Fully responsive across mobile, β β β’ Smooth touch interactions, local β
β tablet, and desktop browsers β β storage, and system integration β
ββββββββββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββββββ
```
**Key Integration Benefit:**
> π **Unified Codebase:** Both platforms share 100% of the same Dart/Flutter source code, ensuring consistent features, styling, and business logic across web and mobile.
*Caption: Figure 14B-1 β Multi-platform client deployment architecture.*
---
### π€ Speaking Script
> "To make SafeSpace as accessible as possible, we deploy our frontend across two distinct platforms from a single codebase.
>
> First, we compiled the application using the Flutter Web engine. We deployed the resulting web folder to **Netlify**, utilizing their global content delivery network. This allows users to access the full mental health platform instantly on any browser without downloading an app.
>
> Second, we packaged the application into a native **Android Mobile APK**. This version runs natively on Android devices, offering a smoother user interface, touch gestures, and local device storage.
>
> Sharing a single codebase guarantees that whether a user logs in via web or mobile, they get the exact same experience, theme modes, Arabic support, and mental wellness tools."
---
### π‘ Jury Q&A
**Q: Why host the web build on Netlify instead of hosting it directly on Hugging Face alongside the API?**
> "Separating the frontend and backend is a modern web development best practice. Netlify is specialized for static frontends, offering lightning-fast loading speeds, high availability, and global caching close to the user. Hugging Face is dedicated to running our heavy AI models and Python backend, ensuring both systems can scale and operate independently without resource conflict."
**Q: Are there any differences in functionality between the mobile APK and the Web app?**
> "No, the features are completely identical. Both the APK and the Web app communicate with the same hosted backend API and Supabase database. The only difference is the deployment medium: Netlify provides immediate browser-based access, while the APK offers a native app experience on mobile devices."
---
---
## Slide 14B-2: Backend Hosting: Containerization & Cloud Deployment
### Slide Title:
> **Automated & Zero-Maintenance Backend Deployment**
### Visual Layout:
**A simplified deployment workflow diagram (horizontal):**
```
ββββββββββββ ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ
βDeveloper ββββββΆβ Git Push to ββββββΆβ Auto-Rebuild via ββββββΆβ Public API β
β Machine β β Hugging Faceβ β Docker Container β β 15+ Endpointsβ
ββββββββββββ ββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ
```
**Core Backend Highlights:**
* **Docker Containerization:** Packages the Python FastAPI code, PyTorch models, and all system dependencies together so it runs exactly the same in any environment.
* **Hugging Face Spaces Hosting:** Automatically triggers a fresh build and redeployment every time new code is pushed to the repository.
* **Public API Endpoints:** Over 15 hosted REST API endpoints serve the client app, handling authentication, assessments, check-ins, journal entries, and model analysis.
* **DevOps Simplification:** Eliminates the need for manually setting up CI/CD pipelines, SSL certificates, or database connectors.
*Caption: Figure 14B-2 β Automated containerized hosting pipeline.*
---
### π€ Speaking Script
> "Instead of managing physical servers or configuring complex cloud virtual machines, we containerized our backend using Docker and deployed it on Hugging Face Spaces.
>
> Whenever we push code changes to the repository, Hugging Face automatically detects our configuration, builds a new Docker container, and redeploys the live application.
>
> This setup exposes over 15 public API endpoints that securely handle user authentication, daily check-ins, journal submissions, and the wellness recommendation engine. This zero-maintenance DevOps approach allowed us to focus completely on refining the application logic rather than managing server infrastructure."
---
### π‘ Jury Q&A
**Q: What is the main benefit of containerizing the backend with Docker?**
> "Machine learning applications have complex system dependencies like PyTorch, Transformers, and scientific libraries. Docker packages the exact operating system, library versions, and model weights into a single container. This ensures that the backend runs exactly the same on our local development machine as it does on the cloud server, eliminating any configuration or library version errors."
**Q: You mentioned 15+ API endpoints. What do they do?**
> "The API endpoints handle all core business logic: user registration and login, adding and updating goals, saving daily check-in logs (mood, sleep, and energy), storing private journal entries, requesting text/DASS assessment evaluations, and retrieving personalized recommendations. The client apps communicate with these endpoints entirely via secure HTTPS JSON requests."
---
---
## Slide 14B-3: Performance & User Experience Optimization
### Slide Title:
> **Optimizing Response Times for a Seamless User Experience**
### Visual Layout:
**Before/After Optimization Comparison:**
```
β UNOPTIMIZED BACKEND β
OPTIMIZED BACKEND
ββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββ
β β’ Loading models per request β β β’ Pre-cached AI models in RAM β
β β’ Cold starts on model weight β β β’ Gradient-free calculations β
β β’ High processing overhead β β β’ Truncated text inputs β
β β β β
β β± Response time: ~8.0 seconds β β β‘ Response time: <1.5 seconds β
ββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββ
```
**Key User Benefits:**
* **Instant Feedback:** Users receive immediate results after writing down their daily thoughts or completing wellness questionnaires.
* **Responsive Flow:** Short response latency ensures a fluid and natural conversation flow when interacting with the wellness helper.
* **Data Integrity:** Reliable backend processing guarantees that user input is securely analyzed and saved without timeout issues.
*Caption: Figure 14B-3 β Latency optimization from 8s to under 1.5s.*
---
### π€ Speaking Script
> "A key priority of our system design was providing a fast, responsive user experience.
>
> Initially, loading deep learning models, tokenizers, and weights on every request took around **8 seconds**, which is far too slow for a fluid interactive experience.
>
> We optimized this by keeping our models pre-cached in system memory so they only load once on startup. We also disabled gradient computations during prediction and limited the maximum text input size to fit typical journal entry lengths.
>
> These optimizations brought our response latency down from **8 seconds to under 1.5 seconds**. This ensures that users receive instant wellness insights and predictions without any frustrating delays."
---
### π‘ Jury Q&A
**Q: Why is a response time under 1.5 seconds critical for this type of application?**
> "When users are sharing sensitive feelings, a fast response is vital for maintaining user engagement and trust. If an app hangs for 8 seconds after a journal entry is submitted, users might think it has crashed or feel anxious about the delay. Keeping latency low ensures a seamless, supportive, and highly responsive user experience."
**Q: How does this optimization affect your server resources?**
> "By caching the models in memory and avoiding the overhead of loading them from disk on every request, we greatly reduce CPU utilization. Disabling gradients also minimizes memory usage during predictions, allowing our server to handle multiple concurrent users efficiently with minimal resources."
|