TetherInterview / app.py
SamanthaStorm's picture
Update app.py
b9cc423 verified
import gradio as gr
# Define detection patterns
patterns = [
{
"id": "identity_erosion_001",
"name": "Loss of Personal Joy",
"trigger_keywords": ["used to love", "don’t anymore", "haven’t done that in years", "stopped doing"],
"concern": "Identity erosion / subtle control",
"follow_up_therapist": "What made you stop?",
"follow_up_cop": "When did you stop doing that, and did anyone tell you not to?",
"insight": "Loss of joyful or self-expressive activities may reflect identity suppression or partner-based discouragement.",
"escalation": "Moderate"
},
{
"id": "economic_control_001",
"name": "Self-Denial Framed as Budgeting",
"trigger_keywords": ["we can’t afford", "not in the budget", "no money for that"],
"concern": "Covert economic control",
"follow_up_therapist": "Has there ever been something they wanted to spend money on that you didn’t think you could afford?",
"follow_up_cop": "Who decides what money gets spent on?",
"insight": "When financial limitations are selectively applied to personal growth, it's often a form of control.",
"escalation": "Moderate"
},
{
"id": "control_checkins_001",
"name": "Monitoring & Check-ins",
"trigger_keywords": ["have to check in", "need to be home by", "text when I get there"],
"concern": "Surveillance / conditional autonomy",
"follow_up_therapist": "What happens if you're late or forget to check in?",
"follow_up_cop": "What happens if you don’t check in or come home late?",
"insight": "Frequent required check-ins can signal coercive oversight or fear-based compliance.",
"escalation": "High"
},
{
"id": "lethal_intimidation_001",
"name": "Excessive Weapon Presence or Intimidation",
"trigger_keywords": [
"guns in the house", "keeps a knife on him", "built his own gun",
"gun isn’t locked", "open carry at home", "he always wears his knife",
"refused to put guns in a safe", "too many weapons", "it makes me nervous"
],
"concern": "Implied threat or coercive intimidation via weapon access",
"follow_up_therapist": "How do you feel about the weapons being kept around — is that something you’re okay with?",
"follow_up_cop": "Has there ever been a time where the presence of those weapons made you feel unsafe or changed how you responded in an argument?",
"insight": "Unsafely stored or emotionally charged weapon presence can signal power imbalances, intimidation, and elevated risk of harm — especially when one partner is uncomfortable but compliance continues.",
"escalation": "High"
},
{
"id": "digital_control_001",
"name": "Digital Control via Shared or Monitored Social Media",
"trigger_keywords": [
"we have a joint facebook", "shared account", "they manage our social media",
"he doesn’t let me post", "i’m not allowed on social media", "we don’t really use social media"
],
"concern": "Digital surveillance or identity suppression",
"follow_up_therapist": "Was the joint account something you both wanted — or more their idea?",
"follow_up_cop": "Have you ever felt like you couldn’t use social media freely or had to get permission before posting?",
"insight": "Joint or controlled online accounts often signal deeper patterns of digital surveillance, identity suppression, or reputational control.",
"escalation": "Moderate"
},
{
"id": "fawning_behavior_001",
"name": "Hyper-Attunement to Partner’s Preferences",
"trigger_keywords": [
"he doesn’t like when i", "she prefers i don’t", "i try not to upset them",
"he’d hate that", "i just avoid it", "he gets upset when"
],
"concern": "Chronic fear-based adjustment or internalized control",
"follow_up_therapist": "What do you think would happen if you did it anyway?",
"follow_up_cop": "Have you ever changed plans or avoided doing something because you didn’t want to upset them?",
"insight": "Hyper-attunement to a partner’s preferences often reveals chronic behavioral conditioning rooted in fear, not genuine compromise.",
"escalation": "Moderate"
},
{
"id": "minimizing_behavior_001",
"name": "Minimizing or Defending the Abuser’s Behavior",
"trigger_keywords": [
"he’s not abusive", "she didn’t mean to", "he just has a temper",
"it’s not that bad", "he was just drunk", "she had a rough childhood",
"it’s not like he hits me"
],
"concern": "Normalization or justification of harm",
"follow_up_therapist": "It sounds like you’re trying to make sense of their behavior — what part of you still feels unsure about how to name it?",
"follow_up_cop": "Have you ever felt scared even if they didn’t physically hurt you?",
"insight": "Minimizing or justifying harm without prompting signals grooming, normalization, or an internalized need to protect the abuser’s image.",
"escalation": "High"
}
]
danger_questions = [
{
"id": "da_1",
"question": "Has the physical violence increased in frequency or severity?",
"tags": ["threat", "control"],
"follow_ups": [
"What triggered the most recent incident?",
"What has changed since the first time it happened?"
]
},
{
"id": "da_2",
"question": "Has your partner ever used a weapon against you or threatened you with one?",
"tags": ["threat", "lethal_intimidation_001"],
"follow_ups": [
"Where are the weapons usually kept?",
"Has the presence of those weapons ever changed how you responded in an argument?"
]
},
{
"id": "da_3",
"question": "Does your partner try to control most of your daily activities?",
"tags": ["control", "monitoring"],
"follow_ups": [
"Can you describe a time they told you not to do something?",
"What happens if you don’t follow their preferences?"
]
},
{
"id": "da_4",
"question": "Is your partner constantly or violently jealous?",
"tags": ["projection", "insults", "control"],
"follow_ups": [
"How do they respond when you talk to friends or coworkers?",
"Have they accused you of cheating or lying without reason?"
]
},
{
"id": "da_5",
"question": "Have you left your partner after living together and then returned?",
"tags": ["recovery phase", "trauma bond", "guilt tripping"],
"follow_ups": [
"What made you leave the first time?",
"What made you go back?"
]
},
{
"id": "da_6",
"question": "Has your partner ever threatened to kill you or themselves?",
"tags": ["threat", "suicidal threat", "control"],
"follow_ups": [
"How did you respond when they said that?",
"Have they made this kind of threat more than once?"
]
},
{
"id": "da_7",
"question": "Does your partner frequently put you down or humiliate you?",
"tags": ["insults", "dismissiveness", "gaslighting"],
"follow_ups": [
"Can you remember something they said that stuck with you?",
"How do you usually respond when that happens?"
]
},
{
"id": "da_8",
"question": "Do you feel afraid to disagree with your partner?",
"tags": ["control", "dismissiveness", "emotional threat"],
"follow_ups": [
"What do you think might happen if you did?",
"Have you ever avoided speaking up to keep the peace?"
]
},
{
"id": "da_9",
"question": "Does your partner follow or stalk you, or monitor your movements?",
"tags": ["control", "digital control", "monitoring"],
"follow_ups": [
"How do they keep track of where you are?",
"Do you ever feel like you’re being watched or tracked?"
]
},
{
"id": "da_10",
"question": "Has your partner ever forced or pressured you into sexual activity?",
"tags": ["control", "threat", "guilt tripping"],
"follow_ups": [
"Do you feel like you could say no safely?",
"How do they usually respond when you aren’t in the mood?"
]
},
{
"id": "da_11",
"question": "Does your partner isolate you from friends or family?",
"tags": ["control", "digital control", "identity erosion"],
"follow_ups": [
"Has anyone expressed concern about your relationship?",
"Do you feel like you can talk to others freely?"
]
},
{
"id": "da_12",
"question": "Do you rely on your partner for transportation, money, or housing?",
"tags": ["economic control", "access restriction"],
"follow_ups": [
"What would happen if you needed to leave suddenly?",
"Do you have access to your own money or bank account?"
]
},
{
"id": "da_13",
"question": "Has your partner ever harmed or threatened your pets?",
"tags": ["threat", "emotional threat"],
"follow_ups": [
"What happened when they did that?",
"Did it change how you behaved afterward?"
]
},
{
"id": "da_14",
"question": "Has your partner ever destroyed your property or personal items?",
"tags": ["control", "threat", "emotional threat"],
"follow_ups": [
"Do they ever break or throw things during arguments?",
"How do you usually respond when they destroy something?"
]
},
{
"id": "da_15",
"question": "Have you ever needed medical attention because of something your partner did?",
"tags": ["threat", "escalation risk"],
"follow_ups": [
"Did anyone help you at the time?",
"Was it reported to anyone?"
]
}
]
# Analysis function
def analyze_input(text, role):
role_key = "therapist" if role == "Therapist" else "cop"
input_text = text.lower()
results = []
for pattern in patterns:
if any(keyword in input_text for keyword in pattern["trigger_keywords"]):
results.append(
f"🔍 Pattern Detected: {pattern['name']}\n"
f"Concern: {pattern['concern']}\n"
f"Follow-Up Question: {pattern[f'follow_up_{role_key}']}\n"
f"Insight: {pattern['insight']}\n"
f"Escalation Risk: {pattern['escalation']}\n"
)
if not results:
return "No clear abuse pattern detected. Continue listening for contradictions, self-blame, or fear-based justifications."
return "\n\n".join(results)
# ——— Gradio Danger Assessment Wizard ———————————————————————————————————————
def danger_assessment_wizard():
with gr.Blocks() as demo:
gr.Markdown("## 🔍 Danger Assessment Interview")
gr.Markdown("Answer each question honestly. Follow-up questions will appear if you answer 'Yes'.")
yes_responses = []
followup_textboxes = []
for dq in danger_questions:
gr.Markdown(f"**{dq['question']}**")
answer = gr.Radio(["Yes", "No"], label="Your Answer", value=None)
yes_responses.append(answer)
fups = []
for fup in dq["follow_ups"]:
box = gr.Textbox(label=f"Follow-up: {fup}", visible=False)
fups.append(box)
followup_textboxes.append(box)
def toggle_visibility(ans, *args):
return [gr.update(visible=(ans == "Yes")) for _ in args]
answer.change(
toggle_visibility,
inputs=[answer] + fups,
outputs=fups
)
submit = gr.Button("Submit Responses")
output = gr.Textbox(label="Summary / Next Step", lines=5)
def summarize(*args):
yes_count = sum([1 for a in args[:len(yes_responses)] if a == "Yes"])
return f"✅ You answered 'Yes' to {yes_count} danger indicators. Follow-up responses captured for risk review."
submit.click(fn=summarize, inputs=yes_responses + followup_textboxes, outputs=output)
return demo
# ——— Launch the Danger Wizard ————————————————————————————————————————————
if __name__ == "__main__":
danger_assessment_wizard().launch()
# Gradio UI
gr.Interface(
fn=analyze_input,
inputs=[
gr.Textbox(lines=4, label="What did the person say?"),
gr.Radio(["Therapist", "Law Enforcement"], label="Your Role")
],
outputs="text",
title="DV Pattern Recognition Tool (Prototype)",
description="Enter a client or witness quote. The tool flags DV-related behavioral cues and suggests follow-up questions based on your role.")