Spaces:
Running
Running
| import pandas as pd | |
| from geopy.geocoders import Nominatim | |
| from geopy.distance import geodesic | |
| import requests | |
| import gradio as gr | |
| import os | |
| # 🔐 Your OpenRouter API Key (keep this secret) | |
| OPENROUTER_API_KEY = os.getenv('OPENROUTER_API_KEY') | |
| # 📂 Load your accident dataset | |
| df = pd.read_csv("final_merged.csv") # Replace with your file | |
| # 🌐 Get coordinates for user location | |
| def geocode_location(location_name): | |
| geolocator = Nominatim(user_agent="accident-warning-system") | |
| location = geolocator.geocode(location_name) | |
| return (location.latitude, location.longitude) if location else None | |
| # 📍 Find nearest accident locations | |
| def find_nearest_accidents(user_latlon, df, top_n=10): | |
| df['DISTANCE'] = df.apply( | |
| lambda row: geodesic(user_latlon, (row['LATITUDE'], row['LONGITUDE'])).meters, axis=1) | |
| return df.sort_values('DISTANCE').head(top_n) | |
| # 🧪 Filter by atmospheric and road condition | |
| def filter_by_conditions(df, atmosphere, road_condition): | |
| return df[ | |
| df['ATMOSPH_COND_DESC'].str.contains(atmosphere, case=False, na=False) & | |
| df['SURFACE_COND_DESC'].str.contains(road_condition, case=False, na=False) | |
| ] | |
| # 📊 Summarize accident data | |
| def summarize_data(df): | |
| return { | |
| "total_accidents": len(df), | |
| "severe_accidents": (df["SEVERITY"] == "Serious").sum(), | |
| "fatalities": int(df["NO_PERSONS_KILLED"].sum()), | |
| "common_types": df["ACCIDENT_TYPE_DESC"].value_counts().head(3).to_dict(), | |
| "age_groups": df["AGE_GROUP"].value_counts().head(2).to_dict(), | |
| "user_types": df["ROAD_USER_TYPE"].value_counts().head(2).to_dict() | |
| } | |
| # 🧾 Format readable summary | |
| def format_summary(summary, location, atmosphere, road_condition): | |
| return ( | |
| f"📍 Location: {location}\n" | |
| f"🌦️ Atmosphere: {atmosphere}\n" | |
| f"🛣️ Road Condition: {road_condition}\n\n" | |
| f"🚧 Accidents Nearby: {summary['total_accidents']}\n" | |
| f"❗ Severe Accidents: {summary['severe_accidents']}\n" | |
| f"☠️ Fatalities: {summary['fatalities']}\n" | |
| f"🔁 Common Accident Types: {', '.join(summary['common_types'].keys())}\n" | |
| f"👥 Age Groups Involved: {', '.join(summary['age_groups'].keys())}\n" | |
| f"🚶♂️ User Types Affected: {', '.join(summary['user_types'].keys())}\n" | |
| ) | |
| # 💬 Generate LLM warning | |
| def get_llm_warning(summary, location, atmosphere, road_condition): | |
| prompt = f""" | |
| A driver is traveling to "{location}" during "{atmosphere}" weather and "{road_condition}" road conditions. | |
| Nearby accident statistics: | |
| - Total accidents: {summary['total_accidents']} | |
| - Severe: {summary['severe_accidents']} | |
| - Fatalities: {summary['fatalities']} | |
| - Common types: {summary['common_types']} | |
| - Age groups involved: {summary['age_groups']} | |
| - Road users involved: {summary['user_types']} | |
| Give a short safety warning with practical advice based on this data. | |
| """ | |
| headers = { | |
| "Authorization": f"Bearer {OPENROUTER_API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| payload = { | |
| "model": "openai/gpt-3.5-turbo", | |
| "messages": [{"role": "user", "content": prompt}] | |
| } | |
| try: | |
| response = requests.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload) | |
| if response.status_code == 200: | |
| return response.json()['choices'][0]['message']['content'] | |
| else: | |
| return f"⚠️ LLM Error: {response.status_code} - {response.text}" | |
| except Exception as e: | |
| return f"⚠️ Request failed: {e}" | |
| # 🤖 Gradio function | |
| def advisory_bot(location, atmosphere, road_condition): | |
| coords = geocode_location(location) | |
| if not coords: | |
| return "❌ Could not find the specified location.", "" | |
| nearest_df = find_nearest_accidents(coords, df) | |
| filtered_df = filter_by_conditions(nearest_df, atmosphere, road_condition) | |
| if filtered_df.empty: | |
| return f"⚠️ No recent accident data found near '{location}' for these conditions.", "" | |
| summary = summarize_data(filtered_df) | |
| summary_text = format_summary(summary, location, atmosphere, road_condition) | |
| llm_warning = get_llm_warning(summary, location, atmosphere, road_condition) | |
| return summary_text, llm_warning | |
| # 🎛️ Gradio UI | |
| gr.Interface( | |
| fn=advisory_bot, | |
| inputs=[ | |
| gr.Textbox(label="📍 Location (e.g., Plenty Road, Melbourne)"), | |
| gr.Textbox(label="🌦️ Atmosphere (e.g., Rain, Fog, Clear)"), | |
| gr.Textbox(label="🛣️ Road Condition (e.g., Wet, Dry)") | |
| ], | |
| outputs=[ | |
| gr.Textbox(label="📊 Accident Summary"), | |
| gr.Textbox(label="🛑 Safety Warning") | |
| ], | |
| title="🚧 Accident Risk Advisory", | |
| description="Input a location, weather, and road condition to get a data-based accident summary and safety warning." | |
| ).launch() | |