IDKHowToCodeFr commited on
Commit
3b532f8
·
verified ·
1 Parent(s): 359459d

Upload folder using huggingface_hub

Browse files
ARCHITECTURE.md CHANGED
@@ -2,57 +2,76 @@
2
 
3
  HeartFlow OS is a distributed Edge AI platform. It bridges the gap between high-level Python MLOps and low-level embedded systems (ESP32/Arduino) by orchestrating live telemetry, automated model training, and zero-dependency C transpilation.
4
 
5
- ## System Topology
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  ```mermaid
8
  graph TD
9
- A[Patient Sensors / Simulator] -->|WebSocket: 60Hz| B(FastAPI Backend)
10
- B <-->|Logs & State| C[(SQLite DB)]
11
- B <-->|Inference| D[Scikit-Learn Ensemble]
12
- B -->|Transpilation| E{AST Compiler}
13
- E -->|Generates model.h| F[PlatformIO Firmware]
14
- F -->|Flashed to| G[ESP32 Edge Device]
15
-
16
- H[React / Next.js UI] <-->|WebSocket Stream| B
17
- H <-->|REST API| B
18
-
19
- I[CSV Dataset] -->|Upload| H
20
- H -->|/retrain endpoint| B
21
- B -->|Train & Evaluate F1| D
22
  ```
23
 
24
- ## Directory Structure
25
-
26
- | Directory / File | Purpose |
27
- | :--- | :--- |
28
- | **`backend/`** | Python FastAPI application. |
29
- | `backend/main.py` | WebSocket router, dependency injection, and REST endpoints. |
30
- | `backend/models.py` | MLOps script: Loads dataset, trains ensemble, checks F1 score against `registry.json`, and saves `.pkl` files on success. |
31
- | `backend/export.py` | AST Compiler: Parses Python decision trees into `if/else` C logic. Applies INT8 quantization. |
32
- | `backend/ensemble.py` | Soft-voting runtime inference engine. |
33
- | `backend/test_c_export.py` | Cross-language integrity test ensuring Python models and C-code outputs match. |
34
- | **`frontend/`** | Next.js 16 Application. |
35
- | `frontend/src/app/layout.tsx`| Root layout containing the global telemetry socket context and universal footer. |
36
- | `frontend/src/context/` | Contains `TelemetryContext.tsx` which manages the WebSocket stream with exponential backoff. |
37
- | **`firmware/`** | PlatformIO C++ Project for edge microcontrollers. |
38
- | `firmware/platformio.ini` | Build configuration for `esp32dev` with `-O3` optimization flags. |
39
- | `firmware/src/main.cpp` | Main Arduino wrapper that includes the generated `model.h` and executes `predict()`. |
40
- | **`docker-compose.yml`** | Full-stack orchestration configuration. |
41
-
42
- ## Data Flow: Background Retraining (MLOps)
43
-
44
- 1. User uploads a CSV via the **MLOps UI**.
45
- 2. FastAPI validates the schema and appends it to `patient_dataset.csv`.
46
- 3. A background task invokes `train_models()`.
47
- 4. A new Random Forest is trained. Its F1-score is evaluated against a test set.
48
- 5. If the new score is $\ge$ the `active_version` score in `registry.json`, the `.pkl` files are overwritten and the live Ensemble model is hot-reloaded.
49
- 6. If the new score degrades, the model is rejected (Automatic Rollback).
50
-
51
- ## Data Flow: Edge Compilation (TinyML)
52
-
53
- 1. User requests an export via the **Edge Compiler UI** (`/export_tinyml`).
54
- 2. `export.py` loads the active `.pkl` models.
55
- 3. The Scikit-Learn tree object is recursively traversed.
56
- 4. Leaf nodes are identified and converted into raw `printf` or standard `return` C-strings.
57
- 5. If `quantize=True`, 64-bit float thresholds are mapped to 8-bit integers.
58
- 6. A self-contained `model.h` file is returned, containing a single `int predict(float features[])` function. No dynamic memory (`malloc`/`free`) is used, guaranteeing memory safety on embedded controllers.
 
2
 
3
  HeartFlow OS is a distributed Edge AI platform. It bridges the gap between high-level Python MLOps and low-level embedded systems (ESP32/Arduino) by orchestrating live telemetry, automated model training, and zero-dependency C transpilation.
4
 
5
+ ## Core Flow Diagrams
6
+
7
+ ### 1. Data Cleaning & Feature Selection Pipeline
8
+
9
+ ```mermaid
10
+ graph TD
11
+ A[Raw CSV Dataset] --> B{Drop Redundant Columns}
12
+ B -->|Remove| C[Patient Number, Alert Flags]
13
+ B --> D[Sanitize Encodings]
14
+ D -->|Fix \ufffd -> °| E[Feature Engineering]
15
+ E -->|Create Risk_Severity| F[Risk_Severity = HR > 105 + SpO2 < 94]
16
+ F --> G[Imputation]
17
+ G -->|SimpleImputer: Mean| H[Scaling]
18
+ H -->|StandardScaler| I[Clean Feature Matrix]
19
+ I --> J[Train / Test Split 80:20]
20
+ ```
21
+
22
+ ### 2. MLOps Background Retraining
23
+
24
+ ```mermaid
25
+ graph TD
26
+ A[New CSV Upload via UI] --> B(FastAPI /retrain)
27
+ B --> C[Background Thread: train_models]
28
+ C --> D[Preprocess Data & Fit Transformers]
29
+ D --> E[Train 5 Models: KNN, SVM, LogReg, RF, MLP]
30
+ E --> F[Calculate Weighted F1 Score]
31
+ F --> G{Is F1 > Active Version?}
32
+ G -->|Yes| H[Save .pkl files, Update registry.json]
33
+ G -->|No| I[Rollback, Discard Models]
34
+ H --> J[Hot-Reload Live Inference Pipeline]
35
+ ```
36
+
37
+ ### 3. Edge Compilation (TinyML)
38
 
39
  ```mermaid
40
  graph TD
41
+ A[Export Request /export_tinyml] --> B[Load Active .pkl Random Forest]
42
+ B --> C[Traverse AST Trees Recursively]
43
+ C --> D{Quantization Enabled?}
44
+ D -->|Yes| E[Map Float64 to INT8 thresholds]
45
+ D -->|No| F[Keep Float32 thresholds]
46
+ E --> G[Generate C Header: model.h]
47
+ F --> G
48
+ G -->|Zero-Malloc| H[PlatformIO / ESP32 Compile]
 
 
 
 
 
49
  ```
50
 
51
+ ## Detailed Explanations
52
+
53
+ ### Data Cleaning and Feature Selection
54
+ Raw patient data is noisy and often contains missing or invalid readings. The preprocessing pipeline (`backend/preprocessing.py`) handles this systematically:
55
+ 1. **Dimensionality Reduction**: Redundant or target-leakage columns (like `Heart Rate Alert` or `Patient Number`) are dropped to prevent the model from overfitting on administrative flags.
56
+ 2. **Encoding Fixes**: Unicode corruption (e.g., `\ufffd` instead of `°`) is sanitized.
57
+ 3. **Imputation**: Missing sensor readings are populated using a `SimpleImputer(strategy='mean')`. The imputer is fitted on the training set and serialized to `imputer.pkl` to prevent data leakage during live inference.
58
+ 4. **Feature Engineering**: A custom `Risk_Severity` feature is synthesized by combining critical thresholds: `(Heart Rate > 105) + (SpO2 < 94)`. This gives the decision trees a powerful non-linear hint.
59
+ 5. **Standardization**: All continuous features are scaled to a standard normal distribution via `StandardScaler`, ensuring distance-based algorithms (like KNN and SVM) compute correctly.
60
+
61
+ ### Intelligence Pipeline (Ensemble)
62
+ HeartFlow doesn't rely on a single algorithm. It trains five distinct models:
63
+ - **K-Nearest Neighbors (KNN)**
64
+ - **Support Vector Machine (SVM)**
65
+ - **Logistic Regression (LogReg)**
66
+ - **Random Forest (RF)**
67
+ - **Multilayer Perceptron (MLP Neural Network)**
68
+
69
+ During live telemetry inference (`backend/ensemble.py`), the system aggregates the probability vectors from all five models. It performs a **soft-vote**, returning the highest confidence average as the final diagnosis.
70
+
71
+ ### Fault-Tolerant Retraining (MLOps)
72
+ When a clinician uploads a new batch of data via the `/mlops` UI, the system trains the entire ensemble in a background thread without dropping live WebSocket connections.
73
+ It evaluates the newly trained models against a 20% holdout test set. If the new `weighted F1-Score` is higher than the `active_version` tracked in `registry.json`, the `.pkl` files are hot-swapped. If the score degrades, the new models are destroyed (Automated Rollback).
74
+
75
+ ### Edge Transpilation
76
+ Running Python on an ESP32 is too heavy. The `backend/export.py` script traverses the AST (Abstract Syntax Tree) of the trained Scikit-Learn Random Forest and writes pure, `if/else` C++ code into a `model.h` file.
77
+ To shrink the firmware size by 75%, it applies **INT8 Quantization**, scaling floating-point sensor thresholds into 8-bit integers. The resulting inference function uses zero dynamic memory (`malloc`/`free`), ensuring the microcontroller never crashes from heap fragmentation.
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -15,8 +15,8 @@ pinned: false
15
  <a href="https://huggingface.co/spaces/IDKHowToCodeFR/HEARTFLOW_OS" target="_blank">
16
  <img src="https://img.shields.io/badge/🤗_HuggingFace-Live_Demo-FFD21E.svg?style=for-the-badge" alt="Hugging Face Space" />
17
  </a>
18
- <a href="https://heartflow-os.vercel.app" target="_blank">
19
- <img src="https://img.shields.io/badge/🌐_Website-Live_App-black.svg?style=for-the-badge&logo=vercel" alt="Live Website" />
20
  </a>
21
  </p>
22
 
 
15
  <a href="https://huggingface.co/spaces/IDKHowToCodeFR/HEARTFLOW_OS" target="_blank">
16
  <img src="https://img.shields.io/badge/🤗_HuggingFace-Live_Demo-FFD21E.svg?style=for-the-badge" alt="Hugging Face Space" />
17
  </a>
18
+ <a href="https://idkhowtocodefr.github.io/HEARTFLOW_OS" target="_blank">
19
+ <img src="https://img.shields.io/badge/🌐_Website-Live_App-black.svg?style=for-the-badge&logo=githubpages" alt="Live Website" />
20
  </a>
21
  </p>
22
 
frontend/src/app/architecture/page.tsx CHANGED
@@ -96,6 +96,59 @@ export default function Architecture() {
96
 
97
  </div>
98
  </motion.div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  </motion.div>
100
  </main>
101
  );
 
96
 
97
  </div>
98
  </motion.div>
99
+
100
+ {/* Detailed Specifications */}
101
+ <motion.div variants={staggerContainer} initial="hidden" animate="show" className="w-full flex flex-col gap-8">
102
+
103
+ <motion.div variants={fadeUp} className="border-t-4 border-ink pt-8">
104
+ <h2 className="text-[20px] md:text-[24px] font-sans font-black tracking-[-0.02em] uppercase text-ink mb-6">
105
+ [ SPEC_01 ] Data Sanitization & Feature Engineering
106
+ </h2>
107
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
108
+ <div className="bg-white border-2 border-ink p-6">
109
+ <h3 className="text-[12px] text-hazard font-bold tracking-[0.1em] mb-4 uppercase">/// Pipeline_Execution</h3>
110
+ <p className="text-[13px] md:text-[14px] text-slate leading-relaxed uppercase mb-4">
111
+ Raw telemetry is hostile. The ingestion script aggressively drops redundant alert flags to prevent target-leakage. Broken unicode encodings from edge sensors are patched on the fly.
112
+ </p>
113
+ <div className="font-mono text-[10px] md:text-[11px] bg-ink text-canvas-cream p-4 border-l-4 border-hazard">
114
+ <span className="text-slate">01</span> DROP: 'Heart Rate Alert', 'Patient Number'<br/>
115
+ <span className="text-slate">02</span> PATCH: '\ufffd' -&gt; '°'<br/>
116
+ <span className="text-slate">03</span> ENCODE: LabelEncoder(Predicted Disease)
117
+ </div>
118
+ </div>
119
+ <div className="bg-white border-2 border-ink p-6">
120
+ <h3 className="text-[12px] text-hazard font-bold tracking-[0.1em] mb-4 uppercase">/// Feature_Synthesis</h3>
121
+ <p className="text-[13px] md:text-[14px] text-slate leading-relaxed uppercase mb-4">
122
+ Missing sensor drops are repaired using a fitted <code className="bg-canvas-cream px-1 text-ink">SimpleImputer(mean)</code>. We inject a non-linear hint directly into the AST: <code className="bg-canvas-cream px-1 text-ink">Risk_Severity</code>. All floats are strictly normalized via <code className="bg-canvas-cream px-1 text-ink">StandardScaler</code>.
123
+ </p>
124
+ <div className="font-mono text-[10px] md:text-[11px] bg-ink text-canvas-cream p-4 border-l-4 border-hazard">
125
+ Risk_Severity = (HR &gt; 105) + (SpO2 &lt; 94)<br/>
126
+ Imputer.fit_transform(continuous_features)<br/>
127
+ Scaler.fit_transform(continuous_features)
128
+ </div>
129
+ </div>
130
+ </div>
131
+ </motion.div>
132
+
133
+ <motion.div variants={fadeUp} className="border-t-4 border-ink pt-8">
134
+ <h2 className="text-[20px] md:text-[24px] font-sans font-black tracking-[-0.02em] uppercase text-ink mb-6">
135
+ [ SPEC_02 ] Soft-Voting Ensemble & MLOps
136
+ </h2>
137
+ <div className="bg-white border-2 border-ink p-6">
138
+ <p className="text-[13px] md:text-[14px] text-slate leading-relaxed uppercase mb-6 max-w-3xl">
139
+ Single-model inference is clinically insufficient. HeartFlow_OS aggregates probability distributions from 5 disparate algorithms: <strong>KNN, SVM, LogReg, Random Forest, and a Neural Network (MLP)</strong>.
140
+ <br/><br/>
141
+ When a clinician uploads a new batch dataset, the API spawns a background thread. It retrains all 5 models, calculates the weighted F1-Score against a 20% holdout, and checks <code className="bg-canvas-cream px-1 text-ink">registry.json</code>. If the new score degrades, the batch is destroyed. If it improves, the active `.pkl` weights are hot-swapped globally without dropping WebSocket streams.
142
+ </p>
143
+ <div className="flex flex-col md:flex-row gap-4 items-center justify-start text-[12px] font-bold">
144
+ <div className="bg-ink text-white px-4 py-2">F1 SCORE &gt; ACTIVE_V1</div>
145
+ <div className="text-ink">━━▶</div>
146
+ <div className="bg-hazard text-white px-4 py-2 border-2 border-hazard shadow-[4px_4px_0px_0px_rgba(10,10,10,1)]">HOT_SWAP_MODELS()</div>
147
+ </div>
148
+ </div>
149
+ </motion.div>
150
+
151
+ </motion.div>
152
  </motion.div>
153
  </main>
154
  );
frontend/src/app/layout.tsx CHANGED
@@ -57,7 +57,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
57
  </div>
58
  <div className="flex flex-wrap items-center justify-center gap-4 md:gap-8">
59
  <a href="https://huggingface.co/spaces/IDKHowToCodeFR/HEARTFLOW_OS" target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">HUGGING_FACE</a>
60
- <a href="https://heartflow-os.vercel.app" target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">LIVE_APP</a>
61
  <Link href="/architecture" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">ARCHITECTURE.MD</Link>
62
  <a href={`${process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"}/docs`} target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">API_DOCS</a>
63
  <a href="https://github.com/IDKHowToCodeFR/HEARTFLOW_OS" target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">GITHUB_REPO</a>
 
57
  </div>
58
  <div className="flex flex-wrap items-center justify-center gap-4 md:gap-8">
59
  <a href="https://huggingface.co/spaces/IDKHowToCodeFR/HEARTFLOW_OS" target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">HUGGING_FACE</a>
60
+ <a href="https://idkhowtocodefr.github.io/HEARTFLOW_OS" target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">LIVE_APP</a>
61
  <Link href="/architecture" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">ARCHITECTURE.MD</Link>
62
  <a href={`${process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000"}/docs`} target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">API_DOCS</a>
63
  <a href="https://github.com/IDKHowToCodeFR/HEARTFLOW_OS" target="_blank" rel="noopener noreferrer" className="text-[12px] font-bold tracking-[0.05em] uppercase text-ink hover:text-hazard transition-colors">GITHUB_REPO</a>