File size: 10,520 Bytes
72fa741 f197ef4 72fa741 f197ef4 74b92bb f197ef4 5787f49 f825171 f197ef4 03c760f f197ef4 f825171 f197ef4 80a0142 f197ef4 f825171 f197ef4 f825171 f197ef4 f825171 f197ef4 80a0142 f197ef4 80a0142 f197ef4 f825171 f197ef4 80a0142 f197ef4 80a0142 f197ef4 4ec826f f197ef4 5787f49 4dde19a f197ef4 4dde19a f197ef4 4ec826f f197ef4 f825171 f197ef4 72fa741 f197ef4 f825171 f197ef4 f825171 f197ef4 f825171 f197ef4 73f0497 f197ef4 73f0497 f197ef4 72fa741 f825171 f197ef4 f825171 f197ef4 72fa741 f825171 f197ef4 03c760f f197ef4 72fa741 f197ef4 72fa741 f825171 f197ef4 f825171 f197ef4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
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
) |