|
import os |
|
import numpy as np |
|
import pandas as pd |
|
import streamlit as st |
|
from transformers import ( |
|
pipeline, |
|
AutoTokenizer, |
|
AutoModelForSequenceClassification, |
|
AutoModelForSeq2SeqLM |
|
) |
|
from keybert import KeyBERT |
|
|
|
|
|
@st.cache_resource |
|
def load_sentiment_pipeline(): |
|
model_name = "mayf/amazon_reviews_bert_ft" |
|
tok = AutoTokenizer.from_pretrained(model_name, use_auth_token=True) |
|
mdl = AutoModelForSequenceClassification.from_pretrained( |
|
model_name, |
|
use_auth_token=True |
|
) |
|
return pipeline( |
|
"sentiment-analysis", |
|
model=mdl, |
|
tokenizer=tok, |
|
return_all_scores=True |
|
) |
|
|
|
@st.cache_resource |
|
def load_keybert_model(): |
|
return KeyBERT(model="all-MiniLM-L6-v2") |
|
|
|
|
|
@st.cache_resource |
|
def load_flant5_pipeline(): |
|
seq_tok = AutoTokenizer.from_pretrained("google/flan-t5-base") |
|
seq_model = AutoModelForSeq2SeqLM.from_pretrained("google/flan-t5-base") |
|
return pipeline( |
|
"text2text-generation", |
|
model=seq_model, |
|
tokenizer=seq_tok, |
|
max_new_tokens=300, |
|
do_sample=True, |
|
temperature=0.7 |
|
) |
|
|
|
LABEL_MAP = { |
|
"LABEL_0": "Very Negative", |
|
"LABEL_1": "Negative", |
|
"LABEL_2": "Neutral", |
|
"LABEL_3": "Positive", |
|
"LABEL_4": "Very Positive" |
|
} |
|
|
|
|
|
def main(): |
|
st.title("📊 Amazon Review Analyzer") |
|
|
|
review = st.text_area("Enter your review:") |
|
if not st.button("Analyze Review"): |
|
return |
|
if not review: |
|
st.warning("Please enter a review to analyze.") |
|
return |
|
|
|
progress = st.progress(0) |
|
|
|
|
|
progress.text("Loading models...") |
|
sentiment_pipeline = load_sentiment_pipeline() |
|
kw_model = load_keybert_model() |
|
generation_pipeline = load_flant5_pipeline() |
|
progress.progress(20) |
|
|
|
|
|
progress.text("Analyzing sentiment...") |
|
raw_scores = sentiment_pipeline(review)[0] |
|
sentiment_results = {LABEL_MAP[item['label']]: float(item['score']) for item in raw_scores} |
|
progress.progress(40) |
|
|
|
|
|
progress.text("Extracting keywords...") |
|
keywords = kw_model.extract_keywords( |
|
review, |
|
keyphrase_ngram_range=(1, 2), |
|
stop_words="english", |
|
top_n=3 |
|
) |
|
progress.progress(60) |
|
|
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
st.subheader("Sentiment Scores") |
|
st.json({k: round(v, 4) for k, v in sentiment_results.items()}) |
|
with col2: |
|
st.subheader("Top 3 Keywords") |
|
for kw, score in keywords: |
|
st.write(f"• {kw} ({score:.4f})") |
|
|
|
|
|
progress.text("Rendering chart...") |
|
df_scores = pd.DataFrame.from_dict( |
|
sentiment_results, |
|
orient='index', |
|
columns=['score'] |
|
) |
|
df_scores.index.name = 'Sentiment' |
|
st.bar_chart(df_scores) |
|
progress.progress(80) |
|
|
|
|
|
max_label, max_score = max(sentiment_results.items(), key=lambda x: x[1]) |
|
st.markdown(f"**Highest Sentiment:** **{max_label}** ({max_score:.4f})") |
|
|
|
|
|
progress.text("Generating detailed recommendations...") |
|
if max_label in ["Very Negative", "Negative", "Neutral"]: |
|
prompt = ( |
|
"You are a senior product quality and customer experience specialist at an e-commerce food retailer. |
|
|
|
" |
|
f"Customer Review: |
|
\"{review}\" |
|
|
|
" |
|
"Please analyze this feedback and provide **three** distinct, actionable improvement recommendations designed to reduce customer pain points. |
|
" |
|
"For each recommendation, include: |
|
" |
|
" 1. **Recommendation Title**: a concise summary of the action. |
|
" |
|
" 2. the specific issue or frustration extracted from the review. |
|
" |
|
" 3. why this action addresses the pain point and how it will improve the customer experience. |
|
" |
|
" 4. a bullet-point list of 3–5 clear steps for operations or product teams to execute. |
|
" |
|
" 5. how to measure the impact. |
|
|
|
" |
|
"Write each recommendation in at least 5–7 sentences, grounding every detail in the customer's own words. " |
|
"Avoid generic advice—focus on specifics from the review. |
|
|
|
" |
|
"Recommendations: |
|
" |
|
) |
|
response = generation_pipeline(prompt) |
|
detailed = response[0]["generated_text"] |
|
st.markdown(detailed) |
|
else: |
|
st.info("Detailed recommendations are provided only for Neutral, Negative, or Very Negative reviews.") |
|
|
|
|
|
progress.progress(100) |
|
progress.text("Done!") |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |
|
|
|
|