Add PulseFlow Gradio demo app

#2
Files changed (1) hide show
  1. app.py +141 -0
app.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py β€” PulseFlow MLOps Demo Space
2
+ import gradio as gr
3
+ import pandas as pd
4
+ import numpy as np
5
+ import json
6
+ from datetime import datetime
7
+
8
+ # Simulate the PulseFlow pipeline stages
9
+ def run_etl(uploaded_file):
10
+ if uploaded_file is None:
11
+ df = pd.DataFrame({
12
+ "feature_1": np.random.randn(100),
13
+ "feature_2": np.random.randn(100),
14
+ "feature_3": np.random.rand(100) * 100,
15
+ "target": np.random.randint(0, 2, 100)
16
+ })
17
+ source = "generated sample data (100 rows)"
18
+ else:
19
+ df = pd.read_csv(uploaded_file.name)
20
+ source = f"uploaded file ({len(df)} rows)"
21
+
22
+ nulls_before = df.isnull().sum().sum()
23
+ df = df.dropna()
24
+ nulls_after = df.isnull().sum().sum()
25
+
26
+ report = {
27
+ "source": source,
28
+ "rows_loaded": len(df),
29
+ "columns": list(df.columns),
30
+ "nulls_removed": int(nulls_before - nulls_after),
31
+ "dtypes": {c: str(t) for c, t in df.dtypes.items()},
32
+ "timestamp": datetime.utcnow().isoformat() + "Z"
33
+ }
34
+ return df.head(10), json.dumps(report, indent=2)
35
+
36
+ def run_training(n_estimators, max_depth, test_size):
37
+ from sklearn.ensemble import RandomForestClassifier
38
+ from sklearn.model_selection import train_test_split
39
+ from sklearn.metrics import accuracy_score, f1_score
40
+
41
+ np.random.seed(42)
42
+ X = np.random.randn(500, 5)
43
+ y = (X[:, 0] + X[:, 1] > 0).astype(int)
44
+
45
+ X_train, X_test, y_train, y_test = train_test_split(
46
+ X, y, test_size=test_size / 100, random_state=42
47
+ )
48
+
49
+ model = RandomForestClassifier(
50
+ n_estimators=int(n_estimators),
51
+ max_depth=int(max_depth),
52
+ random_state=42
53
+ )
54
+ model.fit(X_train, y_train)
55
+ preds = model.predict(X_test)
56
+
57
+ metrics = {
58
+ "experiment": "enterprise_mlops_training",
59
+ "model": "RandomForestClassifier",
60
+ "n_estimators": int(n_estimators),
61
+ "max_depth": int(max_depth),
62
+ "test_size_pct": test_size,
63
+ "accuracy": round(accuracy_score(y_test, preds), 4),
64
+ "f1_score": round(f1_score(y_test, preds), 4),
65
+ "train_samples": len(X_train),
66
+ "test_samples": len(X_test),
67
+ "status": "completed",
68
+ "mlflow_uri": "See GitHub repo to connect your MLflow instance",
69
+ "timestamp": datetime.utcnow().isoformat() + "Z"
70
+ }
71
+ return json.dumps(metrics, indent=2)
72
+
73
+ def run_inference(f1, f2, f3, f4, f5):
74
+ features = [f1, f2, f3, f4, f5]
75
+ score = 1 / (1 + np.exp(-sum(features[:2])))
76
+ prediction = int(score > 0.5)
77
+ result = {
78
+ "endpoint": "/predict",
79
+ "input": {"features": features},
80
+ "prediction": prediction,
81
+ "confidence": round(float(score if prediction == 1 else 1 - score), 4),
82
+ "model": "RandomForestClassifier v0.1.0",
83
+ "latency_ms": round(np.random.uniform(2, 8), 2),
84
+ "status": "200 OK",
85
+ "timestamp": datetime.utcnow().isoformat() + "Z"
86
+ }
87
+ return json.dumps(result, indent=2)
88
+
89
+ # UI
90
+ with gr.Blocks(title="PulseFlow MLOps", theme=gr.themes.Soft()) as demo:
91
+ gr.Markdown("""
92
+ # PulseFlow MLOps Pipeline
93
+ **Production-grade open source MLOps** β€” ETL β†’ Training β†’ FastAPI Inference
94
+
95
+ [![PyPI](https://img.shields.io/pypi/v/pulseflow-mlops)](https://pypi.org/project/pulseflow-mlops/)
96
+ [![GitHub](https://img.shields.io/badge/GitHub-PulseFlow-black)](https://github.com/anilatambharii/PulseFlow)
97
+ [![AmbhariiLabs](https://img.shields.io/badge/Org-AmbhariiLabs-blue)](https://huggingface.co/AmbhariiLabs)
98
+
99
+ Built by [Anil Prasad](https://www.linkedin.com/in/anilsprasad) β€” Head of Engineering & Product, Duke Energy | Founder, Ambharii Labs
100
+ """)
101
+
102
+ with gr.Tabs():
103
+ with gr.Tab("Stage 1 β€” ETL"):
104
+ gr.Markdown("Upload a CSV or use generated sample data to simulate the ingestion and preprocessing pipeline.")
105
+ with gr.Row():
106
+ file_input = gr.File(label="Upload CSV (optional)", file_types=[".csv"])
107
+ etl_btn = gr.Button("Run ETL Pipeline", variant="primary")
108
+ data_preview = gr.Dataframe(label="Processed Data Preview (first 10 rows)")
109
+ etl_report = gr.Code(label="ETL Report (JSON)", language="json")
110
+ etl_btn.click(run_etl, inputs=[file_input], outputs=[data_preview, etl_report])
111
+
112
+ with gr.Tab("Stage 2 β€” Training"):
113
+ gr.Markdown("Configure hyperparameters and run the training pipeline. Metrics mirror what MLflow captures in production.")
114
+ with gr.Row():
115
+ n_est = gr.Slider(10, 200, value=100, step=10, label="n_estimators")
116
+ max_d = gr.Slider(2, 20, value=5, step=1, label="max_depth")
117
+ test_s = gr.Slider(10, 40, value=20, step=5, label="Test size %")
118
+ train_btn = gr.Button("Run Training", variant="primary")
119
+ train_output = gr.Code(label="MLflow Experiment Results (JSON)", language="json")
120
+ train_btn.click(run_training, inputs=[n_est, max_d, test_s], outputs=[train_output])
121
+
122
+ with gr.Tab("Stage 3 β€” Inference"):
123
+ gr.Markdown("Simulate the FastAPI `/predict` endpoint. In production this runs via `uvicorn deployment.app.main:app`.")
124
+ with gr.Row():
125
+ f1 = gr.Number(value=0.5, label="Feature 1")
126
+ f2 = gr.Number(value=-0.3, label="Feature 2")
127
+ f3 = gr.Number(value=1.2, label="Feature 3")
128
+ f4 = gr.Number(value=0.0, label="Feature 4")
129
+ f5 = gr.Number(value=0.8, label="Feature 5")
130
+ infer_btn = gr.Button("Run Inference", variant="primary")
131
+ infer_output = gr.Code(label="API Response (JSON)", language="json")
132
+ infer_btn.click(run_inference, inputs=[f1, f2, f3, f4, f5], outputs=[infer_output])
133
+
134
+ gr.Markdown("""
135
+ ---
136
+ **Install locally:** `pip install pulseflow-mlops` |
137
+ **Full stack:** `docker-compose up --build` |
138
+ **Docs:** [GitHub README](https://github.com/anilatambharii/PulseFlow)
139
+ """)
140
+
141
+ demo.launch()