File size: 4,138 Bytes
c2295d1
 
5ea6795
 
 
c2295d1
5ea6795
 
c2295d1
 
 
 
5ea6795
c2295d1
 
 
5ea6795
 
 
 
 
c2295d1
 
5ea6795
6141da1
 
c2295d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5ea6795
c2295d1
6141da1
 
 
c2295d1
6141da1
 
5ea6795
6141da1
 
 
5ea6795
c2295d1
 
 
 
 
 
 
5ea6795
c2295d1
 
 
6141da1
 
c2295d1
 
6141da1
c2295d1
6141da1
 
c2295d1
 
 
 
 
 
 
 
 
 
 
5ea6795
c2295d1
 
 
 
 
 
 
 
 
 
5ea6795
6141da1
c2295d1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 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'<a href="data:application/octet-stream;base64,{b64}" download="digital_twin_report.pdf">πŸ“„ Download PDF Report</a>'
    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.")