From 42bce022ada1294a9d217cf607733bffd90a86ea Mon Sep 17 00:00:00 2001 From: Lynn Delaere Date: Thu, 11 Dec 2025 13:36:12 +0000 Subject: [PATCH] Refactor architecture documentation for FastAPI backend, enhancing project description, scope, and component overview. --- docs/Architecture/Backend-Architecture.md | 228 +++++++++++++++++++ docs/Architecture/tijdelijke_arch_app.md | 264 ---------------------- 2 files changed, 228 insertions(+), 264 deletions(-) create mode 100644 docs/Architecture/Backend-Architecture.md delete mode 100644 docs/Architecture/tijdelijke_arch_app.md diff --git a/docs/Architecture/Backend-Architecture.md b/docs/Architecture/Backend-Architecture.md new file mode 100644 index 0000000..6846aa7 --- /dev/null +++ b/docs/Architecture/Backend-Architecture.md @@ -0,0 +1,228 @@ +# Software Architectuur: FastAPI Backend + +## Inleiding & Scope + +### Projectbeschrijving + +Het **Signapse** platform vertaalt gebarentaal naar tekst via een combinatie van computer vision, deep learning en een mobiele/webclient. De backend levert een uniforme **FastAPI**-laag die mediastreams van de client verwerkt, keypoints extraheert, AI-modellen aanroept en resultaten terugstuurt in realtime. + +### Scope van dit document + +Dit document beschrijft de **backendlaag** die de frontends aanstuurt: + +- FastAPI-applicatie, routers en lifecycle (`server/src/main.py`) +- Integratie met het `smart_gestures` AI-package +- Request/response-validatie via Pydantic schema's +- Endpoints (REST + WebSocket) inclusief doel en contracten +- Datastromen tussen client, keypoint-service en inferentie-modellen + +Voor details over de AI-modellen zelf, zie [AI-Architecture.md](./AI-Architecture.md). + +## Overzicht Architectuur + +### High-level backend-architectuur + +De backend bestaat uit een **gelaagde FastAPI-app**: + +1. **Transportlaag**: REST & WebSocket endpoints, CORS, versiebeheer. +2. **Routerlaag**: Logische modules (`root`, `keypoints`, `alphabet`, `gestures`, `ws`) met eigen prefixes en tags. +3. **Service/AI-laag**: Aanroepen naar `smart_gestures` (ASL/VGT feed-forward modellen + LSTM voor woorden) en MediaPipe detectors voor keypoints. +4. **Validatielaag**: Pydantic schema's die vorm en constraints afdwingen (aantal landmarks, sequentielengte, etc.). + +Alle zware objecten (MediaPipe detectors, PyTorch-modellen) worden **éénmalig geinitialiseerd** bij import zodat elk request enkel inference uitvoert. + +### Contextdiagram + +```mermaid +graph LR + subgraph Client["Client (Expo/React Native/Web)"] + CAM["CameraView & hooks
client/app/camera.tsx"] + APIClient["API helpers
client/lib/api.ts"] + end + + subgraph Backend["FastAPI backend
server/src/main.py"] + ROOT["Root & Health
routes/root.py"] + KP["Keypoints router
/keypoints/*"] + ALPHA["Alphabet router
/alphabet/{asl|vgt}/*"] + GEST["Gestures router
/gestures/lstm/*"] + WS["WebSocket /ws"] + end + + subgraph AI["AI & Feature laag"] + MP["MediaPipe Hands/Holistic
cv2 + mediapipe"] + ASL["smart_gestures.alphabet.ASLModel"] + VGT["smart_gestures.alphabet.VGTModel"] + LSTM["smart_gestures.gestures.LSTMModel"] + end + + CAM -->|Frames| APIClient + APIClient -->|Images| KP + KP -->|21/258 keypoints| APIClient + APIClient -->|Landmarks JSON| ALPHA + APIClient -->|Sequences (40×258)| GEST + ALPHA -->|REST response| APIClient + GEST -->|REST response| APIClient + WS -->|Realtime feedback| APIClient + + KP --> MP + ALPHA --> ASL + ALPHA --> VGT + GEST --> LSTM +``` + +## Kerncomponenten + +### FastAPI-applicatie & runtime + +- Entry point: `server/src/main.py` + - Stelt logging/waarschuwingen in en dwingt CPU-mode af voor MediaPipe/TensorFlow. + - Initialiseert `FastAPI` met titel, beschrijving en `__version__` (gelezen uit `pyproject.toml` via `const.py`). + - Registreert CORS (`allow_origins=["*"]`) zodat web en mobiele clients kunnen verbinden tijdens development. + - Includeert routers (`root`, `ws`, `alphabet`, `gestures`, `keypoints`). +- Deployment: `server/Dockerfile` bouwt een Python 3.12 container, installeert `smart-gestures` als lokaal package en start via `fastapi run src/main.py --host 0.0.0.0 --port 8000`. +- Runtime dependencies (uit `server/pyproject.toml`): + - `fastapi[standard]`, `uvicorn`, `pydantic` + - `smart-gestures==0.3.3` (bundelt getrainde modellen) + - Tools voor linting/typing (black, isort, mypy, flake8) voor kwaliteitsborging + +### Routerlagen + +| Router | Prefix | Belangrijkste verantwoordelijkheden | Files | +|--------|--------|-------------------------------------|-------| +| `root` | `/` | Health-check, versie-informatie, redirects | `routes/root.py` | +| `keypoints` | `/keypoints` | MediaPipe integratie voor hands & pose, beeldvalidatie | `routes/keypoints/__init__.py` | +| `alphabet` | `/alphabet` | ASL/VGT klassen & predictions | `routes/alphabet/asl_model`, `vgt_model` | +| `gestures` | `/gestures` | LSTM woordherkenning (klassen + predict) | `routes/gestures/lstm_model` | +| `ws` | `/ws` | Stateful WebSocket kanaal voor realtime feedback | `routes/ws/connection.py`, `websocket/connection_manager.py` | + +### Validatie & schema's + +- Alle requests/responses gebruiken Pydantic schema's (`server/src/schemas`). +- `PredictBody` dwingt exact 21 `HandLandmark` entries af (`NUM_POINTS`). +- `LSTMPredictBody` valideert 40 frames met `field_validator` en zet data om naar een `numpy`-array (`to_numpy_sequence()`). +- `HandKeypointsResponse`, `PoseLandmark` en `LSTMFrame` standaardiseren MediaPipe output zodat frontend en backend dezelfde structuur delen. +- `StatusResponse`, `ClassesResponse` en `LSTMClassesResponse` documenteren metadata voor automatische OpenAPI docs. + +### AI-integratie (smart_gestures) + +- De `smart_gestures` package wordt via een lokale path dependency geladen (`[tool.uv.sources]`). +- Modellen (`ASLModel`, `VGTModel`, `LSTMModel`) laden `.pth` bestanden bij import en bieden een `.predict(...)` API die `(naam, confidence)` teruggeeft. +- De routers converteren Pydantic objecten naar Python lijsten/dicts vóór inferentie. +- Normalisatie (translatie, scaling) en tensor-conversies zitten in het package zodat de backend puur orchestration doet. + +### WebSocket infrastructuur + +- `routes/ws/connection.py` exposeert `/ws` en gebruikt `ConnectionManager`. +- `ConnectionManager` houdt `active_connections: dict[str, WebSocket]` bij, accepteert clients, broadcast berichten en verwijdert clients bij disconnect. +- Dit kanaal is voorlopig bedoeld voor notificaties/experimentele realtime feedback maar de infrastructuur is klaar voor streaming predictions. + +### Foutafhandeling & observability + +- Inputfouten worden vertaald naar `HTTPException`: + - `400` bij lege bestanden of verkeerde landmark-aantallen. + - `404` als er geen hand/pose gevonden wordt. + - `500` bij onverwachte predictieproblemen (LSTM). +- Alle responses zijn JSON en beschreven in de OpenAPI-spec (`/docs` & `/redoc`). +- Logging van `absl`, `tensorflow` en `mediapipe` is onderdrukt in `main.py` om bruikbare logs over te houden voor backend events. + +## Endpointcatalogus + +### Root & status + +| Endpoint | Methode | Doel | Request | Response | +|----------|---------|------|---------|----------| +| `/` | GET | Redirect naar `/health` als startpunt voor monitoring. | - | `307` Redirect | +| `/health` | GET | Geeft API-versie terug (monitorable via load balancers). | - | `{ "version": "0.3.2" }` (`StatusResponse`) | + +### Keypoints (MediaPipe) + +| Endpoint | Methode | Doel | Request | Response | +|----------|---------|------|---------|----------| +| `/keypoints/` | POST | Backwards compat. endpoint dat direct redirect naar `/keypoints/hands`. | `multipart/form-data` met `image` | `307` Redirect | +| `/keypoints/hands` | POST | Extraheert **21 hand-landmarks** via MediaPipe Hands. | `multipart/form-data`, single frame (JPEG/PNG). Validatie op lege bestanden. | `HandKeypointsResponse` (21 × `{x,y,z}`) | +| `/keypoints/pose` | POST | Bouwt één `LSTMFrame` (pose + beide handen) voor sequential models. | `multipart/form-data` met frame. | `LSTMFrame` (33 pose + 2×21 hand landmarks). | + +Technische highlights: +- `prepare_image()` decodeert bytes → `numpy` → RGB. +- Persistente MediaPipe detectors vermijden init-overhead per request. + +### Alphabet (ASL/VGT) + +| Endpoint | Methode | Doel | Request | Response | +|----------|---------|------|---------|----------| +| `/alphabet/asl/classes` | GET | Geeft lijst van 35 ASL-klassen uit het model JSON. | - | `ClassesResponse` (`["a","b",...]`) | +| `/alphabet/asl/predict` | POST | Voorspelt ASL-letter/cijfer op basis van 21 landmarks. | `PredictBody` (`landmarks: list[HandLandmark]`) | `PredictResponse` (`prediction`, `confidence`) | +| `/alphabet/vgt/classes` | GET | Geeft lijst van VGT-klassen. | - | `ClassesResponse` | +| `/alphabet/vgt/predict` | POST | Voorspelt VGT-letter (wrist-to-middle normalisatie in model). | `PredictBody` | `PredictResponse` | + +Binnenkomende landmarks worden geconverteerd naar dicts met `.model_dump()` en vervolgens aan het betreffende model doorgegeven. Exceptions worden vertaald naar `400 Bad Request`. + +### Gestures (LSTM woordherkenning) + +| Endpoint | Methode | Doel | Request | Response | +|----------|---------|------|---------|----------| +| `/gestures/lstm/classes` | GET | Geeft mapping van gebaren → class-id (voor UI dropdowns). | - | `LSTMClassesResponse` (`{ "hallo": 3, ... }`) | +| `/gestures/lstm/predict` | POST | Voorspelt woorden uit sequenties van 40 frames. | `LSTMPredictBody` (`frames: list[LSTMFrame]`) | `LSTMPredictResponse` (`prediction`, `confidence`) | + +`LSTMPredictBody.to_numpy_sequence()` zet de frames om naar `numpy (40, 258)` voordat `model.predict()` wordt aangeroepen. Inputvalidatie onderscheidt tussen `ValueError` (400) en andere fouten (500). + +### WebSocket + +| Endpoint | Type | Doel | Payload | Gedrag | +|----------|------|------|---------|--------| +| `/ws` | WebSocket | Bi-directionele kanaal voor realtime feedback of multi-user sessies. | Vrij tekstprotocol (nu broadcast). | Iedere binnenkomende message wordt naar alle clients gestuurd; connect/disconnect events worden automatisch gebroadcast. | + +Gebruik `ConnectionManager` om toekomstige features zoals push-notificaties voor predictions te implementeren. + +## Datastromen & Sequenties + +### Alfabet-herkenning (ASL/VGT) + +1. **Frame capture** in `client/app/camera.tsx`. +2. **Upload frame** → `POST /keypoints/hands`; backend decodeert bytes, draait MediaPipe Hands en retourneert 21 landmarks. +3. **Client valideert** response en bouwt `PredictBody`. +4. **Client → /alphabet/{asl|vgt}/predict** met landmarks. +5. **Router** converteert landmarks naar lijst dicts, roept `ASLModel` of `VGTModel` aan: + - Normalisatie & tensorconversie gebeurt in `smart_gestures`. + - Softmax → confidence, mapping naar klasse. +6. **Response** (`prediction`, `confidence`) wordt in UI getoond en eventueel gebruikt om woorden op te bouwen. + +### Woord-herkenning (LSTM) + +1. **Sequencing**: client verzamelt 40 opeenvolgende frames en extraheert per frame pose + hand-landmarks (kan bouwstenen hergebruiken van `/keypoints/pose`). +2. **Request** naar `/gestures/lstm/predict` met `frames`. +3. **Validatie**: `LSTMPredictBody` checkt lengte en structuren en zet om naar `(40,258)` numpy-array. +4. **Inferentie**: `LSTMModel.predict()` draait normalisatie, voert forward pass, berekent confidence. +5. **Response** bevat `prediction` + `confidence`. Frontend toont woord + probabiliteit of annuleert als drempel niet gehaald wordt. + +### WebSocket feedback + +1. Client opent `ws:///ws` en ontvangt bevestiging. +2. Elke message (bv. "prediction: hallo") wordt gebroadcast naar alle aangesloten clients. +3. Disconnects worden opgeschoond door `ConnectionManager`. +4. Dankzij deze infrastructuur kan de backend later streaming predictions pushen zonder extra endpoints. + +## Client-integratie & Deployability + +- **Client code**: + - API-helper: `client/lib/api.ts` (fetch wrappers, JSON parsing, error handling). + - Camera workflow: `client/app/camera.tsx` en hooks bouwen de pipeline uit sectie hierboven. + - UI logica combineert alphabet predictions tot woorden of triggert LSTM-requests. +- **CORS & Security**: + - Alle origins zijn toegestaan tijdens development; productieconfig kan `allow_origins` beperken tot vertrouwde domeinen/apps. + - File uploads verlopen via HTTPS om fotogegevens te beschermen. +- **Versiebeheer & observability**: + - `/health` exposeert `__version__` zodat monitoring kan checken of de juiste release draait. + - `fastapi[standard]` levert automatische Swagger UI op `/docs` en ReDoc op `/redoc`, bruikbaar voor QA en integrators. +- **Containerisatie**: + - Dependencies (cv2, MediaPipe) vereisen systeemlibraries (`libgl1`, `libglib2.0-0`), vastgelegd in de Dockerfile. + - Environ-variabelen zoals `MPLCONFIGDIR` en `TMPDIR` worden ingesteld zodat MediaPipe en matplotlib kunnen schrijven in sandbox directories. + +--- + +**Document-informatie**: + +- **Versie**: 1.0 +- **Datum**: December 2025 +- **Auteurs**: Lynn Delaere +- **Contact**: Zie [GitHub repository](https://github.com/vives-project-xp/Signapse) diff --git a/docs/Architecture/tijdelijke_arch_app.md b/docs/Architecture/tijdelijke_arch_app.md deleted file mode 100644 index 05a9f40..0000000 --- a/docs/Architecture/tijdelijke_arch_app.md +++ /dev/null @@ -1,264 +0,0 @@ -## 4. Datastroom & Verwerking - -### 4.1 Alfabet-herkenning Pipeline (ASL/VGT) - -``` -┌─────────────┐ -│ Camera │ -│ Input │ -└──────┬──────┘ - │ Raw image (JPEG/PNG) - │ -┌──────▼──────────────────────────────────────────────┐ -│ Client Application (Web/Mobile) │ -│ - Capture image from camera │ -│ - Send via HTTP POST to /keypoints │ -└──────┬──────────────────────────────────────────────┘ - │ HTTP multipart/form-data - │ -┌──────▼──────────────────────────────────────────────┐ -│ Backend: /keypoints endpoint │ -│ File: server/src/routes/keypoints/__init__.py │ -│ │ -│ 1. Decode image bytes → numpy array │ -│ 2. Convert BGR → RGB │ -│ 3. MediaPipe Hands.process() │ -│ 4. Extract 21 landmarks per hand │ -│ 5. Return JSON: {landmarks: [...]} │ -└──────┬──────────────────────────────────────────────┘ - │ JSON response: 21 × {x, y, z} - │ -┌──────▼──────────────────────────────────────────────┐ -│ Client Application │ -│ - Receive landmarks JSON │ -│ - Send to /asl/predict OR /vgt/predict │ -└──────┬──────────────────────────────────────────────┘ - │ HTTP POST with landmarks - │ -┌──────▼──────────────────────────────────────────────┐ -│ Backend: /asl/predict of /vgt/predict endpoint │ -│ Files: server/src/routes/alphabet/{asl,vgt}_model/ │ -│ │ -│ 1. Validate input (21 landmarks) │ -│ 2. Convert to list of dicts │ -│ 3. Call model.predict(landmarks) │ -│ ├─ Normalize landmarks │ -│ ├─ Convert to PyTorch tensor │ -│ ├─ Model inference (forward pass) │ -│ ├─ Softmax → probabilities │ -│ └─ Argmax → predicted class │ -│ 4. Map class index → class name │ -│ 5. Return JSON: {prediction: "a"} │ -└──────┬──────────────────────────────────────────────┘ - │ JSON response: {prediction: string} - │ -┌──────▼──────────────────────────────────────────────┐ -│ Client Application │ -│ - Display predicted letter/number │ -│ - Update UI / build word │ -└─────────────────────────────────────────────────────┘ -``` - -### 4.2 Woord-herkenning Pipeline (LSTM) - -``` -┌─────────────┐ -│ Camera │ -│ Stream │ -└──────┬──────┘ - │ Video stream (continuous frames) - │ -┌──────▼──────────────────────────────────────────────┐ -│ Client Application │ -│ - Capture 40 consecutive frames │ -│ - For each frame: │ -│ ├─ Extract pose keypoints (33 × 4) │ -│ ├─ Extract left hand keypoints (21 × 3) │ -│ └─ Extract right hand keypoints (21 × 3) │ -│ - Build sequence: [frame1, frame2, ..., frame40] │ -│ - Each frame: 258 features │ -└──────┬──────────────────────────────────────────────┘ - │ Sequence: 40 × 258 numpy array - │ -┌──────▼──────────────────────────────────────────────┐ -│ Client Application │ -│ - Send sequence to /lstm/predict │ -└──────┬──────────────────────────────────────────────┘ - │ HTTP POST with sequence JSON - │ -┌──────▼──────────────────────────────────────────────┐ -│ Backend: /lstm/predict endpoint │ -│ File: server/src/routes/gestures/lstm_model/ │ -│ │ -│ 1. Parse JSON → numpy array (40 × 258) │ -│ 2. Validate sequence shape │ -│ 3. Call model.predict(sequence) │ -│ ├─ Normalize hand keypoints │ -│ ├─ Convert to PyTorch tensor │ -│ ├─ LSTM forward pass (processes sequence) │ -│ ├─ Extract final hidden state │ -│ ├─ Fully connected layer │ -│ ├─ Softmax → probabilities │ -│ ├─ Argmax → predicted class │ -│ └─ Max probability → confidence │ -│ 4. Map class index → word name │ -│ 5. Return JSON: {prediction: "hallo", │ -│ confidence: 0.95} │ -└──────┬──────────────────────────────────────────────┘ - │ JSON response: {prediction, confidence} - │ -┌──────▼──────────────────────────────────────────────┐ -│ Client Application │ -│ - Display recognized word + confidence │ -│ - Update UI / conversation log │ -└─────────────────────────────────────────────────────┘ -``` - -### 4.3 Belangrijke modules per stap - -| Stap | Module/Bestand | Verantwoordelijkheid | -|------|----------------|----------------------| -| Camera capture | `client/app/camera.tsx` | Frame capture, UI | -| Keypoint extractie | `server/src/routes/keypoints/__init__.py` | MediaPipe integratie | -| ASL inferentie | `notebooks/package/smart_gestures/alphabet/asl_model/model.py` | Model loading, normalisatie, predictie | -| VGT inferentie | `notebooks/package/smart_gestures/alphabet/vgt_model/model.py` | Model loading, normalisatie, predictie | -| LSTM inferentie | `notebooks/package/smart_gestures/gestures/lstm_model/model.py` | Sequentie-verwerking, LSTM predictie | -| API routing | `server/src/main.py` | FastAPI setup, CORS, endpoints registratie | -| Schemas | `server/src/schemas/` | Request/response validatie (Pydantic) | - ---- -### 5.2 Backend Stack - -| Technologie | Versie | Rol | -|------------|--------|-----| -| **FastAPI** | ≥0.104 | REST API framework | -| **Pydantic** | ≥2.5 | Data validatie + serialisatie | -| **Uvicorn** | ≥0.24 | ASGI server | - -#### FastAPI -- **Performance**: Async/await support, hoge throughput -- **Developer Experience**: Automatische OpenAPI docs, type hints -- **Validatie**: Pydantic integratie voor robuuste input validatie - -## 6. Integratie met de Rest van het Systeem - -### 6.1 API-architectuur - -De AI-modellen worden aangeboden via een **RESTful API** gebouwd met FastAPI. - -#### Endpoint-overzicht - -| Endpoint | Method | Functie | Input | Output | -|----------|--------|---------|-------|--------| -| `/keypoints` | POST | Extraheer hand landmarks | Image (multipart) | JSON: 21 landmarks | -| `/asl/classes` | GET | Lijst ASL klassen | - | JSON: array van 35 strings | -| `/asl/predict` | POST | ASL letter predictie | JSON: landmarks | JSON: predicted class | -| `/vgt/classes` | GET | Lijst VGT klassen | - | JSON: array van 26 strings | -| `/vgt/predict` | POST | VGT letter predictie | JSON: landmarks | JSON: predicted class | -| `/lstm/classes` | GET | Lijst LSTM woorden | - | JSON: gesture map | -| `/lstm/predict` | POST | Woord predictie | JSON: sequence | JSON: prediction + confidence | -| `/health` | GET | Server status | - | JSON: status + versie | - -#### API Documentatie -FastAPI genereert automatisch **interactieve API-documentatie**: -- **Swagger UI**: `http://localhost:8000/docs` -- **ReDoc**: `http://localhost:8000/redoc` - -### 6.2 Request/Response Flow - -```python -# Voorbeeld: ASL predictie request -POST /asl/predict -Content-Type: application/json - -{ - "landmarks": [ - {"x": 0.5, "y": 0.6, "z": 0.0}, - {"x": 0.52, "y": 0.58, "z": -0.02}, - ... // 21 landmarks totaal - ] -} - -# Response -{ - "prediction": "a" -} -``` - -```python -# Voorbeeld: LSTM predictie request -POST /lstm/predict -Content-Type: application/json - -{ - "sequence": [ - [0.1, 0.2, ..., 0.5], // Frame 1: 258 features - [0.1, 0.2, ..., 0.5], // Frame 2: 258 features - ... // 40 frames totaal - ] -} - -# Response -{ - "prediction": "hallo", - "confidence": 0.95 -} -``` - -### 6.3 Client-side Integratie - -#### Web Client (React/TypeScript) -- **Locatie**: `client/` directory -- **API calls**: `client/lib/api.ts` -- **Camera**: `client/app/camera.tsx` -- **Features**: - - Real-time camera feed - - Frame capture en upload naar `/keypoints` - - Landmarks verzamelen voor sequentie-opbouw - - Display van predictions - -#### Typische client-side flow: -1. **Capture frame** van camera (CameraView component) -2. **Upload naar `/keypoints`** → ontvang landmarks -3. **Upload landmarks naar `/asl/predict` of `/vgt/predict`** → ontvang letter -4. **Build word** door letters te combineren (useWordBuilder hook) -5. OF **Build sequence** van 40 frames → upload naar `/lstm/predict` → ontvang woord - -### 6.4 WebSocket Support - -Hoewel de huidige implementatie primair REST gebruikt, is er infrastructuur voor **WebSocket**-communicatie: -- **ConnectionManager**: `server/src/websocket/connection_manager.py` -- **Doel**: Real-time bidirectionele communicatie (toekomstige feature) -- **Gebruik**: Live streaming van predictions, multi-user sessies - -### 6.5 CORS & Security - -```python -# server/src/main.py -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], # Development: alle origins toegestaan - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) -``` - -**Productie**: Origins beperken tot specifieke domeinen (smart glasses app, web client). - -### 6.6 Error Handling - -De API implementeert **gestructureerde error responses**: -- **400 Bad Request**: Ongeldige input (bijv. verkeerde aantal landmarks) -- **404 Not Found**: Geen hand gedetecteerd in afbeelding -- **500 Internal Server Error**: Model inference errors - -Voorbeeld: -```json -{ - "detail": "Invalid input: Expected 21 landmarks, got 15" -} -``` - ---- -