# app.py - FactoryRAG+: Condition Monitoring with Dashboard, PDF Export, Anomaly Detection & Digital Twin 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 import base64 from io import BytesIO from fpdf import FPDF # Streamlit config st.set_page_config(page_title="FactoryRAG+ - Smart Sensor Twin", layout="wide") st.title("๐Ÿญ FactoryRAG+: Smart Dashboard with AI Monitoring, PDF Reporting & Digital Twin") # Load models EMBED_MODEL = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') GEN_MODEL = pipeline('text2text-generation', model='google/flan-t5-base') # Upload data uploaded_file = st.sidebar.file_uploader("๐Ÿ“‚ Upload your condition monitoring CSV", type=["csv"]) if uploaded_file: df = pd.read_csv(uploaded_file) numeric_cols = df.select_dtypes(include=np.number).columns.tolist() st.success("โœ… Data loaded successfully!") st.subheader("๐Ÿ“Š Sensor Snapshot") st.dataframe(df.head()) # --- Multi-signal Dashboard --- st.subheader("๐Ÿ“ˆ Sensor Dashboard") selected_cols = st.multiselect("Select signals to visualize", numeric_cols, default=numeric_cols[:3]) fig, ax = plt.subplots(len(selected_cols), 1, figsize=(8, 2 * len(selected_cols))) if len(selected_cols) == 1: ax = [ax] for i, col in enumerate(selected_cols): ax[i].plot(df[col], label=col) ax[i].set_ylabel(col) ax[i].legend() st.pyplot(fig) # --- Convert Logs to Chunks --- def convert_to_chunks(df): chunks = [] for idx, row in df.iterrows(): sentence = f"[Log {idx}] " + ", ".join([f"{col}: {row[col]:.2f}" for col in numeric_cols]) chunks.append(sentence) return chunks if 'chunks' not in st.session_state: st.session_state.chunks = convert_to_chunks(df) st.session_state.embeddings = EMBED_MODEL.encode(st.session_state.chunks) # --- Anomaly Detection --- st.subheader("๐Ÿšจ Anomaly Detection (Isolation Forest)") iso = IsolationForest(contamination=0.02) anomaly_labels = iso.fit_predict(df[numeric_cols]) df['anomaly'] = ['โŒ' if x == -1 else '' for x in anomaly_labels] st.write("Anomaly Flags:") st.dataframe(df[df['anomaly'] == 'โŒ'].head(5)) # --- Technical Question Answering --- st.subheader("๐Ÿง  Ask Expert Questions") query = st.text_input("Ask a question like 'Where is instability?' or 'Are anomalies visible?'") if query: query_vec = EMBED_MODEL.encode([query])[0] sims = np.dot(st.session_state.embeddings, query_vec) top_idxs = np.argsort(sims)[-3:][::-1] context = "\n".join([st.session_state.chunks[i] for i in top_idxs]) prompt = f"Context:\n{context}\n\nAs a reliability engineer, answer: {query}" response = GEN_MODEL(prompt, max_length=256)[0]['generated_text'] st.subheader("๐Ÿค– FactoryGPT Answer") st.markdown(response) # --- Digital Twin Metrics --- st.subheader("๐Ÿงช Digital Twin Summary") twin_report = "" for col in selected_cols: max_v = df[col].max() min_v = df[col].min() mean_v = df[col].mean() twin_report += f"{col}\nโ†’ Max: {max_v:.2f}, Min: {min_v:.2f}, Avg: {mean_v:.2f}\n\n" st.code(twin_report) # --- PDF Export --- st.subheader("๐Ÿ“ค Export Digital Twin Report as PDF") pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=12) pdf.multi_cell(0, 10, f"FactoryRAG+ Digital Twin Report\n\nSelected Signals: {', '.join(selected_cols)}\n\n" + twin_report) pdf_bytes = pdf.output(dest='S').encode('latin1') b64 = base64.b64encode(pdf_bytes).decode() href = f'๐Ÿ“„ Download PDF Report' st.markdown(href, unsafe_allow_html=True) else: st.info("๐Ÿ‘ˆ Upload a sensor log CSV file to explore digital twin analysis, waveform charts, anomaly detection, and PDF export.")