Spaces:
Sleeping
Sleeping
Commit ยท
9788e26
1
Parent(s): e2047f6
Integrated Hugging Face model for cloud deployment
Browse files
app.py
CHANGED
|
@@ -5,6 +5,8 @@ from pathlib import Path
|
|
| 5 |
from typing import Dict
|
| 6 |
import pandas as pd
|
| 7 |
import streamlit as st
|
|
|
|
|
|
|
| 8 |
|
| 9 |
# -------------------------------------------------------------------------
|
| 10 |
# Page Configuration
|
|
@@ -20,34 +22,33 @@ st.caption("Streamlit front-end for the Deloitte-ready Twitter Sentiment Intelli
|
|
| 20 |
|
| 21 |
try:
|
| 22 |
# -------------------------------------------------------------------------
|
| 23 |
-
#
|
| 24 |
# -------------------------------------------------------------------------
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
if str(SRC_PATH) not in sys.path:
|
| 28 |
-
sys.path.insert(0, str(SRC_PATH))
|
| 29 |
|
| 30 |
-
# โ
Updated imports to use lightweight remote model loader
|
| 31 |
-
from twitter_sentiment.config import load_config
|
| 32 |
-
from twitter_sentiment.model_loader import get_model
|
| 33 |
-
from twitter_sentiment.predictor import predict_with_threshold
|
| 34 |
-
|
| 35 |
-
# -------------------------------------------------------------------------
|
| 36 |
-
# Cached dependencies (โ
lightweight version)
|
| 37 |
-
# -------------------------------------------------------------------------
|
| 38 |
@st.cache_resource(show_spinner=False)
|
| 39 |
-
def
|
| 40 |
-
"""
|
| 41 |
-
|
| 42 |
-
pipeline =
|
| 43 |
-
|
| 44 |
-
|
|
|
|
| 45 |
|
| 46 |
# -------------------------------------------------------------------------
|
| 47 |
-
#
|
| 48 |
# -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
def format_probabilities(probabilities: Dict[str, float]) -> pd.DataFrame:
|
| 50 |
-
"""Convert
|
| 51 |
return (
|
| 52 |
pd.DataFrame.from_dict(probabilities, orient="index", columns=["confidence"])
|
| 53 |
.sort_values("confidence", ascending=False)
|
|
@@ -55,70 +56,27 @@ try:
|
|
| 55 |
)
|
| 56 |
|
| 57 |
# -------------------------------------------------------------------------
|
| 58 |
-
#
|
| 59 |
# -------------------------------------------------------------------------
|
| 60 |
-
def main()
|
| 61 |
-
"
|
| 62 |
-
|
|
|
|
| 63 |
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
st.header("๐ Model Snapshot")
|
| 67 |
-
if hasattr(pipeline, "classes_"):
|
| 68 |
-
st.write("**Classes:**", ", ".join(pipeline.classes_))
|
| 69 |
-
else:
|
| 70 |
-
st.write("**Model:** Loaded remotely")
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
st.
|
| 75 |
else:
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
label="โฌ๏ธ Download Metrics JSON",
|
| 80 |
-
data=json.dumps(metrics or {}, indent=2).encode("utf-8"),
|
| 81 |
-
file_name="metrics.json",
|
| 82 |
-
mime="application/json",
|
| 83 |
-
)
|
| 84 |
-
st.info(
|
| 85 |
-
"๐ Tip: Integrate Oracle Autonomous Database by updating `config/settings.yaml`."
|
| 86 |
-
)
|
| 87 |
|
| 88 |
-
# ---------------------- Tabs ----------------------
|
| 89 |
-
tab_predict, tab_metrics = st.tabs(["๐ฎ Predict", "โ๏ธ Model Governance"])
|
| 90 |
-
|
| 91 |
-
# ---------------------- Prediction Tab ----------------------
|
| 92 |
-
with tab_predict:
|
| 93 |
-
st.subheader("Real-Time Sentiment Assessment")
|
| 94 |
-
user_input = st.text_area("Enter a tweet or customer comment:", height=150)
|
| 95 |
-
if st.button("Run Analysis", type="primary"):
|
| 96 |
-
if not user_input.strip():
|
| 97 |
-
st.warning("โ ๏ธ Please enter text to analyse.")
|
| 98 |
-
else:
|
| 99 |
-
label, probabilities = predict_with_threshold(user_input, config)
|
| 100 |
-
st.success(f"Predicted Sentiment: **{label.title()}**")
|
| 101 |
-
st.dataframe(format_probabilities(probabilities), use_container_width=True)
|
| 102 |
-
|
| 103 |
-
# ---------------------- Metrics Tab ----------------------
|
| 104 |
-
with tab_metrics:
|
| 105 |
-
st.subheader("Operational Metrics")
|
| 106 |
-
if metrics:
|
| 107 |
-
metrics_df = (
|
| 108 |
-
pd.DataFrame(metrics, index=["score"])
|
| 109 |
-
.T.rename(columns={"score": "value"})
|
| 110 |
-
)
|
| 111 |
-
st.dataframe(metrics_df, use_container_width=True)
|
| 112 |
-
else:
|
| 113 |
-
st.info("Metrics will appear after local training run (see `scripts/train.py`).")
|
| 114 |
-
|
| 115 |
-
# ---------------------- Footer ----------------------
|
| 116 |
st.markdown("---")
|
| 117 |
st.caption("ยฉ 2025 Deloitte-aligned Sentiment Analytics Accelerator")
|
| 118 |
|
| 119 |
-
# -------------------------------------------------------------------------
|
| 120 |
-
# Entry Point
|
| 121 |
-
# -------------------------------------------------------------------------
|
| 122 |
if __name__ == "__main__":
|
| 123 |
main()
|
| 124 |
|
|
|
|
| 5 |
from typing import Dict
|
| 6 |
import pandas as pd
|
| 7 |
import streamlit as st
|
| 8 |
+
from huggingface_hub import hf_hub_download
|
| 9 |
+
import joblib
|
| 10 |
|
| 11 |
# -------------------------------------------------------------------------
|
| 12 |
# Page Configuration
|
|
|
|
| 22 |
|
| 23 |
try:
|
| 24 |
# -------------------------------------------------------------------------
|
| 25 |
+
# Download model from Hugging Face Hub (no local artifacts needed)
|
| 26 |
# -------------------------------------------------------------------------
|
| 27 |
+
MODEL_REPO = "vishnu-coder/twitter-sentiment-model"
|
| 28 |
+
MODEL_FILENAME = "sentiment_pipeline.joblib"
|
|
|
|
|
|
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
@st.cache_resource(show_spinner=False)
|
| 31 |
+
def load_model():
|
| 32 |
+
"""Download and load the trained model from Hugging Face Hub."""
|
| 33 |
+
model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILENAME)
|
| 34 |
+
pipeline = joblib.load(model_path)
|
| 35 |
+
return pipeline
|
| 36 |
+
|
| 37 |
+
pipeline = load_model()
|
| 38 |
|
| 39 |
# -------------------------------------------------------------------------
|
| 40 |
+
# Helper function for predictions
|
| 41 |
# -------------------------------------------------------------------------
|
| 42 |
+
def predict_sentiment(text: str) -> tuple[str, Dict[str, float]]:
|
| 43 |
+
"""Predict sentiment and confidence scores."""
|
| 44 |
+
probs = pipeline.predict_proba([text])[0]
|
| 45 |
+
classes = pipeline.classes_
|
| 46 |
+
label = classes[probs.argmax()]
|
| 47 |
+
probabilities = dict(zip(classes, probs))
|
| 48 |
+
return label, probabilities
|
| 49 |
+
|
| 50 |
def format_probabilities(probabilities: Dict[str, float]) -> pd.DataFrame:
|
| 51 |
+
"""Convert probabilities to styled DataFrame."""
|
| 52 |
return (
|
| 53 |
pd.DataFrame.from_dict(probabilities, orient="index", columns=["confidence"])
|
| 54 |
.sort_values("confidence", ascending=False)
|
|
|
|
| 56 |
)
|
| 57 |
|
| 58 |
# -------------------------------------------------------------------------
|
| 59 |
+
# Streamlit UI
|
| 60 |
# -------------------------------------------------------------------------
|
| 61 |
+
def main():
|
| 62 |
+
st.sidebar.header("๐ Model Snapshot")
|
| 63 |
+
st.sidebar.write("**Source:**", MODEL_REPO)
|
| 64 |
+
st.sidebar.success("โ
Loaded model from Hugging Face Hub")
|
| 65 |
|
| 66 |
+
st.subheader("๐ฎ Real-Time Sentiment Analysis")
|
| 67 |
+
user_input = st.text_area("Enter a tweet or comment:", height=150)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
+
if st.button("Analyze", type="primary"):
|
| 70 |
+
if not user_input.strip():
|
| 71 |
+
st.warning("โ ๏ธ Please enter text to analyze.")
|
| 72 |
else:
|
| 73 |
+
label, probabilities = predict_sentiment(user_input)
|
| 74 |
+
st.success(f"Predicted Sentiment: **{label.title()}**")
|
| 75 |
+
st.dataframe(format_probabilities(probabilities), use_container_width=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
st.markdown("---")
|
| 78 |
st.caption("ยฉ 2025 Deloitte-aligned Sentiment Analytics Accelerator")
|
| 79 |
|
|
|
|
|
|
|
|
|
|
| 80 |
if __name__ == "__main__":
|
| 81 |
main()
|
| 82 |
|