Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -15,7 +15,8 @@ import time
|
|
15 |
|
16 |
# Initialize models
|
17 |
sentiment_analyzer = pipeline("sentiment-analysis", model="cardiffnlp/twitter-roberta-base-sentiment-latest")
|
18 |
-
|
|
|
19 |
|
20 |
class ReviewAnalyzer:
|
21 |
def __init__(self):
|
@@ -43,54 +44,72 @@ class ReviewAnalyzer:
|
|
43 |
return text
|
44 |
|
45 |
def extract_aspect_keywords(self, reviews: List[str]) -> Dict:
|
46 |
-
"""Extract aspect-based sentiment keywords"""
|
47 |
-
|
|
|
48 |
detailed_aspects = []
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
for review in reviews:
|
51 |
if not review.strip() or len(review) < 10:
|
52 |
continue
|
53 |
-
|
|
|
54 |
try:
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
label = aspect['entity_group'].lower()
|
59 |
-
confidence = float(aspect['score'])
|
60 |
-
|
61 |
-
# Map labels to sentiment
|
62 |
-
if 'pos' in label or label == 'positive':
|
63 |
-
sentiment = 'positive'
|
64 |
-
elif 'neg' in label or label == 'negative':
|
65 |
-
sentiment = 'negative'
|
66 |
-
else:
|
67 |
-
continue
|
68 |
-
|
69 |
-
# Count aspects
|
70 |
-
if word not in all_aspects[sentiment]:
|
71 |
-
all_aspects[sentiment][word] = 0
|
72 |
-
all_aspects[sentiment][word] += 1
|
73 |
-
|
74 |
-
detailed_aspects.append({
|
75 |
-
'review': review[:50] + '...',
|
76 |
-
'aspect': word,
|
77 |
-
'sentiment': sentiment,
|
78 |
-
'confidence': round(confidence, 3)
|
79 |
-
})
|
80 |
except:
|
81 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
# Get top aspects
|
84 |
-
top_positive = sorted(
|
85 |
-
top_negative = sorted(
|
86 |
|
87 |
return {
|
88 |
'top_positive_aspects': top_positive,
|
89 |
'top_negative_aspects': top_negative,
|
90 |
'detailed_aspects': detailed_aspects,
|
91 |
'summary': {
|
92 |
-
'total_positive_aspects': len(
|
93 |
-
'total_negative_aspects': len(
|
94 |
}
|
95 |
}
|
96 |
|
|
|
15 |
|
16 |
# Initialize models
|
17 |
sentiment_analyzer = pipeline("sentiment-analysis", model="cardiffnlp/twitter-roberta-base-sentiment-latest")
|
18 |
+
# Use a simpler ABSA approach with keyword extraction instead of the problematic model
|
19 |
+
absa_analyzer = None
|
20 |
|
21 |
class ReviewAnalyzer:
|
22 |
def __init__(self):
|
|
|
44 |
return text
|
45 |
|
46 |
def extract_aspect_keywords(self, reviews: List[str]) -> Dict:
|
47 |
+
"""Extract aspect-based sentiment keywords using rule-based approach"""
|
48 |
+
positive_aspects = {}
|
49 |
+
negative_aspects = {}
|
50 |
detailed_aspects = []
|
51 |
|
52 |
+
# Define aspect keywords
|
53 |
+
aspect_keywords = {
|
54 |
+
'quality': ['quality', 'build', 'material', 'durable', 'cheap', 'flimsy'],
|
55 |
+
'price': ['price', 'cost', 'expensive', 'cheap', 'value', 'money', 'affordable'],
|
56 |
+
'delivery': ['delivery', 'shipping', 'fast', 'slow', 'quick', 'late'],
|
57 |
+
'service': ['service', 'support', 'staff', 'helpful', 'rude', 'friendly'],
|
58 |
+
'design': ['design', 'look', 'beautiful', 'ugly', 'style', 'appearance'],
|
59 |
+
'usability': ['easy', 'difficult', 'simple', 'complex', 'user-friendly'],
|
60 |
+
'performance': ['performance', 'speed', 'fast', 'slow', 'efficient']
|
61 |
+
}
|
62 |
+
|
63 |
for review in reviews:
|
64 |
if not review.strip() or len(review) < 10:
|
65 |
continue
|
66 |
+
|
67 |
+
# Get sentiment for the review
|
68 |
try:
|
69 |
+
sentiment_result = sentiment_analyzer(review)[0]
|
70 |
+
review_sentiment = 'positive' if 'pos' in sentiment_result['label'].lower() else 'negative'
|
71 |
+
confidence = float(sentiment_result['score'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
except:
|
73 |
continue
|
74 |
+
|
75 |
+
review_lower = review.lower()
|
76 |
+
|
77 |
+
# Check for aspect mentions
|
78 |
+
for aspect, keywords in aspect_keywords.items():
|
79 |
+
for keyword in keywords:
|
80 |
+
if keyword in review_lower:
|
81 |
+
# Determine if this specific aspect mention is positive or negative
|
82 |
+
aspect_sentiment = review_sentiment
|
83 |
+
|
84 |
+
# Add to aspect counts
|
85 |
+
if aspect_sentiment == 'positive':
|
86 |
+
if aspect not in positive_aspects:
|
87 |
+
positive_aspects[aspect] = 0
|
88 |
+
positive_aspects[aspect] += 1
|
89 |
+
else:
|
90 |
+
if aspect not in negative_aspects:
|
91 |
+
negative_aspects[aspect] = 0
|
92 |
+
negative_aspects[aspect] += 1
|
93 |
+
|
94 |
+
detailed_aspects.append({
|
95 |
+
'review': review[:50] + '...',
|
96 |
+
'aspect': aspect,
|
97 |
+
'sentiment': aspect_sentiment,
|
98 |
+
'confidence': round(confidence, 3)
|
99 |
+
})
|
100 |
+
break # Only count each aspect once per review
|
101 |
|
102 |
# Get top aspects
|
103 |
+
top_positive = sorted(positive_aspects.items(), key=lambda x: x[1], reverse=True)[:10]
|
104 |
+
top_negative = sorted(negative_aspects.items(), key=lambda x: x[1], reverse=True)[:10]
|
105 |
|
106 |
return {
|
107 |
'top_positive_aspects': top_positive,
|
108 |
'top_negative_aspects': top_negative,
|
109 |
'detailed_aspects': detailed_aspects,
|
110 |
'summary': {
|
111 |
+
'total_positive_aspects': len(positive_aspects),
|
112 |
+
'total_negative_aspects': len(negative_aspects)
|
113 |
}
|
114 |
}
|
115 |
|