SamanthaStorm commited on
Commit
933d668
Β·
verified Β·
1 Parent(s): 2eb2ad0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -22
app.py CHANGED
@@ -560,22 +560,50 @@ def analyze_composite(msg1, date1, msg2, date2, msg3, date3, *answers_and_none):
560
  sentiments = [r[0][3]['label'] for r in results]
561
  stages = [r[0][4] for r in results]
562
  darvo_scores = [r[0][5] for r in results]
563
- tone_tags= [r[0][6] for r in results]
564
  dates_used = [r[1] or "Undated" for r in results] # Store dates for future mapping
565
- # Calculate escalation bump *after* model results exist
 
566
  escalation_bump = 0
567
  for result, _ in results:
568
  abuse_score, threshold_labels, top_patterns, sentiment, stage, darvo_score, tone_tag = result
 
569
  if darvo_score > 0.65:
570
  escalation_bump += 3
571
- if tone_tag in ["forced accountability flip", "emotional threat"]:
 
572
  escalation_bump += 2
 
573
  if abuse_score > 80:
574
  escalation_bump += 2
 
575
  if stage == 2:
576
  escalation_bump += 3
577
 
578
- # Now we can safely calculate hybrid_score
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  hybrid_score = escalation_score + escalation_bump if escalation_score is not None else 0
580
  risk_level = (
581
  "High" if hybrid_score >= 16 else
@@ -583,10 +611,6 @@ def analyze_composite(msg1, date1, msg2, date2, msg3, date3, *answers_and_none):
583
  "Low"
584
  )
585
 
586
- # Now compute scores and allow override
587
- abuse_scores = [r[0][0] for r in results]
588
- stages = [r[0][4] for r in results]
589
-
590
  # Post-check override (e.g. stage 2 or high abuse score forces Moderate risk)
591
  if any(score > 70 for score in abuse_scores) or any(stage == 2 for stage in stages):
592
  if risk_level == "Low":
@@ -597,27 +621,18 @@ def analyze_composite(msg1, date1, msg2, date2, msg3, date3, *answers_and_none):
597
 
598
  # --- Composite Abuse Score with Weighted Patterns ---
599
  composite_abuse_scores = []
600
-
601
  for result, _ in results:
602
  abuse_score, threshold_labels, top_patterns, _, _, _, _ = result
603
  weighted_score = 0
604
  total_weight = 0
605
-
606
  for label, score in top_patterns:
607
  weight = PATTERN_WEIGHTS.get(label, 1.0)
608
  weighted_score += score * weight
609
  total_weight += weight
610
-
611
- if total_weight > 0:
612
- final_score = (weighted_score / total_weight) * 100
613
- else:
614
- final_score = 0
615
-
616
  composite_abuse_scores.append(final_score)
617
 
618
  composite_abuse = int(round(sum(composite_abuse_scores) / len(composite_abuse_scores)))
619
-
620
-
621
  most_common_stage = max(set(stages), key=stages.count)
622
  stage_text = RISK_STAGE_LABELS[most_common_stage]
623
 
@@ -630,27 +645,27 @@ def analyze_composite(msg1, date1, msg2, date2, msg3, date3, *answers_and_none):
630
  out = f"Abuse Intensity: {composite_abuse}%\n"
631
  out += "πŸ“Š This reflects the strength and severity of detected abuse patterns in the message(s).\n\n"
632
 
633
- # Save this line for later use at the
634
  if escalation_score is None:
635
  escalation_text = "πŸ“‰ Escalation Potential: Unknown (Checklist not completed)\n"
636
  escalation_text += "⚠️ *This section was not completed. Escalation potential is unknown.*\n"
637
- hybrid_score = 0 # βœ… fallback so it's defined for generate_risk_snippet
638
  else:
639
  escalation_text = f"🧨 **Escalation Potential: {risk_level} ({escalation_score}/{sum(w for _, w in ESCALATION_QUESTIONS)})**\n"
640
  escalation_text += "This score comes directly from the safety checklist and functions as a standalone escalation risk score.\n"
641
  escalation_text += "It indicates how many serious risk factors are present based on your answers to the safety checklist.\n"
642
- # Derive top_label from the strongest top_patterns across all messages
 
643
  top_label = None
644
  if results:
645
  sorted_patterns = sorted(
646
  [(label, score) for r in results for label, score in r[0][2]],
647
  key=lambda x: x[1],
648
  reverse=True
649
- )
650
  if sorted_patterns:
651
  top_label = f"{sorted_patterns[0][0]} – {int(round(sorted_patterns[0][1] * 100))}%"
652
  if top_label is None:
653
  top_label = "Unknown – 0%"
 
654
  out += generate_risk_snippet(composite_abuse, top_label, hybrid_score if escalation_score is not None else 0, most_common_stage)
655
  out += f"\n\n{stage_text}"
656
  out += darvo_blurb
@@ -658,6 +673,7 @@ def analyze_composite(msg1, date1, msg2, date2, msg3, date3, *answers_and_none):
658
  for i, tone in enumerate(tone_tags):
659
  label = tone if tone else "none"
660
  out += f"β€’ Message {i+1}: *{label}*\n"
 
661
  print(f"DEBUG: avg_darvo = {avg_darvo}")
662
  pattern_labels = [r[0][2][0][0] for r in results] # top label for each message
663
  timeline_image = generate_abuse_score_chart(dates_used, abuse_scores, pattern_labels)
 
560
  sentiments = [r[0][3]['label'] for r in results]
561
  stages = [r[0][4] for r in results]
562
  darvo_scores = [r[0][5] for r in results]
563
+ tone_tags = [r[0][6] for r in results]
564
  dates_used = [r[1] or "Undated" for r in results] # Store dates for future mapping
565
+
566
+ # Calculate escalation bump
567
  escalation_bump = 0
568
  for result, _ in results:
569
  abuse_score, threshold_labels, top_patterns, sentiment, stage, darvo_score, tone_tag = result
570
+
571
  if darvo_score > 0.65:
572
  escalation_bump += 3
573
+
574
+ if tone_tag in ["forced accountability flip", "emotional threat", "aggressive dismissal", "mocking detachment"]:
575
  escalation_bump += 2
576
+
577
  if abuse_score > 80:
578
  escalation_bump += 2
579
+
580
  if stage == 2:
581
  escalation_bump += 3
582
 
583
+ if "threat" in threshold_labels or "aggression" in threshold_labels:
584
+ escalation_bump += 4
585
+
586
+ # Helper: score trend of pattern severity
587
+ def message_severity_index(threshold_labels):
588
+ weights = {
589
+ "recovery": 0,
590
+ "dismissiveness": 1,
591
+ "deflection": 1,
592
+ "guilt tripping": 2,
593
+ "control": 3,
594
+ "gaslighting": 3,
595
+ "aggression": 4,
596
+ "threat": 5,
597
+ }
598
+ return max([weights.get(label, 0) for label in threshold_labels], default=0)
599
+
600
+ severity_levels = [message_severity_index(r[0][1]) for r in results]
601
+ if len(severity_levels) >= 2 and severity_levels == sorted(severity_levels):
602
+ escalation_bump += 2
603
+
604
+ escalation_bump = min(escalation_bump, 10)
605
+
606
+ # Final escalation score
607
  hybrid_score = escalation_score + escalation_bump if escalation_score is not None else 0
608
  risk_level = (
609
  "High" if hybrid_score >= 16 else
 
611
  "Low"
612
  )
613
 
 
 
 
 
614
  # Post-check override (e.g. stage 2 or high abuse score forces Moderate risk)
615
  if any(score > 70 for score in abuse_scores) or any(stage == 2 for stage in stages):
616
  if risk_level == "Low":
 
621
 
622
  # --- Composite Abuse Score with Weighted Patterns ---
623
  composite_abuse_scores = []
 
624
  for result, _ in results:
625
  abuse_score, threshold_labels, top_patterns, _, _, _, _ = result
626
  weighted_score = 0
627
  total_weight = 0
 
628
  for label, score in top_patterns:
629
  weight = PATTERN_WEIGHTS.get(label, 1.0)
630
  weighted_score += score * weight
631
  total_weight += weight
632
+ final_score = (weighted_score / total_weight) * 100 if total_weight > 0 else 0
 
 
 
 
 
633
  composite_abuse_scores.append(final_score)
634
 
635
  composite_abuse = int(round(sum(composite_abuse_scores) / len(composite_abuse_scores)))
 
 
636
  most_common_stage = max(set(stages), key=stages.count)
637
  stage_text = RISK_STAGE_LABELS[most_common_stage]
638
 
 
645
  out = f"Abuse Intensity: {composite_abuse}%\n"
646
  out += "πŸ“Š This reflects the strength and severity of detected abuse patterns in the message(s).\n\n"
647
 
 
648
  if escalation_score is None:
649
  escalation_text = "πŸ“‰ Escalation Potential: Unknown (Checklist not completed)\n"
650
  escalation_text += "⚠️ *This section was not completed. Escalation potential is unknown.*\n"
 
651
  else:
652
  escalation_text = f"🧨 **Escalation Potential: {risk_level} ({escalation_score}/{sum(w for _, w in ESCALATION_QUESTIONS)})**\n"
653
  escalation_text += "This score comes directly from the safety checklist and functions as a standalone escalation risk score.\n"
654
  escalation_text += "It indicates how many serious risk factors are present based on your answers to the safety checklist.\n"
655
+
656
+ # Derive top label
657
  top_label = None
658
  if results:
659
  sorted_patterns = sorted(
660
  [(label, score) for r in results for label, score in r[0][2]],
661
  key=lambda x: x[1],
662
  reverse=True
663
+ )
664
  if sorted_patterns:
665
  top_label = f"{sorted_patterns[0][0]} – {int(round(sorted_patterns[0][1] * 100))}%"
666
  if top_label is None:
667
  top_label = "Unknown – 0%"
668
+
669
  out += generate_risk_snippet(composite_abuse, top_label, hybrid_score if escalation_score is not None else 0, most_common_stage)
670
  out += f"\n\n{stage_text}"
671
  out += darvo_blurb
 
673
  for i, tone in enumerate(tone_tags):
674
  label = tone if tone else "none"
675
  out += f"β€’ Message {i+1}: *{label}*\n"
676
+
677
  print(f"DEBUG: avg_darvo = {avg_darvo}")
678
  pattern_labels = [r[0][2][0][0] for r in results] # top label for each message
679
  timeline_image = generate_abuse_score_chart(dates_used, abuse_scores, pattern_labels)