kevinziyadaaser's picture
Update app.py
03c760f verified
import gradio as gr
import requests
import json
import time
API_URL = "https://kevinziyadaaser-gbv-text-detector.hf.space/predict/detailed"
def analyze_text(text):
"""
Send text to the FastAPI backend for GBV analysis.
Returns formatted results for Gradio display.
"""
if not text or len(text.strip()) < 15:
return (
"❌ **Error:** Please enter at least 15 characters of text for analysis.",
{},
"Input validation failed"
)
word_count = len(text.strip().split())
if word_count < 15:
return (
f"❌ **Error:** Please provide at least 12 words for reliable analysis. You provided {word_count} words.",
{},
"Input too short"
)
try:
payload = {"text": text}
headers = {"Content-Type": "application/json"}
response = requests.post(
API_URL,
json=payload,
headers=headers,
timeout=30
)
if response.status_code == 200:
data = response.json()
harmful_status = "🚨 **HARMFUL CONTENT DETECTED**" if data['is_harmful'] else "βœ… **CONTENT APPEARS SAFE**"
summary = f"""
{harmful_status}
- **Confidence:** {data['harmful_confidence']*100:.1f}%
**πŸ“‹ GBV Category:** {data['gbv_category']}
- **Confidence:** {data['category_confidence']*100:.1f}%
**πŸ” Analysis:** {data['analysis']}
"""
probabilities_dict = {k: float(v) for k, v in data['all_probabilities'].items()}
return summary, probabilities_dict, f"βœ… Analysis completed successfully"
else:
try:
error_detail = response.json().get('detail', 'Unknown error')
except:
error_detail = f"HTTP {response.status_code}: {response.text}"
return (
f"❌ **API Error:** {error_detail}",
{},
f"API returned status code {response.status_code}"
)
except requests.exceptions.Timeout:
return (
"⏰ **Timeout Error:** The API took too long to respond. Please try again.",
{},
"Request timed out"
)
except requests.exceptions.ConnectionError:
return (
"πŸ”Œ **Connection Error:** Cannot reach the API. Please check if the backend is running.",
{},
"Connection failed"
)
except Exception as e:
return (
f"❌ **Unexpected Error:** {str(e)}",
{},
"Unexpected error occurred"
)
def check_api_status():
"""Check if the API is responding."""
try:
status_url = API_URL.replace('/predict/detailed', '/status')
response = requests.get(status_url, timeout=10)
if response.status_code == 200:
data = response.json()
if data.get('models_loaded', False):
return "🟒 API is ready and models are loaded"
else:
return "🟑 API is running but models are still loading"
else:
return f"πŸ”΄ API returned status code {response.status_code}"
except Exception as e:
return f"πŸ”΄ API is not accessible: {str(e)}"
def create_interface():
"""Create and configure the Gradio interface."""
api_status = check_api_status()
with gr.Blocks(
title="GBV Text Analysis Tool",
theme=gr.themes.Soft(),
css="""
.gradio-container {
max-width: 900px !important;
}
.analysis-header {
text-align: center;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
padding: 2rem;
border-radius: 1rem;
margin-bottom: 2rem;
}
.example-text {
font-style: italic;
color: #666;
font-size: 0.9em;
}
"""
) as iface:
# Header
gr.HTML(f"""
<div class="analysis-header">
<h1 style="margin: 0; font-size: 2.5em;">πŸ” GBV Text Analysis Tool</h1>
<p style="margin: 0.5rem 0 0 0; font-size: 1.2em; opacity: 0.9;">
AI-Powered Detection and Categorization of Gender-Based Violence in Text
</p>
</div>
""")
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### πŸ“ Enter Text for Analysis")
text_input = gr.Textbox(
label="Input Text",
placeholder="Enter the text you want to analyze for potential Gender-Based Violence indicators...\n\nExample: 'He threatened to hurt her if she didn't listen to him.'",
lines=6,
max_lines=10
)
analyze_button = gr.Button(
"πŸš€ Analyze Text",
variant="primary",
size="lg"
)
status_output = gr.Textbox(
label="Status",
value="Ready for analysis...",
interactive=False,
max_lines=2
)
with gr.Column(scale=3):
gr.Markdown("### πŸ“Š Analysis Results")
summary_output = gr.Markdown(
label="Analysis Summary",
value="*Results will appear here after analysis...*"
)
probabilities_output = gr.Label(
label="Category Probabilities",
num_top_classes=8
)
gr.Markdown("### πŸ’‘ Try These Examples")
example_texts = [
"After he came home late from a bar in Kabalagala, he started an argument over nothing, and when I tried to walk away, he grabbed my arm, threw my phone against the wall smashing it, and then pushed me so hard I fell over the coffee table and got a deep cut on my leg.",
"After finally finding the strength to leave the abusive situation, I contacted a local women's shelter in Kampala that provided me with a safe place to stay, and they connected me with a counselor who is now helping me work through the trauma and a legal aid clinic to help me file for a protection order.",
"We became deeply concerned for our young niece after noticing she was often left alone to care for her younger siblings for entire weekends without enough food, and she seemed terrified of her uncle, who would often shout at her and force her to miss school to work on his market stall.",
"After a bitter argument, my former friend started a malicious campaign against me in our university WhatsApp group, spreading fabricated stories and posting old, private photos of me to try and ruin my reputation among my classmates and lecturers.",
"Even though I blocked his number and all his social media profiles weeks ago, my ex-partner continues to create new accounts to send me messages, has shown up at my workplace near Acacia Mall twice, and I've even heard from my neighbours that they've seen his car parked down the street from my apartment late at night.",
"At the party last weekend, a man I barely knew kept pressuring me to go somewhere private with him despite my repeated refusals, and later, when I was trying to leave, he followed me and cornered me, leaving me with a profound sense of violation and trauma that I am now struggling to process.",
"My husband, who manages all our family finances, took my name off the land title for our shamba without telling me, and now he only gives me a small amount of money for food each week, refusing to let me use the boda for transport or even buy airtime for my phone without his explicit permission.",
"For months, he has been systematically isolating me from my family in Masaka by telling them lies about me, and he constantly criticizes everything I do, from the way I cook matoke to how I speak, making me feel so worthless and stupid that I've started to believe that I'm the one who is actually the problem in our relationship.",
"After he came home late from a bar in Kabalagala, he started an argument over nothing, and when I tried to walk away, he grabbed my arm, threw my phone against the wall smashing it, and then pushed me so hard I fell over the coffee table and got a deep cut on my leg."
]
with gr.Row():
for i, example in enumerate(example_texts):
if i < 4: # First row
gr.Button(
example[:40] + "..." if len(example) > 40 else example,
size="sm"
).click(
lambda ex=example: ex,
outputs=text_input
)
with gr.Row():
for i, example in enumerate(example_texts[4:], 5):
gr.Button(
example[:40] + "..." if len(example) > 40 else example,
size="sm"
).click(
lambda ex=example: ex,
outputs=text_input
)
analyze_button.click(
fn=analyze_text,
inputs=text_input,
outputs=[summary_output, probabilities_output, status_output]
)
text_input.submit(
fn=analyze_text,
inputs=text_input,
outputs=[summary_output, probabilities_output, status_output]
)
gr.HTML("""
<div style="text-align: center; margin-top: 2rem; padding: 1rem; background: #f8f9fa; border-radius: 0.5rem;">
<p style="margin: 0; color: #666;">
<strong>Note:</strong> This tool is designed for research and awareness purposes.
For minimum 15 words required for reliable predictions.
</p>
</div>
""")
return iface
if __name__ == "__main__":
app = create_interface()
app.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)