Spaces:
Sleeping
Sleeping
| import os | |
| import json | |
| import requests | |
| import gradio as gr | |
| from openai import OpenAI | |
| # Load API keys from Hugging Face Secrets | |
| OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] | |
| WEATHER_API_KEY = os.environ["WEATHER_API_KEY"] | |
| client = OpenAI(api_key=OPENAI_API_KEY) | |
| # Weather Function | |
| def get_current_weather(location, unit='celsius'): | |
| url = ( | |
| f"http://api.openweathermap.org/data/2.5/weather" | |
| f"?q={location}" | |
| f"&appid={WEATHER_API_KEY}" | |
| f"&units=metric" | |
| ) | |
| response = requests.get(url) | |
| data = response.json() | |
| if response.status_code != 200: | |
| return {"error": data.get("message", "Weather data unavailable")} | |
| return { | |
| "location": location, | |
| "temperature": data["main"]["temp"], | |
| "humidity": data["main"]["humidity"], | |
| "weather": data["weather"][0]["description"] | |
| } | |
| # Chat logic | |
| def weather_chat(user_message): | |
| try: | |
| tools = [ | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "get_current_weather", | |
| "description": "Get current weather information for a city", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "location": {"type": "string", "description": "City name"} | |
| }, | |
| "required": ["location"] | |
| } | |
| } | |
| } | |
| ] | |
| messages = [ | |
| { | |
| "role": "system", | |
| "content": """ | |
| You are a professional weather bot/assistant. | |
| Rules: | |
| - Answer weather-related questions. | |
| - Use Celsius and Fahrenheit only. | |
| - If the question is unrelated to weather, politely decline. | |
| """ | |
| }, | |
| {"role": "user", "content": user_message} | |
| ] | |
| response = client.chat.completions.create( | |
| model="gpt-5-nano", | |
| messages=messages, | |
| tools=tools | |
| ) | |
| assistant_message = response.choices[0].message | |
| if assistant_message.tool_calls: | |
| tool_call = assistant_message.tool_calls[0] | |
| args = json.loads(tool_call.function.arguments) | |
| weather_data = get_current_weather(args["location"]) | |
| messages.append(assistant_message) | |
| messages.append( | |
| { | |
| "role": "tool", | |
| "tool_call_id": tool_call.id, | |
| "content": json.dumps(weather_data) | |
| } | |
| ) | |
| final_response = client.chat.completions.create( | |
| model="gpt-5-nano", | |
| messages=messages | |
| ) | |
| return final_response.choices[0].message.content | |
| else: | |
| return assistant_message.content | |
| except Exception: | |
| return "Hello! I'm here to provide weather updates only. Please ask me questions related to weather." | |
| # ----------------------------- | |
| # Custom Modern Theme + CSS | |
| # ----------------------------- | |
| custom_css = """ | |
| body { | |
| background: linear-gradient(135deg, #0f172a, #1e293b); | |
| } | |
| .gradio-container { | |
| font-family: 'Poppins', sans-serif; | |
| } | |
| .main-title { | |
| text-align: center; | |
| font-size: 52px; | |
| font-weight: 900; | |
| margin-bottom: 15px; | |
| background: linear-gradient( | |
| 90deg, | |
| #ff6b6b, | |
| #feca57, | |
| #48dbfb, | |
| #1dd1a1, | |
| #5f27cd, | |
| #ff9ff3 | |
| ); | |
| background-size: 400% 400%; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: gradientMove 8s ease infinite; | |
| } | |
| @keyframes gradientMove { | |
| 0% { | |
| background-position: 0% 50%; | |
| } | |
| 50% { | |
| background-position: 100% 50%; | |
| } | |
| 100% { | |
| background-position: 0% 50%; | |
| } | |
| } | |
| .sub-title { | |
| text-align: center; | |
| color: #91AC80; | |
| font-size: 18px; | |
| margin-bottom: 25px; | |
| } | |
| .weather-box { | |
| border-radius: 20px; | |
| padding: 20px; | |
| background: rgba(255,255,255,0.08); | |
| backdrop-filter: blur(10px); | |
| box-shadow: 0px 8px 32px rgba(0,0,0,0.3); | |
| } | |
| footer { | |
| visibility: hidden; | |
| } | |
| """ | |
| def respond(message, chat_history): | |
| if not message: | |
| return "", history | |
| response = weather_chat(message) | |
| history.append({"role": "user", "content": message}) | |
| history.append({"role": "assistant", "content": response}) | |
| return "", history | |
| with gr.Blocks() as demo: | |
| gr.HTML( | |
| ''' | |
| <div class="main-title">π¦οΈ SkyMind WeatherAI π€οΈ</div> | |
| <div class="sub-title">Intelligent Real-time Weather Updates Forecast Assistant π</div> | |
| ''' | |
| ) | |
| with gr.Column(elem_classes="weather-card"): | |
| chatbot = gr.Chatbot( | |
| #type="messages", | |
| height=500, | |
| #bubble_full_width=False, | |
| avatar_images=(None, "https://cdn-icons-png.flaticon.com/512/1779/1779940.png"), | |
| allow_tags=False | |
| ) | |
| msg = gr.Textbox( | |
| placeholder="Ask weather like: Weather in Dubai, Mumbai, Shanghai?...", | |
| lines=1, | |
| show_label=False | |
| ) | |
| with gr.Row(): | |
| submit_btn = gr.Button("π Get Weather", variant="primary") | |
| copy_btn = gr.Button("π Copy Answer") | |
| copy_js = """ | |
| function copyToClipboard() { | |
| const messages = document.querySelectorAll('.message.bot'); | |
| if (messages.length > 0) { | |
| const latestMessage = messages[messages.length - 1].innerText; | |
| navigator.clipboard.writeText(latestMessage); | |
| alert("β Weather response copied!"); | |
| } | |
| } | |
| """ | |
| msg.submit(respond, [msg, chatbot], [msg, chatbot]) | |
| submit_btn.click(respond, [msg, chatbot], [msg, chatbot]) | |
| copy_btn.click(None, None, None, js=copy_js) | |
| demo.launch(share=True, css=custom_css, theme=gr.themes.Soft()) | |