import gradio as gr import joblib import numpy as np from intent import predict_intent from topic_model import get_review_topic from huggingface_hub import hf_hub_download class TextPreprocessor: """Stub class to mimic the preprocessing step used when training. The original pipeline was pickled with this class defined in ``__main__`` (a notebook). When the module is imported on HuggingFace the class lives in ``app`` instead, so unpickling fails unless we make a dummy version available under the old name. """ def __init__(self): pass def fit(self, X, y=None): return self def transform(self, X): return X def fit_transform(self, X, y=None): return X def __call__(self, x): return x # register stub in __main__ so joblib can resolve the name during unpickling import __main__ __main__.TextPreprocessor = TextPreprocessor # download sentiment pipeline and other assets from the space repo pipeline_file = hf_hub_download( repo_id="Maarij-Aqeel/Customer_review_analyzer", filename="sentiment_pipeline.pkl" ) vectorizer_file = hf_hub_download( repo_id="Maarij-Aqeel/Customer_review_analyzer", filename="tfidf_vectorizer.pkl" ) nmf_file = hf_hub_download( repo_id="Maarij-Aqeel/Customer_review_analyzer", filename="nmf_model.pkl" ) try: sentiment_pipeline = joblib.load(pipeline_file) except Exception as e: # pragma: no cover - helpful when learning raise RuntimeError("could not load sentiment pipeline: %s" % e) try: vectorizer = joblib.load(vectorizer_file) nmf_model = joblib.load(nmf_file) except Exception as e: raise RuntimeError("could not load vectorizer/nmf model: %s" % e) # the pipeline predicts integer labels (-1, 0, 1) corresponding to # default negative/neutral/positive sentiment. map them to human-readable # strings for display. label_map = { -1: "negative", 0: "neutral", 1: "positive", } def analyze_review(review_text: str): """Return sentiment, intent, topic keywords, and confidence scores for a piece of text.""" if not review_text: return "", "", "" # Get sentiment prediction and confidence scores pred = sentiment_pipeline.predict([review_text])[0] sentiment = label_map.get(pred, str(pred)) # Get probability scores for all classes proba = sentiment_pipeline.predict_proba([review_text])[0] # Map probabilities to sentiment labels confidence_map = { -1: proba[0], # negative 0: proba[1], # neutral 1: proba[2], # positive } confidence_score = confidence_map.get(pred, 0.0) confidence_text = f"Sentiment: {sentiment}\nConfidence: {confidence_score:.2%}" intent = predict_intent(review_text) topic = get_review_topic(review_text, vectorizer, nmf_model) return confidence_text, intent, topic # build a simple Gradio interface with one text input and multiple outputs. iface = gr.Interface( fn=analyze_review, inputs=gr.Textbox(lines=4, placeholder="Enter a customer review...", label="Customer Review"), outputs=[ gr.Textbox(label="Sentiment & Confidence Score"), gr.Textbox(label="Predicted Intent"), gr.Textbox(label="Topic / Keywords"), ], title="Customer Review Analyzer", description=( "Enter a customer review to analyze its sentiment, predicted intent, " "identified topics, and model confidence scores. This interactive demo " "showcases how the NLP system works in a real-world setting." ), examples=[ ["I love this product! Amazing quality and fast delivery."], ["The package arrived damaged and the refund process was slow."], ["Average product, nothing special."], ], ) if __name__ == "__main__": iface.launch()