Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -98,6 +98,47 @@ def generate_risk_snippet(abuse_score, top_label):
|
|
| 98 |
title, summary, advice = RISK_SNIPPETS[risk_level]
|
| 99 |
return f"\n\n{title}\n{summary} (Pattern: **{top_label}**)\n💡 {advice}"
|
| 100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 101 |
# --- Escalation Quiz Questions & Weights ---
|
| 102 |
ESCALATION_QUESTIONS = [
|
| 103 |
("Partner has access to firearms or weapons", 4),
|
|
@@ -150,6 +191,12 @@ def analyze_composite(msg1, msg2, msg3, *answers_and_none):
|
|
| 150 |
out = f"Abuse Intensity: {composite_abuse}%\n"
|
| 151 |
out += f"Escalation Potential: {escalation_level} ({escalation_score}/{sum(w for _,w in ESCALATION_QUESTIONS)})"
|
| 152 |
out += generate_risk_snippet(composite_abuse, top_pattern)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
return out
|
| 154 |
|
| 155 |
textbox_inputs = [
|
|
@@ -170,4 +217,4 @@ iface = gr.Interface(
|
|
| 170 |
)
|
| 171 |
|
| 172 |
if __name__ == "__main__":
|
| 173 |
-
iface.launch()
|
|
|
|
| 98 |
title, summary, advice = RISK_SNIPPETS[risk_level]
|
| 99 |
return f"\n\n{title}\n{summary} (Pattern: **{top_label}**)\n💡 {advice}"
|
| 100 |
|
| 101 |
+
# --- DARVO Detection ---
|
| 102 |
+
DARVO_PATTERNS = {
|
| 103 |
+
"blame shifting", "projection", "dismissiveness", "guilt tripping", "contradictory statements"
|
| 104 |
+
}
|
| 105 |
+
DARVO_MOTIFS = [
|
| 106 |
+
"i guess i’m the bad guy", "after everything i’ve done", "you always twist everything",
|
| 107 |
+
"so now it’s all my fault", "i’m the villain", "i’m always wrong", "you never listen",
|
| 108 |
+
"you’re attacking me", "i’m done trying", "i’m the only one who cares"
|
| 109 |
+
]
|
| 110 |
+
|
| 111 |
+
def detect_contradiction(message):
|
| 112 |
+
contradiction_flag = False
|
| 113 |
+
contradiction_phrases = [
|
| 114 |
+
(r"\b(i love you).{0,15}(i hate you|you ruin everything)", re.IGNORECASE),
|
| 115 |
+
(r"\b(i’m sorry).{0,15}(but you|if you hadn’t)", re.IGNORECASE),
|
| 116 |
+
(r"\b(i’m trying).{0,15}(you never|why do you)", re.IGNORECASE),
|
| 117 |
+
(r"\b(do what you want).{0,15}(you’ll regret it|i always give everything)", re.IGNORECASE),
|
| 118 |
+
(r"\b(i don’t care).{0,15}(you never think of me)", re.IGNORECASE),
|
| 119 |
+
(r"\b(i guess i’m just).{0,15}(the bad guy|worthless|never enough)", re.IGNORECASE),
|
| 120 |
+
]
|
| 121 |
+
for pattern, flags in contradiction_phrases:
|
| 122 |
+
if re.search(pattern, message, flags):
|
| 123 |
+
contradiction_flag = True
|
| 124 |
+
break
|
| 125 |
+
return contradiction_flag
|
| 126 |
+
|
| 127 |
+
def calculate_darvo_score(patterns, sentiment_before, sentiment_after, motifs_found, contradiction_flag=False):
|
| 128 |
+
pattern_hits = len([p.lower() for p in patterns if p.lower() in DARVO_PATTERNS])
|
| 129 |
+
pattern_score = pattern_hits / len(DARVO_PATTERNS)
|
| 130 |
+
sentiment_shift_score = max(0.0, sentiment_after - sentiment_before)
|
| 131 |
+
motif_hits = len([m.lower() for m in motifs_found if m.lower() in DARVO_MOTIFS])
|
| 132 |
+
motif_score = motif_hits / len(DARVO_MOTIFS)
|
| 133 |
+
contradiction_score = 1.0 if contradiction_flag else 0.0
|
| 134 |
+
darvo_score = (
|
| 135 |
+
0.3 * pattern_score +
|
| 136 |
+
0.3 * sentiment_shift_score +
|
| 137 |
+
0.25 * motif_score +
|
| 138 |
+
0.15 * contradiction_score
|
| 139 |
+
)
|
| 140 |
+
return round(min(darvo_score, 1.0), 3)
|
| 141 |
+
|
| 142 |
# --- Escalation Quiz Questions & Weights ---
|
| 143 |
ESCALATION_QUESTIONS = [
|
| 144 |
("Partner has access to firearms or weapons", 4),
|
|
|
|
| 191 |
out = f"Abuse Intensity: {composite_abuse}%\n"
|
| 192 |
out += f"Escalation Potential: {escalation_level} ({escalation_score}/{sum(w for _,w in ESCALATION_QUESTIONS)})"
|
| 193 |
out += generate_risk_snippet(composite_abuse, top_pattern)
|
| 194 |
+
|
| 195 |
+
avg_darvo = round(sum([r[3] for r in results]) / len(results), 3)
|
| 196 |
+
if avg_darvo > 0.25:
|
| 197 |
+
darvo_descriptor = "moderate" if avg_darvo < 0.65 else "high"
|
| 198 |
+
out += f"\n\nDARVO Score: {avg_darvo} → This indicates a **{darvo_descriptor} likelihood** of narrative reversal (DARVO), where the speaker may be denying, attacking, or reversing blame."
|
| 199 |
+
|
| 200 |
return out
|
| 201 |
|
| 202 |
textbox_inputs = [
|
|
|
|
| 217 |
)
|
| 218 |
|
| 219 |
if __name__ == "__main__":
|
| 220 |
+
iface.launch()
|