Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| from PIL import Image | |
| import matplotlib.pyplot as plt | |
| import networkx as nx | |
| import json | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| import torch | |
| torch.cuda.empty_cache() | |
| #import openai | |
| import os | |
| import numpy as np | |
| # Ensure models and datasets are available | |
| from download_models import download_all | |
| # Run only if critical file is missing | |
| if not os.path.exists("P&ID-Symbols-3/train/_annotations.coco.json"): | |
| with st.spinner("Downloading required files (models & datasets)..."): | |
| download_all() | |
| from pipeline.detector import detect_symbols_and_lines | |
| from pipeline.graph_builder import build_graph | |
| from pipeline.gnn_model import run_gnn | |
| from pipeline.agent import generate_agent_actions | |
| st.set_page_config(layout="wide") | |
| st.title(" Agentic Predictive Maintenance (P&ID Graph + GNN)") | |
| # Initialize session state variables | |
| if "G" not in st.session_state: | |
| st.session_state.G = None | |
| if "feature_map" not in st.session_state: | |
| st.session_state.feature_map = {} | |
| if "scores" not in st.session_state: | |
| st.session_state.scores = {} | |
| #uploaded_file = st.file_uploader("Upload a P&ID Image", type=["png", "jpg", "jpeg"]) | |
| #if uploaded_file: | |
| # === User can choose from downloaded dataset OR upload their own === | |
| st.subheader("Upload or Select a P&ID Drawing") | |
| local_dataset_dir = "P&ID-Symbols-3/P&ID-Symbols-3/test" | |
| image_files = [] | |
| if os.path.exists(local_dataset_dir): | |
| image_files = [f for f in os.listdir(local_dataset_dir) if f.lower().endswith((".png", ".jpg", ".jpeg"))] | |
| else: | |
| st.warning(f"Dataset folder not found: {local_dataset_dir}. Please run download_models.py to download it.") | |
| selected_image = st.selectbox("Select a sample from P&ID-Symbols-3:", ["-- Select an example --"] + image_files) | |
| uploaded_file = st.file_uploader("...Or upload your own P&ID image", type=["png", "jpg", "jpeg"]) | |
| image = None | |
| image_source = "" | |
| if selected_image and selected_image != "-- Select an example --": | |
| image_path = os.path.join(local_dataset_dir, selected_image) | |
| image = Image.open(image_path) | |
| image_source = f"Sample from dataset: {selected_image}" | |
| elif uploaded_file: | |
| image = Image.open(uploaded_file) | |
| image_source = f"Uploaded: {uploaded_file.name}" | |
| if image: | |
| st.image(image, caption=image_source, use_column_width=True) | |
| #image = Image.open(uploaded_file) | |
| #st.image(image, caption="P&ID Diagram", use_column_width=True) | |
| if st.button(" Run Detection and Analysis"): | |
| # Uncomment these when detection and graph building pipelines are ready | |
| detections, annotations, class_names = detect_symbols_and_lines(image) | |
| graph = build_graph(image, detections, annotations, class_names) | |
| st.info("Running anomaly detection on the graph (simulated for now)...") | |
| fig, feature_map, red_nodes, central_node, scores, G = run_gnn() | |
| st.session_state.G = G | |
| st.session_state.feature_map = feature_map | |
| st.session_state.scores = scores | |
| st.pyplot(fig) | |
| actions = generate_agent_actions(fig, feature_map, red_nodes, central_node, scores) | |
| for action in actions: | |
| st.write(action) | |
| # === DeepSeek Local Model Setup === | |
| def load_deepseek_model(): | |
| model_name = "deepseek-ai/deepseek-coder-1.3b-instruct" # Lightweight version | |
| # model_name = "deepseek-ai/deepseek-llm-7b" # Larger but more capable | |
| tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) | |
| '''model = AutoModelForCausalLM.from_pretrained( | |
| model_name, | |
| torch_dtype=torch.float16, | |
| device_map="auto", | |
| trust_remote_code=True''' | |
| model = AutoModelForCausalLM.from_pretrained( | |
| model_name, | |
| torch_dtype=torch.float16, | |
| device_map="cpu", | |
| #load_in_4bit=True, # 4-bit quantization | |
| trust_remote_code=True | |
| ) | |
| return model, tokenizer | |
| # === Q&A Interface === | |
| st.subheader(" Ask Questions About the Graph (DeepSeek Local)") | |
| user_query = st.chat_input("Ask a question about the graph...") | |
| if user_query: | |
| G = st.session_state.get("G") | |
| feature_map = st.session_state.get("feature_map", {}) | |
| scores = st.session_state.get("scores", []) | |
| if G is not None and feature_map and len(scores) > 0: | |
| graph_data = { | |
| "nodes": [ | |
| { | |
| "id": str(i), | |
| "label": feature_map[i] if i < len(feature_map) else f"Node {i}", | |
| "score": float(scores[i]) if i < len(scores) else 0.0 | |
| } | |
| for i in G.nodes() | |
| ], | |
| "edges": [ | |
| {"source": str(u), "target": str(v)} | |
| for u, v in G.edges() | |
| ] | |
| } | |
| prompt = ( | |
| "You are an expert graph analyst. Analyze this P&ID graph and answer the question.\n\n" | |
| "### Graph Data:\n" | |
| f"{json.dumps(graph_data, indent=2)}\n\n" | |
| "### Question:\n" | |
| f"{user_query}\n\n" | |
| "### Answer:\n" | |
| ) | |
| try: | |
| with st.spinner("Thinking (via DeepSeek Local)..."): | |
| # Load model (cached after first run) | |
| model, tokenizer = load_deepseek_model() | |
| # Generate response | |
| inputs = tokenizer(prompt, return_tensors="pt").to(model.device) | |
| outputs = model.generate( | |
| **inputs, | |
| max_new_tokens=128, | |
| temperature=0.7, | |
| do_sample=True | |
| ) | |
| answer = tokenizer.decode(outputs[0], skip_special_tokens=True) | |
| # Remove the prompt from the answer | |
| answer = answer[len(prompt):].strip() | |
| st.markdown(f"**DeepSeek:** {answer}") | |
| except Exception as e: | |
| st.error(f"DeepSeek error: {e}") | |
| st.error("Make sure you have enough GPU memory (8GB+ recommended for 7B model)") | |
| else: | |
| st.warning("Graph or scores are not ready yet.") | |