File size: 4,979 Bytes
da254ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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()