SamanthaStorm commited on
Commit
4026c4d
·
verified ·
1 Parent(s): 0e9226e

Upload 6 files

Browse files
Files changed (3) hide show
  1. abuse_type_mapping.py +46 -0
  2. app.py +25 -5
  3. gitattributes +35 -0
abuse_type_mapping.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def determine_abuse_type(detected_labels):
2
+ abuse_type = None
3
+ abuser_profile = None
4
+ advice = None
5
+
6
+ labels = set(detected_labels)
7
+
8
+ if {"extreme_control", "gaslighting", "dismissiveness", "physical_threat"} & labels:
9
+ abuse_type = "Intimate Terrorism"
10
+ abuser_profile = "Strategic and controlling"
11
+ advice = (
12
+ "This pattern reflects coercive control and potential ongoing abuse. "
13
+ "Formal support such as domestic violence programs, legal protection, or shelters are recommended. "
14
+ "Placating or confronting the abuser may increase danger."
15
+ )
16
+
17
+ elif {"mockery", "insults", "deflection", "blame_shifting"} & labels:
18
+ abuse_type = "Situational Couple Violence"
19
+ abuser_profile = "Emotionally reactive"
20
+ advice = (
21
+ "This may reflect escalated conflict without a long-term control pattern. "
22
+ "Boundary-setting and conflict de-escalation are key. Professional mediation or trauma-informed therapy may help."
23
+ )
24
+
25
+ elif {"control", "manipulation"}.issubset(labels) and "physical_threat" in labels:
26
+ abuse_type = "Mutual Violent Control"
27
+ abuser_profile = "Both partners using control"
28
+ advice = (
29
+ "This suggests high mutual danger. Professional separation guidance and safety planning are strongly advised."
30
+ )
31
+
32
+ elif {"physical_threat"} & labels and "extreme_control" not in labels:
33
+ abuse_type = "Violent Resistance"
34
+ abuser_profile = "Victim using defensive violence"
35
+ advice = (
36
+ "This may reflect a survivor reacting to coercion. Legal and psychological support may help clarify power dynamics."
37
+ )
38
+
39
+ elif {"gaslighting", "obscure_formal", "dismissiveness"} & labels and "physical_threat" not in labels:
40
+ abuse_type = "Nonviolent Coercive Control"
41
+ abuser_profile = "Controlling but covert"
42
+ advice = (
43
+ "This pattern involves emotional control without physical harm. Emotional validation, documentation, and external support are important."
44
+ )
45
+
46
+ return abuse_type, abuser_profile, advice
app.py CHANGED
@@ -4,6 +4,7 @@ import numpy as np
4
  from transformers import AutoModelForSequenceClassification, AutoTokenizer
5
  from transformers import RobertaForSequenceClassification, RobertaTokenizer
6
  from motif_tagging import detect_motifs
 
7
 
8
  # custom fine-tuned sentiment model
9
  sentiment_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tether-sentiment")
@@ -75,6 +76,15 @@ def calculate_abuse_level(scores, thresholds, motif_hits=None):
75
 
76
  return base_score
77
 
 
 
 
 
 
 
 
 
 
78
  def interpret_abuse_level(score):
79
  if score > 80:
80
  return "Extreme / High Risk"
@@ -121,17 +131,21 @@ def analyze_messages(input_text, risk_flags):
121
  if non_abusive_confident and danger_flag_count == 0 and not matched_phrases:
122
  return "This message is classified as non-abusive."
123
 
124
- abuse_level = calculate_abuse_level(scores, adjusted_thresholds, motif_hits=[label for label, _ in matched_phrases])
 
 
 
 
 
125
  abuse_description = interpret_abuse_level(abuse_level)
 
 
126
 
127
  if danger_flag_count >= 2:
128
  resources = "Immediate assistance recommended. Please seek professional help or contact emergency services."
129
  else:
130
  resources = "For more information on abuse patterns, consider reaching out to support groups or professional counselors."
131
-
132
- scored_patterns = [
133
- (label, score) for label, score in zip(PATTERN_LABELS, scores[:15]) if label != "non_abusive"
134
- ]
135
  # Override top patterns if a high-risk motif was detected
136
  override_labels = {"physical_threat", "suicidal_threat", "extreme_control"}
137
  override_matches = [label for label, _ in matched_phrases if label in override_labels]
@@ -151,6 +165,7 @@ def analyze_messages(input_text, risk_flags):
151
 
152
  if abuse_level >= 15:
153
  result += f"Most Likely Patterns:\n{top_pattern_explanations}\n\n"
 
154
 
155
  f"⚠️ Critical Danger Flags Detected: {danger_flag_count} of 3\n"
156
  "Resources: " + resources + "\n\n"
@@ -169,6 +184,11 @@ def analyze_messages(input_text, risk_flags):
169
  for label, phrase in matched_phrases:
170
  phrase_clean = phrase.replace('"', "'").strip()
171
  result += f"• {label.replace('_', ' ').title()}: “{phrase_clean}”\n"
 
 
 
 
 
172
  return result
173
 
174
  iface = gr.Interface(
 
4
  from transformers import AutoModelForSequenceClassification, AutoTokenizer
5
  from transformers import RobertaForSequenceClassification, RobertaTokenizer
6
  from motif_tagging import detect_motifs
7
+ from abuse_type_mapping import determine_abuse_type
8
 
9
  # custom fine-tuned sentiment model
10
  sentiment_model = AutoModelForSequenceClassification.from_pretrained("SamanthaStorm/tether-sentiment")
 
76
 
77
  return base_score
78
 
79
+ # Boost score if high-risk motifs were detected
80
+ motif_hits = motif_hits or []
81
+ if any(label in motif_hits for label in {"physical_threat", "suicidal_threat", "extreme_control"}):
82
+ base_score = max(base_score, 75.0) # Push to "Severe / Harmful Pattern Present"
83
+ if matched_phrases:
84
+ pattern_labels_used.extend([label for label, _ in matched_phrases])
85
+ abuse_level = calculate_abuse_level(scores, adjusted_thresholds, motif_hits=[label for label, _ in matched_phrases])
86
+ return base_score
87
+
88
  def interpret_abuse_level(score):
89
  if score > 80:
90
  return "Extreme / High Risk"
 
131
  if non_abusive_confident and danger_flag_count == 0 and not matched_phrases:
132
  return "This message is classified as non-abusive."
133
 
134
+ scored_patterns = [
135
+ (label, score) for label, score in zip(PATTERN_LABELS, scores[:15]) if label != "non_abusive"]
136
+
137
+ pattern_labels_used = [label for label, score in scored_patterns if score > adjusted_thresholds[label]]
138
+
139
+ abuse_level = calculate_abuse_level(scores, adjusted_thresholds)
140
  abuse_description = interpret_abuse_level(abuse_level)
141
+ pattern_labels_used = [label for label, _ in matched_phrases]
142
+ abuse_type, abuser_profile, advice = determine_abuse_type(pattern_labels_used)
143
 
144
  if danger_flag_count >= 2:
145
  resources = "Immediate assistance recommended. Please seek professional help or contact emergency services."
146
  else:
147
  resources = "For more information on abuse patterns, consider reaching out to support groups or professional counselors."
148
+
 
 
 
149
  # Override top patterns if a high-risk motif was detected
150
  override_labels = {"physical_threat", "suicidal_threat", "extreme_control"}
151
  override_matches = [label for label, _ in matched_phrases if label in override_labels]
 
165
 
166
  if abuse_level >= 15:
167
  result += f"Most Likely Patterns:\n{top_pattern_explanations}\n\n"
168
+
169
 
170
  f"⚠️ Critical Danger Flags Detected: {danger_flag_count} of 3\n"
171
  "Resources: " + resources + "\n\n"
 
184
  for label, phrase in matched_phrases:
185
  phrase_clean = phrase.replace('"', "'").strip()
186
  result += f"• {label.replace('_', ' ').title()}: “{phrase_clean}”\n"
187
+
188
+ if abuse_type:
189
+ result += f"\n\n🧠 Likely Abuse Type: {abuse_type}"
190
+ result += f"\n🧠 Abuser Profile: {abuser_profile}"
191
+ result += f"\n📘 Safety Tip: {advice}"
192
  return result
193
 
194
  iface = gr.Interface(
gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text