Spaces:
Running
Running
Upload 2 files
Browse files- app.py +122 -0
- requirements.txt +4 -0
app.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from geopy.geocoders import Nominatim
|
| 3 |
+
from geopy.distance import geodesic
|
| 4 |
+
import requests
|
| 5 |
+
import gradio as gr
|
| 6 |
+
import os
|
| 7 |
+
|
| 8 |
+
# 🔐 Your OpenRouter API Key (keep this secret)
|
| 9 |
+
OPENROUTER_API_KEY = os.getenv('OPENROUTER_API_KEY')
|
| 10 |
+
|
| 11 |
+
# 📂 Load your accident dataset
|
| 12 |
+
df = pd.read_csv("final_merged.csv") # Replace with your file
|
| 13 |
+
|
| 14 |
+
# 🌐 Get coordinates for user location
|
| 15 |
+
def geocode_location(location_name):
|
| 16 |
+
geolocator = Nominatim(user_agent="accident-warning-system")
|
| 17 |
+
location = geolocator.geocode(location_name)
|
| 18 |
+
return (location.latitude, location.longitude) if location else None
|
| 19 |
+
|
| 20 |
+
# 📍 Find nearest accident locations
|
| 21 |
+
def find_nearest_accidents(user_latlon, df, top_n=10):
|
| 22 |
+
df['DISTANCE'] = df.apply(
|
| 23 |
+
lambda row: geodesic(user_latlon, (row['LATITUDE'], row['LONGITUDE'])).meters, axis=1)
|
| 24 |
+
return df.sort_values('DISTANCE').head(top_n)
|
| 25 |
+
|
| 26 |
+
# 🧪 Filter by atmospheric and road condition
|
| 27 |
+
def filter_by_conditions(df, atmosphere, road_condition):
|
| 28 |
+
return df[
|
| 29 |
+
df['ATMOSPH_COND_DESC'].str.contains(atmosphere, case=False, na=False) &
|
| 30 |
+
df['SURFACE_COND_DESC'].str.contains(road_condition, case=False, na=False)
|
| 31 |
+
]
|
| 32 |
+
|
| 33 |
+
# 📊 Summarize accident data
|
| 34 |
+
def summarize_data(df):
|
| 35 |
+
return {
|
| 36 |
+
"total_accidents": len(df),
|
| 37 |
+
"severe_accidents": (df["SEVERITY"] == "Serious").sum(),
|
| 38 |
+
"fatalities": int(df["NO_PERSONS_KILLED"].sum()),
|
| 39 |
+
"common_types": df["ACCIDENT_TYPE_DESC"].value_counts().head(3).to_dict(),
|
| 40 |
+
"age_groups": df["AGE_GROUP"].value_counts().head(2).to_dict(),
|
| 41 |
+
"user_types": df["ROAD_USER_TYPE"].value_counts().head(2).to_dict()
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
# 🧾 Format readable summary
|
| 45 |
+
def format_summary(summary, location, atmosphere, road_condition):
|
| 46 |
+
return (
|
| 47 |
+
f"📍 Location: {location}\n"
|
| 48 |
+
f"🌦️ Atmosphere: {atmosphere}\n"
|
| 49 |
+
f"🛣️ Road Condition: {road_condition}\n\n"
|
| 50 |
+
f"🚧 Accidents Nearby: {summary['total_accidents']}\n"
|
| 51 |
+
f"❗ Severe Accidents: {summary['severe_accidents']}\n"
|
| 52 |
+
f"☠️ Fatalities: {summary['fatalities']}\n"
|
| 53 |
+
f"🔁 Common Accident Types: {', '.join(summary['common_types'].keys())}\n"
|
| 54 |
+
f"👥 Age Groups Involved: {', '.join(summary['age_groups'].keys())}\n"
|
| 55 |
+
f"🚶♂️ User Types Affected: {', '.join(summary['user_types'].keys())}\n"
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
# 💬 Generate LLM warning
|
| 59 |
+
def get_llm_warning(summary, location, atmosphere, road_condition):
|
| 60 |
+
prompt = f"""
|
| 61 |
+
A driver is traveling to "{location}" during "{atmosphere}" weather and "{road_condition}" road conditions.
|
| 62 |
+
|
| 63 |
+
Nearby accident statistics:
|
| 64 |
+
- Total accidents: {summary['total_accidents']}
|
| 65 |
+
- Severe: {summary['severe_accidents']}
|
| 66 |
+
- Fatalities: {summary['fatalities']}
|
| 67 |
+
- Common types: {summary['common_types']}
|
| 68 |
+
- Age groups involved: {summary['age_groups']}
|
| 69 |
+
- Road users involved: {summary['user_types']}
|
| 70 |
+
|
| 71 |
+
Give a short safety warning with practical advice based on this data.
|
| 72 |
+
"""
|
| 73 |
+
headers = {
|
| 74 |
+
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
|
| 75 |
+
"Content-Type": "application/json"
|
| 76 |
+
}
|
| 77 |
+
payload = {
|
| 78 |
+
"model": "openai/gpt-3.5-turbo",
|
| 79 |
+
"messages": [{"role": "user", "content": prompt}]
|
| 80 |
+
}
|
| 81 |
+
try:
|
| 82 |
+
response = requests.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload)
|
| 83 |
+
if response.status_code == 200:
|
| 84 |
+
return response.json()['choices'][0]['message']['content']
|
| 85 |
+
else:
|
| 86 |
+
return f"⚠️ LLM Error: {response.status_code} - {response.text}"
|
| 87 |
+
except Exception as e:
|
| 88 |
+
return f"⚠️ Request failed: {e}"
|
| 89 |
+
|
| 90 |
+
# 🤖 Gradio function
|
| 91 |
+
def advisory_bot(location, atmosphere, road_condition):
|
| 92 |
+
coords = geocode_location(location)
|
| 93 |
+
if not coords:
|
| 94 |
+
return "❌ Could not find the specified location.", ""
|
| 95 |
+
|
| 96 |
+
nearest_df = find_nearest_accidents(coords, df)
|
| 97 |
+
filtered_df = filter_by_conditions(nearest_df, atmosphere, road_condition)
|
| 98 |
+
|
| 99 |
+
if filtered_df.empty:
|
| 100 |
+
return f"⚠️ No recent accident data found near '{location}' for these conditions.", ""
|
| 101 |
+
|
| 102 |
+
summary = summarize_data(filtered_df)
|
| 103 |
+
summary_text = format_summary(summary, location, atmosphere, road_condition)
|
| 104 |
+
llm_warning = get_llm_warning(summary, location, atmosphere, road_condition)
|
| 105 |
+
|
| 106 |
+
return summary_text, llm_warning
|
| 107 |
+
|
| 108 |
+
# 🎛️ Gradio UI
|
| 109 |
+
gr.Interface(
|
| 110 |
+
fn=advisory_bot,
|
| 111 |
+
inputs=[
|
| 112 |
+
gr.Textbox(label="📍 Location (e.g., Plenty Road, Melbourne)"),
|
| 113 |
+
gr.Textbox(label="🌦️ Atmosphere (e.g., Rain, Fog, Clear)"),
|
| 114 |
+
gr.Textbox(label="🛣️ Road Condition (e.g., Wet, Dry)")
|
| 115 |
+
],
|
| 116 |
+
outputs=[
|
| 117 |
+
gr.Textbox(label="📊 Accident Summary"),
|
| 118 |
+
gr.Textbox(label="🛑 Safety Warning")
|
| 119 |
+
],
|
| 120 |
+
title="🚧 Accident Risk Advisory",
|
| 121 |
+
description="Input a location, weather, and road condition to get a data-based accident summary and safety warning."
|
| 122 |
+
).launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pandas
|
| 2 |
+
geopy
|
| 3 |
+
gradio
|
| 4 |
+
requests
|