Tether / app.py
SamanthaStorm's picture
Update app.py
d315105 verified
raw
history blame
6.89 kB
import gradio as gr
import torch
import numpy as np
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
from transformers import RobertaForSequenceClassification, RobertaTokenizer
from motif_tagging import detect_motifs
import re
# --- Sentiment Model: T5-based Emotion Classifier ---
sentiment_tokenizer = AutoTokenizer.from_pretrained("mrm8488/t5-base-finetuned-emotion")
sentiment_model = AutoModelForSeq2SeqLM.from_pretrained("mrm8488/t5-base-finetuned-emotion")
EMOTION_TO_SENTIMENT = {
"joy": "supportive",
"love": "supportive",
"surprise": "supportive",
"neutral": "supportive",
"sadness": "undermining",
"anger": "undermining",
"fear": "undermining",
"disgust": "undermining",
"shame": "undermining",
"guilt": "undermining"
}
# --- Abuse Detection Model ---
model_name = "SamanthaStorm/autotrain-jlpi4-mllvp"
model = RobertaForSequenceClassification.from_pretrained(model_name, trust_remote_code=True)
tokenizer = RobertaTokenizer.from_pretrained(model_name, trust_remote_code=True)
LABELS = [
"blame shifting", "contradictory statements", "control", "dismissiveness",
"gaslighting", "guilt tripping", "insults", "obscure language",
"projection", "recovery phase", "threat"
]
THRESHOLDS = {
"blame shifting": 0.3,
"contradictory statements": 0.32,
"control": 0.48,
"dismissiveness": 0.45,
"gaslighting": 0.30,
"guilt tripping": 0.20,
"insults": 0.34,
"obscure language": 0.25,
"projection": 0.35,
"recovery phase": 0.25,
"threat": 0.25
}
PATTERN_WEIGHTS = {
"gaslighting": 1.3,
"control": 1.2,
"dismissiveness": 0.8,
"blame shifting": 0.8,
"contradictory statements": 0.75
}
EXPLANATIONS = {
"blame shifting": "Blame-shifting is when one person redirects responsibility onto someone else to avoid accountability.",
"contradictory statements": "Contradictory statements confuse the listener by flipping positions or denying previous claims.",
"control": "Control restricts another person’s autonomy through coercion, manipulation, or threats.",
"dismissiveness": "Dismissiveness is belittling or disregarding another person’s feelings, needs, or opinions.",
"gaslighting": "Gaslighting involves making someone question their own reality, memory, or perceptions.",
"guilt tripping": "Guilt-tripping uses guilt to manipulate someone’s actions or decisions.",
"insults": "Insults are derogatory or demeaning remarks meant to shame, belittle, or hurt someone.",
"obscure language": "Obscure language manipulates through complexity, vagueness, or superiority to confuse the other person.",
"projection": "Projection accuses someone else of the very behaviors or intentions the speaker is exhibiting.",
"recovery phase": "Recovery phase statements attempt to soothe or reset tension without acknowledging harm or change.",
"threat": "Threats use fear of harm (physical, emotional, or relational) to control or intimidate someone."
}
RISK_SNIPPETS = {
"low": (
"🟢 Risk Level: Low",
"The language patterns here do not strongly indicate abuse.",
"Continue to check in with yourself and notice how you feel in response to repeated patterns."
),
"moderate": (
"⚠️ Risk Level: Moderate to High",
"This language includes control, guilt, or reversal tactics.",
"These patterns often lead to emotional confusion and reduced self-trust. Document these messages or talk with someone safe."
),
"high": (
"🛑 Risk Level: High",
"Language includes threats or coercive control, which are strong indicators of escalation.",
"Consider creating a safety plan or contacting a support line. Trust your sense of unease."
)
}
def generate_risk_snippet(abuse_score, top_label):
if abuse_score >= 85:
risk_level = "high"
elif abuse_score >= 60:
risk_level = "moderate"
else:
risk_level = "low"
title, summary, advice = RISK_SNIPPETS[risk_level]
return f"\n\n{title}\n{summary} (Pattern: **{top_label}**)\n💡 {advice}"
# --- Escalation Quiz Questions & Weights ---
ESCALATION_QUESTIONS = [
("Partner has access to firearms or weapons", 4),
("Partner threatened to kill you", 3),
("Partner threatened you with a weapon", 3),
("Partner ever choked or strangled you", 4),
("Partner injured or threatened your pet(s)", 3),
("Partner destroyed property to intimidate you", 2),
("Partner forced you into unwanted sexual acts", 3),
("Partner threatened to take away your children", 2),
("Violence has increased in frequency or severity", 3),
("Partner monitors your calls/GPS/social media", 2)
]
# --- Core Analysis Functions (unchanged) ---
# ... (analyze_single_message, calculate_darvo_score, etc.)
# --- Composite Analysis with Escalation Quiz ---
def analyze_composite(msg1, msg2, msg3, *answers_and_none):
# split args: first len(ESCALATION_QUESTIONS) are checkboxes, last is none_of_above
responses = answers_and_none[:len(ESCALATION_QUESTIONS)]
none_selected = answers_and_none[-1]
# compute escalation score
if none_selected:
escalation_score = 0
else:
escalation_score = sum(w for (_, w), a in zip(ESCALATION_QUESTIONS, responses) if a)
# bucket
if escalation_score >= 16:
escalation_level = "High"
elif escalation_score >= 8:
escalation_level = "Moderate"
else:
escalation_level = "Low"
# existing abuse analysis
thresholds = THRESHOLDS.copy()
messages = [msg1, msg2, msg3]
active = [m for m in messages if m.strip()]
if not active:
return "Please enter at least one message."
results = [analyze_single_message(m, thresholds, []) for m in active]
abuse_scores = [r[0] for r in results]
top_pattern = max({label for r in results for label in r[2]}, key=lambda l: abuse_scores[0])
composite_abuse = round(sum(abuse_scores)/len(abuse_scores),2)
# build output
out = f"Abuse Intensity: {composite_abuse}%\n"
out += f"Escalation Potential: {escalation_level} ({escalation_score}/{sum(w for _,w in ESCALATION_QUESTIONS)})"
# abuse snippet
out += generate_risk_snippet(composite_abuse, top_pattern)
return out
# --- Gradio Interface ---
textbox_inputs = [
gr.Textbox(label="Message 1"),
gr.Textbox(label="Message 2"),
gr.Textbox(label="Message 3")
]
# Escalation quiz inputs
quiz_boxes = [gr.Checkbox(label=q) for q, _ in ESCALATION_QUESTIONS]
none_box = gr.Checkbox(label="None of the above")
iface = gr.Interface(
fn=analyze_composite,
inputs=textbox_inputs + quiz_boxes + [none_box],
outputs=gr.Textbox(label="Results"),
title="Abuse Pattern Detector + Escalation Quiz",
allow_flagging="manual"
)
if __name__ == "__main__":
iface.launch()