Spaces:
Paused
Paused
| import torch | |
| import torch.nn.functional as F | |
| import gradio as gr | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| from bertopic import BERTopic | |
| from sentence_transformers import SentenceTransformer | |
| import os | |
| # --- 1. CONFIGURATION --- | |
| # Tránh xung đột luồng khi chạy tokenizer | |
| os.environ["TOKENIZERS_PARALLELISM"] = "false" | |
| ROBERTA_PATH = "roberta_base_checkpoint" | |
| BERTOPIC_PATH = "bertopic_checkpoint" | |
| # --- 2. INITIALIZATION (Runs once at startup) --- | |
| print("--- System Initializing ---") | |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| print(f"Device detected: {device.type.upper()}") | |
| # Load RoBERTa | |
| tokenizer = AutoTokenizer.from_pretrained(ROBERTA_PATH) | |
| roberta_model = AutoModelForSequenceClassification.from_pretrained(ROBERTA_PATH).to(device) | |
| roberta_model.eval() | |
| # Load BERTopic | |
| embedding_model = SentenceTransformer("all-MiniLM-L6-v2") | |
| topic_model = BERTopic.load(BERTOPIC_PATH, embedding_model=embedding_model) | |
| print("--- All models loaded successfully! ---") | |
| # --- 3. CORE LOGIC --- | |
| def analyze_review(text): | |
| if not text.strip(): | |
| return "Please enter some text", None, None, "" | |
| # --- Sentiment Analysis (RoBERTa) --- | |
| inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=256).to(device) | |
| with torch.no_grad(): | |
| outputs = roberta_model(**inputs) | |
| probs = F.softmax(outputs.logits, dim=1) | |
| pred_idx = torch.argmax(probs, dim=1).item() | |
| # Matching common sentiment output formats | |
| sentiment_labels = ['Negative 😡', 'Neutral 😐', 'Positive 😊'] | |
| sentiment = sentiment_labels[pred_idx] | |
| confidence = probs[0][pred_idx].item() | |
| # --- Topic Modeling (BERTopic) --- | |
| new_topics, _ = topic_model.transform([text]) | |
| topic_id = int(new_topics[0]) | |
| if topic_id != -1: | |
| keywords_data = topic_model.get_topic(topic_id) | |
| # Extracting top 5 keywords | |
| keywords_list = ", ".join([word for word, score in keywords_data[:5]]) | |
| else: | |
| keywords_list = "Outlier (No specific topic detected)" | |
| return sentiment, f"{confidence:.2%}", topic_id, keywords_list | |
| # --- 4. GRADIO INTERFACE (WEB & API) --- | |
| with gr.Blocks(title="Food Review Analysis Tool") as demo: | |
| gr.Markdown("# 📊 Food Review Analysis System") | |
| gr.Markdown("An integrated pipeline using **RoBERTa** for Sentiment and **BERTopic** for Topic Extraction.") | |
| with gr.Row(): | |
| with gr.Column(): | |
| input_text = gr.Textbox( | |
| label="Review Content", | |
| placeholder="e.g., The pizza was delicious but the delivery took two hours!", | |
| lines=5 | |
| ) | |
| btn = gr.Button("Analyze Now", variant="primary") | |
| with gr.Column(): | |
| out_sentiment = gr.Label(label="Sentiment Prediction") | |
| out_confidence = gr.Textbox(label="Confidence Score") | |
| with gr.Row(): | |
| out_topic_id = gr.Number(label="Topic ID") | |
| out_keywords = gr.Textbox(label="Main Keywords") | |
| # Event binding | |
| btn.click( | |
| fn=analyze_review, | |
| inputs=input_text, | |
| outputs=[out_sentiment, out_confidence, out_topic_id, out_keywords] | |
| ) | |
| # Examples for quick testing | |
| gr.Examples( | |
| examples=[ | |
| ["The food was amazing, very delicious!"], | |
| ["Service was very slow and the waiter was rude."], | |
| ["While the truffle-infused risotto was a masterpiece, the deafening noise made it hard to enjoy."] | |
| ], | |
| inputs=input_text | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch() |