Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -2,10 +2,10 @@ import gradio as gr
|
|
2 |
import re
|
3 |
from transformers import pipeline as hf_pipeline
|
4 |
|
5 |
-
# Load SST
|
6 |
sst_classifier = hf_pipeline(
|
7 |
"text-classification",
|
8 |
-
model="
|
9 |
top_k=None,
|
10 |
truncation=True
|
11 |
)
|
@@ -18,29 +18,45 @@ emotion_pipeline = hf_pipeline(
|
|
18 |
truncation=True
|
19 |
)
|
20 |
|
21 |
-
#
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
top_k=None,
|
26 |
-
truncation=True
|
27 |
-
)
|
28 |
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
results = results[0]
|
34 |
-
return [r['label'] for r in results if r['score'] >= threshold]
|
35 |
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
def get_emotion_profile(text):
|
38 |
emotions = emotion_pipeline(text)
|
39 |
if isinstance(emotions, list) and isinstance(emotions[0], list):
|
40 |
emotions = emotions[0]
|
41 |
return {e['label'].lower(): round(e['score'], 3) for e in emotions}
|
42 |
|
43 |
-
#
|
44 |
def get_emotional_tone_tag(emotions, sentiment, patterns, abuse_score=0):
|
45 |
sadness = emotions.get("sadness", 0)
|
46 |
joy = emotions.get("joy", 0)
|
@@ -49,67 +65,35 @@ def get_emotional_tone_tag(emotions, sentiment, patterns, abuse_score=0):
|
|
49 |
anger = emotions.get("anger", 0)
|
50 |
fear = emotions.get("fear", 0)
|
51 |
|
52 |
-
if (
|
53 |
-
sadness > 0.4 and
|
54 |
-
any(p in patterns for p in ["blame shifting", "guilt tripping", "recovery phase"]) and
|
55 |
-
(sentiment == "undermining" or abuse_score > 40)
|
56 |
-
):
|
57 |
return "performative regret"
|
58 |
-
if (
|
59 |
-
(joy > 0.3 or sadness > 0.4) and
|
60 |
-
any(p in patterns for p in ["control", "gaslighting"]) and
|
61 |
-
sentiment == "undermining"
|
62 |
-
):
|
63 |
return "coercive warmth"
|
64 |
-
if (
|
65 |
-
(neutral + disgust) > 0.5 and
|
66 |
-
any(p in patterns for p in ["dismissiveness", "projection", "obscure language"]) and
|
67 |
-
sentiment == "undermining"
|
68 |
-
):
|
69 |
return "cold invalidation"
|
70 |
-
if (
|
71 |
-
(sadness + fear) > 0.5 and
|
72 |
-
sentiment == "supportive" and
|
73 |
-
all(p in ["recovery phase"] for p in patterns)
|
74 |
-
):
|
75 |
return "genuine vulnerability"
|
76 |
-
if (
|
77 |
-
(anger + disgust) > 0.5 and
|
78 |
-
any(p in patterns for p in ["control", "threat", "insults", "dismissiveness"]) and
|
79 |
-
sentiment == "undermining"
|
80 |
-
):
|
81 |
return "emotional threat"
|
82 |
-
if (
|
83 |
-
sadness > 0.6 and
|
84 |
-
any(p in patterns for p in ["guilt tripping", "projection"]) and
|
85 |
-
sentiment == "undermining"
|
86 |
-
):
|
87 |
return "weaponized sadness"
|
88 |
-
if (
|
89 |
-
neutral > 0.5 and
|
90 |
-
any(p in patterns for p in ["dismissiveness", "obscure language"]) and
|
91 |
-
sentiment == "undermining"
|
92 |
-
):
|
93 |
return "toxic resignation"
|
94 |
|
95 |
return None
|
96 |
|
97 |
-
#
|
98 |
def analyze_message(text):
|
99 |
-
|
100 |
-
|
101 |
-
sentiment_label = "supportive" if
|
102 |
-
sentiment_score = round(
|
103 |
|
104 |
-
# Emotions
|
105 |
emotions = get_emotion_profile(text)
|
106 |
emotion_summary = "\n".join([f"{k.title()}: {v:.2f}" for k, v in emotions.items()])
|
107 |
|
108 |
-
#
|
109 |
-
|
110 |
-
|
111 |
-
# Tone tag
|
112 |
-
tone_tag = get_emotional_tone_tag(emotions, sentiment_label, patterns)
|
113 |
tone_output = tone_tag if tone_tag else "None detected"
|
114 |
|
115 |
return (
|
@@ -118,13 +102,13 @@ def analyze_message(text):
|
|
118 |
f"🔍 Tone Tag: {tone_output}"
|
119 |
)
|
120 |
|
121 |
-
#
|
122 |
iface = gr.Interface(
|
123 |
fn=analyze_message,
|
124 |
inputs=gr.Textbox(lines=4, placeholder="Paste a message here..."),
|
125 |
outputs="text",
|
126 |
title="Tether SST + Emotional Tone Tagger",
|
127 |
-
description="
|
128 |
)
|
129 |
|
130 |
iface.launch()
|
|
|
2 |
import re
|
3 |
from transformers import pipeline as hf_pipeline
|
4 |
|
5 |
+
# Load SST model (temporary baseline)
|
6 |
sst_classifier = hf_pipeline(
|
7 |
"text-classification",
|
8 |
+
model="distilbert-base-uncased-finetuned-sst-2-english",
|
9 |
top_k=None,
|
10 |
truncation=True
|
11 |
)
|
|
|
18 |
truncation=True
|
19 |
)
|
20 |
|
21 |
+
# Lexicon enhancement preprocessing
|
22 |
+
negations = {"not", "never", "no", "none", "nobody", "nothing", "neither", "nowhere", "hardly", "scarcely", "barely"}
|
23 |
+
amplifiers = {"very", "really", "extremely", "so", "totally", "completely", "absolutely", "utterly", "super"}
|
24 |
+
softeners = {"slightly", "somewhat", "a bit", "a little", "mildly", "fairly", "kind of"}
|
|
|
|
|
|
|
25 |
|
26 |
+
def preprocess_sentiment_text(text):
|
27 |
+
words = text.lower().split()
|
28 |
+
modified = []
|
29 |
+
negate = False
|
|
|
|
|
30 |
|
31 |
+
for word in words:
|
32 |
+
stripped = re.sub(r'\W+', '', word)
|
33 |
+
|
34 |
+
if stripped in negations:
|
35 |
+
negate = True
|
36 |
+
modified.append("<NEG>")
|
37 |
+
continue
|
38 |
+
if stripped in amplifiers:
|
39 |
+
modified.append(f"<AMP>{word}")
|
40 |
+
continue
|
41 |
+
if stripped in softeners:
|
42 |
+
modified.append(f"<SOFT>{word}")
|
43 |
+
continue
|
44 |
+
if negate:
|
45 |
+
modified.append(f"<NEG>{word}")
|
46 |
+
negate = False
|
47 |
+
else:
|
48 |
+
modified.append(word)
|
49 |
+
|
50 |
+
return " ".join(modified)
|
51 |
+
|
52 |
+
# Emotion mapping
|
53 |
def get_emotion_profile(text):
|
54 |
emotions = emotion_pipeline(text)
|
55 |
if isinstance(emotions, list) and isinstance(emotions[0], list):
|
56 |
emotions = emotions[0]
|
57 |
return {e['label'].lower(): round(e['score'], 3) for e in emotions}
|
58 |
|
59 |
+
# Tone tagging logic
|
60 |
def get_emotional_tone_tag(emotions, sentiment, patterns, abuse_score=0):
|
61 |
sadness = emotions.get("sadness", 0)
|
62 |
joy = emotions.get("joy", 0)
|
|
|
65 |
anger = emotions.get("anger", 0)
|
66 |
fear = emotions.get("fear", 0)
|
67 |
|
68 |
+
if sadness > 0.4 and any(p in patterns for p in ["blame shifting", "guilt tripping", "recovery phase"]) and (sentiment == "undermining" or abuse_score > 40):
|
|
|
|
|
|
|
|
|
69 |
return "performative regret"
|
70 |
+
if (joy > 0.3 or sadness > 0.4) and any(p in patterns for p in ["control", "gaslighting"]) and sentiment == "undermining":
|
|
|
|
|
|
|
|
|
71 |
return "coercive warmth"
|
72 |
+
if (neutral + disgust) > 0.5 and any(p in patterns for p in ["dismissiveness", "projection", "obscure language"]) and sentiment == "undermining":
|
|
|
|
|
|
|
|
|
73 |
return "cold invalidation"
|
74 |
+
if (sadness + fear) > 0.5 and sentiment == "supportive" and all(p in ["recovery phase"] for p in patterns):
|
|
|
|
|
|
|
|
|
75 |
return "genuine vulnerability"
|
76 |
+
if (anger + disgust) > 0.5 and any(p in patterns for p in ["control", "threat", "insults", "dismissiveness"]) and sentiment == "undermining":
|
|
|
|
|
|
|
|
|
77 |
return "emotional threat"
|
78 |
+
if sadness > 0.6 and any(p in patterns for p in ["guilt tripping", "projection"]) and sentiment == "undermining":
|
|
|
|
|
|
|
|
|
79 |
return "weaponized sadness"
|
80 |
+
if neutral > 0.5 and any(p in patterns for p in ["dismissiveness", "obscure language"]) and sentiment == "undermining":
|
|
|
|
|
|
|
|
|
81 |
return "toxic resignation"
|
82 |
|
83 |
return None
|
84 |
|
85 |
+
# Main function
|
86 |
def analyze_message(text):
|
87 |
+
preprocessed = preprocess_sentiment_text(text)
|
88 |
+
sentiment_result = sst_classifier(preprocessed)[0]
|
89 |
+
sentiment_label = "supportive" if sentiment_result["label"] == "POSITIVE" else "undermining"
|
90 |
+
sentiment_score = round(sentiment_result["score"] * 100, 2)
|
91 |
|
|
|
92 |
emotions = get_emotion_profile(text)
|
93 |
emotion_summary = "\n".join([f"{k.title()}: {v:.2f}" for k, v in emotions.items()])
|
94 |
|
95 |
+
# Temporarily pass empty abuse pattern list until Tether model is added
|
96 |
+
tone_tag = get_emotional_tone_tag(emotions, sentiment_label, patterns=[])
|
|
|
|
|
|
|
97 |
tone_output = tone_tag if tone_tag else "None detected"
|
98 |
|
99 |
return (
|
|
|
102 |
f"🔍 Tone Tag: {tone_output}"
|
103 |
)
|
104 |
|
105 |
+
# Interface
|
106 |
iface = gr.Interface(
|
107 |
fn=analyze_message,
|
108 |
inputs=gr.Textbox(lines=4, placeholder="Paste a message here..."),
|
109 |
outputs="text",
|
110 |
title="Tether SST + Emotional Tone Tagger",
|
111 |
+
description="Applies lexicon-enhanced preprocessing, classifies sentiment, profiles emotion, and infers tone tags based on behavior logic."
|
112 |
)
|
113 |
|
114 |
iface.launch()
|