SamanthaStorm commited on
Commit
4292d1b
Β·
verified Β·
1 Parent(s): 293a004

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -75
app.py CHANGED
@@ -9,7 +9,7 @@ model_name = "SamanthaStorm/abuse-pattern-detector-v2"
9
  model = RobertaForSequenceClassification.from_pretrained(model_name)
10
  tokenizer = RobertaTokenizer.from_pretrained(model_name)
11
 
12
- # Define the final label order your model used
13
  LABELS = [
14
  "gaslighting", "mockery", "dismissiveness", "control",
15
  "guilt_tripping", "apology_baiting", "blame_shifting", "projection",
@@ -17,120 +17,119 @@ LABELS = [
17
  "obscure_formal", "recovery_phase", "suicidal_threat", "physical_threat",
18
  "extreme_control"
19
  ]
20
- TOTAL_LABELS = 17
21
 
22
- # Our model outputs 17 labels:
23
- # - First 14 are abuse pattern categories
24
- # - Last 3 are Danger Assessment cues
25
- TOTAL_LABELS = 17
26
- # Individual thresholds for each of the 17 labels
27
  THRESHOLDS = {
28
  "gaslighting": 0.15,
29
  "mockery": 0.15,
30
- "dismissiveness": 0.30,
31
- "control": 0.13,
32
  "guilt_tripping": 0.15,
33
  "apology_baiting": 0.15,
34
  "blame_shifting": 0.15,
35
- "projection": 0.20,
36
  "contradictory_statements": 0.15,
37
  "manipulation": 0.15,
38
  "deflection": 0.15,
39
- "insults": 0.20,
40
- "obscure_formal": 0.20,
41
  "recovery_phase": 0.15,
42
- "suicidal_threat": 0.09,
43
- "physical_threat": 0.50,
44
- "extreme_control": 0.30
45
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  def analyze_messages(input_text):
47
  input_text = input_text.strip()
48
  if not input_text:
49
- return "Please enter a message for analysis."
50
 
51
- # Tokenize
52
  inputs = tokenizer(input_text, return_tensors="pt", truncation=True, padding=True)
53
  with torch.no_grad():
54
  outputs = model(**inputs)
 
55
 
56
- # Squeeze out batch dimension
57
- logits = outputs.logits.squeeze(0)
58
-
59
- # Convert to probabilities
60
- scores = torch.sigmoid(logits).numpy()
61
- print("Scores:", scores)
62
- print("Danger Scores:", scores[14:]) # suicidal, physical, extreme
63
 
64
- pattern_count = 0
65
- danger_flag_count = 0
 
66
 
67
- for i, (label, score) in enumerate(zip(LABELS, scores)):
68
- if score > THRESHOLDS[label]:
69
- if i < 14:
70
- pattern_count += 1
71
- else:
72
- danger_flag_count += 1
73
-
74
- # Optional debug print
75
- for i, s in enumerate(scores):
76
- print(LABELS[i], "=", round(s, 3))
77
-
78
- danger_assessment = (
79
- "High" if danger_flag_count >= 2 else
80
- "Moderate" if danger_flag_count == 1 else
81
- "Low"
82
- )
83
- # Treat high-scoring danger cues as abuse patterns as well
84
- for danger_label in ["suicidal_threat", "physical_threat", "extreme_control"]:
85
- if scores[LABELS.index(danger_label)] > THRESHOLDS[danger_label]:
86
- pattern_count += 1
87
- # Set resources
88
- if danger_assessment == "High":
89
  resources = (
90
- "**Immediate Help:** If you are in immediate danger, please call 911.\n\n"
91
- "**Crisis Support:** National DV Hotline – Safety Planning: [thehotline.org/plan-for-safety](https://www.thehotline.org/plan-for-safety)\n"
92
- "**Legal Assistance:** WomensLaw – Legal Help for Survivors: [womenslaw.org](https://www.womenslaw.org)\n"
93
- "**Specialized Support:** For LGBTQ+, immigrants, and neurodivergent survivors, please consult local services."
94
  )
95
- elif danger_assessment == "Moderate":
96
  resources = (
97
- "**Safety Planning:** The Hotline – What Is Emotional Abuse?: [thehotline.org/resources](https://www.thehotline.org/resources)\n"
98
- "**Relationship Health:** One Love Foundation – Digital Relationship Health: [joinonelove.org](https://www.joinonelove.org)\n"
99
- "**Support Chat:** National Domestic Violence Hotline Chat: [thehotline.org](https://www.thehotline.org)\n"
100
- "**Specialized Groups:** Look for support groups tailored for LGBTQ+, immigrant, and neurodivergent communities."
101
  )
102
  else:
103
  resources = (
104
- "**Educational Resources:** Love Is Respect – Healthy Relationships: [loveisrespect.org](https://www.loveisrespect.org)\n"
105
- "**Therapy Finder:** Psychology Today – Find a Therapist: [psychologytoday.com](https://www.psychologytoday.com)\n"
106
- "**Relationship Tools:** Relate – Relationship Health Tools: [relate.org.uk](https://www.relate.org.uk)\n"
107
- "**Community Support:** Consider community-based and online support groups, especially those focused on LGBTQ+, immigrant, and neurodivergent survivors."
108
  )
109
 
110
- # Output
111
  result_md = (
112
- f"**Abuse Pattern Count:** {pattern_count}\n\n"
113
- f"**Support Resources:**\n{resources}"
 
 
 
114
  )
115
 
 
116
  with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w") as f:
117
  f.write(result_md)
118
  report_path = f.name
119
 
120
  return result_md, report_path
121
 
122
- # Build the Gradio interface
123
  with gr.Blocks() as demo:
124
- gr.Markdown("# Abuse Pattern Detector - Risk Analysis")
125
- gr.Markdown("Enter one or more messages (separated by newlines) for analysis.")
126
-
127
- text_input = gr.Textbox(label="Input Messages", lines=10, placeholder="Type your message(s) here...")
128
- result_output = gr.Markdown(label="Analysis Result")
129
- download_output = gr.File(label="Download Report (.txt)")
130
-
131
- text_input.submit(analyze_messages, inputs=text_input, outputs=[result_output, download_output])
132
  analyze_btn = gr.Button("Analyze")
133
- analyze_btn.click(analyze_messages, inputs=text_input, outputs=[result_output, download_output])
134
-
135
  if __name__ == "__main__":
136
  demo.launch()
 
9
  model = RobertaForSequenceClassification.from_pretrained(model_name)
10
  tokenizer = RobertaTokenizer.from_pretrained(model_name)
11
 
12
+ # Define labels
13
  LABELS = [
14
  "gaslighting", "mockery", "dismissiveness", "control",
15
  "guilt_tripping", "apology_baiting", "blame_shifting", "projection",
 
17
  "obscure_formal", "recovery_phase", "suicidal_threat", "physical_threat",
18
  "extreme_control"
19
  ]
 
20
 
21
+ # Custom thresholds per label (feel free to adjust)
 
 
 
 
22
  THRESHOLDS = {
23
  "gaslighting": 0.15,
24
  "mockery": 0.15,
25
+ "dismissiveness": 0.15,
26
+ "control": 0.10,
27
  "guilt_tripping": 0.15,
28
  "apology_baiting": 0.15,
29
  "blame_shifting": 0.15,
30
+ "projection": 0.15,
31
  "contradictory_statements": 0.15,
32
  "manipulation": 0.15,
33
  "deflection": 0.15,
34
+ "insults": 0.15,
35
+ "obscure_formal": 0.15,
36
  "recovery_phase": 0.15,
37
+ "suicidal_threat": 0.20,
38
+ "physical_threat": 0.20,
39
+ "extreme_control": 0.20,
40
  }
41
+
42
+ # Label categories
43
+ PATTERN_LABELS = LABELS[:14]
44
+ DANGER_LABELS = LABELS[14:]
45
+
46
+ def calculate_abuse_level(scores, thresholds):
47
+ triggered_scores = [score for label, score in zip(LABELS, scores) if score > thresholds[label]]
48
+ if not triggered_scores:
49
+ return 0.0
50
+ return round(np.mean(triggered_scores) * 100, 2)
51
+
52
+ def interpret_abuse_level(score):
53
+ if score > 80:
54
+ return "Extreme / High Risk"
55
+ elif score > 60:
56
+ return "Severe / Harmful Pattern Present"
57
+ elif score > 40:
58
+ return "Likely Abuse"
59
+ elif score > 20:
60
+ return "Mild Concern"
61
+ else:
62
+ return "Very Low / Likely Safe"
63
+
64
  def analyze_messages(input_text):
65
  input_text = input_text.strip()
66
  if not input_text:
67
+ return "Please enter a message for analysis.", None
68
 
69
+ # Tokenize and predict
70
  inputs = tokenizer(input_text, return_tensors="pt", truncation=True, padding=True)
71
  with torch.no_grad():
72
  outputs = model(**inputs)
73
+ scores = torch.sigmoid(outputs.logits.squeeze(0)).numpy()
74
 
75
+ # Count triggered labels
76
+ pattern_count = sum(score > THRESHOLDS[label] for label, score in zip(PATTERN_LABELS, scores[:14]))
77
+ danger_flag_count = sum(score > THRESHOLDS[label] for label, score in zip(DANGER_LABELS, scores[14:]))
 
 
 
 
78
 
79
+ # Abuse level calculation
80
+ abuse_level = calculate_abuse_level(scores, THRESHOLDS)
81
+ abuse_description = interpret_abuse_level(abuse_level)
82
 
83
+ # Resource logic
84
+ if danger_flag_count >= 2:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  resources = (
86
+ "**Immediate Help:** Call 911 if in danger.\n\n"
87
+ "**Crisis Support:** National DV Hotline – [thehotline.org/plan-for-safety](https://www.thehotline.org/plan-for-safety/)\n"
88
+ "**Legal Support:** WomensLaw – [womenslaw.org](https://www.womenslaw.org/)\n"
89
+ "**Specialized Services:** RAINN, StrongHearts, LGBTQ+, immigrant, neurodivergent resources"
90
  )
91
+ elif danger_flag_count == 1:
92
  resources = (
93
+ "**Emotional Abuse Info:** [thehotline.org/resources](https://www.thehotline.org/resources/what-is-emotional-abuse/)\n"
94
+ "**Relationship Education:** [joinonelove.org](https://www.joinonelove.org/)\n"
95
+ "**Support Chat:** [thehotline.org](https://www.thehotline.org/)\n"
96
+ "**Community Groups:** LGBTQ+, immigrant, and neurodivergent spaces"
97
  )
98
  else:
99
  resources = (
100
+ "**Healthy Relationships:** [loveisrespect.org](https://www.loveisrespect.org/)\n"
101
+ "**Find a Therapist:** [psychologytoday.com](https://www.psychologytoday.com/us/therapists)\n"
102
+ "**Relationship Tools:** [relate.org.uk](https://www.relate.org.uk/)\n"
103
+ "**Online Peer Support:** (including identity-focused groups)"
104
  )
105
 
 
106
  result_md = (
107
+ f"### πŸ“‹ Analysis Summary\n\n"
108
+ f"**Abuse Pattern Count:** {pattern_count}\n"
109
+ f"**Danger Cues Detected:** {danger_flag_count}\n"
110
+ f"**Abuse Level:** {abuse_level}% ({abuse_description})\n\n"
111
+ f"### πŸ›Ÿ Suggested Support Resources\n{resources}"
112
  )
113
 
114
+ # Save to .txt
115
  with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w") as f:
116
  f.write(result_md)
117
  report_path = f.name
118
 
119
  return result_md, report_path
120
 
121
+ # Interface
122
  with gr.Blocks() as demo:
123
+ gr.Markdown("# πŸ” Abuse Pattern Detector")
124
+ gr.Markdown("Paste one or more messages for analysis (multi-line supported).")
125
+
126
+ text_input = gr.Textbox(label="Text Message(s)", lines=10, placeholder="Paste messages here...")
127
+ result_output = gr.Markdown()
128
+ file_output = gr.File(label="πŸ“₯ Download Analysis (.txt)")
129
+
130
+ text_input.submit(analyze_messages, inputs=text_input, outputs=[result_output, file_output])
131
  analyze_btn = gr.Button("Analyze")
132
+ analyze_btn.click(analyze_messages, inputs=text_input, outputs=[result_output, file_output])
133
+
134
  if __name__ == "__main__":
135
  demo.launch()