SamanthaStorm commited on
Commit
384efe9
·
verified ·
1 Parent(s): 64f5cfa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -78
app.py CHANGED
@@ -1,13 +1,10 @@
1
- import easyocr
2
- import numpy as np
3
-
4
- # create a reader once
5
- ocr_reader = easyocr.Reader(["en"], gpu=False)
6
  import gradio as gr
7
  import torch
8
  from transformers import pipeline as hf_pipeline, AutoModelForSequenceClassification, AutoTokenizer
9
  from PIL import Image
10
  import io
 
 
11
 
12
  # ——— 1) Emotion Pipeline ————————————————————————————————————————————————
13
  emotion_pipeline = hf_pipeline(
@@ -18,11 +15,7 @@ emotion_pipeline = hf_pipeline(
18
  )
19
 
20
  def get_emotion_profile(text):
21
- """
22
- Returns a dict of emotion scores for the input text.
23
- """
24
  results = emotion_pipeline(text)
25
- # Some pipelines return a list of lists
26
  if isinstance(results, list) and isinstance(results[0], list):
27
  results = results[0]
28
  return {r["label"].lower(): round(r["score"], 3) for r in results}
@@ -55,11 +48,15 @@ THRESHOLDS = {
55
  "threat": 0.15
56
  }
57
 
58
- # ——— 3) Emotional-Tone Tagging —————————————————————————————————————————————
 
 
 
59
  def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
60
  """
61
  Assigns one of 18 nuanced tone categories based on emotion scores, patterns, and text.
62
  """
 
63
  sadness = emotion_profile.get("sadness", 0)
64
  joy = emotion_profile.get("joy", 0)
65
  neutral = emotion_profile.get("neutral", 0)
@@ -68,62 +65,40 @@ def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
68
  fear = emotion_profile.get("fear", 0)
69
  surprise = emotion_profile.get("surprise", 0)
70
 
71
- def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
72
- if "support" in text_lower or "hope" in text_lower or "grace" in text_lower:
73
  return "supportive"
74
- if (
75
- sadness > 0.4 and
76
- any(p in patterns for p in ["blame shifting", "guilt tripping", "recovery phase"])
77
- ):
78
  return "performative regret"
79
 
80
  # 2. Coercive Warmth
81
- if (
82
- (joy > 0.3 or sadness > 0.4) and
83
- any(p in patterns for p in ["control", "gaslighting"])
84
- ):
85
  return "coercive warmth"
86
 
87
  # 3. Cold Invalidation
88
- if (
89
- (neutral + disgust) > 0.5 and
90
- any(p in patterns for p in ["dismissiveness", "projection", "obscure language"])
91
- ):
92
  return "cold invalidation"
93
 
94
  # 4. Genuine Vulnerability
95
- if (
96
- (sadness + fear) > 0.5 and
97
- all(p == "recovery phase" for p in patterns)
98
- ):
99
  return "genuine vulnerability"
100
 
101
  # 5. Emotional Threat
102
- if (
103
- (anger + disgust) > 0.5 and
104
- any(p in patterns for p in ["control", "threat", "insults", "dismissiveness"])
105
- ):
106
  return "emotional threat"
107
 
108
  # 6. Weaponized Sadness
109
- if (
110
- sadness > 0.6 and
111
- any(p in patterns for p in ["guilt tripping", "projection"])
112
- ):
113
  return "weaponized sadness"
114
 
115
  # 7. Toxic Resignation
116
- if (
117
- neutral > 0.5 and
118
- any(p in patterns for p in ["dismissiveness", "obscure language"])
119
- ):
120
  return "toxic resignation"
121
 
122
  # 8. Indignant Reproach
123
- if (
124
- anger > 0.5 and
125
- any(p in patterns for p in ["guilt tripping", "contradictory statements"])
126
- ):
127
  return "indignant reproach"
128
 
129
  # 9. Confrontational
@@ -131,10 +106,7 @@ def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
131
  return "confrontational"
132
 
133
  # 10. Passive Aggression
134
- if (
135
- neutral > 0.6 and
136
- any(p in patterns for p in ["dismissiveness", "projection"])
137
- ):
138
  return "passive aggression"
139
 
140
  # 11. Sarcastic Mockery
@@ -146,11 +118,7 @@ def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
146
  return "menacing threat"
147
 
148
  # 13. Pleading Concern
149
- if (
150
- sadness > 0.3 and
151
- any(k in text_lower for k in APOLOGY_KEYWORDS) and
152
- not patterns
153
- ):
154
  return "pleading concern"
155
 
156
  # 14. Fear-mongering
@@ -175,43 +143,30 @@ def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
175
 
176
  return None
177
 
178
- # ——— 4) Single-message Analysis ———————————————————————————————————————————
179
  def analyze_message(text):
180
  text_lower = text.lower()
181
- # 1) Emotion
182
  emotion_profile = get_emotion_profile(text)
183
- # 2) Patterns
184
  toks = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
185
  with torch.no_grad():
186
  logits = model(**toks).logits.squeeze(0)
187
  scores = torch.sigmoid(logits).cpu().numpy()
188
- active_patterns = [lab for lab, sc in zip(LABELS, scores) if sc >= THRESHOLDS[lab]]
189
- # append recovery-phase if apology
190
  if any(k in text_lower for k in APOLOGY_KEYWORDS) and "recovery phase" not in active_patterns:
191
  active_patterns.append("recovery phase")
192
- # 3) Tone
193
  tone_tag = get_emotional_tone_tag(emotion_profile, active_patterns, text_lower)
194
- return {
195
- "emotion_profile": emotion_profile,
196
- "active_patterns": active_patterns,
197
- "tone_tag": tone_tag
198
- }
199
 
200
- # ——— 5) Composite Wrapper ————————————————————————————————————————————————
201
  def analyze_composite(uploaded_file, *texts):
202
  outputs = []
203
-
204
- # 1) Handle an uploaded file
205
  if uploaded_file is not None:
206
- # uploaded_file may be a file-like object or just a path string
207
  try:
208
  raw = uploaded_file.read()
209
  except Exception:
210
- # fall back to opening the path
211
  with open(uploaded_file, "rb") as f:
212
  raw = f.read()
213
 
214
- # get the filename (or just lowercase the string if it's a path)
215
  name = (
216
  uploaded_file.name.lower() if hasattr(uploaded_file, "name") else uploaded_file.lower()
217
  )
@@ -249,19 +204,13 @@ def analyze_composite(uploaded_file, *texts):
249
 
250
  # ——— 7) Gradio interface ———————————————————————————————————————————————
251
  message_inputs = [gr.Textbox(label="Message")]
252
-
253
  iface = gr.Interface(
254
  fn=analyze_composite,
255
- inputs=[
256
- gr.File(
257
- file_types=[".txt", ".png", ".jpg", ".jpeg"],
258
- label="Upload text or image"
259
- )
260
- ] + message_inputs, # <— here the list closes, then we concatenate
261
  outputs=gr.Textbox(label="Analysis"),
262
  title="Tether Analyzer (extended tone tags)",
263
  description="Emotion profiling, pattern tags, and a wide set of nuanced tone categories—no abuse score or DARVO."
264
  )
265
 
266
  if __name__ == "__main__":
267
- iface.launch()
 
 
 
 
 
 
1
  import gradio as gr
2
  import torch
3
  from transformers import pipeline as hf_pipeline, AutoModelForSequenceClassification, AutoTokenizer
4
  from PIL import Image
5
  import io
6
+ import easyocr
7
+ import numpy as np
8
 
9
  # ——— 1) Emotion Pipeline ————————————————————————————————————————————————
10
  emotion_pipeline = hf_pipeline(
 
15
  )
16
 
17
  def get_emotion_profile(text):
 
 
 
18
  results = emotion_pipeline(text)
 
19
  if isinstance(results, list) and isinstance(results[0], list):
20
  results = results[0]
21
  return {r["label"].lower(): round(r["score"], 3) for r in results}
 
48
  "threat": 0.15
49
  }
50
 
51
+ # ——— 3) Initialize EasyOCR reader ————————————————————————————————————————————
52
+ ocr_reader = easyocr.Reader(["en"], gpu=False)
53
+
54
+ # ——— 4) Emotional-Tone Tagging —————————————————————————————————————————————
55
  def get_emotional_tone_tag(emotion_profile, patterns, text_lower):
56
  """
57
  Assigns one of 18 nuanced tone categories based on emotion scores, patterns, and text.
58
  """
59
+ # unpack all emotion scores before any rules
60
  sadness = emotion_profile.get("sadness", 0)
61
  joy = emotion_profile.get("joy", 0)
62
  neutral = emotion_profile.get("neutral", 0)
 
65
  fear = emotion_profile.get("fear", 0)
66
  surprise = emotion_profile.get("surprise", 0)
67
 
68
+ # 0. Support override
69
+ if any(k in text_lower for k in ["support", "hope", "grace"]):
70
  return "supportive"
71
+
72
+ # 1. Performative Regret
73
+ if sadness > 0.4 and any(p in patterns for p in ["blame shifting", "guilt tripping", "recovery phase"]):
 
74
  return "performative regret"
75
 
76
  # 2. Coercive Warmth
77
+ if (joy > 0.3 or sadness > 0.4) and any(p in patterns for p in ["control", "gaslighting"]):
 
 
 
78
  return "coercive warmth"
79
 
80
  # 3. Cold Invalidation
81
+ if (neutral + disgust) > 0.5 and any(p in patterns for p in ["dismissiveness", "projection", "obscure language"]):
 
 
 
82
  return "cold invalidation"
83
 
84
  # 4. Genuine Vulnerability
85
+ if (sadness + fear) > 0.5 and all(p == "recovery phase" for p in patterns):
 
 
 
86
  return "genuine vulnerability"
87
 
88
  # 5. Emotional Threat
89
+ if (anger + disgust) > 0.5 and any(p in patterns for p in ["control", "threat", "insults", "dismissiveness"]):
 
 
 
90
  return "emotional threat"
91
 
92
  # 6. Weaponized Sadness
93
+ if sadness > 0.6 and any(p in patterns for p in ["guilt tripping", "projection"]):
 
 
 
94
  return "weaponized sadness"
95
 
96
  # 7. Toxic Resignation
97
+ if neutral > 0.5 and any(p in patterns for p in ["dismissiveness", "obscure language"]):
 
 
 
98
  return "toxic resignation"
99
 
100
  # 8. Indignant Reproach
101
+ if anger > 0.5 and any(p in patterns for p in ["guilt tripping", "contradictory statements"]):
 
 
 
102
  return "indignant reproach"
103
 
104
  # 9. Confrontational
 
106
  return "confrontational"
107
 
108
  # 10. Passive Aggression
109
+ if neutral > 0.6 and any(p in patterns for p in ["dismissiveness", "projection"]):
 
 
 
110
  return "passive aggression"
111
 
112
  # 11. Sarcastic Mockery
 
118
  return "menacing threat"
119
 
120
  # 13. Pleading Concern
121
+ if sadness > 0.3 and any(k in text_lower for k in APOLOGY_KEYWORDS) and not patterns:
 
 
 
 
122
  return "pleading concern"
123
 
124
  # 14. Fear-mongering
 
143
 
144
  return None
145
 
146
+ # ——— 5) Single message analysis ———————————————————————————————————————————
147
  def analyze_message(text):
148
  text_lower = text.lower()
 
149
  emotion_profile = get_emotion_profile(text)
 
150
  toks = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
151
  with torch.no_grad():
152
  logits = model(**toks).logits.squeeze(0)
153
  scores = torch.sigmoid(logits).cpu().numpy()
154
+ active_patterns = [label for label, prob in zip(LABELS, scores) if prob >= THRESHOLDS[label]]
 
155
  if any(k in text_lower for k in APOLOGY_KEYWORDS) and "recovery phase" not in active_patterns:
156
  active_patterns.append("recovery phase")
 
157
  tone_tag = get_emotional_tone_tag(emotion_profile, active_patterns, text_lower)
158
+ return {"emotion_profile": emotion_profile, "active_patterns": active_patterns, "tone_tag": tone_tag}
 
 
 
 
159
 
160
+ # ——— 6) Composite wrapper ———————————————————————————————————————————————
161
  def analyze_composite(uploaded_file, *texts):
162
  outputs = []
 
 
163
  if uploaded_file is not None:
 
164
  try:
165
  raw = uploaded_file.read()
166
  except Exception:
 
167
  with open(uploaded_file, "rb") as f:
168
  raw = f.read()
169
 
 
170
  name = (
171
  uploaded_file.name.lower() if hasattr(uploaded_file, "name") else uploaded_file.lower()
172
  )
 
204
 
205
  # ——— 7) Gradio interface ———————————————————————————————————————————————
206
  message_inputs = [gr.Textbox(label="Message")]
 
207
  iface = gr.Interface(
208
  fn=analyze_composite,
209
+ inputs=[gr.File(file_types=[".txt",".png",".jpg",".jpeg"], label="Upload text or image")] + message_inputs,
 
 
 
 
 
210
  outputs=gr.Textbox(label="Analysis"),
211
  title="Tether Analyzer (extended tone tags)",
212
  description="Emotion profiling, pattern tags, and a wide set of nuanced tone categories—no abuse score or DARVO."
213
  )
214
 
215
  if __name__ == "__main__":
216
+ iface.launch()