VatsalPatel18 commited on
Commit
de6500f
1 Parent(s): 69ee1ea

Upload 6 files

Browse files
Files changed (6) hide show
  1. Dockerfile +50 -0
  2. app.py +101 -0
  3. download_model.py +15 -0
  4. functions.py +280 -0
  5. requirements.txt +8 -0
  6. style.css +11 -0
Dockerfile ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Python image as a base image
2
+ FROM python:3.11-slim
3
+
4
+ # Set environment variables
5
+ ENV PYTHONUNBUFFERED=1 \
6
+ PYTHONDONTWRITEBYTECODE=1 \
7
+ GRADIO_SERVER_NAME="0.0.0.0" \
8
+ REPO_ID="microsoft/Phi-3-mini-4k-instruct-gguf" \
9
+ MODEL_FILE="Phi-3-mini-4k-instruct-q4.gguf"
10
+
11
+ # Create a working directory
12
+ WORKDIR /app
13
+
14
+ # Install dependencies for building C++ extensions and SSL
15
+ RUN apt-get update && \
16
+ apt-get install -y --no-install-recommends \
17
+ build-essential \
18
+ cmake \
19
+ openssl \
20
+ wget \
21
+ && apt-get clean \
22
+ && rm -rf /var/lib/apt/lists/*
23
+
24
+ # Copy the requirements file
25
+ COPY requirements.txt /app/
26
+
27
+ # Install Python dependencies
28
+ RUN pip install --no-cache-dir -r requirements.txt
29
+
30
+ # Copy SSL certificates
31
+ COPY certificates /app/certificates
32
+
33
+ # Copy the rest of the application code
34
+ COPY . /app/
35
+
36
+ # Create the cache directory with appropriate permissions
37
+ RUN mkdir -p /app/hf_cache && chmod -R 777 /app/hf_cache
38
+
39
+ # Ensure the model is downloaded
40
+ RUN python download_model.py
41
+
42
+ # Expose the port that Gradio will run on
43
+ EXPOSE 7860
44
+
45
+ # Set the user to root
46
+ USER root
47
+
48
+ # Run the application
49
+ CMD ["python", "app.py"]
50
+
app.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from langchain.agents import Tool
4
+ from langchain_community.llms import LlamaCpp
5
+ from langchain.agents import initialize_agent
6
+ from functions import get_weather_info, get_forecast, shutdown
7
+ from huggingface_hub import hf_hub_download
8
+
9
+ # Set custom cache directory
10
+ cache_dir = "/app/hf_cache"
11
+ os.makedirs(cache_dir, exist_ok=True)
12
+
13
+ # Download the model directly in the app
14
+ model_path = hf_hub_download(
15
+ repo_id=os.environ.get("REPO_ID", "microsoft/Phi-3-mini-4k-instruct-gguf"),
16
+ filename=os.environ.get("MODEL_FILE", "Phi-3-mini-4k-instruct-q4.gguf"),
17
+ cache_dir=cache_dir
18
+ )
19
+
20
+ # Initialize the LlamaCpp model
21
+ llm = LlamaCpp(
22
+ model_path=model_path,
23
+ n_ctx=4096,
24
+ n_gpu_layers=-1
25
+ )
26
+
27
+ # Define tools
28
+ weather_tool = Tool(
29
+ name="WeatherLookup",
30
+ func=lambda city: get_weather_info(city),
31
+ description="Useful to get the current weather (Today) information for a city. It includes information on temperature, pressure, humidity, wind, clouds, and rain."
32
+ )
33
+
34
+ forecast_tool = Tool(
35
+ name="ForecastLookup",
36
+ func=lambda city: get_forecast(city),
37
+ description="Useful to get the weather forecast for the next two days for a city. It includes information on temperature, pressure, humidity, wind, clouds, and rain."
38
+ )
39
+
40
+ # Tools (Include both Weather and Forecast Tools)
41
+ tools = [weather_tool, forecast_tool]
42
+
43
+ # Initialize Agent
44
+ agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)
45
+
46
+ def respond(message, history):
47
+ try:
48
+ # Create the prompt based on the history
49
+ prompt = "\n".join([f"{'User' if i % 2 == 0 else 'Assistant'}: {m[0]}" for i, m in enumerate(history)]) + "\nAssistant:"
50
+
51
+ # Generate response using LangChain agent
52
+ response = agent.run(message)
53
+
54
+ # Update history with the assistant's response
55
+ history.append((message, response))
56
+
57
+ return response, history
58
+ except Exception as e:
59
+ return f"An error occurred: {e}", history
60
+
61
+ # Define the Gradio interface
62
+ with gr.Blocks(css="style.css") as demo:
63
+ gr.Markdown(
64
+ """
65
+ # Weather Chatbot
66
+ Get real-time weather forecasts or chat with our assistant. Type your queries in natural language.
67
+ """
68
+ )
69
+ with gr.Row():
70
+ with gr.Column():
71
+ message = gr.Textbox(label="Ask a weather question or chat with the assistant", lines=2, placeholder="Type your question here...")
72
+ response = gr.Textbox(label="Response", lines=2)
73
+ state = gr.State([])
74
+ btn = gr.Button("Submit")
75
+ btn.click(respond, [message, state], [response, state])
76
+ shutdown_btn = gr.Button("Shutdown")
77
+ shutdown_btn.click(shutdown, [], response)
78
+
79
+ gr.Examples(
80
+ examples=[
81
+ ["What's the weather in New York?"],
82
+ ["Tell me the weather forecast for Tokyo."],
83
+ ["What's the temperature in London?"]
84
+ ],
85
+ inputs=message
86
+ )
87
+
88
+ # Launch the Gradio interface
89
+ def main():
90
+ demo.launch(
91
+ server_name="0.0.0.0",
92
+ server_port=7860,
93
+ ssl_keyfile="/app/certificates/selfsigned.key",
94
+ ssl_certfile="/app/certificates/selfsigned.crt",
95
+ ssl_verify=False, # Disable SSL verification for development
96
+ share=True,
97
+ )
98
+
99
+ if __name__ == "__main__":
100
+ main()
101
+
download_model.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from huggingface_hub import hf_hub_download
3
+
4
+ def download_model():
5
+ model_path = "./model/phi-3-gguf/Phi-3-mini-4k-instruct-q4.gguf"
6
+ if not os.path.exists(model_path):
7
+ hf_hub_download(
8
+ repo_id="microsoft/Phi-3-mini-4k-instruct-gguf",
9
+ filename="Phi-3-mini-4k-instruct-q4.gguf",
10
+ local_dir="model/phi-3-gguf"
11
+ )
12
+
13
+ if __name__ == "__main__":
14
+ download_model()
15
+
functions.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from collections import defaultdict
3
+ from datetime import datetime, timedelta
4
+ import json
5
+ import pandas as pd
6
+ import threading
7
+ import time
8
+ import os
9
+ import signal
10
+
11
+ api_key = "c6dfc4d92a8f972d237ef696ec87b37a"
12
+
13
+ def shutdown():
14
+ # Wait a bit before shutdown to allow the response to be returned
15
+ def stop():
16
+ time.sleep(1)
17
+ os.kill(os.getpid(), signal.SIGTERM) # Send SIGTERM to the current process to stop Gradio
18
+ os._exit(0)
19
+ threading.Thread(target=stop).start()
20
+ return "Shutting down and closing the Gradio window..."
21
+
22
+ def get_weather_info(city):
23
+ """Fetches current weather information for a city using OpenWeatherMap API."""
24
+
25
+ url_current = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
26
+ response_current = requests.get(url_current)
27
+ if response_current.status_code != 200:
28
+ return "Error: Could not fetch weather data."
29
+ data_current = response_current.json()
30
+
31
+ weather_description = data_current['weather'][0]['description']
32
+ temperature_current = data_current['main']['temp']
33
+ temperature_feels_like = data_current['main']['feels_like']
34
+ temperature_min = data_current['main']['temp_min']
35
+ temperature_max = data_current['main']['temp_max']
36
+ pressure_sea_level = data_current['main'].get('sea_level', data_current['main']['pressure'])
37
+ pressure_ground_level = data_current['main'].get('grnd_level', data_current['main']['pressure'])
38
+ humidity = data_current['main']['humidity']
39
+ visibility = data_current['visibility']
40
+ wind_speed = data_current['wind']['speed']
41
+ wind_deg = data_current['wind']['deg']
42
+ clouds = data_current['clouds']['all']
43
+ rain = data_current.get('rain', {}).get('1h', 0)
44
+ dt = datetime.utcfromtimestamp(data_current['dt']).strftime('%Y-%m-%d %H:%M:%S')
45
+ timezone = data_current['timezone']
46
+ city_name = data_current['name']
47
+ response_code = data_current['cod']
48
+
49
+ formatted_info = (
50
+ f"Weather: {weather_description}, "
51
+ f"Temperature: current {temperature_current}°C, feels like {temperature_feels_like}°C, min {temperature_min}°C, max {temperature_max}°C, "
52
+ f"Pressure: sea level {pressure_sea_level} hPa, ground level {pressure_ground_level} hPa, "
53
+ f"Humidity: {humidity}%, "
54
+ f"Visibility: {visibility} meters, "
55
+ f"Wind: speed {wind_speed} m/s, deg {wind_deg}, "
56
+ f"Clouds: {clouds}%, "
57
+ f"Rain: {rain} mm, "
58
+ f"Date/Time: {dt}, "
59
+ f"Timezone: {timezone} seconds, "
60
+ f"City Name: {city_name}, "
61
+ f"Response Code: {response_code}"
62
+ )
63
+
64
+ return formatted_info
65
+
66
+ def get_forecast(city):
67
+ """Fetches 2-day weather forecast for a city using OpenWeatherMap API and restructures the data into a table format."""
68
+ url_forecast = f"http://api.openweathermap.org/data/2.5/forecast?q={city}&appid={api_key}&units=metric"
69
+ response_forecast = requests.get(url_forecast)
70
+ if response_forecast.status_code != 200:
71
+ return "Error: Could not fetch forecast data."
72
+ forecast_json = response_forecast.json()
73
+
74
+ current_date = datetime.now().date()
75
+ forecast_dates = [current_date + timedelta(days=i) for i in range(1, 3)]
76
+ important_hours = ['09:00:00', '15:00:00', '21:00:00']
77
+
78
+ data = []
79
+
80
+ for entry in forecast_json['list']:
81
+ date, time = entry['dt_txt'].split()
82
+ date_obj = datetime.strptime(date, '%Y-%m-%d').date()
83
+ if date_obj in forecast_dates and time in important_hours:
84
+ data.append({
85
+ 'Date': date,
86
+ 'Time': time,
87
+ 'Temperature': entry['main']['temp'],
88
+ 'Feels Like': entry['main']['feels_like'],
89
+ 'Temp Min': entry['main']['temp_min'],
90
+ 'Temp Max': entry['main']['temp_max'],
91
+ 'Pressure': entry['main']['pressure'],
92
+ 'Humidity': entry['main']['humidity'],
93
+ 'Weather': entry['weather'][0]['description'],
94
+ 'Icon': entry['weather'][0]['icon'],
95
+ 'Wind Speed': entry['wind']['speed'],
96
+ 'Wind Deg': entry['wind']['deg'],
97
+ 'Visibility': entry['visibility'],
98
+ 'Pop': entry['pop'],
99
+ 'Rain': entry['rain']['3h'] if 'rain' in entry else 0,
100
+ 'Clouds': entry['clouds']['all']
101
+ })
102
+
103
+ df = pd.DataFrame(data)
104
+ df.set_index(['Date', 'Time'], inplace=True)
105
+ return df
106
+
107
+ def restructure_forecast_00(forecast_json):
108
+ """Restructures the forecast JSON data into a single-line sentence format."""
109
+ current_date = datetime.now().date()
110
+ forecast_dates = [current_date + timedelta(days=i) for i in range(1, 3)]
111
+ important_hours = ['09:00:00', '12:00:00', '15:00:00', '18:00:00', '21:00:00']
112
+
113
+ structured_data = defaultdict(dict)
114
+
115
+ for entry in forecast_json['list']:
116
+ date, time = entry['dt_txt'].split()
117
+ date_obj = datetime.strptime(date, '%Y-%m-%d').date()
118
+ if date_obj in forecast_dates and time in important_hours:
119
+ structured_data[date][time] = {
120
+ 'temperature': entry['main']['temp'],
121
+ 'feels like': entry['main']['feels_like'],
122
+ 'temp min': entry['main']['temp_min'],
123
+ 'temp max': entry['main']['temp_max'],
124
+ 'pressure': entry['main']['pressure'],
125
+ 'humidity': entry['main']['humidity'],
126
+ 'weather': entry['weather'][0]['description'],
127
+ 'icon': entry['weather'][0]['icon'],
128
+ 'wind speed': entry['wind']['speed'],
129
+ 'wind deg': entry['wind']['deg'],
130
+ 'visibility': entry['visibility'],
131
+ 'pop': entry['pop'],
132
+ 'rain': entry['rain']['3h'] if 'rain' in entry else 0,
133
+ 'clouds': entry['clouds']['all']
134
+ }
135
+
136
+ return format_forecast(structured_data, forecast_dates)
137
+
138
+ def format_forecast_00(structured_data, forecast_dates):
139
+ """Formats the structured forecast data into a single-line sentence format."""
140
+ formatted_forecast = []
141
+ for date in forecast_dates:
142
+ date_str = str(date)
143
+ for time, data in structured_data[date_str].items():
144
+ formatted_forecast.append(
145
+ f"{date_str} : {time} ( " +
146
+ ", ".join(f"{key} - {value}" for key, value in data.items()) +
147
+ " )"
148
+ )
149
+ return "\n".join(formatted_forecast)
150
+
151
+
152
+ def restructure_forecast2(forecast_json):
153
+ """Restructures the forecast JSON data into a nested dictionary by date and time, including the next three days."""
154
+ current_date = datetime.now().date()
155
+ forecast_dates = [current_date + timedelta(days=i) for i in range(1, 3)]
156
+
157
+ structured_data = defaultdict(dict)
158
+
159
+ for entry in forecast_json['list']:
160
+ date, time = entry['dt_txt'].split()
161
+ date_obj = datetime.strptime(date, '%Y-%m-%d').date()
162
+ if date_obj in forecast_dates:
163
+ structured_data[date][time] = {
164
+ 'temperature': entry['main']['temp'],
165
+ 'feels_like': entry['main']['feels_like'],
166
+ 'temp_min': entry['main']['temp_min'],
167
+ 'temp_max': entry['main']['temp_max'],
168
+ 'pressure': entry['main']['pressure'],
169
+ 'humidity': entry['main']['humidity'],
170
+ 'weather': entry['weather'][0]['description'],
171
+ 'icon': entry['weather'][0]['icon'],
172
+ 'wind_speed': entry['wind']['speed'],
173
+ 'wind_deg': entry['wind']['deg'],
174
+ 'visibility': entry['visibility'],
175
+ 'pop': entry['pop'],
176
+ 'rain': entry['rain']['3h'] if 'rain' in entry else 0,
177
+ 'clouds': entry['clouds']['all']
178
+ }
179
+
180
+ return {str(date): structured_data[str(date)] for date in forecast_dates}
181
+
182
+ def restructure_forecast_0(forecast_json):
183
+ """Restructures the forecast JSON data into a nested dictionary by date and specific times."""
184
+ current_date = datetime.now().date()
185
+ forecast_dates = [current_date + timedelta(days=i) for i in range(1, 3)]
186
+ important_hours = ['09:00:00', '12:00:00', '15:00:00', '18:00:00', '21:00:00']
187
+
188
+ structured_data = defaultdict(dict)
189
+
190
+ for entry in forecast_json['list']:
191
+ date, time = entry['dt_txt'].split()
192
+ date_obj = datetime.strptime(date, '%Y-%m-%d').date()
193
+ if date_obj in forecast_dates and time in important_hours:
194
+ structured_data[date][time] = {
195
+ 'temperature': entry['main']['temp'],
196
+ 'feels_like': entry['main']['feels_like'],
197
+ 'temp_min': entry['main']['temp_min'],
198
+ 'temp_max': entry['main']['temp_max'],
199
+ 'pressure': entry['main']['pressure'],
200
+ 'humidity': entry['main']['humidity'],
201
+ 'weather': entry['weather'][0]['description'],
202
+ 'icon': entry['weather'][0]['icon'],
203
+ 'wind_speed': entry['wind']['speed'],
204
+ 'wind_deg': entry['wind']['deg'],
205
+ 'visibility': entry['visibility'],
206
+ 'pop': entry['pop'],
207
+ 'rain': entry['rain']['3h'] if 'rain' in entry else 0,
208
+ 'clouds': entry['clouds']['all']
209
+ }
210
+
211
+ return {str(date): structured_data[str(date)] for date in forecast_dates}
212
+
213
+
214
+ def restructure_forecast3(forecast_json):
215
+ """Restructures the forecast JSON data into a nested dictionary by date and time, including the next three days."""
216
+ current_date = datetime.now().date()
217
+ forecast_dates = [current_date + timedelta(days=i) for i in range(1, 4)]
218
+
219
+ structured_data = defaultdict(dict)
220
+
221
+ for entry in forecast_json['list']:
222
+ date, time = entry['dt_txt'].split()
223
+ date_obj = datetime.strptime(date, '%Y-%m-%d').date()
224
+ if date_obj in forecast_dates:
225
+ structured_data[date][time] = {
226
+ 'temperature': entry['main']['temp'],
227
+ 'feels_like': entry['main']['feels_like'],
228
+ 'temp_min': entry['main']['temp_min'],
229
+ 'temp_max': entry['main']['temp_max'],
230
+ 'pressure': entry['main']['pressure'],
231
+ 'humidity': entry['main']['humidity'],
232
+ 'weather': entry['weather'][0]['description'],
233
+ 'icon': entry['weather'][0]['icon'],
234
+ 'wind_speed': entry['wind']['speed'],
235
+ 'wind_deg': entry['wind']['deg'],
236
+ 'visibility': entry['visibility'],
237
+ 'pop': entry['pop'],
238
+ 'rain': entry['rain']['3h'] if 'rain' in entry else 0,
239
+ 'clouds': entry['clouds']['all']
240
+ }
241
+
242
+ return {str(date): structured_data[str(date)] for date in forecast_dates}
243
+
244
+
245
+ def get_weather_info_0(city):
246
+ """Fetches current weather information for a city using OpenWeatherMap API."""
247
+
248
+ url_current = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
249
+ response_current = requests.get(url_current)
250
+ if response_current.status_code != 200:
251
+ return "Error: Could not fetch weather data."
252
+ data_current = response_current.json()
253
+
254
+ response = {
255
+ 'coordinates': data_current['coord'],
256
+ 'weather': data_current['weather'][0],
257
+ 'temperature': {
258
+ 'current': data_current['main']['temp'],
259
+ 'feels_like': data_current['main']['feels_like'],
260
+ 'min': data_current['main']['temp_min'],
261
+ 'max': data_current['main']['temp_max']
262
+ },
263
+ 'pressure': {
264
+ 'sea_level': data_current['main'].get('sea_level', data_current['main']['pressure']),
265
+ 'ground_level': data_current['main'].get('grnd_level', data_current['main']['pressure'])
266
+ },
267
+ 'humidity': data_current['main']['humidity'],
268
+ 'visibility': data_current['visibility'],
269
+ 'wind': data_current['wind'],
270
+ 'clouds': data_current['clouds'],
271
+ 'rain': data_current.get('rain', {}),
272
+ 'dt': data_current['dt'],
273
+ 'sys': data_current['sys'],
274
+ 'timezone': data_current['timezone'],
275
+ 'id': data_current['id'],
276
+ 'name': data_current['name'],
277
+ 'cod': data_current['cod']
278
+ }
279
+
280
+ return json.dumps(response, indent=2)
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ gradio
2
+ pandas
3
+ transformers
4
+ llama-cpp-python
5
+ langchain
6
+ langchain-community
7
+ huggingface_hub
8
+ python-dotenv
style.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ background-color: #f0f4f8;
3
+ }
4
+ .gr-textbox, .gr-output {
5
+ background-color: #ffffff;
6
+ border: 1px solid #e0e7ec;
7
+ }
8
+ .gr-button {
9
+ background-color: #d0d7dc;
10
+ color: #000000;
11
+ }