SamanthaStorm commited on
Commit
9784a67
·
verified ·
1 Parent(s): a95563f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +156 -16
app.py CHANGED
@@ -11,6 +11,17 @@ from datetime import datetime
11
  from torch.nn.functional import sigmoid
12
  from collections import Counter
13
  import logging
 
 
 
 
 
 
 
 
 
 
 
14
  # Add this after imports
15
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
16
 
@@ -26,9 +37,6 @@ model_name = "SamanthaStorm/tether-multilabel-v4"
26
  model = AutoModelForSequenceClassification.from_pretrained(model_name).to(device)
27
  tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=False)
28
 
29
- # Tone model
30
- tone_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tone-tag-multilabel-v1").to(device)
31
- tone_tokenizer = AutoTokenizer.from_pretrained("SamanthaStorm/tone-tag-multilabel-v1", use_fast=False)
32
 
33
  # Sentiment model
34
  sentiment_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tether-sentiment").to(device)
@@ -126,6 +134,142 @@ THREAT_MOTIFS = [
126
  "if you just behaved, this wouldn't happen", "this is your fault",
127
  "you're making me hurt you", "i warned you", "you should have listened"
128
  ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
  def predict_darvo_score(text):
131
  """Predict DARVO score for given text"""
@@ -161,19 +305,6 @@ def get_risk_stage(patterns, sentiment):
161
  logger.error(f"Error determining risk stage: {e}")
162
  return 1
163
 
164
- def get_emotional_tone_tag(text, emotions, sentiment, patterns, abuse_score):
165
- """Get emotional tone tag for text"""
166
- try:
167
- inputs = tone_tokenizer(text, return_tensors="pt", truncation=True, padding=True)
168
- inputs = {k: v.to(device) for k, v in inputs.items()}
169
- with torch.no_grad():
170
- logits = tone_model(**inputs).logits[0]
171
- probs = torch.sigmoid(logits).cpu().numpy()
172
- scores = dict(zip(TONE_LABELS, np.round(probs, 3)))
173
- return max(scores, key=scores.get)
174
- except Exception as e:
175
- logger.error(f"Error in emotional tone analysis: {e}")
176
- return "unknown"
177
 
178
  @spaces.GPU
179
  def compute_abuse_score(matched_scores, sentiment):
@@ -243,7 +374,16 @@ def analyze_single_message(text, thresholds):
243
  explicit_abuse_words = ['fuck', 'bitch', 'shit', 'ass', 'dick']
244
  explicit_abuse = any(word in text.lower() for word in explicit_abuse_words)
245
  logger.debug(f"Explicit abuse detected: {explicit_abuse}")
 
 
 
 
 
 
 
246
 
 
 
247
  # Abuse model inference
248
  inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
249
  inputs = {k: v.to(device) for k, v in inputs.items()} # Move to GPU
 
11
  from torch.nn.functional import sigmoid
12
  from collections import Counter
13
  import logging
14
+ from transformers import pipeline as hf_pipeline
15
+
16
+ # Add this with your other model loading code
17
+ emotion_pipeline = hf_pipeline(
18
+ "text-classification",
19
+ model="j-hartmann/emotion-english-distilroberta-base",
20
+ top_k=6,
21
+ truncation=True,
22
+ device=0 if torch.cuda.is_available() else -1 # GPU support
23
+ )
24
+
25
  # Add this after imports
26
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
27
 
 
37
  model = AutoModelForSequenceClassification.from_pretrained(model_name).to(device)
38
  tokenizer = AutoTokenizer.from_pretrained(model_name, use_fast=False)
39
 
 
 
 
40
 
41
  # Sentiment model
42
  sentiment_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tether-sentiment").to(device)
 
134
  "if you just behaved, this wouldn't happen", "this is your fault",
135
  "you're making me hurt you", "i warned you", "you should have listened"
136
  ]
137
+ def get_emotion_profile(text):
138
+ emotions = emotion_pipeline(text)
139
+ if isinstance(emotions, list) and isinstance(emotions[0], list):
140
+ emotions = emotions[0]
141
+ return {e['label'].lower(): round(e['score'], 3) for e in emotions}
142
+
143
+ def get_emotional_tone_tag(text, sentiment, patterns, abuse_score):
144
+ # Get emotions first
145
+ emotions = get_emotion_profile(text)
146
+
147
+ sadness = emotions.get("sadness", 0)
148
+ joy = emotions.get("joy", 0)
149
+ neutral = emotions.get("neutral", 0)
150
+ disgust = emotions.get("disgust", 0)
151
+ anger = emotions.get("anger", 0)
152
+ fear = emotions.get("fear", 0)
153
+
154
+ # 1. Performative Regret
155
+ if (
156
+ sadness > 0.4 and
157
+ any(p in patterns for p in ["blame shifting", "guilt tripping", "recovery phase"]) and
158
+ (sentiment == "undermining" or abuse_score > 40)
159
+ ):
160
+ return "performative regret"
161
+
162
+ # 2. Coercive Warmth
163
+ if (
164
+ (joy > 0.3 or sadness > 0.4) and
165
+ any(p in patterns for p in ["control", "gaslighting"]) and
166
+ sentiment == "undermining"
167
+ ):
168
+ return "coercive warmth"
169
+
170
+ # 3. Cold Invalidation
171
+ if (
172
+ (neutral + disgust) > 0.5 and
173
+ any(p in patterns for p in ["dismissiveness", "projection", "obscure language"]) and
174
+ sentiment == "undermining"
175
+ ):return "cold invalidation"
176
+
177
+ # 4. Genuine Vulnerability
178
+ if (
179
+ (sadness + fear) > 0.5 and
180
+ sentiment == "supportive" and
181
+ all(p in ["recovery phase"] for p in patterns)
182
+ ):
183
+ return "genuine vulnerability"
184
+
185
+ # 5. Emotional Threat
186
+ if (
187
+ (anger + disgust) > 0.5 and
188
+ any(p in patterns for p in ["control", "insults", "dismissiveness"]) and
189
+ sentiment == "undermining"
190
+ ):
191
+ return "emotional threat"
192
+
193
+ # 6. Weaponized Sadness
194
+ if (
195
+ sadness > 0.6 and
196
+ any(p in patterns for p in ["guilt tripping", "projection"]) and
197
+ sentiment == "undermining"
198
+ ):
199
+ return "weaponized sadness"
200
+
201
+ # 7. Toxic Resignation
202
+ if (
203
+ neutral > 0.5 and
204
+ any(p in patterns for p in ["dismissiveness", "obscure language"]) and
205
+ sentiment == "undermining"
206
+ ):
207
+ return "toxic resignation"
208
+ # 8. Aggressive Dismissal
209
+ if (
210
+ anger > 0.5 and
211
+ any(p in patterns for p in ["aggression", "insults", "control"]) and
212
+ sentiment == "undermining"
213
+ ):
214
+ return "aggressive dismissal"
215
+ # 9. Deflective Hostility
216
+ if (
217
+ (0.2 < anger < 0.7 or 0.2 < disgust < 0.7) and
218
+ any(p in patterns for p in ["deflection", "projection"]) and
219
+ sentiment == "undermining"
220
+ ):
221
+ return "deflective hostility"
222
+ # 10. Mocking Detachment
223
+ if (
224
+ (neutral + joy) > 0.5 and
225
+ any(p in patterns for p in ["mockery", "insults", "projection"]) and
226
+ sentiment == "undermining"
227
+ ):
228
+ return "mocking detachment"
229
+ # 11. Contradictory Gaslight
230
+ if (
231
+ (joy + anger + sadness) > 0.5 and
232
+ any(p in patterns for p in ["gaslighting", "contradictory statements"]) and
233
+ sentiment == "undermining"
234
+ ):
235
+ return "contradictory gaslight"
236
+ # 12. Calculated Neutrality
237
+ if (
238
+ neutral > 0.6 and
239
+ any(p in patterns for p in ["obscure language", "deflection", "dismissiveness"]) and
240
+ sentiment == "undermining"
241
+ ):
242
+ return "calculated neutrality"
243
+ # 13. Forced Accountability Flip
244
+ if (
245
+ (anger + disgust) > 0.5 and
246
+ any(p in patterns for p in ["blame shifting", "manipulation", "projection"]) and
247
+ sentiment == "undermining"
248
+ ):
249
+ return "forced accountability flip"
250
+ # 14. Conditional Affection
251
+ if (
252
+ joy > 0.4 and
253
+ any(p in patterns for p in ["apology baiting", "control", "recovery phase"]) and
254
+ sentiment == "undermining"
255
+ ):
256
+ return "conditional affection"
257
+
258
+ if (
259
+ (anger + disgust) > 0.5 and
260
+ any(p in patterns for p in ["blame shifting", "projection", "deflection"]) and
261
+ sentiment == "undermining"
262
+ ):
263
+ return "forced accountability flip"
264
+
265
+ # Emotional Instability Fallback
266
+ if (
267
+ (anger + sadness + disgust) > 0.6 and
268
+ sentiment == "undermining"
269
+ ):
270
+ return "emotional instability"
271
+
272
+ return None
273
 
274
  def predict_darvo_score(text):
275
  """Predict DARVO score for given text"""
 
305
  logger.error(f"Error determining risk stage: {e}")
306
  return 1
307
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
 
309
  @spaces.GPU
310
  def compute_abuse_score(matched_scores, sentiment):
 
374
  explicit_abuse_words = ['fuck', 'bitch', 'shit', 'ass', 'dick']
375
  explicit_abuse = any(word in text.lower() for word in explicit_abuse_words)
376
  logger.debug(f"Explicit abuse detected: {explicit_abuse}")
377
+ # Get sentiment
378
+ sent_inputs = sentiment_tokenizer(text, return_tensors="pt", truncation=True, padding=True)
379
+ sent_inputs = {k: v.to(device) for k, v in sent_inputs.items()}
380
+ with torch.no_grad():
381
+ sent_logits = sentiment_model(**sent_inputs).logits[0]
382
+ sent_probs = torch.softmax(sent_logits, dim=-1).cpu().numpy()
383
+ sentiment = SENTIMENT_LABELS[int(np.argmax(sent_probs))]
384
 
385
+ # Get tone using emotion-based approach
386
+ tone_tag = get_emotional_tone_tag(text, sentiment, threshold_labels, abuse_score)
387
  # Abuse model inference
388
  inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
389
  inputs = {k: v.to(device) for k, v in inputs.items()} # Move to GPU