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()