File size: 4,484 Bytes
fe6b66c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
834f0ff
1202ad3
b7213fa
 
 
31f28ee
834f0ff
 
 
 
31f28ee
1202ad3
834f0ff
 
 
 
 
 
fe6b66c
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
: import gradio as gr
import re
from transformers import pipeline as hf_pipeline

# Load SST model (temporary baseline)
sst_classifier = hf_pipeline(
    "text-classification",
    model="distilbert-base-uncased-finetuned-sst-2-english",
    top_k=None,
    truncation=True
)

# Load emotion classifier
emotion_pipeline = hf_pipeline(
    "text-classification",
    model="j-hartmann/emotion-english-distilroberta-base",
    top_k=None,
    truncation=True
)

# Lexicon enhancement preprocessing
negations = {"not", "never", "no", "none", "nobody", "nothing", "neither", "nowhere", "hardly", "scarcely", "barely"}
amplifiers = {"very", "really", "extremely", "so", "totally", "completely", "absolutely", "utterly", "super"}
softeners = {"slightly", "somewhat", "a bit", "a little", "mildly", "fairly", "kind of"}

def preprocess_sentiment_text(text):
    words = text.lower().split()
    modified = []
    negate = False

    for word in words:
        stripped = re.sub(r'\W+', '', word)

        if stripped in negations:
            negate = True
            modified.append("<NEG>")
            continue
        if stripped in amplifiers:
            modified.append(f"<AMP>{word}")
            continue
        if stripped in softeners:
            modified.append(f"<SOFT>{word}")
            continue
        if negate:
            modified.append(f"<NEG>{word}")
            negate = False
        else:
            modified.append(word)

    return " ".join(modified)

# Emotion mapping
def get_emotion_profile(text):
    emotions = emotion_pipeline(text)
    if isinstance(emotions, list) and isinstance(emotions[0], list):
        emotions = emotions[0]
    return {e['label'].lower(): round(e['score'], 3) for e in emotions}

# Tone tagging logic
def get_emotional_tone_tag(emotions, sentiment, patterns, abuse_score=0):
    sadness = emotions.get("sadness", 0)
    joy = emotions.get("joy", 0)
    neutral = emotions.get("neutral", 0)
    disgust = emotions.get("disgust", 0)
    anger = emotions.get("anger", 0)
    fear = emotions.get("fear", 0)

    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):
        return "performative regret"
    if (joy > 0.3 or sadness > 0.4) and any(p in patterns for p in ["control", "gaslighting"]) and sentiment == "undermining":
        return "coercive warmth"
    if (neutral + disgust) > 0.5 and any(p in patterns for p in ["dismissiveness", "projection", "obscure language"]) and sentiment == "undermining":
        return "cold invalidation"
    if (sadness + fear) > 0.5 and sentiment == "supportive" and all(p in ["recovery phase"] for p in patterns):
        return "genuine vulnerability"
    if (anger + disgust) > 0.5 and any(p in patterns for p in ["control", "threat", "insults", "dismissiveness"]) and sentiment == "undermining":
        return "emotional threat"
    if sadness > 0.6 and any(p in patterns for p in ["guilt tripping", "projection"]) and sentiment == "undermining":
        return "weaponized sadness"
    if neutral > 0.5 and any(p in patterns for p in ["dismissiveness", "obscure language"]) and sentiment == "undermining":
        return "toxic resignation"

    return None

# Main function
def analyze_message(text):
    preprocessed = preprocess_sentiment_text(text)
    sst_output = sst_classifier(preprocessed)
    sentiment = sst_output[0]
    sentiment_label = "supportive" if sentiment["label"] == "POSITIVE" else "undermining"
    sentiment_score = round(sentiment["score"] * 100, 2)

    emotions = get_emotion_profile(text)
    emotion_summary = "\n".join([f"{k.title()}: {v:.2f}" for k, v in emotions.items()])

    # Temporarily pass empty abuse pattern list until Tether model is added
    tone_tag = get_emotional_tone_tag(emotions, sentiment_label, patterns=[])
    tone_output = tone_tag if tone_tag else "None detected"

    return (
        f"🧠 Sentiment: {sentiment_label.title()} ({sentiment_score}%)\n\n"
        f"🎭 Emotional Profile:\n{emotion_summary}\n\n"
        f"🔍 Tone Tag: {tone_output}"
    )
# Interface
iface = gr.Interface(
    fn=analyze_message,
    inputs=gr.Textbox(lines=4, placeholder="Paste a message here..."),
    outputs="text",
    title="Tether SST + Emotional Tone Tagger",
    description="Applies lexicon-enhanced preprocessing, classifies sentiment, profiles emotion, and infers tone tags based on behavior logic."
)

iface.launch()