FGPT / app.py
bhagwandas's picture
Update app.py
eb0d83d verified
raw
history blame
8.4 kB
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sentence_transformers import SentenceTransformer
from transformers import pipeline
from sklearn.ensemble import IsolationForest
from io import BytesIO
# App Config
st.set_page_config(
page_title="FactoryGPT 5.0 – Maintenance Dashboard",
page_icon="🧠",
layout="wide"
)
# Load NLP + Anomaly Models
EMBED_MODEL = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
GEN_MODEL = pipeline('text2text-generation', model='google/flan-t5-base')
# Optional: Units per parameter
unit_map = {
"temperature": "Β°C",
"vibration": "mm/s",
"pressure": "bar",
"current": "A",
"voltage": "V",
"speed": "RPM"
}
# Style
st.markdown("""
<style>
html, body, [class*="css"] {
font-family: 'Segoe UI', sans-serif;
background-color: #0f1117;
color: #f0f0f0;
}
.card {
background-color: #1a1c23;
padding: 1rem;
border-radius: 10px;
margin-bottom: 1rem;
box-shadow: 0 0 8px rgba(88,166,255,0.2);
}
</style>
""", unsafe_allow_html=True)
# Header
st.markdown("""
<div style='text-align: center;'>
<h1 style='color: #58a6ff;'>🏭 FactoryGPT 5.0 – Technical Maintenance Dashboard</h1>
<p style='color: #bbb;'>Anomaly Monitoring β€’ Parameter Trends β€’ Role-Based Intelligence</p>
<hr style='border-top: 2px solid #888;'>
</div>
""", unsafe_allow_html=True)
# File Upload
uploaded_file = st.sidebar.file_uploader("πŸ“‚ Upload sensor log (CSV)", type=["csv"])
if uploaded_file:
df = pd.read_csv(uploaded_file)
numeric_cols = df.select_dtypes(include=np.number).columns.tolist()
# Anomaly Detection
iso = IsolationForest(contamination=0.02, random_state=42)
labels = iso.fit_predict(df[numeric_cols])
df['status'] = ['❌ Fault Detected' if x == -1 else 'βœ… Healthy' for x in labels]
df['maintenance_flag'] = ['πŸ”§ Inspect Required' if x == -1 else '🟒 Stable' for x in labels]
# NLP Embeddings
if 'chunks' not in st.session_state or 'embeddings' not in st.session_state:
chunks = [
f"[Entry {i}] " + ", ".join([f"{col}: {row[col]:.2f}" for col in numeric_cols])
for i, row in df.iterrows()
]
embeddings = EMBED_MODEL.encode(chunks)
st.session_state.chunks = chunks
st.session_state.embeddings = embeddings
# Health Summary
col1, col2 = st.columns(2)
with col1:
st.markdown("### 🧠 Machine Health Summary")
status_counts = df['status'].value_counts()
fig1, ax1 = plt.subplots(figsize=(5, 4))
bars = ax1.bar(status_counts.index, status_counts.values, color=["red", "green"])
ax1.set_title("Detected Machine Health Conditions", fontsize=14)
ax1.set_ylabel("Record Count")
ax1.set_xlabel("Status")
ax1.set_facecolor("#0f1117")
ax1.tick_params(colors='white')
ax1.title.set_color('white')
ax1.xaxis.label.set_color('white')
ax1.yaxis.label.set_color('white')
for spine in ax1.spines.values():
spine.set_edgecolor('white')
for bar in bars:
height = bar.get_height()
ax1.annotate(f'{height:,}', xy=(bar.get_x() + bar.get_width()/2, height),
xytext=(0, 6), textcoords="offset points", ha='center', color='white')
st.pyplot(fig1)
with col2:
st.markdown("### πŸ§ͺ Parameters Monitored")
st.markdown(f"""
<div class="card">
{' β€’ '.join(numeric_cols)}
</div>
""", unsafe_allow_html=True)
# Trend Plot
st.markdown("### πŸ“‰ Sensor Trend (with Fault Overlay)")
col3, col4 = st.columns(2)
time_col = col3.selectbox("πŸ•’ Time Column", ["None"] + list(df.columns))
trend_param = col4.selectbox("πŸ“Œ Select Parameter", numeric_cols)
if time_col != "None":
df = df.sort_values(by=time_col)
x_vals = df[time_col] if time_col != "None" else df.index
y_vals = df[trend_param]
y_label = f"{trend_param} ({unit_map.get(trend_param.lower(), '')})"
fig2, ax2 = plt.subplots(figsize=(8, 4.5))
ax2.plot(x_vals, y_vals, label=trend_param, color="skyblue", linewidth=1.5)
ax2.scatter(
x_vals[df['status'] == '❌ Fault Detected'],
y_vals[df['status'] == '❌ Fault Detected'],
color='red', label='Fault Detected', zorder=5
)
ax2.set_title(f"{trend_param} Sensor Trend")
ax2.set_xlabel("Time" if time_col != "None" else "Index")
ax2.set_ylabel(y_label)
ax2.legend()
ax2.set_facecolor("#0f1117")
ax2.tick_params(colors='white')
ax2.title.set_color('white')
ax2.xaxis.label.set_color('white')
ax2.yaxis.label.set_color('white')
for spine in ax2.spines.values():
spine.set_edgecolor('white')
st.pyplot(fig2)
img_buffer = BytesIO()
fig2.savefig(img_buffer, format='png', bbox_inches="tight")
st.download_button("πŸ“· Download Trend Chart (PNG)", img_buffer.getvalue(), file_name="sensor_trend.png")
# Fault Rate Over Time
if time_col != "None":
st.markdown("### πŸ“ˆ Fault Rate Over Time")
df[time_col] = pd.to_datetime(df[time_col], errors='coerce')
df['fault_flag'] = df['status'].apply(lambda x: 1 if x == '❌ Fault Detected' else 0)
freq = 'H' if (df[time_col].max() - df[time_col].min()).days <= 3 else 'D'
grouped = df.set_index(time_col)['fault_flag'].resample(freq).mean() * 100
fig3, ax3 = plt.subplots(figsize=(8, 4))
ax3.plot(grouped.index, grouped, color='orange', linewidth=2)
ax3.set_title("Fault Rate Over Time")
ax3.set_ylabel("Fault Rate (%)")
ax3.set_xlabel("Time")
ax3.set_facecolor("#0f1117")
ax3.tick_params(colors='white')
ax3.title.set_color('white')
ax3.yaxis.label.set_color('white')
ax3.xaxis.label.set_color('white')
for spine in ax3.spines.values():
spine.set_edgecolor('white')
st.pyplot(fig3)
# Export Faults
st.markdown("### πŸ“€ Export Anomalies")
fault_df = df[df['status'] == '❌ Fault Detected']
buf = BytesIO()
fault_df.to_csv(buf, index=False)
st.download_button("⬇️ Download Fault Log", data=buf.getvalue(), file_name="faults.csv", mime="text/csv")
# Metadata correlation
st.markdown("### 🏷️ Fault Distribution by Machine/Component")
meta_cols = [c for c in df.columns if 'machine' in c.lower() or 'component' in c.lower()]
for col in meta_cols:
st.markdown(f"**{col} – Fault Frequency**")
st.bar_chart(df[df['status'] == '❌ Fault Detected'][col].value_counts())
# Role Assistant
st.markdown("### πŸ’¬ Technical Assistant by Role")
roles = {
"Operator": {
"description": "Focus on equipment behavior. Spot abnormal patterns and guide simple actions.",
"style": "Explain simply. Emphasize safety and when to alert maintenance."
},
"Maintenance": {
"description": "Diagnose machine issues. Recommend parts to inspect or replace.",
"style": "Use technical language. Mention symptoms and sensor causes."
},
"Engineer": {
"description": "Analyze system behavior. Identify root causes or instability.",
"style": "Use RCA format. Discuss fault thresholds, control issues, and next steps."
}
}
role = st.selectbox("πŸ‘€ Select your role", roles.keys())
question = st.text_input("🧠 Ask a question")
if question:
qvec = EMBED_MODEL.encode([question])[0]
sims = np.dot(st.session_state.embeddings, qvec)
idxs = np.argsort(sims)[-5:][::-1]
context = "\n".join([st.session_state.chunks[i] for i in idxs])
prompt = (
f"ROLE: {role}\n"
f"RESPONSIBILITIES: {roles[role]['description']}\n"
f"COMMUNICATION STYLE: {roles[role]['style']}\n\n"
f"DATA CONTEXT:\n{context}\n\n"
f"QUESTION:\n{question}\n\n"
f"ANSWER:\n"
)
result = GEN_MODEL(prompt, max_length=400)[0]['generated_text']
st.markdown(f"**πŸ€– Response:**\n\n{result}")
else:
st.info("πŸ‘ˆ Upload a sensor CSV file to generate your technical dashboard.")