import streamlit as st import pandas as pd import numpy as np import pickle import tensorflow as tf import neattext.functions as nfx from tensorflow.keras.models import load_model from tensorflow.keras.layers import InputLayer, Dense from PIL import Image # 1. Set Page Config st.set_page_config(page_title="Disaster Tweet Detector", page_icon="🚨", layout="centered") # 2. The Absolute Final Recovery Fix # We manually define the input shape (5000) to bypass the broken file metadata @st.cache_resource def load_assets(): # This function creates a dummy layer that Keras expects def fix_input_layer(**kwargs): # We force the shape to be 5000 because that's what your vectorizer produces return InputLayer(shape=(5000,)) # This dummy function ignores the Keras 3 'DTypePolicy' def fix_dtype(*args, **kwargs): return None custom_objects = { 'InputLayer': fix_input_layer, 'SafeInputLayer': fix_input_layer, 'DTypePolicy': fix_dtype, # If it complains about Dense again, we use the standard Dense 'Dense': Dense } # Load the model ignoring the 'compile' step and using our manual fixes model = load_model( 'disaster_model.h5', custom_objects=custom_objects, compile=False ) # Load the vectorizer with open('vectorizer.pkl', 'rb') as f: vect = pickle.load(f) return model, vect # 3. Preprocessing Function def clean_text(text): text = text.lower() text = nfx.remove_hashtags(text) text = nfx.remove_urls(text) text = nfx.remove_userhandles(text) text = nfx.remove_multiple_spaces(text) text = nfx.remove_special_characters(text) return text # --- App Interface --- try: model, vect = load_assets() except Exception as e: st.error(f"Critical Deployment Error: {e}") st.warning("Manual Override triggered. Please refresh the page.") st.stop() st.title("🚨 Disaster Tweet Detector") st.markdown("Analyzing social media sentiment for emergency response.") try: img = Image.open('disaster_wordcloud.png') st.image(img, caption="Common Disaster Keywords", use_container_width=True) except: pass st.subheader("Analyze a Tweet") user_input = st.text_area("Enter tweet text:", placeholder="e.g., Massive earthquake reported!") if st.button("Predict"): if user_input.strip() != "": cleaned_msg = clean_text(user_input) # Convert text to the 5000-feature vector vect_text = vect.transform([cleaned_msg]).toarray() # Prediction logic prediction = model.predict(vect_text) probability = float(prediction[0][0]) st.divider() if probability > 0.5: st.error(f"### ⚠️ Real Disaster Detected! ({probability:.2%})") st.progress(probability) else: st.success(f"### ✅ Normal Tweet ({(1-probability):.2%})") st.progress(1 - probability) with st.expander("Technical Details"): st.write(f"Processed Text: {cleaned_msg}") st.write(f"Vector Shape: {vect_text.shape}") else: st.warning("Please enter text.") st.divider() st.caption("Data Science Portfolio")