Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -12,7 +12,6 @@ RATING_MAP = {
|
|
12 |
2: "Positive (⭐⭐⭐)"
|
13 |
}
|
14 |
|
15 |
-
# Load models
|
16 |
@st.cache_resource
|
17 |
def load_models():
|
18 |
sentiment_model = pipeline(
|
@@ -22,23 +21,20 @@ def load_models():
|
|
22 |
ner_model = pipeline("ner", model="dslim/bert-base-NER")
|
23 |
return sentiment_model, ner_model
|
24 |
|
25 |
-
# Sentiment analysis
|
26 |
def analyze_sentiment(text, model):
|
27 |
result = model(text)[0]
|
28 |
-
rating = int(result['label'].split('_')[-1])
|
29 |
return {
|
30 |
'rating': rating,
|
31 |
'label': RATING_MAP[rating],
|
32 |
'score': result['score']
|
33 |
}
|
34 |
|
35 |
-
# Entity extraction
|
36 |
def extract_aspects(text, model):
|
37 |
entities = model(text)
|
38 |
aspects = []
|
39 |
current_entity = ""
|
40 |
|
41 |
-
# Merge subword tokens
|
42 |
for entity in entities:
|
43 |
if entity['word'].startswith('##'):
|
44 |
current_entity += entity['word'][2:]
|
@@ -59,7 +55,6 @@ def extract_aspects(text, model):
|
|
59 |
|
60 |
return [a for a in aspects if a['type'] in ['PRODUCT', 'ORG', 'PERSON']]
|
61 |
|
62 |
-
# Visualization functions
|
63 |
def plot_sentiment_distribution(df):
|
64 |
fig, ax = plt.subplots()
|
65 |
df['label'].value_counts().loc[list(RATING_MAP.values())].plot.pie(
|
@@ -84,41 +79,32 @@ def plot_wordcloud(negative_reviews):
|
|
84 |
ax.axis('off')
|
85 |
return fig
|
86 |
|
87 |
-
# Main app
|
88 |
def main():
|
89 |
st.title("Restaurant Review Analyzer")
|
90 |
st.markdown("Using fine-tuned model for sentiment and aspect analysis")
|
91 |
|
92 |
-
# Initialize models
|
93 |
sentiment_model, ner_model = load_models()
|
94 |
|
95 |
-
# Sidebar controls
|
96 |
st.sidebar.header("Analysis Options")
|
97 |
analysis_mode = st.sidebar.radio(
|
98 |
"Select Mode",
|
99 |
["Single Review", "Batch Analysis"]
|
100 |
)
|
101 |
|
102 |
-
# Initialize session state
|
103 |
if 'history' not in st.session_state:
|
104 |
st.session_state.history = pd.DataFrame(
|
105 |
columns=['text', 'rating', 'label', 'date', 'aspects']
|
106 |
)
|
107 |
|
108 |
if analysis_mode == "Single Review":
|
109 |
-
# Single review analysis
|
110 |
user_input = st.text_area("Enter or paste a restaurant review:", height=150)
|
111 |
|
112 |
if st.button("Analyze"):
|
113 |
if user_input:
|
114 |
with st.spinner("Analyzing..."):
|
115 |
-
# Sentiment analysis
|
116 |
sentiment = analyze_sentiment(user_input, sentiment_model)
|
117 |
-
|
118 |
-
# Aspect extraction
|
119 |
aspects = extract_aspects(user_input, ner_model)
|
120 |
|
121 |
-
# Save to history
|
122 |
new_entry = pd.DataFrame([{
|
123 |
'text': user_input,
|
124 |
'rating': sentiment['rating'],
|
@@ -131,7 +117,6 @@ def main():
|
|
131 |
ignore_index=True
|
132 |
)
|
133 |
|
134 |
-
# Display results
|
135 |
st.subheader("Analysis Results")
|
136 |
col1, col2 = st.columns(2)
|
137 |
with col1:
|
@@ -149,7 +134,6 @@ def main():
|
|
149 |
st.warning("Please enter a review")
|
150 |
|
151 |
else:
|
152 |
-
# Batch analysis mode
|
153 |
uploaded_file = st.file_uploader("Upload CSV file", type=["csv"])
|
154 |
|
155 |
if uploaded_file:
|
@@ -181,21 +165,17 @@ def main():
|
|
181 |
)
|
182 |
st.success(f"Completed analysis of {len(df)} reviews")
|
183 |
|
184 |
-
# Display historical data and visualizations
|
185 |
if not st.session_state.history.empty:
|
186 |
st.divider()
|
187 |
st.header("Analysis History")
|
188 |
|
189 |
-
# Raw data display
|
190 |
with st.expander("View Raw Data"):
|
191 |
st.dataframe(st.session_state.history)
|
192 |
|
193 |
-
# Visualizations
|
194 |
st.subheader("Sentiment Distribution")
|
195 |
fig1 = plot_sentiment_distribution(st.session_state.history)
|
196 |
st.pyplot(fig1)
|
197 |
|
198 |
-
# Negative reviews word cloud
|
199 |
negative_reviews = st.session_state.history[
|
200 |
st.session_state.history['rating'] == 0
|
201 |
]['text'].tolist()
|
@@ -207,7 +187,6 @@ def main():
|
|
207 |
else:
|
208 |
st.info("No negative reviews yet")
|
209 |
|
210 |
-
# Time trend analysis
|
211 |
if len(st.session_state.history) > 1:
|
212 |
st.subheader("Rating Trend Over Time")
|
213 |
time_df = st.session_state.history.copy()
|
|
|
12 |
2: "Positive (⭐⭐⭐)"
|
13 |
}
|
14 |
|
|
|
15 |
@st.cache_resource
|
16 |
def load_models():
|
17 |
sentiment_model = pipeline(
|
|
|
21 |
ner_model = pipeline("ner", model="dslim/bert-base-NER")
|
22 |
return sentiment_model, ner_model
|
23 |
|
|
|
24 |
def analyze_sentiment(text, model):
|
25 |
result = model(text)[0]
|
26 |
+
rating = int(result['label'].split('_')[-1])
|
27 |
return {
|
28 |
'rating': rating,
|
29 |
'label': RATING_MAP[rating],
|
30 |
'score': result['score']
|
31 |
}
|
32 |
|
|
|
33 |
def extract_aspects(text, model):
|
34 |
entities = model(text)
|
35 |
aspects = []
|
36 |
current_entity = ""
|
37 |
|
|
|
38 |
for entity in entities:
|
39 |
if entity['word'].startswith('##'):
|
40 |
current_entity += entity['word'][2:]
|
|
|
55 |
|
56 |
return [a for a in aspects if a['type'] in ['PRODUCT', 'ORG', 'PERSON']]
|
57 |
|
|
|
58 |
def plot_sentiment_distribution(df):
|
59 |
fig, ax = plt.subplots()
|
60 |
df['label'].value_counts().loc[list(RATING_MAP.values())].plot.pie(
|
|
|
79 |
ax.axis('off')
|
80 |
return fig
|
81 |
|
|
|
82 |
def main():
|
83 |
st.title("Restaurant Review Analyzer")
|
84 |
st.markdown("Using fine-tuned model for sentiment and aspect analysis")
|
85 |
|
|
|
86 |
sentiment_model, ner_model = load_models()
|
87 |
|
|
|
88 |
st.sidebar.header("Analysis Options")
|
89 |
analysis_mode = st.sidebar.radio(
|
90 |
"Select Mode",
|
91 |
["Single Review", "Batch Analysis"]
|
92 |
)
|
93 |
|
|
|
94 |
if 'history' not in st.session_state:
|
95 |
st.session_state.history = pd.DataFrame(
|
96 |
columns=['text', 'rating', 'label', 'date', 'aspects']
|
97 |
)
|
98 |
|
99 |
if analysis_mode == "Single Review":
|
|
|
100 |
user_input = st.text_area("Enter or paste a restaurant review:", height=150)
|
101 |
|
102 |
if st.button("Analyze"):
|
103 |
if user_input:
|
104 |
with st.spinner("Analyzing..."):
|
|
|
105 |
sentiment = analyze_sentiment(user_input, sentiment_model)
|
|
|
|
|
106 |
aspects = extract_aspects(user_input, ner_model)
|
107 |
|
|
|
108 |
new_entry = pd.DataFrame([{
|
109 |
'text': user_input,
|
110 |
'rating': sentiment['rating'],
|
|
|
117 |
ignore_index=True
|
118 |
)
|
119 |
|
|
|
120 |
st.subheader("Analysis Results")
|
121 |
col1, col2 = st.columns(2)
|
122 |
with col1:
|
|
|
134 |
st.warning("Please enter a review")
|
135 |
|
136 |
else:
|
|
|
137 |
uploaded_file = st.file_uploader("Upload CSV file", type=["csv"])
|
138 |
|
139 |
if uploaded_file:
|
|
|
165 |
)
|
166 |
st.success(f"Completed analysis of {len(df)} reviews")
|
167 |
|
|
|
168 |
if not st.session_state.history.empty:
|
169 |
st.divider()
|
170 |
st.header("Analysis History")
|
171 |
|
|
|
172 |
with st.expander("View Raw Data"):
|
173 |
st.dataframe(st.session_state.history)
|
174 |
|
|
|
175 |
st.subheader("Sentiment Distribution")
|
176 |
fig1 = plot_sentiment_distribution(st.session_state.history)
|
177 |
st.pyplot(fig1)
|
178 |
|
|
|
179 |
negative_reviews = st.session_state.history[
|
180 |
st.session_state.history['rating'] == 0
|
181 |
]['text'].tolist()
|
|
|
187 |
else:
|
188 |
st.info("No negative reviews yet")
|
189 |
|
|
|
190 |
if len(st.session_state.history) > 1:
|
191 |
st.subheader("Rating Trend Over Time")
|
192 |
time_df = st.session_state.history.copy()
|