Vadim Borisov commited on
Commit
88d5272
1 Parent(s): 3ef995c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -44
app.py CHANGED
@@ -2,60 +2,163 @@ import gradio as gr
2
  import spaces
3
  import torch
4
  from transformers import AutoTokenizer, AutoModelForSequenceClassification
 
5
 
6
- # Initialize GPU tensor
7
- zero = torch.Tensor([0]).cuda()
8
- print(f"Initial device: {zero.device}")
9
 
10
  # Load model and tokenizer
11
  model_name = "tabularisai/robust-sentiment-analysis"
12
  tokenizer = AutoTokenizer.from_pretrained(model_name)
13
- model = AutoModelForSequenceClassification.from_pretrained(model_name).cuda()
14
 
15
- @spaces.GPU
16
- def predict_sentiment(text, show_probabilities=False):
17
- print(f"Device inside function: {zero.device}")
18
-
19
- inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True, max_length=512).to(zero.device)
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- with torch.no_grad():
22
- outputs = model(**inputs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
25
- predicted_class = torch.argmax(probabilities, dim=-1).item()
26
 
27
- sentiment_map = {0: "Very Negative", 1: "Negative", 2: "Neutral", 3: "Positive", 4: "Very Positive"}
28
- predicted_sentiment = sentiment_map[predicted_class]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- confidence = probabilities[0][predicted_class].item()
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
- result = f"Sentiment: {predicted_sentiment}\nConfidence: {confidence:.2%}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- if show_probabilities:
35
- result += "Probabilities for each class:\n"
36
- for i, (sentiment, prob) in enumerate(zip(sentiment_map.values(), probabilities[0])):
37
- result += f"{sentiment}: {prob.item():.2%}\n"
 
38
 
39
- return result
40
-
41
- # Create Gradio interface
42
- demo = gr.Interface(
43
- fn=predict_sentiment,
44
- inputs=[
45
- gr.Textbox(lines=5, label="Enter text for sentiment analysis"),
46
- gr.Checkbox(label="Show probabilities for each class")
47
- ],
48
- outputs=gr.Textbox(label="Result"),
49
- title="🎭 Sentiment Analysis Wizard",
50
- description="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.",
51
- examples=[
52
- ["I absolutely loved this movie! The acting was superb and the plot was engaging.", True],
53
- ["The service at this restaurant was terrible. I'll never go back.", False],
54
- ["The product works as expected. Nothing special, but it gets the job done.", True],
55
- ["I'm somewhat disappointed with my purchase. It's not as good as I hoped.", False],
56
- ["This book changed my life! I couldn't put it down and learned so much.", True]
57
- ],
58
- theme=gr.themes.Soft()
59
- )
60
-
61
- demo.launch()
 
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")
9
+ print(f"Using device: {device}")
10
 
11
  # Load model and tokenizer
12
  model_name = "tabularisai/robust-sentiment-analysis"
13
  tokenizer = AutoTokenizer.from_pretrained(model_name)
14
+ model = AutoModelForSequenceClassification.from_pretrained(model_name).to(device)
15
 
16
+ # Define sentiment mapping
17
+ SENTIMENT_MAP = {
18
+ 0: "Very Negative",
19
+ 1: "Negative",
20
+ 2: "Neutral",
21
+ 3: "Positive",
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
+ @spaces.GPU
62
+ def analyze_sentiment(text, show_probabilities=False):
63
+ """
64
+ Analyzes the sentiment of the input text. If the text exceeds the token limit,
65
+ it splits the text into chunks and aggregates the results.
66
+ """
67
+ try:
68
+ chunks = split_text(text)
69
+ all_probabilities = []
70
+ all_predictions = []
71
+ detailed_results = ""
72
+
73
+ for idx, chunk in enumerate(chunks, 1):
74
+ inputs = tokenizer(chunk, return_tensors="pt", truncation=True, padding=True, max_length=512).to(device)
75
+
76
+ with torch.no_grad():
77
+ outputs = model(**inputs)
78
+
79
+ probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1).cpu().numpy()[0]
80
+ predicted_class = probabilities.argmax()
81
+ predicted_sentiment = SENTIMENT_MAP[predicted_class]
82
+ confidence = probabilities[predicted_class]
83
+
84
+ all_probabilities.append(probabilities)
85
+ all_predictions.append(predicted_class)
86
+
87
+ if show_probabilities:
88
+ detailed_results += f"**Chunk {idx}: {predicted_sentiment} ({confidence:.2%})**\n"
89
+ for cls, prob in zip(SENTIMENT_MAP.values(), probabilities):
90
+ detailed_results += f"{cls}: {prob:.2%}\n"
91
+ detailed_results += "\n"
92
+ else:
93
+ detailed_results += f"**Chunk {idx}: {predicted_sentiment} ({confidence:.2%})**\n"
94
+
95
+ # Aggregate results by averaging probabilities
96
+ avg_probabilities = sum(all_probabilities) / len(all_probabilities)
97
+ final_class = avg_probabilities.argmax()
98
+ final_sentiment = SENTIMENT_MAP[final_class]
99
+ final_confidence = avg_probabilities[final_class]
100
+
101
+ result = f"**Overall Sentiment: {final_sentiment}**\nConfidence: {final_confidence:.2%}\n\n"
102
+
103
+ if show_probabilities:
104
+ result += "### Detailed Analysis:\n" + detailed_results
105
+ else:
106
+ result += "### Detailed Analysis:\n" + detailed_results
107
+
108
+ return result
109
+ except Exception as e:
110
+ return f"An error occurred during sentiment analysis: {str(e)}"
111
+
112
+ # Create Gradio interface using Blocks for better layout control
113
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
114
+ gr.Markdown("# 🎭 Sentiment Analysis Wizard")
115
+ gr.Markdown(
116
+ """
117
+ 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**.
118
+ """
119
+ )
120
 
121
+ with gr.Row():
122
+ with gr.Column():
123
+ input_text = gr.Textbox(
124
+ lines=10,
125
+ placeholder="Enter text for sentiment analysis...",
126
+ label="Input Text"
127
+ )
128
+ show_probs = gr.Checkbox(
129
+ label="Show probabilities for each class",
130
+ value=False
131
+ )
132
+ analyze_button = gr.Button("Analyze Sentiment")
133
+ with gr.Column():
134
+ output = gr.Markdown(label="Result")
135
 
136
+ with gr.Accordion("Examples", open=False):
137
+ examples = [
138
+ ["I absolutely loved this movie! The acting was superb and the plot was engaging.", True],
139
+ ["The service at this restaurant was terrible. I'll never go back.", False],
140
+ ["The product works as expected. Nothing special, but it gets the job done.", True],
141
+ ["I'm somewhat disappointed with my purchase. It's not as good as I hoped.", False],
142
+ ["This book changed my life! I couldn't put it down and learned so much.", True]
143
+ ]
144
+ gr.Examples(
145
+ examples=examples,
146
+ inputs=[input_text, show_probs],
147
+ label="Predefined Examples"
148
+ )
149
 
150
+ analyze_button.click(
151
+ fn=analyze_sentiment,
152
+ inputs=[input_text, show_probs],
153
+ outputs=output
154
+ )
155
 
156
+ gr.Markdown(
157
+ """
158
+ ---
159
+ **Developed with ❤️ using Gradio and Transformers by Hugging Face**
160
+ """
161
+ )
162
+
163
+ # Launch the interface
164
+ demo.launch()