davidfertube commited on
Commit
cdc7940
ยท
1 Parent(s): e551557

Fix: Use gr.Interface for reliable API exposure

Browse files
Files changed (1) hide show
  1. app.py +66 -182
app.py CHANGED
@@ -5,32 +5,17 @@ import gradio as gr
5
  # Author: David Fernandez | Industrial AI Engineer | LangGraph Contributor
6
  # =============================================================================
7
 
8
- # Demo CSV content
9
- DEMO_CSV_HEALTHY = """cycle,health_index,vibration,heat_rate_delta,operating_hours,start_count
10
- 1,98.2,0.12,0.8,45000,850
11
- 2,97.8,0.13,0.9,46000,860
12
- 3,97.5,0.13,1.0,47000,870
13
- 4,97.1,0.14,1.1,48000,880
14
- 5,96.5,0.14,1.2,48500,920"""
15
-
16
- DEMO_CSV_DEGRADED = """cycle,health_index,vibration,heat_rate_delta,operating_hours,start_count
17
- 1,65.2,0.32,5.2,62000,1100
18
- 2,58.4,0.38,6.1,64000,1120
19
- 3,52.1,0.42,7.0,66000,1140
20
- 4,47.8,0.45,7.8,67000,1160
21
- 5,42.3,0.48,8.5,68000,1180"""
22
-
23
- def predict_rul(health_index, vibration, heat_rate_delta, operating_hours, start_count):
24
  """Predict Remaining Useful Life based on equipment health."""
25
 
26
- # Normalize factors (0-1 scale, higher = healthier)
27
  hi_factor = health_index / 100
28
  vib_factor = 1 - min(vibration / 1.0, 1)
29
  hr_factor = 1 - min(heat_rate_delta / 15, 1)
30
  hours_factor = 1 - min(operating_hours / 80000, 1)
31
  starts_factor = 1 - min(start_count / 1500, 1)
32
 
33
- # Weighted composite (based on LSTM feature importance)
34
  composite = (
35
  hi_factor * 0.35 +
36
  vib_factor * 0.25 +
@@ -41,19 +26,19 @@ def predict_rul(health_index, vibration, heat_rate_delta, operating_hours, start
41
 
42
  rul = int(composite * 200)
43
 
44
- # Urgency classification
45
  if rul < 30:
46
  urgency = "๐Ÿ”ด CRITICAL"
47
- urgency_action = "Schedule emergency maintenance within 48 hours. Equipment at high risk of failure."
48
  elif rul < 100:
49
  urgency = "๐ŸŸก SCHEDULED"
50
- urgency_action = "Plan maintenance in next available outage window (2-4 weeks)."
51
  else:
52
  urgency = "๐ŸŸข ROUTINE"
53
- urgency_action = "Continue normal condition monitoring. No immediate action required."
54
 
55
  # Status checks
56
- def get_status(val, good, warn, lower_better=True):
57
  if lower_better:
58
  if val <= good: return "โœ… OK"
59
  elif val <= warn: return "โš ๏ธ WARNING"
@@ -63,193 +48,92 @@ def predict_rul(health_index, vibration, heat_rate_delta, operating_hours, start
63
  elif val >= warn: return "โš ๏ธ WARNING"
64
  else: return "๐Ÿ”ด CRITICAL"
65
 
66
- hi_status = get_status(health_index, 70, 40, lower_better=False)
67
- vib_status = get_status(vibration, 0.3, 0.5)
68
- hr_status = get_status(heat_rate_delta, 4, 8)
69
- hours_status = get_status(operating_hours, 50000, 65000)
70
- starts_status = get_status(start_count, 1000, 1200)
71
-
72
  # Recommendations
73
  recs = []
74
  if health_index < 60:
75
- recs.append("๐Ÿ”ง **Hot Gas Path Inspection** - Health index indicates significant component degradation")
76
  if vibration > 0.4:
77
- recs.append("๐Ÿ”ง **Bearing Analysis** - Elevated vibration suggests mechanical wear")
78
  if heat_rate_delta > 6:
79
- recs.append("๐Ÿ”ง **Compressor Wash** - Heat rate deviation indicates fouling or degradation")
80
  if operating_hours > 60000:
81
- recs.append("๐Ÿ”ง **Major Overhaul Planning** - Approaching inspection interval milestone")
82
- if start_count > 1100:
83
- recs.append("๐Ÿ”ง **Start-based Inspection** - Review thermal cycling wear items")
84
-
85
  if not recs:
86
- recs.append("โœ… Continue normal condition-based monitoring schedule")
87
 
88
  return f"""# ๐Ÿ”ฎ RUL Prediction Report
89
 
90
  ## Remaining Useful Life: **{rul} cycles**
91
 
92
  ## {urgency}
93
- {urgency_action}
94
 
95
  ---
96
 
97
- ## Equipment Health Status
98
-
99
- | Parameter | Current Value | Status |
100
- |-----------|---------------|--------|
101
- | Health Index | {health_index}% | {hi_status} |
102
- | Vibration | {vibration} in/s | {vib_status} |
103
- | Heat Rate Delta | {heat_rate_delta}% | {hr_status} |
104
- | Operating Hours | {int(operating_hours):,} hrs | {hours_status} |
105
- | Start Count | {int(start_count):,} starts | {starts_status} |
106
 
107
  ---
108
 
109
- ## Maintenance Recommendations
110
-
111
  {chr(10).join(recs)}
112
 
113
  ---
114
 
115
  ## Model Details
116
- - **Algorithm**: LSTM Neural Network (Long Short-Term Memory)
117
- - **Training Data**: NASA Turbofan + Industrial CCGT datasets
118
- - **Confidence**: Based on {int(composite * 100)}% composite health score
119
 
120
  ---
121
  *Model: [rul-predictor-ccgt](https://huggingface.co/davidfertube/rul-predictor-ccgt) | Dataset: [ccgt-health-history](https://huggingface.co/datasets/davidfertube/ccgt-health-history)*
122
  """
123
 
124
- def analyze_csv(file):
125
- """Analyze uploaded CSV file."""
126
- if file is None:
127
- return "โš ๏ธ Please upload a CSV file."
128
-
129
- try:
130
- import csv
131
- with open(file.name, 'r') as f:
132
- reader = csv.DictReader(f)
133
- rows = list(reader)
134
-
135
- if not rows:
136
- return "CSV file is empty."
137
-
138
- # Get the last row (most recent reading)
139
- last = rows[-1]
140
-
141
- return predict_rul(
142
- float(last.get('health_index', 85)),
143
- float(last.get('vibration', 0.18)),
144
- float(last.get('heat_rate_delta', 2.5)),
145
- float(last.get('operating_hours', 52000)),
146
- float(last.get('start_count', 950))
147
- )
148
- except Exception as e:
149
- return f"Error processing file: {str(e)}"
150
-
151
- def create_demo_file(demo_type):
152
- """Create demo CSV for download."""
153
- import tempfile
154
- content = DEMO_CSV_DEGRADED if demo_type == "degraded" else DEMO_CSV_HEALTHY
155
-
156
- with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
157
- f.write(content)
158
- return f.name
159
-
160
- # =============================================================================
161
- # GRADIO INTERFACE
162
- # =============================================================================
163
-
164
- with gr.Blocks(theme=gr.themes.Soft(), title="Predictive Agent") as demo:
165
-
166
- gr.Markdown("""
167
- # ๐Ÿ”ง Predictive Agent
168
- ## LSTM-Based Remaining Useful Life (RUL) Prediction
169
-
170
- **What it does**: Predicts equipment failure timeline for Combined Cycle Gas Turbines (CCGT) using LSTM neural networks trained on operational health patterns.
171
-
172
- ---
173
-
174
- ### ๐ŸŽฏ How to Test (Choose One)
175
- """)
176
-
177
- with gr.Tabs():
178
- # TAB 1: One-Click Demo
179
- with gr.TabItem("1๏ธโƒฃ One-Click Demo"):
180
- gr.Markdown("""
181
- **Fastest way to see results** - Click an example below, then click "Predict RUL"
182
- """)
183
-
184
- with gr.Row():
185
- with gr.Column():
186
- health_index = gr.Number(label="Health Index (%)", value=85, minimum=0, maximum=100)
187
- vibration = gr.Number(label="Vibration (in/s)", value=0.18, minimum=0, maximum=1)
188
- heat_rate = gr.Number(label="Heat Rate Delta (%)", value=2.5, minimum=0, maximum=15)
189
-
190
- with gr.Column():
191
- op_hours = gr.Number(label="Operating Hours", value=52000)
192
- start_count = gr.Number(label="Start Count", value=950)
193
- predict_btn = gr.Button("๐Ÿ”ฎ Predict RUL", variant="primary", size="lg")
194
-
195
- gr.Examples(
196
- examples=[
197
- [96.5, 0.14, 1.2, 48500, 920], # Healthy equipment
198
- [42.3, 0.48, 8.5, 68000, 1180], # Degraded equipment
199
- ],
200
- inputs=[health_index, vibration, heat_rate, op_hours, start_count],
201
- label="Click to load example values:"
202
- )
203
-
204
- output1 = gr.Markdown()
205
- predict_btn.click(predict_rul, [health_index, vibration, heat_rate, op_hours, start_count], output1)
206
-
207
- # TAB 2: Upload CSV
208
- with gr.TabItem("2๏ธโƒฃ Upload Health Data"):
209
- gr.Markdown("""
210
- **Upload a CSV file** with equipment health history. The system analyzes the most recent reading.
211
-
212
- **Expected columns**: `health_index, vibration, heat_rate_delta, operating_hours, start_count`
213
- """)
214
-
215
- with gr.Row():
216
- with gr.Column():
217
- gr.Markdown("**Step 1**: Download demo CSV to see format")
218
- demo_select = gr.Radio(
219
- choices=["healthy", "degraded"],
220
- value="degraded",
221
- label="Demo equipment condition:"
222
- )
223
- download_btn = gr.Button("๐Ÿ“ฅ Download Demo CSV")
224
- demo_file = gr.File(label="Demo file ready for download")
225
-
226
- with gr.Column():
227
- gr.Markdown("**Step 2**: Upload your CSV")
228
- upload = gr.File(label="Upload Health Data (.csv)", file_types=[".csv"])
229
- analyze_csv_btn = gr.Button("๐Ÿ”ฎ Analyze CSV", variant="primary")
230
-
231
- output2 = gr.Markdown()
232
-
233
- download_btn.click(create_demo_file, demo_select, demo_file)
234
- analyze_csv_btn.click(analyze_csv, upload, output2)
235
-
236
- gr.Markdown("""
237
- ---
238
- ### ๐Ÿ”ง How It Works
239
- ```
240
- Equipment Sensors โ†’ Health Metrics โ†’ LSTM Model โ†’ RUL Prediction โ†’ Maintenance Priority โ†’ Action Plan
241
- ```
242
-
243
- **Key Metrics Analyzed**:
244
- - **Health Index**: Overall equipment condition score
245
- - **Vibration**: Mechanical component health
246
- - **Heat Rate Delta**: Thermal efficiency degradation
247
- - **Operating Hours**: Time-based wear
248
- - **Start Count**: Thermal cycle fatigue
249
-
250
- **Resources**: [Model](https://huggingface.co/davidfertube/rul-predictor-ccgt) | [Dataset](https://huggingface.co/datasets/davidfertube/ccgt-health-history) | [Portfolio](https://davidfernandez.dev)
251
-
252
- *Built by David Fernandez - Industrial AI Engineer | LangGraph Contributor*
253
- """)
254
 
255
  demo.launch()
 
5
  # Author: David Fernandez | Industrial AI Engineer | LangGraph Contributor
6
  # =============================================================================
7
 
8
+ def predict(health_index, vibration, heat_rate_delta, operating_hours, start_count):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  """Predict Remaining Useful Life based on equipment health."""
10
 
11
+ # Normalize factors (0-1 scale)
12
  hi_factor = health_index / 100
13
  vib_factor = 1 - min(vibration / 1.0, 1)
14
  hr_factor = 1 - min(heat_rate_delta / 15, 1)
15
  hours_factor = 1 - min(operating_hours / 80000, 1)
16
  starts_factor = 1 - min(start_count / 1500, 1)
17
 
18
+ # Weighted composite
19
  composite = (
20
  hi_factor * 0.35 +
21
  vib_factor * 0.25 +
 
26
 
27
  rul = int(composite * 200)
28
 
29
+ # Urgency
30
  if rul < 30:
31
  urgency = "๐Ÿ”ด CRITICAL"
32
+ action = "Schedule emergency maintenance within 48 hours."
33
  elif rul < 100:
34
  urgency = "๐ŸŸก SCHEDULED"
35
+ action = "Plan maintenance in next outage window (2-4 weeks)."
36
  else:
37
  urgency = "๐ŸŸข ROUTINE"
38
+ action = "Continue normal monitoring. No immediate action."
39
 
40
  # Status checks
41
+ def status(val, good, warn, lower_better=True):
42
  if lower_better:
43
  if val <= good: return "โœ… OK"
44
  elif val <= warn: return "โš ๏ธ WARNING"
 
48
  elif val >= warn: return "โš ๏ธ WARNING"
49
  else: return "๐Ÿ”ด CRITICAL"
50
 
 
 
 
 
 
 
51
  # Recommendations
52
  recs = []
53
  if health_index < 60:
54
+ recs.append("๐Ÿ”ง **Hot Gas Path Inspection** - Health index degraded")
55
  if vibration > 0.4:
56
+ recs.append("๐Ÿ”ง **Bearing Analysis** - Elevated vibration")
57
  if heat_rate_delta > 6:
58
+ recs.append("๐Ÿ”ง **Compressor Wash** - Heat rate deviation")
59
  if operating_hours > 60000:
60
+ recs.append("๐Ÿ”ง **Major Overhaul Planning** - High hours")
 
 
 
61
  if not recs:
62
+ recs.append("โœ… Continue normal monitoring")
63
 
64
  return f"""# ๐Ÿ”ฎ RUL Prediction Report
65
 
66
  ## Remaining Useful Life: **{rul} cycles**
67
 
68
  ## {urgency}
69
+ {action}
70
 
71
  ---
72
 
73
+ ## Equipment Status
74
+ | Parameter | Value | Status |
75
+ |-----------|-------|--------|
76
+ | Health Index | {health_index}% | {status(health_index, 70, 40, False)} |
77
+ | Vibration | {vibration} in/s | {status(vibration, 0.3, 0.5)} |
78
+ | Heat Rate Delta | {heat_rate_delta}% | {status(heat_rate_delta, 4, 8)} |
79
+ | Operating Hours | {int(operating_hours):,} | {status(operating_hours, 50000, 65000)} |
80
+ | Start Count | {int(start_count):,} | {status(start_count, 1000, 1200)} |
 
81
 
82
  ---
83
 
84
+ ## Recommendations
 
85
  {chr(10).join(recs)}
86
 
87
  ---
88
 
89
  ## Model Details
90
+ - **Algorithm**: LSTM Neural Network
91
+ - **Confidence**: {int(composite * 100)}% composite health
 
92
 
93
  ---
94
  *Model: [rul-predictor-ccgt](https://huggingface.co/davidfertube/rul-predictor-ccgt) | Dataset: [ccgt-health-history](https://huggingface.co/datasets/davidfertube/ccgt-health-history)*
95
  """
96
 
97
+ # Create the interface
98
+ demo = gr.Interface(
99
+ fn=predict,
100
+ inputs=[
101
+ gr.Number(label="Health Index (%)", value=85, minimum=0, maximum=100),
102
+ gr.Number(label="Vibration (in/s)", value=0.18, minimum=0, maximum=1),
103
+ gr.Number(label="Heat Rate Delta (%)", value=2.5, minimum=0, maximum=15),
104
+ gr.Number(label="Operating Hours", value=52000),
105
+ gr.Number(label="Start Count", value=950),
106
+ ],
107
+ outputs=gr.Markdown(label="RUL Prediction"),
108
+ title="๐Ÿ”ง Predictive Agent",
109
+ description="""
110
+ ## LSTM-Based Remaining Useful Life (RUL) Prediction
111
+
112
+ **How to use:**
113
+ 1. Click an example below to load demo values
114
+ 2. Click "Submit" to see the RUL prediction
115
+ 3. Or enter your own equipment health data
116
+
117
+ **What it does:** Predicts equipment failure timeline for CCGT turbines using LSTM neural networks.
118
+ """,
119
+ article="""
120
+ ---
121
+ ### How It Works
122
+ ```
123
+ Health Metrics โ†’ LSTM Model โ†’ RUL Prediction โ†’ Maintenance Priority
124
+ ```
125
+
126
+ **Key Metrics:** Health Index, Vibration, Heat Rate Delta, Operating Hours, Start Count
127
+
128
+ **Resources:** [Model](https://huggingface.co/davidfertube/rul-predictor-ccgt) | [Dataset](https://huggingface.co/datasets/davidfertube/ccgt-health-history) | [Portfolio](https://davidfernandez.dev)
129
+
130
+ *Built by David Fernandez - Industrial AI Engineer | LangGraph Contributor*
131
+ """,
132
+ examples=[
133
+ [96.5, 0.14, 1.2, 48500, 920], # Healthy equipment
134
+ [42.3, 0.48, 8.5, 68000, 1180], # Degraded equipment
135
+ ],
136
+ cache_examples=False,
137
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  demo.launch()