Spaces:
Sleeping
Sleeping
| import os | |
| import requests | |
| import gradio as gr | |
| from dotenv import load_dotenv | |
| from bs4 import BeautifulSoup | |
| # --------------------------------------------- | |
| # Load environment variables | |
| # --------------------------------------------- | |
| load_dotenv() | |
| GROQ_API_KEY = os.getenv("GROQ_API_KEY") | |
| # --------------------------------------------- | |
| # Static coordinates | |
| # --------------------------------------------- | |
| BEACH_COORDS = { | |
| "marina beach": (13.0500, 80.2824), | |
| "kovalam beach": (8.4000, 76.9780), | |
| "goa beach": (15.2993, 74.1240), | |
| "puri beach": (19.7983, 85.8245) | |
| } | |
| # --------------------------------------------- | |
| # Geocoding | |
| # --------------------------------------------- | |
| def get_coordinates(beach): | |
| try: | |
| r = requests.get( | |
| "https://nominatim.openstreetmap.org/search", | |
| params={"q": f"{beach}, India", "format": "json", "limit": 1}, | |
| headers={"User-Agent": "BeachSafetyBot/1.0"}, | |
| timeout=10 | |
| ).json() | |
| if r: | |
| return float(r[0]["lat"]), float(r[0]["lon"]) | |
| except: | |
| pass | |
| return None, None | |
| # --------------------------------------------- | |
| # Weather | |
| # --------------------------------------------- | |
| def get_weather(lat, lon): | |
| try: | |
| d = requests.get( | |
| f"https://api.open-meteo.com/v1/forecast" | |
| f"?latitude={lat}&longitude={lon}" | |
| "&daily=temperature_2m_max,temperature_2m_min" | |
| "¤t_weather=true&timezone=auto", | |
| timeout=10 | |
| ).json() | |
| return { | |
| "temp": d["current_weather"]["temperature"], | |
| "wind": d["current_weather"]["windspeed"], | |
| "min": d["daily"]["temperature_2m_min"][0], | |
| "max": d["daily"]["temperature_2m_max"][0] | |
| } | |
| except: | |
| return {"temp": "N/A", "wind": "N/A", "min": "N/A", "max": "N/A"} | |
| # --------------------------------------------- | |
| # INCOIS alert | |
| # --------------------------------------------- | |
| def has_alert(): | |
| try: | |
| html = requests.get( | |
| "https://incois.gov.in/portal/tsunami.jsp", | |
| timeout=10 | |
| ).text | |
| return "WARNING" in html.upper() | |
| except: | |
| return False | |
| # --------------------------------------------- | |
| # Safety logic | |
| # --------------------------------------------- | |
| def evaluate(wind, alert, beach): | |
| if alert: | |
| return "NOT SUITABLE", "π΄ RED" | |
| try: | |
| wind = float(wind) | |
| except: | |
| wind = 0 | |
| if wind > 12 or "marina" in beach: | |
| return "CAUTION", "π‘ YELLOW" | |
| return "SUITABLE", "π’ GREEN" | |
| # --------------------------------------------- | |
| # Wikipedia crawl | |
| # --------------------------------------------- | |
| def crawl_beach_details(beach): | |
| details = { | |
| "famous_for": "Scenic coastal destination", | |
| "hotspots": ["Local shoreline"], | |
| "safety_rules": ["Follow local advisories"], | |
| "best_time": "Morning and evening" | |
| } | |
| try: | |
| r = requests.get( | |
| f"https://en.wikipedia.org/wiki/{beach.replace(' ', '_')}", | |
| timeout=10 | |
| ) | |
| soup = BeautifulSoup(r.text, "html.parser") | |
| p = soup.select("p")[:3] | |
| if p: | |
| details["famous_for"] = p[0].get_text().split(".")[0] | |
| except: | |
| pass | |
| return details | |
| # --------------------------------------------- | |
| # Groq AI | |
| # --------------------------------------------- | |
| def groq_rewrite(prompt): | |
| if not GROQ_API_KEY: | |
| return None | |
| try: | |
| r = requests.post( | |
| "https://api.groq.com/openai/v1/chat/completions", | |
| headers={ | |
| "Authorization": f"Bearer {GROQ_API_KEY}", | |
| "Content-Type": "application/json" | |
| }, | |
| json={ | |
| "model": "llama-3.3-70b-versatile", | |
| "messages": [{"role": "user", "content": prompt}], | |
| "max_tokens": 400 | |
| }, | |
| timeout=20 | |
| ) | |
| return r.json()["choices"][0]["message"]["content"] | |
| except: | |
| return None | |
| # --------------------------------------------- | |
| # MAIN FUNCTION (Gradio) | |
| # --------------------------------------------- | |
| def beach_safety(question): | |
| msg = question.lower().strip() | |
| beach = msg if "beach" in msg else f"{msg} beach" | |
| lat, lon = BEACH_COORDS.get(beach, get_coordinates(beach)) | |
| if not lat: | |
| return "β Unable to locate this beach in India." | |
| weather = get_weather(lat, lon) | |
| status, color = evaluate(weather["wind"], has_alert(), beach) | |
| details = crawl_beach_details(beach) | |
| response = f""" | |
| ποΈ **{beach.title()}** | |
| **Status:** {status} ({color}) | |
| π‘οΈ Temp: {weather['temp']}Β°C | |
| π¨ Wind: {weather['wind']} km/h | |
| π **Famous For:** | |
| {details['famous_for']} | |
| π **Best Time:** {details['best_time']} | |
| """ | |
| ai = groq_rewrite(response) | |
| return ai if ai else response | |
| # --------------------------------------------- | |
| # Gradio UI | |
| # --------------------------------------------- | |
| demo = gr.Interface( | |
| fn=beach_safety, | |
| inputs=gr.Textbox( | |
| label="Ask about an Indian beach", | |
| placeholder="Is Marina Beach safe today?" | |
| ), | |
| outputs=gr.Markdown(), | |
| title="ποΈ Beach Safety Assistant", | |
| description="Real-time beach safety, weather & advisories for Indian beaches" | |
| ) | |
| demo.launch() | |