Spaces:
Sleeping
Sleeping
File size: 10,917 Bytes
1109b1e 6b8b942 1109b1e dcbbbea 1109b1e 43f6120 1109b1e 6b8b942 1109b1e 8013dad 1109b1e dcbbbea 1109b1e f576150 dcbbbea 1109b1e 72ad95a 1109b1e dcbbbea 1109b1e 528d02a 1109b1e 528d02a 1109b1e 7ad0c80 528d02a 1109b1e dcbbbea 1109b1e 43f6120 72ad95a 43f6120 72ad95a 43f6120 72ad95a 43f6120 72ad95a 43f6120 72ad95a 43f6120 72ad95a 43f6120 72ad95a 43f6120 72ad95a 43f6120 1109b1e 43f6120 1109b1e 43f6120 1109b1e 528d02a 43f6120 1109b1e 528d02a 1109b1e 43f6120 1109b1e 43f6120 ba3a178 1109b1e b9d0416 528d02a b9d0416 43f6120 1109b1e 528d02a |
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 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
import os
import gradio as gr
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.tools import tool
from langchain.pydantic_v1 import BaseModel, Field
import requests
from datetime import datetime
from typing import List
from langchain.tools import Tool
from langchain.prompts import ChatPromptTemplate
from langchain.output_parsers import PydanticOutputParser
from langchain.memory import ConversationBufferMemory
from langchain.agents import AgentExecutor, create_tool_calling_agent
import uuid
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
import gradio as gr
load_dotenv(dotenv_path='api.env.txt')
Langchain_API_KEY = os.getenv('LANGCHAIN_API')
GOOGLE_API_KEY = os.getenv('GOOGLE_API')
WEATHER_API_KEY = os.getenv('WEATHER_API')
os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY
llm = ChatGoogleGenerativeAI(
model="gemini-1.5-flash",
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2,
)
def get_location_from_ip():
ip =requests.get('https://api.ipify.org?format=json').json()['ip']
response = requests.get(f"https://ipapi.co/{ip}/json/").json()
return {
'city': response.get('city'),
'latitude': response.get('latitude'),
'longitude': response.get('longitude')
}
class WeatherInput(BaseModel):
city: str = Field(default=None, description="The city to get the weather for.")
@tool("get_weather_by_location", args_schema=WeatherInput, return_direct=True)
def get_weather_by_location(city: str = None):
"""Get the weather based on the user's location if no city is specified."""
if not city:
location = get_location_from_ip()
city = location['city']
url = f"https://api.tomorrow.io/v4/timelines?apikey={WEATHER_API_KEY}"
payload = {
"location": city,
"fields": ["temperature", "humidity", "windSpeed"],
"units": "metric",
"timesteps": ["1d"],
"startTime": "now",
"endTime": "nowPlus5d",
"timezone": "auto"
}
headers = {
"accept": "application/json",
"content-type": "application/json"
}
response = requests.post(url, json=payload, headers=headers).json()
return format_weather_response(response, city)
def format_weather_response(weather_data, city):
"""Format the weather data into a readable string."""
intervals = weather_data['data']['timelines'][0]['intervals']
response = f"Weather forecast for {city}:\n\n"
for interval in intervals:
date = datetime.fromisoformat(interval['startTime']).strftime("%A, %B %d")
temp = round(interval['values']['temperature'], 1)
humidity = round(interval['values']['humidity'], 1)
wind_speed = round(interval['values']['windSpeed'], 1)
response += f"{date}:\n"
response += f" Temperature: {temp}°C\n"
response += f" Humidity: {humidity}%\n"
response += f" Wind Speed: {wind_speed * 3.6:.1f} km/h\n\n"
return response
get_weather_tool = Tool(
name="get_weather_by_location",
func=get_weather_by_location,
description="Get the current weather for a specific location. If no location is provided, it will return the weather for the current location."
)
class DailyWeather(BaseModel):
date: str
temperature: float
condition: str
humidity: float
wind_speed: float
advice: str
class WeatherOutput(BaseModel):
location: str = Field(description="The location or the city for which the weather is reported")
forecast: List[DailyWeather] = Field(description="The weather forecast for multiple days")
parser = PydanticOutputParser(pydantic_object=WeatherOutput)
prompt = ChatPromptTemplate.from_messages([
("system", """You are WeatherWise, a highly knowledgeable, friendly, and efficient weather assistant. Your primary mission is to provide comprehensive and accurate weather information for cities worldwide, while offering personalized advice tailored to the weather conditions. Approach each interaction with warmth and enthusiasm, as if you're chatting with a good friend about their day. Follow these detailed instructions:
1. **Warm Welcome**: Begin each conversation with a friendly greeting, mentioning the current time of day (e.g., "Good morning!" or "Good evening!") to add a personal touch.
2. **City-Specific Requests**:
- When a user mentions a specific city, immediately use the get_weather_by_location tool to fetch weather data for today and the next few days.
- Always include the city's name in your response for clarity, and express enthusiasm about the location (e.g., "Ah, lovely Paris! Let's see what the weather has in store for the City of Light.").
3. **Current Location Assumption**:
- If a user asks about the weather without mentioning a city (e.g., "What's the weather like today?"), assume they're asking about their current location and take action: Use the get_weather_by_location tool with an empty string.
- Use the get_weather_by_location tool with an empty string as input to retrieve local weather information.
If a user asks about the weather without mentioning a specific city, assume they're asking about their current location. This applies to various phrasings such as:
"What's the weather like today?"
"How's the weather?"
"Will it rain this week?"
"Should I bring a jacket?"
"Is it sunny outside?"
"What's the temperature right now?"
"Any chance of snow soon?"
"Will it be windy later?"
"What's the forecast for the weekend?"
"Is it a good day for outdoor activities?"
In all these cases, use the get_weather_by_location tool with an empty string as input to retrieve local weather information based on the user's current location.
4. **Data Presentation**:
- Use the format_weather tool to present information in a clear, concise, and visually appealing format.
- Include essential details such as temperature (in both Celsius and Fahrenheit), precipitation chance, humidity, wind speed and direction, and overall weather conditions.
- For multi-day forecasts, present a brief overview followed by day-by-day breakdowns.
5. **Personalized Advice**:
Offer tailored, friendly advice based on the weather conditions for each day:
- **Sunny**: "It's a beautiful day! Perfect for a picnic in the park or exploring the city. Don't forget your sunscreen and shades!"
- **Rainy**: "Looks like a cozy day indoors or a chance to splash in puddles! Keep an umbrella handy and maybe curl up with a good book later."
- **Cold**: "Brr! Time to bundle up in your favorite warm layers. How about making some hot cocoa and enjoying the crisp air on a short walk?"
- **Hot**: "Whew, it's a scorcher! Stay cool with light, breathable clothing and plenty of water. Maybe treat yourself to some ice cream?"
6. **Clarifications**:
If the user's request is ambiguous, ask for clarification in a friendly manner:
- "I'd love to help! Could you please specify which city you're curious about?"
- "Just to make sure I give you the most accurate info, which day of the week are you most interested in?"
7. **Avoid Repetition**:
- Keep track of the conversation history to provide context-aware responses.
- If repeating information, frame it as a helpful reminder (e.g., "As I mentioned earlier, but it's worth repeating because it's important...").
8. **Handling Follow-ups**:
- Anticipate potential follow-up questions and offer to provide more details proactively.
- For example: "I've given you an overview, but if you'd like more details about a specific day or any particular weather aspect, just ask!"
9. **Friendly and Informative Tone**:
- Use a conversational, upbeat tone as if chatting with a friend.
- Incorporate weather-related expressions or puns to add a touch of humor when appropriate.
- Show empathy for less-than-ideal weather conditions (e.g., "I know rainy days can be a bummer, but think of how happy the plants are!").
10. **Local Insights**:
- When possible, offer brief, relevant insights about the location in relation to the weather (e.g., "Did you know Paris is actually quite lovely in the rain? It's when the city truly earns its nickname 'City of Light' with all the reflections!").
11. **Closing**:
- End each interaction on a positive note, offering to help with any other weather-related questions.
- Wish the user well based on the forecast (e.g., "Enjoy the sunshine!" or "Stay dry out there!").
Always prioritize accuracy and clarity while maintaining a warm, friendly demeanor. Your goal is to make talking about the weather as enjoyable and helpful as possible!"""),
("human", "{input}"),
("ai", "Good day! I'm WeatherWise, your friendly neighborhood weather expert. I'm excited to help you plan your days with pinpoint weather forecasts and some cheerful advice to boot. What would you like to know about the weather? Whether it's for your location or anywhere around the globe, I'm all ears!"),
("human", "{input}"),
("ai", "Absolutely! I'm thrilled to help you with that. Let me fetch the latest weather information and whip up some tailored advice just for you. Give me just a moment while I consult my meteorological crystal ball!"),
("placeholder", "{agent_scratchpad}"),
])
tools = [get_weather_tool]
message_history = ChatMessageHistory()
agent = create_tool_calling_agent(llm, tools, prompt=prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
output_parser=parser
)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: message_history,
input_messages_key="input",
history_messages_key="chat_history",
)
session_ids = {}
def gradio_interface(user_input, session_id):
# If session_id is not in session_ids, it's a new session
if session_id not in session_ids:
# Generate a new unique session ID
new_session_id = str(uuid.uuid4())
session_ids[session_id] = new_session_id
else:
new_session_id = session_ids[session_id]
result = agent_with_chat_history.invoke(
{"input": user_input},
config={"configurable": {"session_id": new_session_id}}
)
return [[user_input, result['output']]]
with gr.Blocks() as demo:
gr.Markdown("# Weather Assistant")
chatbot = gr.Chatbot()
with gr.Row():
txt = gr.Textbox(
show_label=False,
placeholder="Ask about the weather...",
lines=1,
container=False
)
session_id_box = gr.Textbox(visible=False, value=str(uuid.uuid4()))
txt.submit(gradio_interface, inputs=[txt, session_id_box], outputs=chatbot)
demo.launch(share=True) |