Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse files- ARCHITECTURE.md +68 -49
- README.md +2 -2
- frontend/src/app/architecture/page.tsx +53 -0
- frontend/src/app/layout.tsx +1 -1
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 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
```mermaid
|
| 8 |
graph TD
|
| 9 |
-
A[
|
| 10 |
-
B
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 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 |
-
##
|
| 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 |
-
## 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://
|
| 19 |
-
<img src="https://img.shields.io/badge/🌐_Website-Live_App-black.svg?style=for-the-badge&logo=
|
| 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' -> '°'<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 > 105) + (SpO2 < 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 > 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://
|
| 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>
|