Spaces:
Sleeping
Sleeping
Commit Β·
ee101c4
1
Parent(s): eff1d8c
..
Browse files- ARCHITECTURE_DIAGRAM.md +0 -294
- CLOUD_INTEGRATION_SUMMARY.md +0 -152
- CLOUD_MLOPS_SETUP.md +0 -457
- DEPLOY_TO_HF.md +0 -352
- Dockerfile +2 -9
- HF_SECRETS_SETUP.md +0 -238
- app.py +1 -25
- cloud_config.py +0 -102
- monitoring/evidently_monitor.py +0 -242
- prefect_flows/deploy_schedule.py +0 -26
- prefect_flows/drift_monitoring_flow.py +0 -96
- prefect_flows/training_flow.py +0 -85
- requirements.txt +0 -4
- setup_cloud_mlops.py +0 -151
- startup.sh +0 -66
- trigger_prefect_training.py +0 -14
ARCHITECTURE_DIAGRAM.md
DELETED
|
@@ -1,294 +0,0 @@
|
|
| 1 |
-
# HuggingFace + Cloud MLOps - Complete Workflow
|
| 2 |
-
|
| 3 |
-
## Visual Architecture
|
| 4 |
-
|
| 5 |
-
```
|
| 6 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 7 |
-
β DEVELOPER MACHINE β
|
| 8 |
-
β β
|
| 9 |
-
β 1. Get Prefect API Key β
|
| 10 |
-
β https://app.prefect.cloud/ β Profile β API Keys β
|
| 11 |
-
β β
|
| 12 |
-
β 2. Run Deployment Script β
|
| 13 |
-
β python prepare_hf_deployment.py β
|
| 14 |
-
β ββ Adds files to git β
|
| 15 |
-
β ββ Commits changes β
|
| 16 |
-
β ββ Shows secret configuration steps β
|
| 17 |
-
β β
|
| 18 |
-
β 3. Configure HuggingFace Secrets β
|
| 19 |
-
β https://huggingface.co/spaces/kshitijk20/nss/settings β
|
| 20 |
-
β Add: PREFECT_API_KEY = pnu_xxxxx β
|
| 21 |
-
β β
|
| 22 |
-
β 4. Push to HuggingFace β
|
| 23 |
-
β git push hf main β
|
| 24 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 25 |
-
β
|
| 26 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 27 |
-
β HUGGINGFACE SPACES (Build) β
|
| 28 |
-
β β
|
| 29 |
-
β Docker Build Process: β
|
| 30 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 31 |
-
β β 1. FROM python:3.13-slim β β
|
| 32 |
-
β β 2. COPY requirements.txt β pip install β β
|
| 33 |
-
β β β’ prefect>=2.14.0 β β
|
| 34 |
-
β β β’ evidently>=0.4.0 β β
|
| 35 |
-
β β β’ fastapi, uvicorn, scikit-learn β β
|
| 36 |
-
β β 3. COPY application code β β
|
| 37 |
-
β β β’ app.py, startup.sh, cloud_config.py β β
|
| 38 |
-
β β β’ prefect_flows/, monitoring/ β β
|
| 39 |
-
β β β’ final_model/model.pkl, preprocessor.pkl β β
|
| 40 |
-
β β 4. RUN chmod +x startup.sh β β
|
| 41 |
-
β β 5. RUN python load_data_to_sqlite.py β β
|
| 42 |
-
β β 6. RUN python cloud_config.py (check config) β β
|
| 43 |
-
β β 7. ENTRYPOINT ["./startup.sh"] β β
|
| 44 |
-
β β 8. CMD ["uvicorn", "app:app", ...] β β
|
| 45 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 46 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 47 |
-
β
|
| 48 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 49 |
-
β CONTAINER STARTUP (startup.sh) β
|
| 50 |
-
β β
|
| 51 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 52 |
-
β β π Check Environment Variables β β
|
| 53 |
-
β β β β
|
| 54 |
-
β β if [ -n "$PREFECT_API_KEY" ]; then β β
|
| 55 |
-
β β β
Prefect Cloud API Key detected β β
|
| 56 |
-
β β π§ Configuring Prefect Cloud... β β
|
| 57 |
-
β β prefect config set PREFECT_API_KEY="$PREFECT_API_KEY" β β
|
| 58 |
-
β β prefect cloud workspace ls # Verify connection β β
|
| 59 |
-
β β β
Successfully connected to Prefect Cloud β β
|
| 60 |
-
β β β β
|
| 61 |
-
β β if [ "$AUTO_DEPLOY_FLOWS" = "true" ]; then β β
|
| 62 |
-
β β π¦ Auto-deploying Prefect flows... β β
|
| 63 |
-
β β cd prefect_flows && python deploy_schedule.py β β
|
| 64 |
-
β β fi β β
|
| 65 |
-
β β else β β
|
| 66 |
-
β β βΉοΈ No PREFECT_API_KEY - Cloud features disabled β β
|
| 67 |
-
β β fi β β
|
| 68 |
-
β β β β
|
| 69 |
-
β β if [ -n "$EVIDENTLY_CLOUD_TOKEN" ]; then β β
|
| 70 |
-
β β β
Evidently Cloud enabled β β
|
| 71 |
-
β β else β β
|
| 72 |
-
β β βΉοΈ Using open-source Evidently β β
|
| 73 |
-
β β fi β β
|
| 74 |
-
β β β β
|
| 75 |
-
β β π mkdir -p monitoring/reports final_model logs β β
|
| 76 |
-
β β β
Initialization complete! β β
|
| 77 |
-
β β π Starting FastAPI application... β β
|
| 78 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 79 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 80 |
-
β
|
| 81 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 82 |
-
β FASTAPI APPLICATION (app.py) β
|
| 83 |
-
β β
|
| 84 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 85 |
-
β β from cloud_config import initialize_monitoring β β
|
| 86 |
-
β β cloud_status = initialize_monitoring() β β
|
| 87 |
-
β β β β
|
| 88 |
-
β β app = FastAPI() β β
|
| 89 |
-
β β β β
|
| 90 |
-
β β @app.get("/") β β
|
| 91 |
-
β β def root(): β β
|
| 92 |
-
β β return { β β
|
| 93 |
-
β β "status": "running", β β
|
| 94 |
-
β β "cloud_mlops": { β β
|
| 95 |
-
β β "prefect_cloud": "enabled" β
β β
|
| 96 |
-
β β "evidently": "open-source" β β
|
| 97 |
-
β β } β β
|
| 98 |
-
β β } β β
|
| 99 |
-
β β β β
|
| 100 |
-
β β @app.get("/train") β β
|
| 101 |
-
β β def training_route(): β β
|
| 102 |
-
β β if ENABLE_PREFECT: β β
|
| 103 |
-
β β # Option 1: Trigger via Prefect Cloud β β
|
| 104 |
-
β β training_flow() # Logged to Prefect dashboard β β
|
| 105 |
-
β β else: β β
|
| 106 |
-
β β # Option 2: Direct training β β
|
| 107 |
-
β β training_pipeline.run_pipeline() β β
|
| 108 |
-
β β β β
|
| 109 |
-
β β @app.post("/predict") β β
|
| 110 |
-
β β def predict_route(file): β β
|
| 111 |
-
β β # Make predictions β β
|
| 112 |
-
β β # Optionally log to Evidently β β
|
| 113 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 114 |
-
β β
|
| 115 |
-
β π Running at: https://kshitijk20-nss.hf.space β
|
| 116 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 117 |
-
β
|
| 118 |
-
οΏ½οΏ½ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 119 |
-
β PREFECT CLOUD (External Service) β
|
| 120 |
-
β β
|
| 121 |
-
β Dashboard: https://app.prefect.cloud/ β
|
| 122 |
-
β β
|
| 123 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 124 |
-
β β π Flow Runs β β
|
| 125 |
-
β β ββ training-flow-2026-01-17-14:30:00 β
Success β β
|
| 126 |
-
β β ββ training-flow-2026-01-10-14:30:00 β
Success β β
|
| 127 |
-
β β ββ drift-monitoring-2026-01-17-03:00:00 β
Success β β
|
| 128 |
-
β β β β
|
| 129 |
-
β β π
Deployments β β
|
| 130 |
-
β β ββ weekly-training (Every Sunday 2 AM) β β
|
| 131 |
-
β β ββ daily-drift-check (Every day 3 AM) β β
|
| 132 |
-
β β β β
|
| 133 |
-
β β π Automations β β
|
| 134 |
-
β β ββ Notify on training failure β Slack/Email β β
|
| 135 |
-
β β β β
|
| 136 |
-
β β π Metrics β β
|
| 137 |
-
β β β’ Total runs: 45 β β
|
| 138 |
-
β β β’ Success rate: 97.8% β β
|
| 139 |
-
β β β’ Avg duration: 2.3 min β β
|
| 140 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 141 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 142 |
-
β
|
| 143 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 144 |
-
β EVIDENTLY (Open Source - Local Reports) β
|
| 145 |
-
β β
|
| 146 |
-
β Reports stored in: /app/monitoring/reports/ β
|
| 147 |
-
β β
|
| 148 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 149 |
-
β β drift_report_20260117_143000.html β β
|
| 150 |
-
β β ββ Data Drift: 12% of features drifted β β
|
| 151 |
-
β β ββ Data Quality: 98.5% complete β β
|
| 152 |
-
β β ββ Recommendation: No retraining needed β β
|
| 153 |
-
β β β β
|
| 154 |
-
β β performance_report_20260117_143000.html β β
|
| 155 |
-
β β ββ Accuracy: 94.2% β β
|
| 156 |
-
β β ββ Precision: 93.8% β β
|
| 157 |
-
β β ββ Recall: 95.1% β β
|
| 158 |
-
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 159 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 160 |
-
```
|
| 161 |
-
|
| 162 |
-
## Data Flow Diagram
|
| 163 |
-
|
| 164 |
-
```
|
| 165 |
-
ββββββββββββ βββββββββββββββ ββββββββββββββββ
|
| 166 |
-
β β β β β β
|
| 167 |
-
β User βββββββ>β HuggingFace βββββββ>β FastAPI β
|
| 168 |
-
β β POST β Space β β app.py β
|
| 169 |
-
β β /pred β β β β
|
| 170 |
-
ββββββββββββ βββββββββββββββ ββββββββ¬ββββββββ
|
| 171 |
-
β
|
| 172 |
-
βββββββββββββββββββββββββββββββΌββββββββββββββββββ
|
| 173 |
-
β β β
|
| 174 |
-
β β β
|
| 175 |
-
ββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ
|
| 176 |
-
β Model Files β β Prefect Cloud β β Evidently β
|
| 177 |
-
β β’ model.pkl β β β’ Log training β β β’ Reports β
|
| 178 |
-
β β’ preproc.pkl β β β’ Schedule jobs β β β’ Drift det β
|
| 179 |
-
ββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ
|
| 180 |
-
```
|
| 181 |
-
|
| 182 |
-
## Secrets Flow
|
| 183 |
-
|
| 184 |
-
```
|
| 185 |
-
Developer β Get API Key from Prefect Cloud
|
| 186 |
-
β
|
| 187 |
-
Add to HuggingFace Space Secrets
|
| 188 |
-
β
|
| 189 |
-
Push code: git push hf main
|
| 190 |
-
β
|
| 191 |
-
HuggingFace builds Docker container
|
| 192 |
-
β
|
| 193 |
-
Injects secrets as environment variables
|
| 194 |
-
β
|
| 195 |
-
startup.sh reads $PREFECT_API_KEY
|
| 196 |
-
β
|
| 197 |
-
Configures Prefect Cloud connection
|
| 198 |
-
β
|
| 199 |
-
app.py uses cloud features
|
| 200 |
-
β
|
| 201 |
-
All operations visible in Prefect dashboard
|
| 202 |
-
```
|
| 203 |
-
|
| 204 |
-
## File Interaction Map
|
| 205 |
-
|
| 206 |
-
```
|
| 207 |
-
prepare_hf_deployment.py
|
| 208 |
-
ββ Adds to git:
|
| 209 |
-
β ββ startup.sh
|
| 210 |
-
β ββ cloud_config.py
|
| 211 |
-
β ββ app.py (updated)
|
| 212 |
-
β ββ Dockerfile (updated)
|
| 213 |
-
β ββ prefect_flows/
|
| 214 |
-
ββ Shows: Secret configuration instructions
|
| 215 |
-
|
| 216 |
-
Dockerfile
|
| 217 |
-
ββ Copies: startup.sh, cloud_config.py
|
| 218 |
-
ββ RUN: chmod +x startup.sh
|
| 219 |
-
ββ RUN: python cloud_config.py
|
| 220 |
-
ββ ENTRYPOINT: ./startup.sh
|
| 221 |
-
|
| 222 |
-
startup.sh
|
| 223 |
-
ββ Reads: $PREFECT_API_KEY, $EVIDENTLY_CLOUD_TOKEN
|
| 224 |
-
ββ Configures: Prefect Cloud connection
|
| 225 |
-
ββ Creates: monitoring/reports, final_model
|
| 226 |
-
ββ Starts: uvicorn app:app
|
| 227 |
-
|
| 228 |
-
cloud_config.py
|
| 229 |
-
ββ Reads: All environment variables
|
| 230 |
-
ββ Exports: Configuration status
|
| 231 |
-
ββ Used by: app.py, startup.sh
|
| 232 |
-
|
| 233 |
-
app.py
|
| 234 |
-
ββ Imports: cloud_config
|
| 235 |
-
ββ GET /: Shows cloud status
|
| 236 |
-
ββ GET /train: Can use Prefect Cloud
|
| 237 |
-
ββ POST /predict: Normal predictions
|
| 238 |
-
```
|
| 239 |
-
|
| 240 |
-
---
|
| 241 |
-
|
| 242 |
-
## Success Flow (Happy Path)
|
| 243 |
-
|
| 244 |
-
```
|
| 245 |
-
1. Developer runs: python prepare_hf_deployment.py
|
| 246 |
-
β
Files added to git
|
| 247 |
-
β
Commit created
|
| 248 |
-
|
| 249 |
-
2. Developer adds PREFECT_API_KEY to HF Space
|
| 250 |
-
β
Secret configured
|
| 251 |
-
|
| 252 |
-
3. Developer pushes: git push hf main
|
| 253 |
-
β
Code pushed to HuggingFace
|
| 254 |
-
|
| 255 |
-
4. HuggingFace builds container
|
| 256 |
-
β
Docker image built
|
| 257 |
-
β
Dependencies installed
|
| 258 |
-
|
| 259 |
-
5. Container starts (startup.sh runs)
|
| 260 |
-
β
Prefect Cloud API Key detected
|
| 261 |
-
β
Successfully connected to Prefect Cloud
|
| 262 |
-
β
Initialization complete!
|
| 263 |
-
|
| 264 |
-
6. FastAPI starts
|
| 265 |
-
β
Server running on port 7860
|
| 266 |
-
β
Cloud features enabled
|
| 267 |
-
|
| 268 |
-
7. User calls GET /
|
| 269 |
-
β
Returns: "prefect_cloud": "enabled"
|
| 270 |
-
|
| 271 |
-
8. User calls GET /train
|
| 272 |
-
β
Training executes
|
| 273 |
-
β
Logged to Prefect Cloud dashboard
|
| 274 |
-
|
| 275 |
-
9. Developer checks Prefect dashboard
|
| 276 |
-
β
Sees flow run from HF Space
|
| 277 |
-
β
Views logs and execution graph
|
| 278 |
-
```
|
| 279 |
-
|
| 280 |
-
---
|
| 281 |
-
|
| 282 |
-
## Cost-Free Production MLOps! π
|
| 283 |
-
|
| 284 |
-
```
|
| 285 |
-
βββββββββββββββββββββββββββββββββββββββββββββ
|
| 286 |
-
β Component β Tier β Cost β
|
| 287 |
-
βββββββββββββββββββββββββββββββββββββββββββββ€
|
| 288 |
-
β HuggingFace Spaces β Community β FREE β
β
|
| 289 |
-
β Prefect Cloud β Hobby β FREE β
β
|
| 290 |
-
β Evidently β Open Src β FREE β
β
|
| 291 |
-
βββββββββββββββββββββββββββββββββββββββββββββ€
|
| 292 |
-
β TOTAL MONTHLY COST β $0 β
|
| 293 |
-
βββββββββββββββββββββββββββββββββββββββββββββ
|
| 294 |
-
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CLOUD_INTEGRATION_SUMMARY.md
DELETED
|
@@ -1,152 +0,0 @@
|
|
| 1 |
-
# βοΈ Cloud MLOps Integration - Summary
|
| 2 |
-
|
| 3 |
-
## What Was Added
|
| 4 |
-
|
| 5 |
-
Your HuggingFace Space now automatically sets up **Prefect Cloud** and **Evidently** during Docker build!
|
| 6 |
-
|
| 7 |
-
---
|
| 8 |
-
|
| 9 |
-
## π Quick Checklist
|
| 10 |
-
|
| 11 |
-
### Before Deploying:
|
| 12 |
-
- [ ] Create Prefect Cloud account: https://app.prefect.cloud/
|
| 13 |
-
- [ ] Get API key (Profile β API Keys β Create)
|
| 14 |
-
- [ ] Run: `python prepare_hf_deployment.py`
|
| 15 |
-
|
| 16 |
-
### Add to HuggingFace Secrets:
|
| 17 |
-
- [ ] Go to: https://huggingface.co/spaces/kshitijk20/nss/settings
|
| 18 |
-
- [ ] Add secret: `PREFECT_API_KEY` = `<your-key>`
|
| 19 |
-
- [ ] (Optional) Add: `AUTO_DEPLOY_FLOWS` = `true`
|
| 20 |
-
|
| 21 |
-
### Deploy:
|
| 22 |
-
- [ ] Run: `git push hf main`
|
| 23 |
-
- [ ] Monitor build logs
|
| 24 |
-
- [ ] Check for: "β
Successfully connected to Prefect Cloud"
|
| 25 |
-
|
| 26 |
-
---
|
| 27 |
-
|
| 28 |
-
## π§ What Happens Automatically
|
| 29 |
-
|
| 30 |
-
### During Docker Build:
|
| 31 |
-
1. β
Installs Prefect and Evidently
|
| 32 |
-
2. β
Copies startup.sh and cloud_config.py
|
| 33 |
-
3. β
Creates monitoring directories
|
| 34 |
-
4. β
Makes scripts executable
|
| 35 |
-
|
| 36 |
-
### During Container Startup:
|
| 37 |
-
1. β
Reads PREFECT_API_KEY from HF secrets
|
| 38 |
-
2. β
Configures Prefect Cloud connection
|
| 39 |
-
3. β
Verifies workspace access
|
| 40 |
-
4. β
(Optional) Auto-deploys flows
|
| 41 |
-
5. β
Sets up Evidently monitoring
|
| 42 |
-
6. β
Starts FastAPI app
|
| 43 |
-
|
| 44 |
-
### When You Access the API:
|
| 45 |
-
- β
`GET /` shows cloud MLOps status
|
| 46 |
-
- β
`GET /train` can use Prefect Cloud
|
| 47 |
-
- β
`POST /predict` works normally
|
| 48 |
-
- β
All operations logged to Prefect dashboard
|
| 49 |
-
|
| 50 |
-
---
|
| 51 |
-
|
| 52 |
-
## π New Files
|
| 53 |
-
|
| 54 |
-
| File | Purpose |
|
| 55 |
-
|------|---------|
|
| 56 |
-
| `startup.sh` | Container initialization script |
|
| 57 |
-
| `cloud_config.py` | Cloud services configuration |
|
| 58 |
-
| `HF_SECRETS_SETUP.md` | Secrets reference guide |
|
| 59 |
-
| `CLOUD_MLOPS_SETUP.md` | Complete cloud setup guide |
|
| 60 |
-
| `DEPLOY_TO_HF.md` | Deployment instructions |
|
| 61 |
-
| `prepare_hf_deployment.py` | Deployment helper script |
|
| 62 |
-
|
| 63 |
-
---
|
| 64 |
-
|
| 65 |
-
## π― Required Secrets
|
| 66 |
-
|
| 67 |
-
### Minimum (for cloud features):
|
| 68 |
-
```
|
| 69 |
-
Name: PREFECT_API_KEY
|
| 70 |
-
Value: pnu_... (from app.prefect.cloud)
|
| 71 |
-
```
|
| 72 |
-
|
| 73 |
-
### Optional (advanced):
|
| 74 |
-
```
|
| 75 |
-
AUTO_DEPLOY_FLOWS=true
|
| 76 |
-
USE_PREFECT_FOR_TRAINING=true
|
| 77 |
-
EVIDENTLY_CLOUD_TOKEN=<paid-service>
|
| 78 |
-
```
|
| 79 |
-
|
| 80 |
-
---
|
| 81 |
-
|
| 82 |
-
## π Deploy Commands
|
| 83 |
-
|
| 84 |
-
```bash
|
| 85 |
-
# 1. Prepare
|
| 86 |
-
python prepare_hf_deployment.py
|
| 87 |
-
|
| 88 |
-
# 2. Add secrets to HF Space UI
|
| 89 |
-
# https://huggingface.co/spaces/kshitijk20/nss/settings
|
| 90 |
-
|
| 91 |
-
# 3. Push
|
| 92 |
-
git push hf main
|
| 93 |
-
|
| 94 |
-
# 4. Monitor
|
| 95 |
-
# https://huggingface.co/spaces/kshitijk20/nss
|
| 96 |
-
```
|
| 97 |
-
|
| 98 |
-
---
|
| 99 |
-
|
| 100 |
-
## β
Success Indicators
|
| 101 |
-
|
| 102 |
-
After deployment, check:
|
| 103 |
-
|
| 104 |
-
1. **Build Logs:**
|
| 105 |
-
```
|
| 106 |
-
β
Successfully connected to Prefect Cloud
|
| 107 |
-
β
Initialization complete!
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
2. **Root Endpoint:**
|
| 111 |
-
```bash
|
| 112 |
-
curl https://kshitijk20-nss.hf.space/
|
| 113 |
-
# Should show: "prefect_cloud": "enabled"
|
| 114 |
-
```
|
| 115 |
-
|
| 116 |
-
3. **Prefect Dashboard:**
|
| 117 |
-
- Go to: https://app.prefect.cloud/
|
| 118 |
-
- See flow runs from HF Space
|
| 119 |
-
|
| 120 |
-
---
|
| 121 |
-
|
| 122 |
-
## π° Cost
|
| 123 |
-
|
| 124 |
-
- HuggingFace Spaces: **FREE**
|
| 125 |
-
- Prefect Cloud: **FREE** (Hobby tier)
|
| 126 |
-
- Evidently Open Source: **FREE**
|
| 127 |
-
|
| 128 |
-
**Total: $0** β¨
|
| 129 |
-
|
| 130 |
-
---
|
| 131 |
-
|
| 132 |
-
## π Documentation
|
| 133 |
-
|
| 134 |
-
- **Quick Deploy:** [DEPLOY_TO_HF.md](DEPLOY_TO_HF.md)
|
| 135 |
-
- **Secrets Setup:** [HF_SECRETS_SETUP.md](HF_SECRETS_SETUP.md)
|
| 136 |
-
- **Full Cloud Guide:** [CLOUD_MLOPS_SETUP.md](CLOUD_MLOPS_SETUP.md)
|
| 137 |
-
|
| 138 |
-
---
|
| 139 |
-
|
| 140 |
-
## π Need Help?
|
| 141 |
-
|
| 142 |
-
1. Check build logs in HuggingFace Space
|
| 143 |
-
2. Review [DEPLOY_TO_HF.md](DEPLOY_TO_HF.md) troubleshooting section
|
| 144 |
-
3. Test Prefect key locally first:
|
| 145 |
-
```bash
|
| 146 |
-
export PREFECT_API_KEY="your-key"
|
| 147 |
-
prefect cloud workspace ls
|
| 148 |
-
```
|
| 149 |
-
|
| 150 |
-
---
|
| 151 |
-
|
| 152 |
-
**Ready to deploy?** Run: `python prepare_hf_deployment.py` π
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CLOUD_MLOPS_SETUP.md
DELETED
|
@@ -1,457 +0,0 @@
|
|
| 1 |
-
# βοΈ Cloud MLOps Setup: Prefect Cloud + Evidently AI
|
| 2 |
-
|
| 3 |
-
Complete guide to setting up production-grade MLOps using **Prefect Cloud** and **Evidently AI Cloud** platforms.
|
| 4 |
-
|
| 5 |
-
---
|
| 6 |
-
|
| 7 |
-
## π Why Cloud Platforms?
|
| 8 |
-
|
| 9 |
-
### Prefect Cloud
|
| 10 |
-
- β
**Zero Infrastructure**: No server to manage
|
| 11 |
-
- β
**Hybrid Execution**: Control plane in cloud, workers in your infrastructure
|
| 12 |
-
- β
**Free Tier**: 2 users, 5 workflows, unlimited runs
|
| 13 |
-
- β
**SOC 2 Type II Certified**: Enterprise security
|
| 14 |
-
- β
**Real-time Monitoring**: Live dashboard at app.prefect.cloud
|
| 15 |
-
|
| 16 |
-
### Evidently AI Cloud
|
| 17 |
-
- β
**LLM & ML Monitoring**: 100+ built-in metrics
|
| 18 |
-
- β
**Synthetic Data Generation**: For testing edge cases
|
| 19 |
-
- β
**Automated Evaluation**: Continuous testing dashboards
|
| 20 |
-
- β
**No-Code Interface**: Domain experts can collaborate
|
| 21 |
-
- β
**Open Source Based**: Built on trusted Evidently library
|
| 22 |
-
|
| 23 |
-
---
|
| 24 |
-
|
| 25 |
-
## 1οΈβ£ Prefect Cloud Setup
|
| 26 |
-
|
| 27 |
-
### Step 1: Create Free Account
|
| 28 |
-
1. Go to: https://app.prefect.cloud/
|
| 29 |
-
2. Click **"Start Free"**
|
| 30 |
-
3. Sign up with GitHub, Google, or email
|
| 31 |
-
4. Create your first workspace (e.g., "phishing-detection")
|
| 32 |
-
|
| 33 |
-
### Step 2: Get API Key
|
| 34 |
-
```bash
|
| 35 |
-
# In Prefect Cloud dashboard:
|
| 36 |
-
# 1. Click on your profile (bottom left)
|
| 37 |
-
# 2. Go to "API Keys"
|
| 38 |
-
# 3. Click "Create API Key"
|
| 39 |
-
# 4. Name it "NSS-Project" and copy the key
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
-
### Step 3: Configure Local Environment
|
| 43 |
-
```bash
|
| 44 |
-
# Activate your venv
|
| 45 |
-
.\.venv\Scripts\activate
|
| 46 |
-
|
| 47 |
-
# Login to Prefect Cloud
|
| 48 |
-
prefect cloud login
|
| 49 |
-
|
| 50 |
-
# Paste your API key when prompted
|
| 51 |
-
# Or set it directly:
|
| 52 |
-
prefect config set PREFECT_API_KEY="your-api-key-here"
|
| 53 |
-
|
| 54 |
-
# Verify connection
|
| 55 |
-
prefect cloud workspace ls
|
| 56 |
-
```
|
| 57 |
-
|
| 58 |
-
### Step 4: Update Training Flow for Cloud
|
| 59 |
-
```python
|
| 60 |
-
# prefect_flows/training_flow.py already configured!
|
| 61 |
-
# Just run it and it will sync with Prefect Cloud
|
| 62 |
-
cd prefect_flows
|
| 63 |
-
python training_flow.py
|
| 64 |
-
```
|
| 65 |
-
|
| 66 |
-
### Step 5: Deploy to Prefect Cloud
|
| 67 |
-
```bash
|
| 68 |
-
# Create deployment with schedule
|
| 69 |
-
cd prefect_flows
|
| 70 |
-
python deploy_schedule.py
|
| 71 |
-
|
| 72 |
-
# This creates a deployment visible in Prefect Cloud dashboard
|
| 73 |
-
```
|
| 74 |
-
|
| 75 |
-
### Step 6: Run Worker (Local or Cloud)
|
| 76 |
-
|
| 77 |
-
**Option A: Run Worker Locally (Hybrid Model - Recommended)**
|
| 78 |
-
```bash
|
| 79 |
-
# Start worker on your machine (keeps data secure)
|
| 80 |
-
prefect agent start -q training
|
| 81 |
-
|
| 82 |
-
# Worker polls Prefect Cloud but executes in your environment
|
| 83 |
-
# Your data never leaves your infrastructure!
|
| 84 |
-
```
|
| 85 |
-
|
| 86 |
-
**Option B: Use Prefect Managed Execution (Fully Cloud)**
|
| 87 |
-
```python
|
| 88 |
-
# Update deploy_schedule.py to use managed pool:
|
| 89 |
-
deployment = Deployment.build_from_flow(
|
| 90 |
-
flow=training_flow,
|
| 91 |
-
name="weekly-training",
|
| 92 |
-
work_pool_name="prefect-managed-pool", # Use managed pool
|
| 93 |
-
schedule=CronSchedule(cron="0 2 * * 0", timezone="UTC"),
|
| 94 |
-
)
|
| 95 |
-
```
|
| 96 |
-
|
| 97 |
-
### Step 7: Monitor in Dashboard
|
| 98 |
-
- Go to: https://app.prefect.cloud/
|
| 99 |
-
- View flow runs in real-time
|
| 100 |
-
- Check logs, states, and execution graphs
|
| 101 |
-
- Set up alerts and automations
|
| 102 |
-
|
| 103 |
-
---
|
| 104 |
-
|
| 105 |
-
## 2οΈβ£ Evidently AI Cloud Setup
|
| 106 |
-
|
| 107 |
-
### Understanding Evidently Cloud vs Open Source
|
| 108 |
-
|
| 109 |
-
**Open Source (What we have now):**
|
| 110 |
-
- Generate HTML reports locally
|
| 111 |
-
- Manual drift analysis
|
| 112 |
-
- No centralized dashboard
|
| 113 |
-
|
| 114 |
-
**Evidently Cloud (Upgrade):**
|
| 115 |
-
- Centralized monitoring dashboard
|
| 116 |
-
- Automated continuous testing
|
| 117 |
-
- Alerting and notifications
|
| 118 |
-
- Team collaboration
|
| 119 |
-
- Synthetic data generation
|
| 120 |
-
|
| 121 |
-
### Step 1: Get Access to Evidently Cloud
|
| 122 |
-
```bash
|
| 123 |
-
# Option A: Request Demo (Recommended for production)
|
| 124 |
-
# Go to: https://www.evidentlyai.com/get-demo
|
| 125 |
-
# Book a 1:1 demo to get:
|
| 126 |
-
# - Private cloud deployment
|
| 127 |
-
# - Custom risk assessment
|
| 128 |
-
# - Enterprise features
|
| 129 |
-
|
| 130 |
-
# Option B: Try Open Source First (What we currently have)
|
| 131 |
-
# Already installed! Just use local HTML reports
|
| 132 |
-
```
|
| 133 |
-
|
| 134 |
-
### Step 2: Current Setup (Open Source - Already Working)
|
| 135 |
-
```bash
|
| 136 |
-
# Test current Evidently monitoring
|
| 137 |
-
python test_evidently.py
|
| 138 |
-
|
| 139 |
-
# This generates reports in monitoring/reports/
|
| 140 |
-
# Open HTML files in browser
|
| 141 |
-
```
|
| 142 |
-
|
| 143 |
-
### Step 3: Integrate with Prefect Cloud
|
| 144 |
-
|
| 145 |
-
#### Update Drift Monitoring Flow:
|
| 146 |
-
```python
|
| 147 |
-
# prefect_flows/drift_monitoring_flow.py
|
| 148 |
-
# This flow already integrates both:
|
| 149 |
-
# 1. Evidently for drift detection
|
| 150 |
-
# 2. Prefect Cloud for orchestration
|
| 151 |
-
|
| 152 |
-
# Run it:
|
| 153 |
-
python prefect_flows/drift_monitoring_flow.py
|
| 154 |
-
```
|
| 155 |
-
|
| 156 |
-
#### Schedule Automated Drift Checks:
|
| 157 |
-
```python
|
| 158 |
-
# Create new file: prefect_flows/schedule_drift_monitoring.py
|
| 159 |
-
from prefect.deployments import Deployment
|
| 160 |
-
from prefect.server.schemas.schedules import CronSchedule
|
| 161 |
-
from drift_monitoring_flow import drift_monitoring_flow
|
| 162 |
-
|
| 163 |
-
deployment = Deployment.build_from_flow(
|
| 164 |
-
flow=drift_monitoring_flow,
|
| 165 |
-
name="daily-drift-check",
|
| 166 |
-
schedule=CronSchedule(cron="0 3 * * *", timezone="UTC"), # Daily 3 AM
|
| 167 |
-
work_queue_name="training",
|
| 168 |
-
tags=["monitoring", "drift-detection"],
|
| 169 |
-
)
|
| 170 |
-
|
| 171 |
-
if __name__ == "__main__":
|
| 172 |
-
deployment.apply()
|
| 173 |
-
print("β
Daily drift monitoring scheduled!")
|
| 174 |
-
```
|
| 175 |
-
|
| 176 |
-
---
|
| 177 |
-
|
| 178 |
-
## 3οΈβ£ Complete Cloud MLOps Workflow
|
| 179 |
-
|
| 180 |
-
### Architecture Overview
|
| 181 |
-
```
|
| 182 |
-
ββββββββββββββββββββββββββββββββββββββββοΏ½οΏ½ββββββββββββββ
|
| 183 |
-
β PREFECT CLOUD (Control Plane) β
|
| 184 |
-
β - Flow orchestration β
|
| 185 |
-
β - Scheduling (Weekly training, Daily drift check) β
|
| 186 |
-
β - Real-time monitoring dashboard β
|
| 187 |
-
β - Event-driven automations β
|
| 188 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 189 |
-
β
|
| 190 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 191 |
-
β YOUR INFRASTRUCTURE (Workers) β
|
| 192 |
-
β - Prefect Worker (polls cloud API) β
|
| 193 |
-
β - Training pipeline execution β
|
| 194 |
-
β - Model files (final_model/) β
|
| 195 |
-
β - Evidently drift reports β
|
| 196 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 197 |
-
β
|
| 198 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 199 |
-
β EVIDENTLY (Open Source) β
|
| 200 |
-
β - Data drift detection β
|
| 201 |
-
β - Quality reports β
|
| 202 |
-
β - HTML dashboards (local) β
|
| 203 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 204 |
-
β
|
| 205 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 206 |
-
β HUGGINGFACE SPACES (Deployment) β
|
| 207 |
-
β - FastAPI app serving predictions β
|
| 208 |
-
β - Model inference endpoint β
|
| 209 |
-
β - Public access: kshitijk20-nss.hf.space β
|
| 210 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 211 |
-
```
|
| 212 |
-
|
| 213 |
-
### Daily Operations
|
| 214 |
-
|
| 215 |
-
#### Morning: Check Dashboard
|
| 216 |
-
```
|
| 217 |
-
1. Open Prefect Cloud: https://app.prefect.cloud/
|
| 218 |
-
2. Review overnight flow runs
|
| 219 |
-
3. Check for any failures or warnings
|
| 220 |
-
4. View execution graphs and logs
|
| 221 |
-
```
|
| 222 |
-
|
| 223 |
-
#### Weekly: Automated Training
|
| 224 |
-
```
|
| 225 |
-
Every Sunday 2 AM UTC:
|
| 226 |
-
β Prefect Cloud triggers training flow
|
| 227 |
-
β Worker executes pipeline in your environment
|
| 228 |
-
β New model saved to final_model/
|
| 229 |
-
β Logs visible in Prefect dashboard
|
| 230 |
-
```
|
| 231 |
-
|
| 232 |
-
#### Daily: Drift Monitoring
|
| 233 |
-
```
|
| 234 |
-
Every day 3 AM UTC:
|
| 235 |
-
β Drift monitoring flow runs
|
| 236 |
-
β Evidently checks for data drift
|
| 237 |
-
β If drift > 30%, triggers retraining
|
| 238 |
-
β Report saved to monitoring/reports/
|
| 239 |
-
β Notification sent (if configured)
|
| 240 |
-
```
|
| 241 |
-
|
| 242 |
-
---
|
| 243 |
-
|
| 244 |
-
## 4οΈβ£ Setup Commands (Step-by-Step)
|
| 245 |
-
|
| 246 |
-
### One-Time Setup
|
| 247 |
-
```bash
|
| 248 |
-
# 1. Activate environment
|
| 249 |
-
.\.venv\Scripts\activate
|
| 250 |
-
|
| 251 |
-
# 2. Login to Prefect Cloud
|
| 252 |
-
prefect cloud login
|
| 253 |
-
# Paste your API key
|
| 254 |
-
|
| 255 |
-
# 3. Create deployments
|
| 256 |
-
cd prefect_flows
|
| 257 |
-
python deploy_schedule.py # Weekly training
|
| 258 |
-
|
| 259 |
-
# 4. Start worker (keep running in background)
|
| 260 |
-
# Terminal 1:
|
| 261 |
-
prefect agent start -q training
|
| 262 |
-
|
| 263 |
-
# 5. Test flows manually
|
| 264 |
-
# Terminal 2:
|
| 265 |
-
python training_flow.py
|
| 266 |
-
python drift_monitoring_flow.py
|
| 267 |
-
```
|
| 268 |
-
|
| 269 |
-
### Verify Everything Works
|
| 270 |
-
```bash
|
| 271 |
-
# Check Prefect Cloud connection
|
| 272 |
-
prefect cloud workspace ls
|
| 273 |
-
|
| 274 |
-
# Check deployments
|
| 275 |
-
prefect deployment ls
|
| 276 |
-
|
| 277 |
-
# Run training manually
|
| 278 |
-
cd prefect_flows
|
| 279 |
-
python training_flow.py
|
| 280 |
-
|
| 281 |
-
# Check Prefect Cloud dashboard
|
| 282 |
-
# Go to: https://app.prefect.cloud/
|
| 283 |
-
# You should see your flow run!
|
| 284 |
-
|
| 285 |
-
# Generate Evidently report
|
| 286 |
-
python test_evidently.py
|
| 287 |
-
# Check monitoring/reports/ for HTML files
|
| 288 |
-
```
|
| 289 |
-
|
| 290 |
-
---
|
| 291 |
-
|
| 292 |
-
## 5οΈβ£ Cost Breakdown
|
| 293 |
-
|
| 294 |
-
### Prefect Cloud
|
| 295 |
-
| Tier | Price | Features |
|
| 296 |
-
|------|-------|----------|
|
| 297 |
-
| **Hobby (Free)** | $0 | 2 users, 5 workflows, unlimited runs |
|
| 298 |
-
| **Pro** | Pay per user | Unlimited workflows, SSO, RBAC |
|
| 299 |
-
| **Enterprise** | Custom | Private deployment, dedicated support |
|
| 300 |
-
|
| 301 |
-
**Recommendation**: Start with Free tier (sufficient for this project)
|
| 302 |
-
|
| 303 |
-
### Evidently AI
|
| 304 |
-
| Option | Price | Features |
|
| 305 |
-
|--------|-------|----------|
|
| 306 |
-
| **Open Source** | FREE | Local reports, 100+ metrics |
|
| 307 |
-
| **Cloud** | Contact sales | Centralized dashboard, alerting, team collaboration |
|
| 308 |
-
|
| 309 |
-
**Recommendation**: Use Open Source (what we have now), upgrade to Cloud for production
|
| 310 |
-
|
| 311 |
-
---
|
| 312 |
-
|
| 313 |
-
## 6οΈβ£ Monitoring & Alerts
|
| 314 |
-
|
| 315 |
-
### Prefect Cloud Automations
|
| 316 |
-
Set up alerts in Prefect Cloud UI:
|
| 317 |
-
|
| 318 |
-
1. Go to **Automations** tab
|
| 319 |
-
2. Create automation:
|
| 320 |
-
- **Trigger**: Flow run fails
|
| 321 |
-
- **Action**: Send email/Slack notification
|
| 322 |
-
3. Example triggers:
|
| 323 |
-
- Training fails
|
| 324 |
-
- Drift threshold exceeded
|
| 325 |
-
- Worker goes offline
|
| 326 |
-
|
| 327 |
-
### Evidently Alerts (Open Source)
|
| 328 |
-
```python
|
| 329 |
-
# In drift_monitoring_flow.py (already configured):
|
| 330 |
-
if monitor.check_drift_threshold():
|
| 331 |
-
# Send notification (add your logic here)
|
| 332 |
-
send_alert("β οΈ Model drift detected! Retraining triggered.")
|
| 333 |
-
```
|
| 334 |
-
|
| 335 |
-
---
|
| 336 |
-
|
| 337 |
-
## 7οΈβ£ Advantages Over Local Setup
|
| 338 |
-
|
| 339 |
-
| Feature | Local | Prefect Cloud | Benefit |
|
| 340 |
-
|---------|-------|---------------|---------|
|
| 341 |
-
| Server Management | You maintain | Managed | No DevOps overhead |
|
| 342 |
-
| Availability | Your machine | 99.9% SLA | Production-ready |
|
| 343 |
-
| Collaboration | Single user | Team access | Multi-user support |
|
| 344 |
-
| Monitoring | Terminal logs | Rich dashboard | Better visibility |
|
| 345 |
-
| Scheduling | Cron jobs | Cloud scheduler | More reliable |
|
| 346 |
-
| Security | DIY | SOC 2 certified | Enterprise-grade |
|
| 347 |
-
| Scaling | Manual | Auto-scale | Handle more workflows |
|
| 348 |
-
|
| 349 |
-
---
|
| 350 |
-
|
| 351 |
-
## 8οΈβ£ Next Steps
|
| 352 |
-
|
| 353 |
-
### Immediate (Today)
|
| 354 |
-
- [x] Create Prefect Cloud account
|
| 355 |
-
- [x] Get API key and login
|
| 356 |
-
- [x] Deploy training flow
|
| 357 |
-
- [x] Start worker and test
|
| 358 |
-
|
| 359 |
-
### Short-term (This Week)
|
| 360 |
-
- [ ] Set up automations for failure alerts
|
| 361 |
-
- [ ] Schedule daily drift monitoring
|
| 362 |
-
- [ ] Configure Slack/email notifications
|
| 363 |
-
- [ ] Document team access procedures
|
| 364 |
-
|
| 365 |
-
### Long-term (Next Month)
|
| 366 |
-
- [ ] Evaluate Evidently Cloud (if needed)
|
| 367 |
-
- [ ] Set up CI/CD with GitHub Actions
|
| 368 |
-
- [ ] Implement A/B testing for models
|
| 369 |
-
- [ ] Add more monitoring metrics
|
| 370 |
-
|
| 371 |
-
---
|
| 372 |
-
|
| 373 |
-
## 9οΈβ£ Troubleshooting
|
| 374 |
-
|
| 375 |
-
### Prefect Cloud Connection Issues
|
| 376 |
-
```bash
|
| 377 |
-
# Reset API key
|
| 378 |
-
prefect cloud logout
|
| 379 |
-
prefect cloud login
|
| 380 |
-
|
| 381 |
-
# Check connection
|
| 382 |
-
prefect cloud workspace ls
|
| 383 |
-
|
| 384 |
-
# View logs
|
| 385 |
-
prefect config view --show-sources
|
| 386 |
-
```
|
| 387 |
-
|
| 388 |
-
### Worker Not Picking Up Jobs
|
| 389 |
-
```bash
|
| 390 |
-
# Check worker status
|
| 391 |
-
prefect work-queue ls
|
| 392 |
-
|
| 393 |
-
# Restart worker
|
| 394 |
-
prefect agent start -q training
|
| 395 |
-
|
| 396 |
-
# Check deployment
|
| 397 |
-
prefect deployment ls
|
| 398 |
-
```
|
| 399 |
-
|
| 400 |
-
### Evidently Reports Not Generating
|
| 401 |
-
```bash
|
| 402 |
-
# Verify data exists
|
| 403 |
-
python test_evidently.py
|
| 404 |
-
|
| 405 |
-
# Check reports directory
|
| 406 |
-
dir monitoring\reports
|
| 407 |
-
|
| 408 |
-
# Re-run with debug
|
| 409 |
-
python -v test_evidently.py
|
| 410 |
-
```
|
| 411 |
-
|
| 412 |
-
---
|
| 413 |
-
|
| 414 |
-
## π Resources
|
| 415 |
-
|
| 416 |
-
### Prefect Cloud
|
| 417 |
-
- Dashboard: https://app.prefect.cloud/
|
| 418 |
-
- Documentation: https://docs.prefect.io/latest/cloud/
|
| 419 |
-
- Community: https://prefect.io/slack
|
| 420 |
-
- Status: https://prefect.status.io/
|
| 421 |
-
|
| 422 |
-
### Evidently AI
|
| 423 |
-
- Website: https://www.evidentlyai.com/
|
| 424 |
-
- Documentation: https://docs.evidentlyai.com/
|
| 425 |
-
- GitHub: https://github.com/evidentlyai/evidently
|
| 426 |
-
- Discord: https://discord.com/invite/PyAJuUD5mB
|
| 427 |
-
|
| 428 |
-
### Your Project
|
| 429 |
-
- HuggingFace Space: https://kshitijk20-nss.hf.space
|
| 430 |
-
- Prefect Dashboard: Check after login
|
| 431 |
-
- Evidently Reports: `monitoring/reports/`
|
| 432 |
-
|
| 433 |
-
---
|
| 434 |
-
|
| 435 |
-
## β
Success Checklist
|
| 436 |
-
|
| 437 |
-
- [ ] Prefect Cloud account created
|
| 438 |
-
- [ ] API key configured locally
|
| 439 |
-
- [ ] Training flow deployed to cloud
|
| 440 |
-
- [ ] Worker running and picking up jobs
|
| 441 |
-
- [ ] Weekly schedule active (visible in dashboard)
|
| 442 |
-
- [ ] Drift monitoring flow tested
|
| 443 |
-
- [ ] Evidently reports generating correctly
|
| 444 |
-
- [ ] Automations configured (optional)
|
| 445 |
-
- [ ] Team members invited (if applicable)
|
| 446 |
-
|
| 447 |
-
---
|
| 448 |
-
|
| 449 |
-
**π Congratulations!** You now have a production-grade MLOps stack with:
|
| 450 |
-
- Automated orchestration (Prefect Cloud)
|
| 451 |
-
- Data drift monitoring (Evidently)
|
| 452 |
-
- Scheduled retraining (Weekly)
|
| 453 |
-
- Real-time dashboards
|
| 454 |
-
- Enterprise security
|
| 455 |
-
- Zero infrastructure management
|
| 456 |
-
|
| 457 |
-
All while keeping your data secure in your own environment! π
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DEPLOY_TO_HF.md
DELETED
|
@@ -1,352 +0,0 @@
|
|
| 1 |
-
# π Deploying to HuggingFace with Cloud MLOps
|
| 2 |
-
|
| 3 |
-
## Quick Deploy (5 Steps)
|
| 4 |
-
|
| 5 |
-
### 1οΈβ£ Get Prefect Cloud API Key (Free)
|
| 6 |
-
```bash
|
| 7 |
-
# Visit: https://app.prefect.cloud/
|
| 8 |
-
# Sign up (free) β Profile β API Keys β Create API Key
|
| 9 |
-
# Copy the key (you'll need it in step 3)
|
| 10 |
-
```
|
| 11 |
-
|
| 12 |
-
### 2οΈβ£ Prepare Deployment
|
| 13 |
-
```bash
|
| 14 |
-
# Activate venv
|
| 15 |
-
.\.venv\Scripts\activate
|
| 16 |
-
|
| 17 |
-
# Run preparation script
|
| 18 |
-
python prepare_hf_deployment.py
|
| 19 |
-
|
| 20 |
-
# This will:
|
| 21 |
-
# - Add all necessary files to git
|
| 22 |
-
# - Commit changes
|
| 23 |
-
# - Show HuggingFace secrets configuration
|
| 24 |
-
```
|
| 25 |
-
|
| 26 |
-
### 3οΈβ£ Add Secrets to HuggingFace Space
|
| 27 |
-
```
|
| 28 |
-
Go to: https://huggingface.co/spaces/kshitijk20/nss/settings
|
| 29 |
-
|
| 30 |
-
Add Repository Secret:
|
| 31 |
-
ββββββββββββββββββββββββββββββββββ
|
| 32 |
-
β Name: PREFECT_API_KEY β
|
| 33 |
-
β Value: <paste your API key> β
|
| 34 |
-
ββββββββββββββββββββββββββββββββββ
|
| 35 |
-
|
| 36 |
-
Click "Add secret"
|
| 37 |
-
```
|
| 38 |
-
|
| 39 |
-
### 4οΈβ£ Push to HuggingFace
|
| 40 |
-
```bash
|
| 41 |
-
git push hf main
|
| 42 |
-
```
|
| 43 |
-
|
| 44 |
-
### 5οΈβ£ Monitor Build
|
| 45 |
-
```
|
| 46 |
-
Watch logs at: https://huggingface.co/spaces/kshitijk20/nss
|
| 47 |
-
|
| 48 |
-
Look for:
|
| 49 |
-
β
Prefect Cloud configured successfully
|
| 50 |
-
β
Initialization complete!
|
| 51 |
-
β
Starting FastAPI application...
|
| 52 |
-
```
|
| 53 |
-
|
| 54 |
-
---
|
| 55 |
-
|
| 56 |
-
## What Happens During Docker Build
|
| 57 |
-
|
| 58 |
-
When you push to HuggingFace, Docker will:
|
| 59 |
-
|
| 60 |
-
### Build Phase (Dockerfile)
|
| 61 |
-
```dockerfile
|
| 62 |
-
1. Install Python 3.13 slim
|
| 63 |
-
2. Copy requirements.txt β Install packages
|
| 64 |
-
- fastapi, uvicorn
|
| 65 |
-
- prefect>=2.14.0
|
| 66 |
-
- evidently>=0.4.0
|
| 67 |
-
- scikit-learn, pandas, numpy
|
| 68 |
-
3. Copy application code
|
| 69 |
-
4. Create directories (monitoring/reports, final_model)
|
| 70 |
-
5. Initialize SQLite database
|
| 71 |
-
6. Run cloud_config.py (check for secrets)
|
| 72 |
-
```
|
| 73 |
-
|
| 74 |
-
### Startup Phase (startup.sh)
|
| 75 |
-
```bash
|
| 76 |
-
1. Check for PREFECT_API_KEY environment variable
|
| 77 |
-
ββ If found: Configure Prefect Cloud connection
|
| 78 |
-
β ββ Set PREFECT_API_KEY
|
| 79 |
-
β ββ Set PREFECT_API_URL
|
| 80 |
-
β ββ Verify connection: prefect cloud workspace ls
|
| 81 |
-
ββ If not found: Skip Prefect features
|
| 82 |
-
|
| 83 |
-
2. Check for EVIDENTLY_CLOUD_TOKEN (optional)
|
| 84 |
-
ββ If found: Enable Evidently Cloud
|
| 85 |
-
ββ If not found: Use open-source Evidently
|
| 86 |
-
|
| 87 |
-
3. Create monitoring directories
|
| 88 |
-
4. Start FastAPI application
|
| 89 |
-
```
|
| 90 |
-
|
| 91 |
-
### Runtime (app.py)
|
| 92 |
-
```python
|
| 93 |
-
1. Initialize cloud_config.py
|
| 94 |
-
- Load environment variables
|
| 95 |
-
- Configure Prefect/Evidently
|
| 96 |
-
|
| 97 |
-
2. Start FastAPI with endpoints:
|
| 98 |
-
GET / β System status (shows cloud MLOps status)
|
| 99 |
-
GET /train β Trigger training (can use Prefect)
|
| 100 |
-
POST /predict β Make predictions
|
| 101 |
-
```
|
| 102 |
-
|
| 103 |
-
---
|
| 104 |
-
|
| 105 |
-
## Secrets Configuration
|
| 106 |
-
|
| 107 |
-
### Required (for Cloud MLOps)
|
| 108 |
-
|
| 109 |
-
**PREFECT_API_KEY**
|
| 110 |
-
- **What:** API key from Prefect Cloud
|
| 111 |
-
- **Get it:** https://app.prefect.cloud/ β Profile β API Keys
|
| 112 |
-
- **Purpose:** Connect HF Space to Prefect Cloud for orchestration
|
| 113 |
-
- **Free:** Yes (Hobby tier: 2 users, 5 workflows, unlimited runs)
|
| 114 |
-
|
| 115 |
-
### Optional (Advanced)
|
| 116 |
-
|
| 117 |
-
**PREFECT_WORKSPACE**
|
| 118 |
-
- **What:** Your Prefect workspace name
|
| 119 |
-
- **Example:** `my-org/phishing-detection`
|
| 120 |
-
- **Purpose:** Specify exact workspace (if you have multiple)
|
| 121 |
-
|
| 122 |
-
**AUTO_DEPLOY_FLOWS**
|
| 123 |
-
- **What:** `true` or `false`
|
| 124 |
-
- **Purpose:** Auto-deploy Prefect flows on container start
|
| 125 |
-
- **Default:** `false`
|
| 126 |
-
|
| 127 |
-
**USE_PREFECT_FOR_TRAINING**
|
| 128 |
-
- **What:** `true` or `false`
|
| 129 |
-
- **Purpose:** Use Prefect Cloud when /train endpoint is called
|
| 130 |
-
- **Default:** `false` (direct training)
|
| 131 |
-
|
| 132 |
-
**EVIDENTLY_CLOUD_TOKEN**
|
| 133 |
-
- **What:** Evidently Cloud API token (paid service)
|
| 134 |
-
- **Get it:** https://www.evidentlyai.com/get-demo
|
| 135 |
-
- **Purpose:** Centralized monitoring dashboard
|
| 136 |
-
- **Note:** Open-source Evidently works without this
|
| 137 |
-
|
| 138 |
-
**MONITORING_ENABLED**
|
| 139 |
-
- **What:** `true` or `false`
|
| 140 |
-
- **Purpose:** Enable/disable monitoring features
|
| 141 |
-
- **Default:** `true`
|
| 142 |
-
|
| 143 |
-
**DRIFT_CHECK_ENABLED**
|
| 144 |
-
- **What:** `true` or `false`
|
| 145 |
-
- **Purpose:** Automated drift detection on predictions
|
| 146 |
-
- **Default:** `false`
|
| 147 |
-
|
| 148 |
-
---
|
| 149 |
-
|
| 150 |
-
## Architecture
|
| 151 |
-
|
| 152 |
-
```
|
| 153 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 154 |
-
β HuggingFace Space (Container) β
|
| 155 |
-
β β
|
| 156 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 157 |
-
β β Environment Variables (Secrets from HF UI) β β
|
| 158 |
-
β β β’ PREFECT_API_KEY=pnu_xxx β β
|
| 159 |
-
β β β’ AUTO_DEPLOY_FLOWS=true β β
|
| 160 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 161 |
-
β β β
|
| 162 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 163 |
-
β β startup.sh (Container Initialization) β β
|
| 164 |
-
β β β’ Configures Prefect Cloud β β
|
| 165 |
-
β β β’ Sets up Evidently β β
|
| 166 |
-
β β β’ Creates directories β β
|
| 167 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 168 |
-
β β β
|
| 169 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 170 |
-
β β cloud_config.py (Python Configuration) β β
|
| 171 |
-
β β β’ Reads env vars β β
|
| 172 |
-
β β β’ Initializes monitoring β β
|
| 173 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 174 |
-
β β β
|
| 175 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 176 |
-
β β app.py (FastAPI Application) β β
|
| 177 |
-
β β β’ Serves predictions β β
|
| 178 |
-
β β β’ Training endpoint β β
|
| 179 |
-
β β β’ Reports status β β
|
| 180 |
-
β βββββββββββββββββββββββββββββββββββββββββββββββββ β
|
| 181 |
-
β β
|
| 182 |
-
β https://kshitijk20-nss.hf.space β
|
| 183 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 184 |
-
β
|
| 185 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 186 |
-
β Prefect Cloud (External Service) β
|
| 187 |
-
β β’ Flow orchestration β
|
| 188 |
-
β β’ Scheduling (weekly training) β
|
| 189 |
-
β β’ Monitoring dashboard β
|
| 190 |
-
β β’ Execution logs β
|
| 191 |
-
β β
|
| 192 |
-
β https://app.prefect.cloud/ β
|
| 193 |
-
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 194 |
-
```
|
| 195 |
-
|
| 196 |
-
---
|
| 197 |
-
|
| 198 |
-
## Testing After Deployment
|
| 199 |
-
|
| 200 |
-
### 1. Check System Status
|
| 201 |
-
```bash
|
| 202 |
-
curl https://kshitijk20-nss.hf.space/
|
| 203 |
-
|
| 204 |
-
# Response should show:
|
| 205 |
-
{
|
| 206 |
-
"status": "running",
|
| 207 |
-
"cloud_mlops": {
|
| 208 |
-
"prefect_cloud": "enabled", # β
If API key configured
|
| 209 |
-
"evidently": "open-source",
|
| 210 |
-
"monitoring": "enabled"
|
| 211 |
-
}
|
| 212 |
-
}
|
| 213 |
-
```
|
| 214 |
-
|
| 215 |
-
### 2. Test Training Endpoint
|
| 216 |
-
```bash
|
| 217 |
-
curl -X GET "https://kshitijk20-nss.hf.space/train"
|
| 218 |
-
|
| 219 |
-
# With Prefect: "Training triggered via Prefect Cloud!"
|
| 220 |
-
# Without: "Training successfull !!"
|
| 221 |
-
```
|
| 222 |
-
|
| 223 |
-
### 3. Check Prefect Cloud Dashboard
|
| 224 |
-
```
|
| 225 |
-
1. Go to: https://app.prefect.cloud/
|
| 226 |
-
2. Navigate to "Flow Runs"
|
| 227 |
-
3. You should see training executions from HF Space
|
| 228 |
-
4. Click on a run to see logs and details
|
| 229 |
-
```
|
| 230 |
-
|
| 231 |
-
### 4. Test Prediction
|
| 232 |
-
```bash
|
| 233 |
-
curl -X POST "https://kshitijk20-nss.hf.space/predict" \
|
| 234 |
-
-F "file=@data/phisingData.csv"
|
| 235 |
-
|
| 236 |
-
# Should return HTML table with predictions
|
| 237 |
-
```
|
| 238 |
-
|
| 239 |
-
---
|
| 240 |
-
|
| 241 |
-
## Build Logs Examples
|
| 242 |
-
|
| 243 |
-
### β
Successful Build with Prefect Cloud
|
| 244 |
-
```
|
| 245 |
-
Building Docker image...
|
| 246 |
-
Step 1/15 : FROM python:3.13-slim
|
| 247 |
-
Step 2/15 : COPY requirements.txt
|
| 248 |
-
Step 3/15 : RUN pip install -r requirements.txt
|
| 249 |
-
...
|
| 250 |
-
π Starting Network Security System...
|
| 251 |
-
ββββββββββββββββββββββββββββββββββββββββββ
|
| 252 |
-
β
Prefect Cloud API Key detected
|
| 253 |
-
π§ Configuring Prefect Cloud connection...
|
| 254 |
-
β
Successfully connected to Prefect Cloud
|
| 255 |
-
β
Initialization complete!
|
| 256 |
-
π Starting FastAPI application...
|
| 257 |
-
ββββββββββββββββββββββββββββββββββββββββββ
|
| 258 |
-
INFO: Started server process
|
| 259 |
-
INFO: Uvicorn running on http://0.0.0.0:7860
|
| 260 |
-
```
|
| 261 |
-
|
| 262 |
-
### β οΈ Build without Secrets (Still Works)
|
| 263 |
-
```
|
| 264 |
-
π Starting Network Security System...
|
| 265 |
-
ββββββββββββββββββββββββββββββββββββββββββ
|
| 266 |
-
βΉοΈ No PREFECT_API_KEY found - Prefect Cloud features disabled
|
| 267 |
-
Set PREFECT_API_KEY in HuggingFace Space secrets to enable
|
| 268 |
-
βΉοΈ No EVIDENTLY_CLOUD_TOKEN - Using open-source Evidently
|
| 269 |
-
β
Initialization complete!
|
| 270 |
-
π Starting FastAPI application...
|
| 271 |
-
ββββββββββββββββββββββββββββββββββββββββββ
|
| 272 |
-
INFO: Started server process
|
| 273 |
-
```
|
| 274 |
-
|
| 275 |
-
---
|
| 276 |
-
|
| 277 |
-
## Troubleshooting
|
| 278 |
-
|
| 279 |
-
### Secret not recognized
|
| 280 |
-
**Symptom:** Logs show "No PREFECT_API_KEY found"
|
| 281 |
-
**Fix:**
|
| 282 |
-
1. Verify secret name is exactly `PREFECT_API_KEY` (case-sensitive)
|
| 283 |
-
2. Check secret value has no extra spaces
|
| 284 |
-
3. Rebuild Space: Settings β Factory reboot
|
| 285 |
-
|
| 286 |
-
### Prefect connection fails
|
| 287 |
-
**Symptom:** "Could not connect to Prefect Cloud"
|
| 288 |
-
**Fix:**
|
| 289 |
-
1. Test API key locally first:
|
| 290 |
-
```bash
|
| 291 |
-
export PREFECT_API_KEY="your-key"
|
| 292 |
-
prefect cloud workspace ls
|
| 293 |
-
```
|
| 294 |
-
2. Regenerate key if expired
|
| 295 |
-
3. Check HF Space has internet access (should be fine)
|
| 296 |
-
|
| 297 |
-
### Builds but features don't work
|
| 298 |
-
**Symptom:** App runs but cloud features inactive
|
| 299 |
-
**Fix:**
|
| 300 |
-
1. Check `/` endpoint response for cloud status
|
| 301 |
-
2. Review build logs for initialization messages
|
| 302 |
-
3. Ensure secrets were added BEFORE rebuild
|
| 303 |
-
|
| 304 |
-
---
|
| 305 |
-
|
| 306 |
-
## Cost Summary
|
| 307 |
-
|
| 308 |
-
| Service | Cost | What You Get |
|
| 309 |
-
|---------|------|-------------|
|
| 310 |
-
| **HuggingFace Spaces** | FREE | Docker hosting, public URL |
|
| 311 |
-
| **Prefect Cloud** | FREE | 2 users, 5 workflows, unlimited runs |
|
| 312 |
-
| **Evidently (Open Source)** | FREE | Local HTML reports, 100+ metrics |
|
| 313 |
-
| **Evidently Cloud** | Paid | Centralized dashboard (optional) |
|
| 314 |
-
|
| 315 |
-
**Total Cost: $0** for complete MLOps stack! π
|
| 316 |
-
|
| 317 |
-
---
|
| 318 |
-
|
| 319 |
-
## Next Steps
|
| 320 |
-
|
| 321 |
-
After successful deployment:
|
| 322 |
-
|
| 323 |
-
1. **Monitor Prefect Dashboard:** https://app.prefect.cloud/
|
| 324 |
-
2. **Test API:** https://kshitijk20-nss.hf.space/docs
|
| 325 |
-
3. **Review Documentation:**
|
| 326 |
-
- [CLOUD_MLOPS_SETUP.md](CLOUD_MLOPS_SETUP.md) - Complete cloud setup
|
| 327 |
-
- [HF_SECRETS_SETUP.md](HF_SECRETS_SETUP.md) - Secrets reference
|
| 328 |
-
4. **Set up Automations:** Configure failure alerts in Prefect
|
| 329 |
-
5. **Schedule Training:** Deploy weekly training flow
|
| 330 |
-
|
| 331 |
-
---
|
| 332 |
-
|
| 333 |
-
## Support Resources
|
| 334 |
-
|
| 335 |
-
- **Prefect Cloud:** https://docs.prefect.io/latest/cloud/
|
| 336 |
-
- **HuggingFace Spaces:** https://huggingface.co/docs/hub/spaces
|
| 337 |
-
- **Evidently:** https://docs.evidentlyai.com/
|
| 338 |
-
- **FastAPI:** https://fastapi.tiangolo.com/
|
| 339 |
-
|
| 340 |
-
---
|
| 341 |
-
|
| 342 |
-
## Files Created for Cloud MLOps
|
| 343 |
-
|
| 344 |
-
- β
**startup.sh** - Container initialization script
|
| 345 |
-
- β
**cloud_config.py** - Cloud services configuration
|
| 346 |
-
- β
**HF_SECRETS_SETUP.md** - Secrets documentation
|
| 347 |
-
- β
**CLOUD_MLOPS_SETUP.md** - Complete cloud guide
|
| 348 |
-
- β
**prepare_hf_deployment.py** - Deployment helper
|
| 349 |
-
- β
**Dockerfile** - Updated with cloud setup
|
| 350 |
-
- β
**app.py** - Integrated cloud features
|
| 351 |
-
|
| 352 |
-
All ready for `git push hf main`! π
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dockerfile
CHANGED
|
@@ -22,20 +22,13 @@ RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
|
| 22 |
COPY --chown=user . /app
|
| 23 |
|
| 24 |
# Create necessary directories
|
| 25 |
-
RUN mkdir -p /app/data /app/final_model /app/templates
|
| 26 |
-
|
| 27 |
-
# Make startup script executable
|
| 28 |
-
RUN chmod +x /app/startup.sh
|
| 29 |
|
| 30 |
# run the load_data_to_sqlite.py script to initialize the database
|
| 31 |
RUN python load_data_to_sqlite.py
|
| 32 |
|
| 33 |
-
# Run cloud configuration check (non-blocking)
|
| 34 |
-
RUN python cloud_config.py || echo "Cloud config check completed"
|
| 35 |
-
|
| 36 |
# Expose port 7860 (HF Space requirement)
|
| 37 |
EXPOSE 7860
|
| 38 |
|
| 39 |
-
#
|
| 40 |
-
ENTRYPOINT ["/app/startup.sh"]
|
| 41 |
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
|
| 22 |
COPY --chown=user . /app
|
| 23 |
|
| 24 |
# Create necessary directories
|
| 25 |
+
RUN mkdir -p /app/data /app/final_model /app/templates
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
# run the load_data_to_sqlite.py script to initialize the database
|
| 28 |
RUN python load_data_to_sqlite.py
|
| 29 |
|
|
|
|
|
|
|
|
|
|
| 30 |
# Expose port 7860 (HF Space requirement)
|
| 31 |
EXPOSE 7860
|
| 32 |
|
| 33 |
+
# Run the application
|
|
|
|
| 34 |
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
HF_SECRETS_SETUP.md
DELETED
|
@@ -1,238 +0,0 @@
|
|
| 1 |
-
# π HuggingFace Space Secrets Configuration
|
| 2 |
-
|
| 3 |
-
To enable cloud MLOps features in your HuggingFace Space, add these secrets:
|
| 4 |
-
|
| 5 |
-
## Required Secrets
|
| 6 |
-
|
| 7 |
-
### 1. Prefect Cloud (Recommended)
|
| 8 |
-
Add these to HuggingFace Space Settings β Repository secrets:
|
| 9 |
-
|
| 10 |
-
```
|
| 11 |
-
Name: PREFECT_API_KEY
|
| 12 |
-
Value: <Your Prefect Cloud API Key>
|
| 13 |
-
```
|
| 14 |
-
|
| 15 |
-
**How to get:**
|
| 16 |
-
1. Go to https://app.prefect.cloud/
|
| 17 |
-
2. Click your profile (bottom left) β API Keys
|
| 18 |
-
3. Click "Create API Key"
|
| 19 |
-
4. Name it "HuggingFace-NSS"
|
| 20 |
-
5. Copy the key and paste as secret
|
| 21 |
-
|
| 22 |
-
### 2. Prefect Workspace (Optional)
|
| 23 |
-
```
|
| 24 |
-
Name: PREFECT_WORKSPACE
|
| 25 |
-
Value: <Your workspace ID or name>
|
| 26 |
-
```
|
| 27 |
-
|
| 28 |
-
**How to get:**
|
| 29 |
-
- In Prefect Cloud, go to workspace settings
|
| 30 |
-
- Copy the workspace name (e.g., "my-workspace/phishing-detection")
|
| 31 |
-
|
| 32 |
-
### 3. Auto-Deploy Flows (Optional)
|
| 33 |
-
```
|
| 34 |
-
Name: AUTO_DEPLOY_FLOWS
|
| 35 |
-
Value: true
|
| 36 |
-
```
|
| 37 |
-
Set to `true` if you want flows automatically deployed on container start.
|
| 38 |
-
|
| 39 |
-
---
|
| 40 |
-
|
| 41 |
-
## Optional Secrets
|
| 42 |
-
|
| 43 |
-
### Evidently Cloud (For Enterprise Users)
|
| 44 |
-
```
|
| 45 |
-
Name: EVIDENTLY_CLOUD_TOKEN
|
| 46 |
-
Value: <Your Evidently Cloud Token>
|
| 47 |
-
```
|
| 48 |
-
|
| 49 |
-
```
|
| 50 |
-
Name: EVIDENTLY_PROJECT_ID
|
| 51 |
-
Value: <Your Project ID>
|
| 52 |
-
```
|
| 53 |
-
|
| 54 |
-
**How to get:**
|
| 55 |
-
- Contact Evidently AI for cloud access: https://www.evidentlyai.com/get-demo
|
| 56 |
-
- They will provide token and project ID
|
| 57 |
-
|
| 58 |
-
### Additional Configuration
|
| 59 |
-
```
|
| 60 |
-
Name: MONITORING_ENABLED
|
| 61 |
-
Value: true (default)
|
| 62 |
-
```
|
| 63 |
-
|
| 64 |
-
```
|
| 65 |
-
Name: DRIFT_CHECK_ENABLED
|
| 66 |
-
Value: false (set to true for automated drift checks)
|
| 67 |
-
```
|
| 68 |
-
|
| 69 |
-
---
|
| 70 |
-
|
| 71 |
-
## How to Add Secrets to HuggingFace Space
|
| 72 |
-
|
| 73 |
-
### Method 1: Web UI (Recommended)
|
| 74 |
-
1. Go to your HuggingFace Space: https://huggingface.co/spaces/kshitijk20/nss
|
| 75 |
-
2. Click **"Settings"** tab
|
| 76 |
-
3. Scroll to **"Repository secrets"**
|
| 77 |
-
4. Click **"Add a secret"**
|
| 78 |
-
5. Enter **Name** and **Value**
|
| 79 |
-
6. Click **"Add secret"**
|
| 80 |
-
7. Rebuild your Space (Settings β Factory reboot)
|
| 81 |
-
|
| 82 |
-
### Method 2: CLI
|
| 83 |
-
```bash
|
| 84 |
-
# Install HuggingFace CLI
|
| 85 |
-
pip install huggingface_hub
|
| 86 |
-
|
| 87 |
-
# Login
|
| 88 |
-
huggingface-cli login
|
| 89 |
-
|
| 90 |
-
# Add secret
|
| 91 |
-
huggingface-cli space add-secret kshitijk20/nss PREFECT_API_KEY "your-api-key-here"
|
| 92 |
-
```
|
| 93 |
-
|
| 94 |
-
---
|
| 95 |
-
|
| 96 |
-
## Testing Configuration
|
| 97 |
-
|
| 98 |
-
After adding secrets and rebuilding:
|
| 99 |
-
|
| 100 |
-
1. **Check Logs:**
|
| 101 |
-
- Go to your Space β Logs tab
|
| 102 |
-
- Look for: "β
Prefect Cloud configured successfully"
|
| 103 |
-
|
| 104 |
-
2. **Verify Prefect Connection:**
|
| 105 |
-
- In Prefect Cloud dashboard: https://app.prefect.cloud/
|
| 106 |
-
- Check if deployments appear
|
| 107 |
-
|
| 108 |
-
3. **Test Endpoints:**
|
| 109 |
-
```bash
|
| 110 |
-
# Training endpoint
|
| 111 |
-
curl -X GET "https://kshitijk20-nss.hf.space/train"
|
| 112 |
-
|
| 113 |
-
# Prediction endpoint
|
| 114 |
-
curl -X POST "https://kshitijk20-nss.hf.space/predict" \
|
| 115 |
-
-F "file=@data/phisingData.csv"
|
| 116 |
-
```
|
| 117 |
-
|
| 118 |
-
---
|
| 119 |
-
|
| 120 |
-
## Environment Variables Summary
|
| 121 |
-
|
| 122 |
-
| Variable | Required | Default | Purpose |
|
| 123 |
-
|----------|----------|---------|---------|
|
| 124 |
-
| `PREFECT_API_KEY` | β
Recommended | None | Connect to Prefect Cloud |
|
| 125 |
-
| `PREFECT_API_URL` | β | https://api.prefect.cloud/api | Prefect API endpoint |
|
| 126 |
-
| `PREFECT_WORKSPACE` | β | None | Specific workspace |
|
| 127 |
-
| `AUTO_DEPLOY_FLOWS` | β | false | Auto-deploy on startup |
|
| 128 |
-
| `EVIDENTLY_CLOUD_TOKEN` | β | None | Evidently Cloud (paid) |
|
| 129 |
-
| `EVIDENTLY_PROJECT_ID` | β | None | Evidently project |
|
| 130 |
-
| `MONITORING_ENABLED` | β | true | Enable monitoring |
|
| 131 |
-
| `DRIFT_CHECK_ENABLED` | β | false | Auto drift checks |
|
| 132 |
-
|
| 133 |
-
---
|
| 134 |
-
|
| 135 |
-
## Architecture with Secrets
|
| 136 |
-
|
| 137 |
-
```
|
| 138 |
-
βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 139 |
-
β HuggingFace Space (Docker Container) β
|
| 140 |
-
β ββββββββββββββββββββββββββββββββββββββββββ β
|
| 141 |
-
β β Environment Variables (Secrets) β β
|
| 142 |
-
β β - PREFECT_API_KEY β β
|
| 143 |
-
β β - EVIDENTLY_CLOUD_TOKEN (optional) β β
|
| 144 |
-
β ββββββββββββββββββββββββββββββββββββββββββ β
|
| 145 |
-
β β β
|
| 146 |
-
β ββββββββββββββββββββββββββββββββββββββββββ β
|
| 147 |
-
β β startup.sh (Initialization) β β
|
| 148 |
-
β β - Configures Prefect Cloud β β
|
| 149 |
-
β β - Sets up Evidently β β
|
| 150 |
-
β β - Creates directories β β
|
| 151 |
-
β ββββββββββββββββββββββββββββββββββββββββββ β
|
| 152 |
-
β β β
|
| 153 |
-
β ββββββββββββββββββββββββββββββββββββββββββ β
|
| 154 |
-
β β FastAPI App (app.py) β β
|
| 155 |
-
β β - Serves predictions β β
|
| 156 |
-
β β - Training endpoint β β
|
| 157 |
-
β β - Reports to Prefect Cloud β β
|
| 158 |
-
β βββββββββββββββββββββββββββββββββοΏ½οΏ½οΏ½ββββββββ β
|
| 159 |
-
βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 160 |
-
β
|
| 161 |
-
βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 162 |
-
β Prefect Cloud (Monitoring) β
|
| 163 |
-
β - Flow execution logs β
|
| 164 |
-
β - Training history β
|
| 165 |
-
β - Automated scheduling β
|
| 166 |
-
βββββββββββββββββββββββββββββββββββββββββββββββ
|
| 167 |
-
```
|
| 168 |
-
|
| 169 |
-
---
|
| 170 |
-
|
| 171 |
-
## Troubleshooting
|
| 172 |
-
|
| 173 |
-
### Secret not recognized
|
| 174 |
-
**Problem:** Container doesn't see secret
|
| 175 |
-
**Solution:**
|
| 176 |
-
- Verify secret name matches exactly (case-sensitive)
|
| 177 |
-
- Rebuild Space (Settings β Factory reboot)
|
| 178 |
-
- Check logs for initialization messages
|
| 179 |
-
|
| 180 |
-
### Prefect connection fails
|
| 181 |
-
**Problem:** "Could not connect to Prefect Cloud"
|
| 182 |
-
**Solution:**
|
| 183 |
-
- Verify API key is valid (test locally first)
|
| 184 |
-
- Check PREFECT_API_URL is correct
|
| 185 |
-
- Ensure network access from HF Spaces
|
| 186 |
-
|
| 187 |
-
### Auto-deploy fails
|
| 188 |
-
**Problem:** Flows not deploying automatically
|
| 189 |
-
**Solution:**
|
| 190 |
-
- Set `AUTO_DEPLOY_FLOWS=true`
|
| 191 |
-
- Check prefect_flows/ directory exists
|
| 192 |
-
- Review logs for deployment errors
|
| 193 |
-
|
| 194 |
-
---
|
| 195 |
-
|
| 196 |
-
## Security Best Practices
|
| 197 |
-
|
| 198 |
-
1. **Never commit secrets to git**
|
| 199 |
-
- Use `.gitignore` for local `.env` files
|
| 200 |
-
- Only use HF Space secrets feature
|
| 201 |
-
|
| 202 |
-
2. **Rotate keys regularly**
|
| 203 |
-
- Update Prefect API key monthly
|
| 204 |
-
- Delete old unused keys
|
| 205 |
-
|
| 206 |
-
3. **Use minimal permissions**
|
| 207 |
-
- Create separate API keys for different environments
|
| 208 |
-
- Limit key scope to required operations
|
| 209 |
-
|
| 210 |
-
4. **Monitor access**
|
| 211 |
-
- Check Prefect Cloud audit logs
|
| 212 |
-
- Review Space access logs
|
| 213 |
-
|
| 214 |
-
---
|
| 215 |
-
|
| 216 |
-
## Next Steps
|
| 217 |
-
|
| 218 |
-
After configuration:
|
| 219 |
-
|
| 220 |
-
1. **Test locally first:**
|
| 221 |
-
```bash
|
| 222 |
-
export PREFECT_API_KEY="your-key"
|
| 223 |
-
python cloud_config.py
|
| 224 |
-
```
|
| 225 |
-
|
| 226 |
-
2. **Add to HuggingFace Space**
|
| 227 |
-
3. **Rebuild and monitor logs**
|
| 228 |
-
4. **Verify Prefect Cloud shows deployments**
|
| 229 |
-
5. **Run training to test end-to-end**
|
| 230 |
-
|
| 231 |
-
---
|
| 232 |
-
|
| 233 |
-
## Support
|
| 234 |
-
|
| 235 |
-
- **Prefect Cloud:** https://docs.prefect.io/latest/cloud/
|
| 236 |
-
- **HuggingFace Spaces:** https://huggingface.co/docs/hub/spaces
|
| 237 |
-
- **Evidently:** https://docs.evidentlyai.com/
|
| 238 |
-
- **Project Issues:** Report bugs in your GitHub repository
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
|
@@ -12,16 +12,6 @@ from starlette.responses import RedirectResponse
|
|
| 12 |
import pandas as pd
|
| 13 |
from src.utils.ml_utils.model.estimator import NetworkSecurityModel
|
| 14 |
|
| 15 |
-
# Initialize cloud configuration
|
| 16 |
-
try:
|
| 17 |
-
from cloud_config import initialize_monitoring, ENABLE_PREFECT
|
| 18 |
-
cloud_status = initialize_monitoring()
|
| 19 |
-
logging.info(f"Cloud MLOps initialized: {cloud_status}")
|
| 20 |
-
except Exception as e:
|
| 21 |
-
logging.warning(f"Cloud config initialization failed: {e}")
|
| 22 |
-
ENABLE_PREFECT = False
|
| 23 |
-
cloud_status = {"prefect": False, "evidently": False}
|
| 24 |
-
|
| 25 |
ca = certifi.where()
|
| 26 |
load_dotenv()
|
| 27 |
mongo_db_uri = os.getenv("MONGO_DB_URI")
|
|
@@ -58,11 +48,6 @@ async def root():
|
|
| 58 |
return {
|
| 59 |
"status": "running",
|
| 60 |
"service": "Network Security System - Phishing Detection",
|
| 61 |
-
"cloud_mlops": {
|
| 62 |
-
"prefect_cloud": "enabled" if cloud_status.get("prefect") else "disabled",
|
| 63 |
-
"evidently": "cloud" if cloud_status.get("evidently") else "open-source",
|
| 64 |
-
"monitoring": "enabled" if cloud_status.get("monitoring") else "disabled"
|
| 65 |
-
},
|
| 66 |
"endpoints": {
|
| 67 |
"docs": "/docs",
|
| 68 |
"train": "/train",
|
|
@@ -74,18 +59,9 @@ async def root():
|
|
| 74 |
async def training_route():
|
| 75 |
try:
|
| 76 |
logging.info("Starting training pipeline...")
|
| 77 |
-
|
| 78 |
-
# Run training directly - Prefect Cloud monitoring happens in prefect_flows if needed
|
| 79 |
training_pipeline = Trainingpipeline()
|
| 80 |
training_pipeline.run_pipeline()
|
| 81 |
-
|
| 82 |
-
status_msg = "β
Training completed successfully!"
|
| 83 |
-
if ENABLE_PREFECT:
|
| 84 |
-
status_msg += "\n\nπ Prefect Cloud connected - Run flows via prefect_flows/ directory"
|
| 85 |
-
status_msg += "\n Dashboard: https://app.prefect.cloud/"
|
| 86 |
-
|
| 87 |
-
return Response(status_msg)
|
| 88 |
-
return Response("Training completed successfully (direct mode)")
|
| 89 |
except Exception as e:
|
| 90 |
raise NetworkSecurityException(e, sys)
|
| 91 |
|
|
|
|
| 12 |
import pandas as pd
|
| 13 |
from src.utils.ml_utils.model.estimator import NetworkSecurityModel
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
ca = certifi.where()
|
| 16 |
load_dotenv()
|
| 17 |
mongo_db_uri = os.getenv("MONGO_DB_URI")
|
|
|
|
| 48 |
return {
|
| 49 |
"status": "running",
|
| 50 |
"service": "Network Security System - Phishing Detection",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
"endpoints": {
|
| 52 |
"docs": "/docs",
|
| 53 |
"train": "/train",
|
|
|
|
| 59 |
async def training_route():
|
| 60 |
try:
|
| 61 |
logging.info("Starting training pipeline...")
|
|
|
|
|
|
|
| 62 |
training_pipeline = Trainingpipeline()
|
| 63 |
training_pipeline.run_pipeline()
|
| 64 |
+
return Response("Training completed successfully!")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
except Exception as e:
|
| 66 |
raise NetworkSecurityException(e, sys)
|
| 67 |
|
cloud_config.py
DELETED
|
@@ -1,102 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Cloud MLOps Configuration for HuggingFace Spaces
|
| 3 |
-
Handles Prefect Cloud and Evidently integration via environment variables
|
| 4 |
-
"""
|
| 5 |
-
import os
|
| 6 |
-
import sys
|
| 7 |
-
from pathlib import Path
|
| 8 |
-
|
| 9 |
-
# Prefect Cloud Configuration
|
| 10 |
-
PREFECT_API_KEY = os.getenv("PREFECT_API_KEY")
|
| 11 |
-
PREFECT_API_URL = os.getenv("PREFECT_API_URL", "https://api.prefect.cloud/api")
|
| 12 |
-
PREFECT_WORKSPACE = os.getenv("PREFECT_WORKSPACE")
|
| 13 |
-
AUTO_DEPLOY_FLOWS = os.getenv("AUTO_DEPLOY_FLOWS", "false").lower() == "true"
|
| 14 |
-
|
| 15 |
-
# Evidently Cloud Configuration (Optional)
|
| 16 |
-
EVIDENTLY_CLOUD_TOKEN = os.getenv("EVIDENTLY_CLOUD_TOKEN") or os.getenv("EVIDENTLY_API_KEY")
|
| 17 |
-
EVIDENTLY_PROJECT_ID = os.getenv("EVIDENTLY_PROJECT_ID")
|
| 18 |
-
|
| 19 |
-
# Feature Flags
|
| 20 |
-
ENABLE_PREFECT = PREFECT_API_KEY is not None
|
| 21 |
-
ENABLE_EVIDENTLY_CLOUD = EVIDENTLY_CLOUD_TOKEN is not None
|
| 22 |
-
|
| 23 |
-
# Monitoring Configuration
|
| 24 |
-
MONITORING_ENABLED = os.getenv("MONITORING_ENABLED", "true").lower() == "true"
|
| 25 |
-
DRIFT_CHECK_ENABLED = os.getenv("DRIFT_CHECK_ENABLED", "false").lower() == "true"
|
| 26 |
-
|
| 27 |
-
def setup_prefect_cloud():
|
| 28 |
-
"""Configure Prefect Cloud connection"""
|
| 29 |
-
if not ENABLE_PREFECT:
|
| 30 |
-
print("βΉοΈ Prefect Cloud disabled - No API key provided")
|
| 31 |
-
return False
|
| 32 |
-
|
| 33 |
-
try:
|
| 34 |
-
from prefect import settings
|
| 35 |
-
|
| 36 |
-
print("π§ Configuring Prefect Cloud...")
|
| 37 |
-
os.environ["PREFECT_API_KEY"] = PREFECT_API_KEY
|
| 38 |
-
os.environ["PREFECT_API_URL"] = PREFECT_API_URL
|
| 39 |
-
|
| 40 |
-
if PREFECT_WORKSPACE:
|
| 41 |
-
os.environ["PREFECT_WORKSPACE"] = PREFECT_WORKSPACE
|
| 42 |
-
|
| 43 |
-
print("β
Prefect Cloud configured successfully")
|
| 44 |
-
return True
|
| 45 |
-
except Exception as e:
|
| 46 |
-
print(f"β οΈ Failed to configure Prefect Cloud: {e}")
|
| 47 |
-
return False
|
| 48 |
-
|
| 49 |
-
def setup_evidently_cloud():
|
| 50 |
-
"""Configure Evidently Cloud connection"""
|
| 51 |
-
if not ENABLE_EVIDENTLY_CLOUD:
|
| 52 |
-
print("βΉοΈ Evidently Cloud disabled - Using open source version")
|
| 53 |
-
return False
|
| 54 |
-
|
| 55 |
-
try:
|
| 56 |
-
os.environ["EVIDENTLY_CLOUD_TOKEN"] = EVIDENTLY_CLOUD_TOKEN
|
| 57 |
-
if EVIDENTLY_PROJECT_ID:
|
| 58 |
-
os.environ["EVIDENTLY_PROJECT_ID"] = EVIDENTLY_PROJECT_ID
|
| 59 |
-
|
| 60 |
-
print("β
Evidently Cloud configured successfully")
|
| 61 |
-
return True
|
| 62 |
-
except Exception as e:
|
| 63 |
-
print(f"β οΈ Failed to configure Evidently Cloud: {e}")
|
| 64 |
-
return False
|
| 65 |
-
|
| 66 |
-
def initialize_monitoring():
|
| 67 |
-
"""Initialize monitoring systems"""
|
| 68 |
-
print("\n" + "="*60)
|
| 69 |
-
print("π§ Cloud MLOps Configuration")
|
| 70 |
-
print("="*60)
|
| 71 |
-
|
| 72 |
-
# Setup Prefect
|
| 73 |
-
prefect_ok = setup_prefect_cloud()
|
| 74 |
-
|
| 75 |
-
# Setup Evidently
|
| 76 |
-
evidently_ok = setup_evidently_cloud()
|
| 77 |
-
|
| 78 |
-
# Create monitoring directories
|
| 79 |
-
Path("monitoring/reports").mkdir(parents=True, exist_ok=True)
|
| 80 |
-
Path("final_model").mkdir(parents=True, exist_ok=True)
|
| 81 |
-
|
| 82 |
-
print("\n" + "="*60)
|
| 83 |
-
print("β
Monitoring Configuration Summary")
|
| 84 |
-
print("="*60)
|
| 85 |
-
print(f"Prefect Cloud: {'β
Enabled' if prefect_ok else 'β Disabled'}")
|
| 86 |
-
print(f"Evidently Cloud: {'β
Enabled' if evidently_ok else 'β Open Source'}")
|
| 87 |
-
print(f"Drift Monitoring: {'β
Enabled' if DRIFT_CHECK_ENABLED else 'β Disabled'}")
|
| 88 |
-
print("="*60 + "\n")
|
| 89 |
-
|
| 90 |
-
return {
|
| 91 |
-
"prefect": prefect_ok,
|
| 92 |
-
"evidently": evidently_ok,
|
| 93 |
-
"monitoring": MONITORING_ENABLED
|
| 94 |
-
}
|
| 95 |
-
|
| 96 |
-
if __name__ == "__main__":
|
| 97 |
-
# Run initialization
|
| 98 |
-
config = initialize_monitoring()
|
| 99 |
-
|
| 100 |
-
# Print configuration for debugging
|
| 101 |
-
import json
|
| 102 |
-
print("Configuration:", json.dumps(config, indent=2))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
monitoring/evidently_monitor.py
DELETED
|
@@ -1,242 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Evidently Monitoring Module
|
| 3 |
-
Tracks data drift, model performance, and data quality
|
| 4 |
-
"""
|
| 5 |
-
import pandas as pd
|
| 6 |
-
from evidently.report import Report
|
| 7 |
-
from evidently.metric_preset import DataDriftPreset, DataQualityPreset, TargetDriftPreset
|
| 8 |
-
from evidently.metrics import *
|
| 9 |
-
from datetime import datetime
|
| 10 |
-
import json
|
| 11 |
-
import os
|
| 12 |
-
|
| 13 |
-
class PhishingModelMonitor:
|
| 14 |
-
"""Monitor phishing detection model for drift and performance"""
|
| 15 |
-
|
| 16 |
-
def __init__(self, reference_data_path="data/phisingData.csv"):
|
| 17 |
-
"""
|
| 18 |
-
Initialize monitor with reference dataset
|
| 19 |
-
|
| 20 |
-
Args:
|
| 21 |
-
reference_data_path: Path to the original training data
|
| 22 |
-
"""
|
| 23 |
-
self.reference_data = pd.read_csv(reference_data_path)
|
| 24 |
-
self.reports_dir = "monitoring/reports"
|
| 25 |
-
os.makedirs(self.reports_dir, exist_ok=True)
|
| 26 |
-
|
| 27 |
-
# Check for Evidently Cloud integration
|
| 28 |
-
self.evidently_cloud_token = os.getenv("EVIDENTLY_CLOUD_TOKEN") or os.getenv("EVIDENTLY_API_KEY")
|
| 29 |
-
self.evidently_project_id = os.getenv("EVIDENTLY_PROJECT_ID") or "nss" # Default to "nss"
|
| 30 |
-
self.use_evidently_cloud = self.evidently_cloud_token is not None
|
| 31 |
-
|
| 32 |
-
if self.use_evidently_cloud:
|
| 33 |
-
print(f"β
Evidently Cloud integration enabled (Project: {self.evidently_project_id})")
|
| 34 |
-
try:
|
| 35 |
-
from evidently.ui.workspace.cloud import CloudWorkspace
|
| 36 |
-
# Initialize Evidently Cloud workspace
|
| 37 |
-
self.workspace = CloudWorkspace(
|
| 38 |
-
token=self.evidently_cloud_token,
|
| 39 |
-
url="https://app.evidently.cloud"
|
| 40 |
-
)
|
| 41 |
-
# Get or create project
|
| 42 |
-
try:
|
| 43 |
-
self.project = self.workspace.get_project(self.evidently_project_id)
|
| 44 |
-
print(f"β
Connected to Evidently Cloud project: {self.evidently_project_id}")
|
| 45 |
-
except:
|
| 46 |
-
# Project might be referenced by name, try to find it
|
| 47 |
-
print(f"π¦ Looking for project: {self.evidently_project_id}")
|
| 48 |
-
self.project = None # Will create reports without project reference
|
| 49 |
-
|
| 50 |
-
except Exception as e:
|
| 51 |
-
print(f"β οΈ Evidently Cloud setup warning: {e}")
|
| 52 |
-
self.use_evidently_cloud = False
|
| 53 |
-
else:
|
| 54 |
-
print("βΉοΈ Using Evidently open-source (local reports only)")
|
| 55 |
-
|
| 56 |
-
def generate_data_drift_report(self, current_data: pd.DataFrame):
|
| 57 |
-
"""
|
| 58 |
-
Generate data drift report comparing current data with reference
|
| 59 |
-
Saves locally AND pushes to Evidently Cloud if enabled
|
| 60 |
-
|
| 61 |
-
Args:
|
| 62 |
-
current_data: Recent prediction data
|
| 63 |
-
|
| 64 |
-
Returns:
|
| 65 |
-
Report object and saves HTML report
|
| 66 |
-
"""
|
| 67 |
-
# Create drift report
|
| 68 |
-
report = Report(metrics=[
|
| 69 |
-
DataDriftPreset(),
|
| 70 |
-
DataQualityPreset(),
|
| 71 |
-
])
|
| 72 |
-
|
| 73 |
-
report.run(
|
| 74 |
-
reference_data=self.reference_data,
|
| 75 |
-
current_data=current_data
|
| 76 |
-
)
|
| 77 |
-
|
| 78 |
-
# Save local HTML report
|
| 79 |
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 80 |
-
report_path = f"{self.reports_dir}/drift_report_{timestamp}.html"
|
| 81 |
-
report.save_html(report_path)
|
| 82 |
-
|
| 83 |
-
# Push to Evidently Cloud if enabled
|
| 84 |
-
if self.use_evidently_cloud and self.project:
|
| 85 |
-
try:
|
| 86 |
-
self.workspace.add_report(self.project.id, report)
|
| 87 |
-
print(f"β
Report pushed to Evidently Cloud: {self.evidently_project_id}")
|
| 88 |
-
except Exception as e:
|
| 89 |
-
print(f"β οΈ Failed to push to Evidently Cloud: {e}")
|
| 90 |
-
|
| 91 |
-
# Extract metrics
|
| 92 |
-
report_json = report.as_dict()
|
| 93 |
-
|
| 94 |
-
return {
|
| 95 |
-
"report_path": report_path,
|
| 96 |
-
"metrics": self._extract_drift_metrics(report_json),
|
| 97 |
-
"timestamp": timestamp
|
| 98 |
-
}
|
| 99 |
-
|
| 100 |
-
def generate_model_performance_report(self, current_data: pd.DataFrame,
|
| 101 |
-
predictions: pd.Series,
|
| 102 |
-
actuals: pd.Series = None):
|
| 103 |
-
"""
|
| 104 |
-
Generate model performance report
|
| 105 |
-
|
| 106 |
-
Args:
|
| 107 |
-
current_data: Feature data
|
| 108 |
-
predictions: Model predictions
|
| 109 |
-
actuals: Actual labels (if available)
|
| 110 |
-
"""
|
| 111 |
-
current_data = current_data.copy()
|
| 112 |
-
current_data['prediction'] = predictions
|
| 113 |
-
|
| 114 |
-
if actuals is not None:
|
| 115 |
-
current_data['target'] = actuals
|
| 116 |
-
reference_data = self.reference_data.copy()
|
| 117 |
-
|
| 118 |
-
# Create performance report
|
| 119 |
-
report = Report(metrics=[
|
| 120 |
-
ClassificationQualityMetric(),
|
| 121 |
-
ClassificationClassBalance(),
|
| 122 |
-
ClassificationConfusionMatrix(),
|
| 123 |
-
ClassificationQualityByClass()
|
| 124 |
-
])
|
| 125 |
-
|
| 126 |
-
report.run(
|
| 127 |
-
reference_data=reference_data,
|
| 128 |
-
current_data=current_data,
|
| 129 |
-
column_mapping={
|
| 130 |
-
'target': 'Result',
|
| 131 |
-
'prediction': 'prediction'
|
| 132 |
-
}
|
| 133 |
-
)
|
| 134 |
-
else:
|
| 135 |
-
# Only prediction drift if no actuals
|
| 136 |
-
report = Report(metrics=[
|
| 137 |
-
TargetDriftPreset(),
|
| 138 |
-
])
|
| 139 |
-
|
| 140 |
-
report.run(
|
| 141 |
-
reference_data=self.reference_data,
|
| 142 |
-
current_data=current_data,
|
| 143 |
-
column_mapping={'prediction': 'prediction'}
|
| 144 |
-
)
|
| 145 |
-
|
| 146 |
-
# Save report
|
| 147 |
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 148 |
-
report_path = f"{self.reports_dir}/performance_report_{timestamp}.html"
|
| 149 |
-
report.save_html(report_path)
|
| 150 |
-
|
| 151 |
-
return {
|
| 152 |
-
"report_path": report_path,
|
| 153 |
-
"timestamp": timestamp
|
| 154 |
-
}
|
| 155 |
-
|
| 156 |
-
def _extract_drift_metrics(self, report_json):
|
| 157 |
-
"""Extract key metrics from drift report"""
|
| 158 |
-
try:
|
| 159 |
-
metrics = report_json.get('metrics', [])
|
| 160 |
-
drift_summary = {
|
| 161 |
-
'dataset_drift': False,
|
| 162 |
-
'number_of_drifted_columns': 0,
|
| 163 |
-
'share_of_drifted_columns': 0.0,
|
| 164 |
-
'drifted_features': []
|
| 165 |
-
}
|
| 166 |
-
|
| 167 |
-
for metric in metrics:
|
| 168 |
-
if metric.get('metric') == 'DatasetDriftMetric':
|
| 169 |
-
result = metric.get('result', {})
|
| 170 |
-
drift_summary['dataset_drift'] = result.get('dataset_drift', False)
|
| 171 |
-
drift_summary['number_of_drifted_columns'] = result.get('number_of_drifted_columns', 0)
|
| 172 |
-
drift_summary['share_of_drifted_columns'] = result.get('share_of_drifted_columns', 0.0)
|
| 173 |
-
|
| 174 |
-
# Extract drifted features
|
| 175 |
-
drift_by_columns = result.get('drift_by_columns', {})
|
| 176 |
-
drift_summary['drifted_features'] = [
|
| 177 |
-
col for col, info in drift_by_columns.items()
|
| 178 |
-
if info.get('drift_detected', False)
|
| 179 |
-
]
|
| 180 |
-
break
|
| 181 |
-
|
| 182 |
-
return drift_summary
|
| 183 |
-
except Exception as e:
|
| 184 |
-
return {"error": str(e)}
|
| 185 |
-
|
| 186 |
-
def check_drift_threshold(self, drift_metrics, threshold=0.3):
|
| 187 |
-
"""
|
| 188 |
-
Check if drift exceeds threshold
|
| 189 |
-
|
| 190 |
-
Args:
|
| 191 |
-
drift_metrics: Output from generate_data_drift_report
|
| 192 |
-
threshold: Maximum acceptable share of drifted columns
|
| 193 |
-
|
| 194 |
-
Returns:
|
| 195 |
-
bool: True if retraining is recommended
|
| 196 |
-
"""
|
| 197 |
-
share_drifted = drift_metrics['metrics'].get('share_of_drifted_columns', 0)
|
| 198 |
-
return share_drifted > threshold
|
| 199 |
-
|
| 200 |
-
def save_monitoring_state(self, metrics, filepath="monitoring/monitoring_state.json"):
|
| 201 |
-
"""Save monitoring metrics to file"""
|
| 202 |
-
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
| 203 |
-
|
| 204 |
-
state = {
|
| 205 |
-
"last_check": datetime.now().isoformat(),
|
| 206 |
-
"metrics": metrics
|
| 207 |
-
}
|
| 208 |
-
|
| 209 |
-
with open(filepath, 'w') as f:
|
| 210 |
-
json.dump(state, f, indent=2)
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
# Utility function to monitor predictions
|
| 214 |
-
def monitor_predictions(data_csv_path: str, reference_csv_path: str = "data/phisingData.csv"):
|
| 215 |
-
"""
|
| 216 |
-
Quick function to monitor predictions from CSV
|
| 217 |
-
|
| 218 |
-
Args:
|
| 219 |
-
data_csv_path: Path to CSV with recent predictions
|
| 220 |
-
reference_csv_path: Path to reference training data
|
| 221 |
-
"""
|
| 222 |
-
monitor = PhishingModelMonitor(reference_csv_path)
|
| 223 |
-
current_data = pd.read_csv(data_csv_path)
|
| 224 |
-
|
| 225 |
-
# Generate drift report
|
| 226 |
-
drift_result = monitor.generate_data_drift_report(current_data)
|
| 227 |
-
|
| 228 |
-
print(f"π Drift Report Generated: {drift_result['report_path']}")
|
| 229 |
-
print(f"π Metrics: {drift_result['metrics']}")
|
| 230 |
-
|
| 231 |
-
# Check if retraining needed
|
| 232 |
-
if monitor.check_drift_threshold(drift_result):
|
| 233 |
-
print("β οΈ WARNING: Significant drift detected! Retraining recommended.")
|
| 234 |
-
else:
|
| 235 |
-
print("β
Drift within acceptable limits.")
|
| 236 |
-
|
| 237 |
-
return drift_result
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
if __name__ == "__main__":
|
| 241 |
-
# Example: Monitor predictions
|
| 242 |
-
monitor_predictions("final_model/predicted.csv")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prefect_flows/deploy_schedule.py
DELETED
|
@@ -1,26 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Deploy Prefect flow with scheduling
|
| 3 |
-
Run this script to create a scheduled deployment for automated training
|
| 4 |
-
"""
|
| 5 |
-
from prefect.deployments import Deployment
|
| 6 |
-
from prefect.server.schemas.schedules import CronSchedule
|
| 7 |
-
from training_flow import training_flow
|
| 8 |
-
|
| 9 |
-
# Create deployment with weekly schedule (every Sunday at 2 AM)
|
| 10 |
-
deployment = Deployment.build_from_flow(
|
| 11 |
-
flow=training_flow,
|
| 12 |
-
name="weekly-training",
|
| 13 |
-
schedule=CronSchedule(cron="0 2 * * 0", timezone="UTC"), # Every Sunday at 2 AM UTC
|
| 14 |
-
work_queue_name="training",
|
| 15 |
-
tags=["production", "ml-training", "phishing-detection"],
|
| 16 |
-
description="Weekly automated retraining of phishing detection model",
|
| 17 |
-
version="1.0.0"
|
| 18 |
-
)
|
| 19 |
-
|
| 20 |
-
if __name__ == "__main__":
|
| 21 |
-
# Deploy the flow
|
| 22 |
-
deployment.apply()
|
| 23 |
-
print("β
Deployment created successfully!")
|
| 24 |
-
print("π
Schedule: Every Sunday at 2:00 AM UTC")
|
| 25 |
-
print("\nTo start the worker, run:")
|
| 26 |
-
print(" prefect agent start -q training")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prefect_flows/drift_monitoring_flow.py
DELETED
|
@@ -1,96 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Example: Run Evidently monitoring on scheduled basis
|
| 3 |
-
Can be integrated with Prefect for automated monitoring
|
| 4 |
-
"""
|
| 5 |
-
import sys
|
| 6 |
-
sys.path.append('..')
|
| 7 |
-
|
| 8 |
-
from monitoring.evidently_monitor import PhishingModelMonitor
|
| 9 |
-
from prefect import flow, task
|
| 10 |
-
from prefect.task_runners import ConcurrentTaskRunner
|
| 11 |
-
import pandas as pd
|
| 12 |
-
from src.logging.logger import logging
|
| 13 |
-
|
| 14 |
-
@task(name="check_data_drift")
|
| 15 |
-
def check_drift():
|
| 16 |
-
"""Check for data drift in recent predictions"""
|
| 17 |
-
try:
|
| 18 |
-
logging.info("Checking for data drift...")
|
| 19 |
-
monitor = PhishingModelMonitor()
|
| 20 |
-
|
| 21 |
-
# Load recent predictions
|
| 22 |
-
current_data = pd.read_csv("final_model/predicted.csv")
|
| 23 |
-
|
| 24 |
-
# Generate drift report
|
| 25 |
-
drift_result = monitor.generate_data_drift_report(current_data)
|
| 26 |
-
|
| 27 |
-
logging.info(f"Drift metrics: {drift_result['metrics']}")
|
| 28 |
-
|
| 29 |
-
# Check if retraining needed
|
| 30 |
-
needs_retraining = monitor.check_drift_threshold(drift_result)
|
| 31 |
-
|
| 32 |
-
if needs_retraining:
|
| 33 |
-
logging.warning("β οΈ Significant drift detected! Retraining recommended.")
|
| 34 |
-
else:
|
| 35 |
-
logging.info("β
Drift within acceptable limits.")
|
| 36 |
-
|
| 37 |
-
return {
|
| 38 |
-
"needs_retraining": needs_retraining,
|
| 39 |
-
"drift_metrics": drift_result['metrics'],
|
| 40 |
-
"report_path": drift_result['report_path']
|
| 41 |
-
}
|
| 42 |
-
except Exception as e:
|
| 43 |
-
logging.error(f"Drift monitoring failed: {str(e)}")
|
| 44 |
-
raise
|
| 45 |
-
|
| 46 |
-
@task(name="trigger_retraining")
|
| 47 |
-
def trigger_retraining():
|
| 48 |
-
"""Trigger retraining pipeline if drift detected"""
|
| 49 |
-
try:
|
| 50 |
-
from training_flow import training_flow
|
| 51 |
-
logging.info("Triggering retraining due to drift...")
|
| 52 |
-
|
| 53 |
-
# Run training flow
|
| 54 |
-
result = training_flow()
|
| 55 |
-
|
| 56 |
-
logging.info(f"Retraining completed: {result}")
|
| 57 |
-
return result
|
| 58 |
-
except Exception as e:
|
| 59 |
-
logging.error(f"Retraining failed: {str(e)}")
|
| 60 |
-
raise
|
| 61 |
-
|
| 62 |
-
@flow(
|
| 63 |
-
name="drift-monitoring-flow",
|
| 64 |
-
description="Monitor data drift and trigger retraining if needed",
|
| 65 |
-
task_runner=ConcurrentTaskRunner()
|
| 66 |
-
)
|
| 67 |
-
def drift_monitoring_flow():
|
| 68 |
-
"""
|
| 69 |
-
Main flow for drift monitoring
|
| 70 |
-
Checks drift and triggers retraining if threshold exceeded
|
| 71 |
-
"""
|
| 72 |
-
logging.info("="*50)
|
| 73 |
-
logging.info("Starting Drift Monitoring Flow")
|
| 74 |
-
logging.info("="*50)
|
| 75 |
-
|
| 76 |
-
# Check drift
|
| 77 |
-
drift_result = check_drift()
|
| 78 |
-
|
| 79 |
-
# Trigger retraining if needed
|
| 80 |
-
if drift_result["needs_retraining"]:
|
| 81 |
-
training_result = trigger_retraining()
|
| 82 |
-
return {
|
| 83 |
-
"status": "retraining_triggered",
|
| 84 |
-
"drift": drift_result,
|
| 85 |
-
"training": training_result
|
| 86 |
-
}
|
| 87 |
-
else:
|
| 88 |
-
return {
|
| 89 |
-
"status": "no_action_needed",
|
| 90 |
-
"drift": drift_result
|
| 91 |
-
}
|
| 92 |
-
|
| 93 |
-
if __name__ == "__main__":
|
| 94 |
-
# Run monitoring flow
|
| 95 |
-
result = drift_monitoring_flow()
|
| 96 |
-
print(f"\nπ Monitoring Result: {result}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prefect_flows/training_flow.py
DELETED
|
@@ -1,85 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Prefect Flow for Automated Model Training
|
| 3 |
-
Orchestrates the complete training pipeline with scheduling
|
| 4 |
-
"""
|
| 5 |
-
import sys
|
| 6 |
-
from prefect import flow, task
|
| 7 |
-
from prefect.task_runners import ConcurrentTaskRunner
|
| 8 |
-
from datetime import timedelta
|
| 9 |
-
import logging
|
| 10 |
-
|
| 11 |
-
# Add project root to path
|
| 12 |
-
sys.path.append('..')
|
| 13 |
-
from src.pipeline.training_pipeline import Trainingpipeline
|
| 14 |
-
from src.exception.exception import NetworkSecurityException
|
| 15 |
-
from src.logging.logger import logging as app_logger
|
| 16 |
-
|
| 17 |
-
@task(name="run_training_pipeline", retries=2, retry_delay_seconds=60)
|
| 18 |
-
def train_model():
|
| 19 |
-
"""
|
| 20 |
-
Task to run the complete training pipeline
|
| 21 |
-
"""
|
| 22 |
-
try:
|
| 23 |
-
app_logger.info("Starting training pipeline via Prefect")
|
| 24 |
-
training_pipeline = Trainingpipeline()
|
| 25 |
-
training_pipeline.run_pipeline()
|
| 26 |
-
app_logger.info("Training pipeline completed successfully")
|
| 27 |
-
return {"status": "success", "message": "Model trained successfully"}
|
| 28 |
-
except Exception as e:
|
| 29 |
-
app_logger.error(f"Training pipeline failed: {str(e)}")
|
| 30 |
-
raise NetworkSecurityException(e, sys)
|
| 31 |
-
|
| 32 |
-
@task(name="validate_model")
|
| 33 |
-
def validate_model():
|
| 34 |
-
"""
|
| 35 |
-
Task to validate the trained model
|
| 36 |
-
"""
|
| 37 |
-
try:
|
| 38 |
-
from src.utils.main_utils.utils import load_object
|
| 39 |
-
|
| 40 |
-
app_logger.info("Validating trained model")
|
| 41 |
-
model = load_object("final_model/model.pkl")
|
| 42 |
-
preprocessor = load_object("final_model/preprocessor.pkl")
|
| 43 |
-
|
| 44 |
-
if model is None or preprocessor is None:
|
| 45 |
-
raise ValueError("Model or preprocessor not found")
|
| 46 |
-
|
| 47 |
-
app_logger.info("Model validation successful")
|
| 48 |
-
return {"status": "success", "message": "Model validated"}
|
| 49 |
-
except Exception as e:
|
| 50 |
-
app_logger.error(f"Model validation failed: {str(e)}")
|
| 51 |
-
raise
|
| 52 |
-
|
| 53 |
-
@flow(
|
| 54 |
-
name="phishing-detection-training",
|
| 55 |
-
description="Automated training pipeline for phishing detection model",
|
| 56 |
-
task_runner=ConcurrentTaskRunner()
|
| 57 |
-
)
|
| 58 |
-
def training_flow():
|
| 59 |
-
"""
|
| 60 |
-
Main Prefect flow for training orchestration
|
| 61 |
-
"""
|
| 62 |
-
logging.info("="*50)
|
| 63 |
-
logging.info("Starting Phishing Detection Training Flow")
|
| 64 |
-
logging.info("="*50)
|
| 65 |
-
|
| 66 |
-
# Step 1: Train model
|
| 67 |
-
train_result = train_model()
|
| 68 |
-
logging.info(f"Training result: {train_result}")
|
| 69 |
-
|
| 70 |
-
# Step 2: Validate model
|
| 71 |
-
validation_result = validate_model()
|
| 72 |
-
logging.info(f"Validation result: {validation_result}")
|
| 73 |
-
|
| 74 |
-
logging.info("="*50)
|
| 75 |
-
logging.info("Training flow completed successfully!")
|
| 76 |
-
logging.info("="*50)
|
| 77 |
-
|
| 78 |
-
return {
|
| 79 |
-
"training": train_result,
|
| 80 |
-
"validation": validation_result
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
if __name__ == "__main__":
|
| 84 |
-
# Run the flow locally
|
| 85 |
-
training_flow()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
|
@@ -11,8 +11,4 @@ dagshub
|
|
| 11 |
fastapi
|
| 12 |
uvicorn
|
| 13 |
python-multipart
|
| 14 |
-
# Orchestration
|
| 15 |
-
prefect>=2.14.0
|
| 16 |
-
# Monitoring
|
| 17 |
-
evidently>=0.4.0
|
| 18 |
# -e .
|
|
|
|
| 11 |
fastapi
|
| 12 |
uvicorn
|
| 13 |
python-multipart
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
# -e .
|
setup_cloud_mlops.py
DELETED
|
@@ -1,151 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Quick Setup Script for Prefect Cloud + Evidently
|
| 3 |
-
Run this after getting your Prefect Cloud API key
|
| 4 |
-
"""
|
| 5 |
-
import subprocess
|
| 6 |
-
import sys
|
| 7 |
-
|
| 8 |
-
def run_command(command, description):
|
| 9 |
-
"""Run a command and print result"""
|
| 10 |
-
print(f"\n{'='*60}")
|
| 11 |
-
print(f"π§ {description}")
|
| 12 |
-
print(f"{'='*60}")
|
| 13 |
-
try:
|
| 14 |
-
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
| 15 |
-
print(result.stdout)
|
| 16 |
-
if result.returncode != 0:
|
| 17 |
-
print(f"β Error: {result.stderr}")
|
| 18 |
-
return False
|
| 19 |
-
return True
|
| 20 |
-
except Exception as e:
|
| 21 |
-
print(f"β Exception: {e}")
|
| 22 |
-
return False
|
| 23 |
-
|
| 24 |
-
def main():
|
| 25 |
-
print("""
|
| 26 |
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 27 |
-
β Prefect Cloud + Evidently Setup for NSS Project β
|
| 28 |
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 29 |
-
|
| 30 |
-
Prerequisites:
|
| 31 |
-
1. Created Prefect Cloud account at https://app.prefect.cloud/
|
| 32 |
-
2. Generated API key from dashboard
|
| 33 |
-
3. Virtual environment activated (.venv)
|
| 34 |
-
|
| 35 |
-
""")
|
| 36 |
-
|
| 37 |
-
input("Press Enter to continue...")
|
| 38 |
-
|
| 39 |
-
# Step 1: Check Prefect installation
|
| 40 |
-
if not run_command("prefect --version", "Checking Prefect installation"):
|
| 41 |
-
print("\nβ Prefect not installed. Run: pip install prefect>=2.14.0")
|
| 42 |
-
return
|
| 43 |
-
|
| 44 |
-
# Step 2: Check Evidently installation
|
| 45 |
-
if not run_command("python -c \"import evidently; print(f'Evidently {evidently.__version__}')\"",
|
| 46 |
-
"Checking Evidently installation"):
|
| 47 |
-
print("\nβ Evidently not installed. Run: pip install evidently>=0.4.0")
|
| 48 |
-
return
|
| 49 |
-
|
| 50 |
-
# Step 3: Login to Prefect Cloud
|
| 51 |
-
print("\n" + "="*60)
|
| 52 |
-
print("π Prefect Cloud Login")
|
| 53 |
-
print("="*60)
|
| 54 |
-
print("Please paste your Prefect Cloud API key when prompted...")
|
| 55 |
-
print("(Get it from: https://app.prefect.cloud/ β Profile β API Keys)")
|
| 56 |
-
|
| 57 |
-
if not run_command("prefect cloud login", "Logging into Prefect Cloud"):
|
| 58 |
-
print("\nβ Login failed. Please check your API key.")
|
| 59 |
-
return
|
| 60 |
-
|
| 61 |
-
# Step 4: Verify connection
|
| 62 |
-
if not run_command("prefect cloud workspace ls", "Verifying Prefect Cloud connection"):
|
| 63 |
-
print("\nβ Could not connect to Prefect Cloud.")
|
| 64 |
-
return
|
| 65 |
-
|
| 66 |
-
# Step 5: Create deployments
|
| 67 |
-
print("\n" + "="*60)
|
| 68 |
-
print("π¦ Creating Prefect Deployments")
|
| 69 |
-
print("="*60)
|
| 70 |
-
|
| 71 |
-
deploy_result = subprocess.run(
|
| 72 |
-
"cd prefect_flows && python deploy_schedule.py",
|
| 73 |
-
shell=True,
|
| 74 |
-
capture_output=True,
|
| 75 |
-
text=True
|
| 76 |
-
)
|
| 77 |
-
|
| 78 |
-
if deploy_result.returncode == 0:
|
| 79 |
-
print("β
Weekly training deployment created!")
|
| 80 |
-
print(deploy_result.stdout)
|
| 81 |
-
else:
|
| 82 |
-
print(f"β οΈ Deployment creation skipped or failed: {deploy_result.stderr}")
|
| 83 |
-
|
| 84 |
-
# Step 6: Test Evidently
|
| 85 |
-
print("\n" + "="*60)
|
| 86 |
-
print("π Testing Evidently Monitoring")
|
| 87 |
-
print("="*60)
|
| 88 |
-
|
| 89 |
-
test_result = subprocess.run(
|
| 90 |
-
"python test_evidently.py",
|
| 91 |
-
shell=True,
|
| 92 |
-
capture_output=True,
|
| 93 |
-
text=True
|
| 94 |
-
)
|
| 95 |
-
|
| 96 |
-
if test_result.returncode == 0:
|
| 97 |
-
print("β
Evidently reports generated successfully!")
|
| 98 |
-
print("Check monitoring/reports/ for HTML files")
|
| 99 |
-
else:
|
| 100 |
-
print(f"β οΈ Evidently test failed: {test_result.stderr}")
|
| 101 |
-
|
| 102 |
-
# Final Instructions
|
| 103 |
-
print("""
|
| 104 |
-
|
| 105 |
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 106 |
-
β Setup Complete! π β
|
| 107 |
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 108 |
-
|
| 109 |
-
π NEXT STEPS:
|
| 110 |
-
|
| 111 |
-
1. Start Prefect Worker (keep running):
|
| 112 |
-
Command: prefect agent start -q training
|
| 113 |
-
|
| 114 |
-
2. View Dashboard:
|
| 115 |
-
URL: https://app.prefect.cloud/
|
| 116 |
-
|
| 117 |
-
3. Run Training Flow (test):
|
| 118 |
-
Command: cd prefect_flows && python training_flow.py
|
| 119 |
-
|
| 120 |
-
4. Run Drift Monitoring (test):
|
| 121 |
-
Command: cd prefect_flows && python drift_monitoring_flow.py
|
| 122 |
-
|
| 123 |
-
5. Check Evidently Reports:
|
| 124 |
-
Location: monitoring/reports/*.html
|
| 125 |
-
|
| 126 |
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 127 |
-
|
| 128 |
-
π DOCUMENTATION:
|
| 129 |
-
- Full guide: CLOUD_MLOPS_SETUP.md
|
| 130 |
-
- Prefect Cloud: https://docs.prefect.io/latest/cloud/
|
| 131 |
-
- Evidently: https://docs.evidentlyai.com/
|
| 132 |
-
|
| 133 |
-
ββββββββββββββββββββββββββββββββοΏ½οΏ½βββββββββββββββββββββββ
|
| 134 |
-
|
| 135 |
-
β‘ QUICK TEST:
|
| 136 |
-
Open a new terminal and run:
|
| 137 |
-
|
| 138 |
-
Terminal 1 (Worker):
|
| 139 |
-
> prefect agent start -q training
|
| 140 |
-
|
| 141 |
-
Terminal 2 (Test Flow):
|
| 142 |
-
> cd prefect_flows
|
| 143 |
-
> python training_flow.py
|
| 144 |
-
|
| 145 |
-
Then check: https://app.prefect.cloud/ to see your flow run!
|
| 146 |
-
|
| 147 |
-
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 148 |
-
""")
|
| 149 |
-
|
| 150 |
-
if __name__ == "__main__":
|
| 151 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
startup.sh
DELETED
|
@@ -1,66 +0,0 @@
|
|
| 1 |
-
#!/bin/bash
|
| 2 |
-
# Startup script for HuggingFace Space
|
| 3 |
-
# Initializes Prefect Cloud and Evidently monitoring
|
| 4 |
-
|
| 5 |
-
set -e
|
| 6 |
-
|
| 7 |
-
echo "π Starting Network Security System..."
|
| 8 |
-
echo "ββββββββββββββββββββββββββββββββββββββββββββ"
|
| 9 |
-
|
| 10 |
-
# Check if Prefect Cloud API key is provided
|
| 11 |
-
if [ -n "$PREFECT_API_KEY" ]; then
|
| 12 |
-
echo "β
Prefect Cloud API Key detected"
|
| 13 |
-
echo "π§ Configuring Prefect Cloud connection..."
|
| 14 |
-
|
| 15 |
-
# Set Prefect Cloud API URL (default to cloud)
|
| 16 |
-
export PREFECT_API_URL="${PREFECT_API_URL:-https://api.prefect.cloud/api}"
|
| 17 |
-
|
| 18 |
-
# Configure Prefect
|
| 19 |
-
prefect config set PREFECT_API_KEY="$PREFECT_API_KEY"
|
| 20 |
-
prefect config set PREFECT_API_URL="$PREFECT_API_URL"
|
| 21 |
-
|
| 22 |
-
# Verify connection
|
| 23 |
-
if prefect cloud workspace ls 2>/dev/null; then
|
| 24 |
-
echo "β
Successfully connected to Prefect Cloud"
|
| 25 |
-
|
| 26 |
-
# Optional: Auto-deploy flows if enabled
|
| 27 |
-
if [ "$AUTO_DEPLOY_FLOWS" = "true" ]; then
|
| 28 |
-
echo "π¦ Auto-deploying Prefect flows..."
|
| 29 |
-
cd /app/prefect_flows
|
| 30 |
-
python deploy_schedule.py || echo "β οΈ Flow deployment skipped"
|
| 31 |
-
cd /app
|
| 32 |
-
fi
|
| 33 |
-
else
|
| 34 |
-
echo "β οΈ Warning: Could not connect to Prefect Cloud"
|
| 35 |
-
echo " Prefect features will be limited"
|
| 36 |
-
fi
|
| 37 |
-
else
|
| 38 |
-
echo "βΉοΈ No PREFECT_API_KEY found - Prefect Cloud features disabled"
|
| 39 |
-
echo " Set PREFECT_API_KEY in HuggingFace Space secrets to enable"
|
| 40 |
-
fi
|
| 41 |
-
|
| 42 |
-
# Check if Evidently Cloud token is provided (optional)
|
| 43 |
-
if [ -n "$EVIDENTLY_API_KEY" ]; then
|
| 44 |
-
echo "β
Evidently Cloud Token detected"
|
| 45 |
-
export EVIDENTLY_API_KEY="$EVIDENTLY_API_KEY"
|
| 46 |
-
echo "π§ Evidently Cloud integration enabled"
|
| 47 |
-
else
|
| 48 |
-
echo "βΉοΈ No EVIDENTLY_API_KEY - Using open-source Evidently"
|
| 49 |
-
fi
|
| 50 |
-
|
| 51 |
-
# Create necessary directories
|
| 52 |
-
echo "π Creating directories..."
|
| 53 |
-
mkdir -p /app/monitoring/reports
|
| 54 |
-
mkdir -p /app/final_model
|
| 55 |
-
mkdir -p /app/logs
|
| 56 |
-
|
| 57 |
-
# Set permissions
|
| 58 |
-
chmod +x /app/app.py 2>/dev/null || true
|
| 59 |
-
|
| 60 |
-
echo "ββββββββββββββββββββββββββββββββββββββββββββ"
|
| 61 |
-
echo "β
Initialization complete!"
|
| 62 |
-
echo "π Starting FastAPI application..."
|
| 63 |
-
echo "ββββββββββββββββββββββββββββββββββββββββββββ"
|
| 64 |
-
|
| 65 |
-
# Start the application
|
| 66 |
-
exec "$@"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trigger_prefect_training.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
Trigger Prefect training flow manually
|
| 3 |
-
Use this to run training through Prefect Cloud from command line
|
| 4 |
-
"""
|
| 5 |
-
import sys
|
| 6 |
-
sys.path.append('.')
|
| 7 |
-
|
| 8 |
-
from prefect_flows.training_flow import training_flow
|
| 9 |
-
|
| 10 |
-
if __name__ == "__main__":
|
| 11 |
-
print("π Starting training via Prefect Cloud...")
|
| 12 |
-
result = training_flow()
|
| 13 |
-
print(f"β
Training completed: {result}")
|
| 14 |
-
print("π Check Prefect Cloud dashboard: https://app.prefect.cloud/")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|