Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
-
import spaces
|
3 |
import torch
|
4 |
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
5 |
-
import math
|
6 |
|
7 |
# Initialize device
|
8 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
@@ -22,156 +20,101 @@ SENTIMENT_MAP = {
|
|
22 |
4: "Very Positive"
|
23 |
}
|
24 |
|
25 |
-
def split_text(text, max_length=512):
|
26 |
-
"""
|
27 |
-
Splits the input text into chunks where each chunk has tokens <= max_length.
|
28 |
-
Splitting is done at sentence boundaries to maintain context.
|
29 |
-
"""
|
30 |
-
# Simple sentence splitting based on periods. For more accurate splitting, consider using nltk or spacy.
|
31 |
-
sentences = text.split('. ')
|
32 |
-
chunks = []
|
33 |
-
current_chunk = ""
|
34 |
-
|
35 |
-
for sentence in sentences:
|
36 |
-
# Add the period back if it was removed during splitting
|
37 |
-
if not sentence.endswith('.'):
|
38 |
-
sentence += '.'
|
39 |
-
|
40 |
-
# Check if adding the sentence exceeds the max_length
|
41 |
-
encoded = tokenizer.encode(current_chunk + " " + sentence, truncation=False)
|
42 |
-
if len(encoded) > max_length:
|
43 |
-
if current_chunk:
|
44 |
-
chunks.append(current_chunk.strip())
|
45 |
-
current_chunk = sentence
|
46 |
-
else:
|
47 |
-
# Single sentence longer than max_length, force split
|
48 |
-
for i in range(0, len(encoded), max_length):
|
49 |
-
chunk_tokens = encoded[i:i + max_length]
|
50 |
-
chunk_text = tokenizer.decode(chunk_tokens, skip_special_tokens=True)
|
51 |
-
chunks.append(chunk_text.strip())
|
52 |
-
current_chunk = ""
|
53 |
-
else:
|
54 |
-
current_chunk += " " + sentence
|
55 |
-
|
56 |
-
if current_chunk:
|
57 |
-
chunks.append(current_chunk.strip())
|
58 |
-
|
59 |
-
return chunks
|
60 |
-
|
61 |
-
def aggregate_sentiments(all_probabilities, threshold=0.7):
|
62 |
-
"""
|
63 |
-
Aggregates the sentiment probabilities from all chunks.
|
64 |
-
Prioritizes extreme sentiments if any chunk has a high confidence in them.
|
65 |
-
Otherwise, uses weighted voting based on confidence scores.
|
66 |
-
"""
|
67 |
-
aggregated_probs = torch.tensor(all_probabilities).mean(dim=0).numpy()
|
68 |
-
aggregated_confidence = torch.tensor(all_probabilities).mean(dim=0).max().item()
|
69 |
-
predicted_class = aggregated_probs.argmax()
|
70 |
-
final_sentiment = SENTIMENT_MAP[predicted_class]
|
71 |
-
final_confidence = aggregated_probs[predicted_class]
|
72 |
-
|
73 |
-
# Check for extreme sentiments with high confidence
|
74 |
-
for idx, prob in enumerate(aggregated_probs):
|
75 |
-
if (idx == 0 or idx == 4) and prob > threshold:
|
76 |
-
final_sentiment = SENTIMENT_MAP[idx]
|
77 |
-
final_confidence = prob
|
78 |
-
break
|
79 |
-
|
80 |
-
return final_sentiment, final_confidence, aggregated_probs
|
81 |
-
|
82 |
-
@spaces.GPU
|
83 |
def analyze_sentiment(text, show_probabilities=False):
|
84 |
"""
|
85 |
-
Analyzes the sentiment of the input text
|
86 |
-
it splits the text into chunks and aggregates the results intelligently.
|
87 |
"""
|
88 |
try:
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
# Aggregate results
|
115 |
-
final_sentiment, final_confidence, aggregated_probs = aggregate_sentiments(all_probabilities)
|
116 |
-
|
117 |
-
result = f"**Overall Sentiment: {final_sentiment}**\nConfidence: {final_confidence:.2%}\n\n"
|
118 |
|
119 |
if show_probabilities:
|
120 |
-
result += "### Detailed Analysis:\n"
|
121 |
-
|
122 |
-
|
123 |
-
result += f"{cls}: {prob:.2%}\n"
|
124 |
-
else:
|
125 |
-
result += "### Detailed Analysis:\n" + detailed_results
|
126 |
|
127 |
return result
|
128 |
except Exception as e:
|
129 |
return f"An error occurred during sentiment analysis: {str(e)}"
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
# Create Gradio interface using Blocks for better layout control
|
132 |
-
with gr.Blocks(theme=
|
133 |
-
gr.Markdown("# π Sentiment Analysis Wizard")
|
134 |
gr.Markdown(
|
135 |
"""
|
136 |
-
|
|
|
|
|
|
|
|
|
137 |
"""
|
138 |
)
|
139 |
|
140 |
with gr.Row():
|
141 |
-
with gr.Column():
|
142 |
input_text = gr.Textbox(
|
143 |
lines=10,
|
144 |
-
placeholder="Enter text
|
145 |
-
label="Input Text"
|
146 |
-
|
147 |
-
show_probs = gr.Checkbox(
|
148 |
-
label="Show probabilities for each class",
|
149 |
-
value=False
|
150 |
)
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
output = gr.Markdown(label="Result")
|
154 |
|
155 |
-
with gr.Accordion("
|
156 |
examples = [
|
157 |
["I absolutely loved this movie! The acting was superb and the plot was engaging.", True],
|
158 |
["The service at this restaurant was terrible. I'll never go back.", False],
|
159 |
["The product works as expected. Nothing special, but it gets the job done.", True],
|
160 |
["I'm somewhat disappointed with my purchase. It's not as good as I hoped.", False],
|
161 |
-
["This book changed my life! I couldn't put it down and learned so much.", True]
|
162 |
-
[
|
163 |
-
"""Discover the emotional tone behind any text with our advanced AI model! This app uses a state-of-the-art language model to analyze the sentiment of your text, classifying it into one of five categories: Very Negative, Negative, Neutral, Positive, or Very Positive.
|
164 |
-
|
165 |
-
Discover the emotional tone behind any text with our advanced AI model! This app uses a state-of-the-art language model to analyze the sentiment of your text, classifying it into one of five categories: Very Negative, Negative, Neutral, Positive, or Very Positive.
|
166 |
-
|
167 |
-
FUCK YOU BITCH""",
|
168 |
-
True
|
169 |
-
]
|
170 |
]
|
171 |
gr.Examples(
|
172 |
examples=examples,
|
173 |
inputs=[input_text, show_probs],
|
174 |
-
label="
|
175 |
)
|
176 |
|
177 |
analyze_button.click(
|
@@ -180,12 +123,6 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
180 |
outputs=output
|
181 |
)
|
182 |
|
183 |
-
gr.Markdown(
|
184 |
-
"""
|
185 |
-
---
|
186 |
-
**Developed with β€οΈ using Gradio and Transformers by Hugging Face**
|
187 |
-
"""
|
188 |
-
)
|
189 |
|
190 |
# Launch the interface
|
191 |
-
demo.launch()
|
|
|
1 |
import gradio as gr
|
|
|
2 |
import torch
|
3 |
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
|
|
4 |
|
5 |
# Initialize device
|
6 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
20 |
4: "Very Positive"
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
def analyze_sentiment(text, show_probabilities=False):
|
24 |
"""
|
25 |
+
Analyzes the sentiment of the input text with preprocessing.
|
|
|
26 |
"""
|
27 |
try:
|
28 |
+
# Preprocess text - convert to lowercase
|
29 |
+
text = text.lower()
|
30 |
+
|
31 |
+
# Tokenize and prepare input
|
32 |
+
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512).to(device)
|
33 |
+
|
34 |
+
with torch.no_grad():
|
35 |
+
outputs = model(**inputs)
|
36 |
+
|
37 |
+
probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1).cpu().numpy()[0]
|
38 |
+
predicted_class = probabilities.argmax()
|
39 |
+
predicted_sentiment = SENTIMENT_MAP[predicted_class]
|
40 |
+
confidence = probabilities[predicted_class]
|
41 |
+
|
42 |
+
# Prepare the result with emoji indicators
|
43 |
+
sentiment_emojis = {
|
44 |
+
"Very Negative": "π‘",
|
45 |
+
"Negative": "π",
|
46 |
+
"Neutral": "π",
|
47 |
+
"Positive": "π",
|
48 |
+
"Very Positive": "π€©"
|
49 |
+
}
|
50 |
+
|
51 |
+
result = f"## {sentiment_emojis[predicted_sentiment]} Overall Sentiment: {predicted_sentiment}\n"
|
52 |
+
result += f"### Confidence: {confidence:.2%}\n\n"
|
|
|
|
|
|
|
|
|
53 |
|
54 |
if show_probabilities:
|
55 |
+
result += "### Detailed Analysis:\n"
|
56 |
+
for cls, prob in zip(SENTIMENT_MAP.values(), probabilities):
|
57 |
+
emoji = sentiment_emojis[cls]
|
58 |
+
result += f"{emoji} {cls}: {prob:.2%}\n"
|
|
|
|
|
59 |
|
60 |
return result
|
61 |
except Exception as e:
|
62 |
return f"An error occurred during sentiment analysis: {str(e)}"
|
63 |
|
64 |
+
# Custom theme
|
65 |
+
custom_theme = gr.themes.Soft().set(
|
66 |
+
body_background_fill="*radial-gradient(circle at top left, #f3e7e9, #e3eeff)",
|
67 |
+
block_background_fill="rgba(255, 255, 255, 0.95)",
|
68 |
+
block_border_width="0px",
|
69 |
+
block_shadow="*0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
|
70 |
+
button_primary_background_fill="*linear-gradient(90deg, #4F46E5, #7C3AED)",
|
71 |
+
button_primary_background_fill_hover="*linear-gradient(90deg, #4338CA, #6D28D9)",
|
72 |
+
button_primary_text_color="white",
|
73 |
+
input_background_fill="white",
|
74 |
+
)
|
75 |
+
|
76 |
# Create Gradio interface using Blocks for better layout control
|
77 |
+
with gr.Blocks(theme=custom_theme) as demo:
|
|
|
78 |
gr.Markdown(
|
79 |
"""
|
80 |
+
# π Sentiment Analysis Wizard
|
81 |
+
|
82 |
+
<div style='text-align: center; padding: 1rem; background: rgba(255, 255, 255, 0.5); border-radius: 1rem; margin: 1rem 0;'>
|
83 |
+
Discover the emotional tone behind any text with our advanced AI model! Let our wizard analyze your text and reveal its true sentiment.
|
84 |
+
</div>
|
85 |
"""
|
86 |
)
|
87 |
|
88 |
with gr.Row():
|
89 |
+
with gr.Column(scale=2):
|
90 |
input_text = gr.Textbox(
|
91 |
lines=10,
|
92 |
+
placeholder="Enter your text here to uncover its emotional essence...",
|
93 |
+
label="βοΈ Input Text",
|
94 |
+
show_label=True
|
|
|
|
|
|
|
95 |
)
|
96 |
+
with gr.Row():
|
97 |
+
show_probs = gr.Checkbox(
|
98 |
+
label="π― Show detailed probabilities",
|
99 |
+
value=False
|
100 |
+
)
|
101 |
+
analyze_button = gr.Button("β¨ Analyze Sentiment", variant="primary")
|
102 |
+
|
103 |
+
with gr.Column(scale=1):
|
104 |
output = gr.Markdown(label="Result")
|
105 |
|
106 |
+
with gr.Accordion("π Example Texts", open=False):
|
107 |
examples = [
|
108 |
["I absolutely loved this movie! The acting was superb and the plot was engaging.", True],
|
109 |
["The service at this restaurant was terrible. I'll never go back.", False],
|
110 |
["The product works as expected. Nothing special, but it gets the job done.", True],
|
111 |
["I'm somewhat disappointed with my purchase. It's not as good as I hoped.", False],
|
112 |
+
["This book changed my life! I couldn't put it down and learned so much.", True]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
]
|
114 |
gr.Examples(
|
115 |
examples=examples,
|
116 |
inputs=[input_text, show_probs],
|
117 |
+
label="Try these examples"
|
118 |
)
|
119 |
|
120 |
analyze_button.click(
|
|
|
123 |
outputs=output
|
124 |
)
|
125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
|
127 |
# Launch the interface
|
128 |
+
demo.launch()
|