ddooling commited on
Commit
6dce12e
·
verified ·
1 Parent(s): b779395

Upload folder using huggingface_hub

Browse files
.ipynb_checkpoints/app-checkpoint.py ADDED
@@ -0,0 +1,747 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dotenv import load_dotenv
2
+ import os
3
+
4
+ # Add these imports
5
+ from threading import Thread
6
+ import queue
7
+ from openai import AssistantEventHandler
8
+ from typing_extensions import override
9
+ import json
10
+
11
+ load_dotenv()
12
+
13
+ import openai
14
+ import time
15
+ import gradio as gr
16
+ from autogen import UserProxyAgent, config_list_from_json
17
+ from datetime import timedelta, datetime
18
+ import pandas as pd
19
+ import numpy as np
20
+ from gradio_datetimerange import DateTimeRange
21
+ import os
22
+ from time import sleep
23
+ from gradio_pdf import PDF
24
+
25
+ from pandasai.llm.openai import OpenAI
26
+ from pandasai import Agent
27
+ import matplotlib.pyplot as plt
28
+ import io
29
+ from pandasai import SmartDataframe
30
+ from collections import Counter
31
+ from gradio_pdf import PDF # Ensure you have installed gradio_pdf
32
+
33
+ from tavily import TavilyClient # Ensure you have installed the tavily library
34
+
35
+
36
+ # llmmodel = OpenAI(api_token=os.environ["OPENAI_API_KEY"], model='gpt-4o')
37
+
38
+
39
+ import requests
40
+
41
+
42
+ # Define the directory containing the PDFs
43
+ PDF_DIR = "usedpdfs" # Replace with your directory path
44
+
45
+ # Define your desired default PDF file
46
+ DEFAULT_PDF = "s41597-024-03770-7.pdf" # Replace with your actual PDF filename
47
+
48
+
49
+
50
+ # Ensure the PDF_DIR exists
51
+ if not os.path.isdir(PDF_DIR):
52
+ raise ValueError(f"The directory '{PDF_DIR}' does not exist. Please check the path.")
53
+
54
+
55
+
56
+ # Get list of PDF files in the directory
57
+ pdf_files = [f for f in os.listdir(PDF_DIR) if f.lower().endswith('.pdf')]
58
+
59
+ if DEFAULT_PDF not in pdf_files:
60
+ raise ValueError(f"Default PDF '{DEFAULT_PDF}' not found in '{PDF_DIR}'.")
61
+
62
+ # Check if there are PDF files in the directory
63
+ if not pdf_files:
64
+ raise ValueError(f"No PDF files found in the directory '{PDF_DIR}'.")
65
+
66
+ def display_pdf(selected_file):
67
+ """
68
+ Given the selected file name, return the full path to display in the PDF viewer.
69
+ """
70
+ file_path = os.path.join(PDF_DIR, selected_file)
71
+ return file_path
72
+
73
+
74
+
75
+
76
+
77
+ def web_search(query: str) -> str:
78
+ """
79
+ Performs a web search using the Tavily API and returns the context string.
80
+
81
+ Parameters:
82
+ - query (str): The search query.
83
+
84
+ Returns:
85
+ - str: The context string from the Tavily API or an error message.
86
+ """
87
+ try:
88
+ # Step 1: Instantiate the TavilyClient
89
+ tavily_client = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
90
+
91
+ # Step 2: Execute the search query
92
+ context = tavily_client.get_search_context(query=query)
93
+
94
+ # Step 3: Return the context
95
+ return f"**Web Search Context:**\n{context}"
96
+ except Exception as e:
97
+ return f"Error performing web search: {str(e)}"
98
+
99
+
100
+
101
+ # Ensure the PDF_DIR exists
102
+ if not os.path.isdir(PDF_DIR):
103
+ raise ValueError(f"The directory '{PDF_DIR}' does not exist. Please check the path.")
104
+
105
+ # Get list of PDF files in the directory
106
+ pdf_files = [f for f in os.listdir(PDF_DIR) if f.lower().endswith('.pdf')]
107
+
108
+ # Check if there are PDF files in the directory
109
+ if not pdf_files:
110
+ raise ValueError(f"No PDF files found in the directory '{PDF_DIR}'.")
111
+
112
+ def display_pdf(selected_file):
113
+ """
114
+ Given the selected file name, return the full path to display in the PDF viewer.
115
+ """
116
+ file_path = os.path.join(PDF_DIR, selected_file)
117
+ return file_path
118
+
119
+
120
+
121
+ # Function to generate a date range
122
+ def generate_date_range(start_date, end_date, freq="D"):
123
+ return pd.date_range(start=start_date, end=end_date, freq=freq)
124
+
125
+
126
+ # Function to generate synthetic data for each component
127
+ def generate_synthetic_data(dates):
128
+ # Define random seed for reproducibility
129
+ np.random.seed(0)
130
+
131
+ # Generate random data for each component
132
+ data = {
133
+ "Temperature_Pressure_Relief_Valve": np.random.choice(
134
+ [0, 1], size=len(dates)
135
+ ), # 0 = OK, 1 = Faulty
136
+ "Outlet_Nipple_Assembly": np.random.normal(
137
+ loc=80, scale=10, size=len(dates)
138
+ ), # Temperature in °F
139
+ "Inlet_Nipple": np.random.normal(
140
+ loc=50, scale=5, size=len(dates)
141
+ ), # Temperature in °F
142
+ "Upper_Element": np.random.normal(
143
+ loc=150, scale=20, size=len(dates)
144
+ ), # Wattage (Watts)
145
+ "Lower_Element": np.random.normal(
146
+ loc=150, scale=20, size=len(dates)
147
+ ), # Wattage (Watts)
148
+ "Anode_Rod": np.random.normal(
149
+ loc=7, scale=1.5, size=len(dates)
150
+ ), # Length in inches
151
+ "Drain_Valve": np.random.choice(
152
+ [0, 1], size=len(dates)
153
+ ), # 0 = Closed, 1 = Open
154
+ "Upper_Thermostat": np.random.normal(
155
+ loc=120, scale=10, size=len(dates)
156
+ ), # Temperature in °F
157
+ "Lower_Thermostat": np.random.normal(
158
+ loc=120, scale=10, size=len(dates)
159
+ ), # Temperature in °F
160
+ "Operating_Time": np.random.randint(
161
+ 1, 25, size=len(dates)
162
+ ), # Operating time in hours
163
+ }
164
+
165
+ # Inject an anomaly in the Upper Thermostat values around the midpoint
166
+ midpoint_index = len(dates) // 2
167
+ anomaly_range = (midpoint_index - 5, midpoint_index + 5)
168
+
169
+ # Create a spike in Upper Thermostat values
170
+ data["Upper_Thermostat"][anomaly_range[0] : anomaly_range[1]] = np.random.normal(
171
+ loc=200, scale=5, size=anomaly_range[1] - anomaly_range[0]
172
+ )
173
+
174
+ return pd.DataFrame(data, index=dates)
175
+
176
+
177
+ # Generate the dataset
178
+ start_date = datetime(2023, 10, 1)
179
+ end_date = datetime(2024, 10, 1)
180
+ dates = generate_date_range(start_date, end_date)
181
+
182
+ # Create a DataFrame with synthetic data
183
+ synthetic_dataset = generate_synthetic_data(dates)
184
+
185
+ now = datetime.now()
186
+
187
+ synthetic_dataset["time"] = [
188
+ now - timedelta(hours=5 * i) for i in range(synthetic_dataset.shape[0])
189
+ ]
190
+
191
+ # something whcky happened with the vector store. i don't know what the fuck happened.
192
+ # have to create a new assistant.
193
+
194
+ # you need to have system instructions ilke this
195
+ # You are a helpful assistant and expert at ansewring building automation questions. Always carry out a file search for the desired information. You can augment that information with your general knowledge, but alwasy carry out a file seaach with every query first to see if the relevant information is there, and then add to that afterwards.
196
+
197
+ # name : Building Energy and Efficiency Expert
198
+
199
+ # And also added repitiion of the instructions in the thread / run creation.
200
+
201
+ VECTOR_STORE_ID = os.environ["VECTOR_STORE_ID"] # will need to be updated. what the hell happened??
202
+ ASSISTANT_ID = os.environ["ASSISTANT_ID"]
203
+
204
+
205
+
206
+ # small medium offices are waht is relevant to this dataset.
207
+
208
+ # Initialize the client
209
+ client = openai.OpenAI()
210
+
211
+
212
+ # Step 2: Create a Thread
213
+ thread = client.beta.threads.create()
214
+ thread_id = thread.id
215
+
216
+
217
+ # Define the EventHandler class
218
+ class EventHandler(AssistantEventHandler):
219
+ def __init__(self, response_queue):
220
+ super().__init__()
221
+ self.response_queue = response_queue
222
+
223
+ @override
224
+ def on_text_created(self, text) -> None:
225
+ pass
226
+
227
+ @override
228
+ def on_text_delta(self, delta, snapshot):
229
+ text = delta.value
230
+ self.response_queue.put(text)
231
+
232
+ @override
233
+ def on_event(self, event):
234
+ # Retrieve events that are denoted with 'requires_action'
235
+ # since these will have our tool_calls
236
+ if event.event == 'thread.run.requires_action':
237
+ run_id = event.data.id # Retrieve the run ID from the event data
238
+ self.handle_requires_action(event.data, run_id)
239
+
240
+ def handle_requires_action(self, data, run_id):
241
+ tool_outputs = []
242
+
243
+ for tool in data.required_action.submit_tool_outputs.tool_calls:
244
+ if tool.function.name == "update_weather_forecast":
245
+ print(tool.function.arguments)
246
+ args = json.loads(tool.function.arguments)
247
+ loc = args["location"]
248
+ tool_outputs.append({"tool_call_id": tool.id, "output": update_weather_forecast(loc)})
249
+ elif tool.function.name == "update_weather":
250
+ print(tool.function.arguments)
251
+ args = json.loads(tool.function.arguments)
252
+ loc = args["location"]
253
+ tool_outputs.append({"tool_call_id": tool.id, "output": update_weather(loc)})
254
+ elif tool.function.name == "web_search":
255
+ print(tool.function.arguments)
256
+ args = json.loads(tool.function.arguments)
257
+ query = args["query"]
258
+ tool_outputs.append({"tool_call_id": tool.id, "output": web_search(query)})
259
+
260
+ # Submit all tool_outputs at the same time
261
+ self.submit_tool_outputs(tool_outputs, run_id)
262
+
263
+ def submit_tool_outputs(self, tool_outputs, run_id):
264
+ # Use the submit_tool_outputs_stream helper
265
+ with client.beta.threads.runs.submit_tool_outputs_stream(
266
+ thread_id=self.current_run.thread_id,
267
+ run_id=self.current_run.id,
268
+ tool_outputs=tool_outputs,
269
+ event_handler=EventHandler(self.response_queue),
270
+ ) as stream:
271
+ for text in stream.text_deltas:
272
+ print(text, end="", flush=True)
273
+ print()
274
+
275
+
276
+ def chat(usr_message, history):
277
+ global thread_id
278
+ # start_conversation()
279
+ user_input = usr_message
280
+
281
+ if not thread_id:
282
+ print("Error: Missing thread_id") # Debugging line
283
+ return json.dumps({"error": "Missing thread_id"}), 400
284
+
285
+ print(
286
+ f"Received message: {user_input} for thread ID: {thread_id}"
287
+ ) # Debugging line
288
+
289
+ # Add the user's message to the thread
290
+ client.beta.threads.messages.create(
291
+ thread_id=thread_id, role="user", content=user_input
292
+ )
293
+
294
+ # Create a queue to hold the assistant's response chunks
295
+ response_queue = queue.Queue()
296
+
297
+ # Instantiate the event handler with the queue
298
+
299
+ # Start the streaming run in a separate thread
300
+ def run_stream():
301
+ with client.beta.threads.runs.stream(
302
+ thread_id=thread_id,
303
+ assistant_id=ASSISTANT_ID,
304
+ tool_choice = "required",
305
+ event_handler=EventHandler(response_queue),
306
+ ) as stream:
307
+ stream.until_done()
308
+
309
+ stream_thread = Thread(target=run_stream)
310
+ stream_thread.start()
311
+
312
+ assistant_response = ""
313
+ while True:
314
+ try:
315
+ # Get response chunks from the queue
316
+ chunk = response_queue.get(timeout=0.1)
317
+ assistant_response += chunk
318
+ yield assistant_response
319
+ except queue.Empty:
320
+ # Check if the stream has finished
321
+ if not stream_thread.is_alive():
322
+ break
323
+
324
+ # Wait for the stream thread to finish
325
+ stream_thread.join()
326
+
327
+
328
+ def update_weather(location):
329
+ api_key = os.environ["OPENWEATHERMAP_API_KEY"]
330
+ base_url = "http://api.openweathermap.org/data/2.5/weather"
331
+ params = {"q": location, "appid": api_key, "units": "imperial"}
332
+ response = requests.get(base_url, params=params)
333
+ weather_data = response.json()
334
+
335
+ if response.status_code != 200:
336
+ return f"Error fetching weather data: {weather_data.get('message', 'Unknown error')}"
337
+
338
+ lon = weather_data["coord"]["lon"]
339
+ lat = weather_data["coord"]["lat"]
340
+ main = weather_data["weather"][0]["main"]
341
+ feels_like = weather_data["main"]["feels_like"]
342
+ temp_min = weather_data["main"]["temp_min"]
343
+ temp_max = weather_data["main"]["temp_max"]
344
+ pressure = weather_data["main"]["pressure"]
345
+ visibility = weather_data["visibility"]
346
+ wind_speed = weather_data["wind"]["speed"]
347
+ wind_deg = weather_data["wind"]["deg"]
348
+ sunrise = datetime.fromtimestamp(weather_data["sys"]["sunrise"]).strftime('%H:%M:%S')
349
+ sunset = datetime.fromtimestamp(weather_data["sys"]["sunset"]).strftime('%H:%M:%S')
350
+ temp = weather_data["main"]["temp"]
351
+ humidity = weather_data["main"]["humidity"]
352
+ condition = weather_data["weather"][0]["description"]
353
+
354
+ return f"""**Weather in {location}:**
355
+ - **Coordinates:** (lon: {lon}, lat: {lat})
356
+ - **Temperature:** {temp:.2f}°F (Feels like: {feels_like:.2f}°F)
357
+ - **Min Temperature:** {temp_min:.2f}°F, **Max Temperature:** {temp_max:.2f}°F
358
+ - **Humidity:** {humidity}%
359
+ - **Condition:** {condition.capitalize()}
360
+ - **Pressure:** {pressure} hPa
361
+ - **Visibility:** {visibility} meters
362
+ - **Wind Speed:** {wind_speed} m/s, **Wind Direction:** {wind_deg}°
363
+ - **Sunrise:** {sunrise}, **Sunset:** {sunset}"""
364
+
365
+
366
+
367
+ def update_weather_forecast(location: str) -> str:
368
+ """ Fetches the weather forecast for a given location and returns a formatted string
369
+ Parameters:
370
+ - location: the search term to find weather information
371
+ Returns:
372
+ A formatted string containing the weather forecast data
373
+ """
374
+
375
+ api_key = os.environ["OPENWEATHERMAP_API_KEY"]
376
+ base_url = "http://api.openweathermap.org/data/2.5/forecast"
377
+ params = {
378
+ "q": location,
379
+ "appid": api_key,
380
+ "units": "imperial",
381
+ "cnt": 40 # Request 40 data points (5 days * 8 three-hour periods)
382
+ }
383
+ response = requests.get(base_url, params=params)
384
+ weather_data = response.json()
385
+ if response.status_code != 200:
386
+ return f"Error fetching weather data: {weather_data.get('message', 'Unknown error')}"
387
+
388
+ # Organize forecast data per date
389
+ forecast_data = {}
390
+ for item in weather_data['list']:
391
+ dt_txt = item['dt_txt'] # 'YYYY-MM-DD HH:MM:SS'
392
+ date_str = dt_txt.split(' ')[0] # 'YYYY-MM-DD'
393
+ time_str = dt_txt.split(' ')[1] # 'HH:MM:SS'
394
+ forecast_data.setdefault(date_str, [])
395
+ forecast_data[date_str].append({
396
+ 'time': time_str,
397
+ 'temp': item['main']['temp'],
398
+ 'feels_like': item['main']['feels_like'],
399
+ 'humidity': item['main']['humidity'],
400
+ 'pressure': item['main']['pressure'],
401
+ 'wind_speed': item['wind']['speed'],
402
+ 'wind_deg': item['wind']['deg'],
403
+ 'condition': item['weather'][0]['description'],
404
+ 'visibility': item.get('visibility', 'N/A'), # sometimes visibility may be missing
405
+ })
406
+
407
+ # Process data to create daily summaries
408
+ daily_summaries = {}
409
+ for date_str, forecasts in forecast_data.items():
410
+ temps = [f['temp'] for f in forecasts]
411
+ feels_likes = [f['feels_like'] for f in forecasts]
412
+ humidities = [f['humidity'] for f in forecasts]
413
+ pressures = [f['pressure'] for f in forecasts]
414
+ wind_speeds = [f['wind_speed'] for f in forecasts]
415
+ conditions = [f['condition'] for f in forecasts]
416
+
417
+ min_temp = min(temps)
418
+ max_temp = max(temps)
419
+ avg_temp = sum(temps) / len(temps)
420
+ avg_feels_like = sum(feels_likes) / len(feels_likes)
421
+ avg_humidity = sum(humidities) / len(humidities)
422
+ avg_pressure = sum(pressures) / len(pressures)
423
+ avg_wind_speed = sum(wind_speeds) / len(wind_speeds)
424
+
425
+ # Find the most common weather condition
426
+ condition_counts = Counter(conditions)
427
+ most_common_condition = condition_counts.most_common(1)[0][0]
428
+
429
+ daily_summaries[date_str] = {
430
+ 'min_temp': min_temp,
431
+ 'max_temp': max_temp,
432
+ 'avg_temp': avg_temp,
433
+ 'avg_feels_like': avg_feels_like,
434
+ 'avg_humidity': avg_humidity,
435
+ 'avg_pressure': avg_pressure,
436
+ 'avg_wind_speed': avg_wind_speed,
437
+ 'condition': most_common_condition,
438
+ }
439
+
440
+ # Build the formatted string
441
+ city_name = weather_data['city']['name']
442
+ ret_str = f"**5-Day Weather Forecast for {city_name}:**\n"
443
+
444
+ for date_str in sorted(daily_summaries.keys()):
445
+ summary = daily_summaries[date_str]
446
+ ret_str += f"\n**{date_str}:**\n"
447
+ ret_str += f"- **Condition:** {summary['condition'].capitalize()}\n"
448
+ ret_str += f"- **Min Temperature:** {summary['min_temp']:.2f}°F\n"
449
+ ret_str += f"- **Max Temperature:** {summary['max_temp']:.2f}°F\n"
450
+ ret_str += f"- **Average Temperature:** {summary['avg_temp']:.2f}°F (Feels like {summary['avg_feels_like']:.2f}°F)\n"
451
+ ret_str += f"- **Humidity:** {summary['avg_humidity']:.0f}%\n"
452
+ ret_str += f"- **Pressure:** {summary['avg_pressure']:.0f} hPa\n"
453
+ ret_str += f"- **Wind Speed:** {summary['avg_wind_speed']:.2f} m/s\n"
454
+
455
+ return ret_str
456
+
457
+
458
+ llmmodel = OpenAI(api_token=os.environ["OPENAI_API_KEY"], model='gpt-4o')
459
+
460
+ # Load dataframes
461
+ dfcleaned = pd.read_csv("dfcleaned.csv")
462
+ dfcleaned['Timestamp'] = pd.to_datetime(dfcleaned['Timestamp'])
463
+ dfcleaned['off-nominal'] = dfcleaned['off-nominal'].apply(str)
464
+ dfshaps = pd.read_csv("shaps.csv")
465
+ dfshaps['Timestamp'] = pd.to_datetime(dfshaps['Timestamp'])
466
+
467
+ # Initialize Agent
468
+ agent = Agent([dfcleaned, dfshaps], config={"llm": llmmodel})
469
+
470
+ sdfshaps = SmartDataframe(dfshaps, config={"llm": llmmodel})
471
+ sdfcleaned = SmartDataframe(dfcleaned, config={"llm": llmmodel})
472
+
473
+
474
+
475
+ def process_query(query):
476
+ response = agent.chat(query) # Replace with your actual agent chat implementation
477
+ print(response)
478
+
479
+ # Initialize outputs and visibility flags
480
+ text_output = None
481
+ image_output = None
482
+ dataframe_output = None
483
+ text_visible = False
484
+ image_visible = False
485
+ dataframe_visible = False
486
+
487
+ if isinstance(response, str) and ".png" not in response:
488
+ text_output = response
489
+ text_visible = True
490
+ elif isinstance(response, str) and ".png" in response:
491
+ image_output = response # Assuming response is a filepath or URL to the image
492
+ image_visible = True
493
+ elif isinstance(response, pd.DataFrame):
494
+ dataframe_output = response
495
+ dataframe_visible = True
496
+
497
+ return (
498
+ text_output,
499
+ image_output,
500
+ dataframe_output,
501
+ gr.update(visible=text_visible),
502
+ gr.update(visible=image_visible),
503
+ gr.update(visible=dataframe_visible)
504
+ )
505
+
506
+
507
+
508
+ def gradio_app():
509
+ iface = gr.Interface(
510
+ fn=process_query,
511
+ inputs="text",
512
+ outputs=[
513
+ gr.Textbox(label="Response"),
514
+ gr.Image(label="Plot"),
515
+ gr.DataFrame(label="Dataframe")
516
+ ],
517
+ title="pandasai Query Processor",
518
+ description="Enter your query related to the csv data files."
519
+ )
520
+ return iface
521
+
522
+ with gr.Blocks(
523
+ # theme=gr.themes.Monochrome(primary_hue="green"),
524
+ theme = gr.themes.Soft(),
525
+ ) as demo:
526
+ with gr.Row(): # Combine the two weather functions into a single row
527
+ with gr.Column():
528
+ location1 = gr.Textbox(label="Enter location for weather (e.g., Rio Rancho, New Mexico)",
529
+ value="Cambridge, Massachusetts")
530
+ weather_button = gr.Button("Get Weather")
531
+ # output1 = gr.Markdown(label="Weather Information")
532
+ output1 = gr.Textbox(label="Weather Information", lines=8, max_lines=8, show_label=True, show_copy_button=True)
533
+ weather_button.click(
534
+ fn=update_weather,
535
+ inputs=location1,
536
+ outputs=output1,
537
+ api_name="update_weather",
538
+ )
539
+ with gr.Column():
540
+ location2 = gr.Textbox(label="Enter location for weather forecast (e.g., Rio Rancho, New Mexico)",
541
+ value="Cambridge, Massachusetts")
542
+ weather_forecast_button = gr.Button("Get 5-Day Weather Forecast")
543
+ # output2 = gr.Markdown(label="Weather Forecast Information")
544
+ output2 = gr.Textbox(label="Weather 5-Day Forecast Information", lines=8, max_lines=8,
545
+ show_label=True, show_copy_button=True)
546
+ weather_forecast_button.click(
547
+ fn=update_weather_forecast,
548
+ inputs=location2,
549
+ outputs=output2,
550
+ api_name="update_weather_forecast",
551
+ )
552
+ gr.Markdown("# 📄 PDF Viewer Section")
553
+ gr.Markdown("Select a PDF from the dropdown below to view it.")
554
+
555
+ with gr.Accordion("Open PDF Selection", open=False):
556
+ with gr.Row():
557
+ # Assign a larger scale to the dropdown
558
+ dropdown = gr.Dropdown(
559
+ choices=pdf_files,
560
+ label="Select a PDF",
561
+ value=DEFAULT_PDF, # Set a default value
562
+ scale=1 # This component takes twice the space
563
+ )
564
+ # Assign a smaller scale to the PDF viewer
565
+ pdf_viewer = PDF(
566
+ label="PDF Viewer",
567
+ interactive=True,
568
+ scale=3 ,
569
+ value=display_pdf(DEFAULT_PDF)# This component takes half the space compared to dropdown
570
+ )
571
+
572
+ # Set up the event: when dropdown changes, update the PDF viewer
573
+ dropdown.change(
574
+ fn=display_pdf,
575
+ inputs=dropdown,
576
+ outputs=pdf_viewer
577
+ )
578
+ with gr.Row():
579
+ with gr.Column(scale=1):
580
+ gr.Markdown("# Building Automation Assistant")
581
+
582
+ gr.Markdown(
583
+ "I'm an AI assistant that can help with building maintenance and equipment questions."
584
+ )
585
+
586
+ gr.Markdown("---")
587
+
588
+ # Update the ChatInterface to handle streaming
589
+ chat_interface = gr.ChatInterface(
590
+ chat,
591
+ #show_label=True,
592
+ # show_copy_button=True,
593
+ chatbot=gr.Chatbot(height=750, show_copy_button=True, show_copy_all_button=True,
594
+ avatar_images=("user_avatar.png", "assistant_avatar.png")),
595
+ title="Ask Me Anything",
596
+ examples_per_page= 5,
597
+ # theme="soft", # glass
598
+ description="Type your question about building automation here.",
599
+ examples=[
600
+ "Give the weather forecast for Cambridge, MA",
601
+ "Give me the weather forecast for New York, NY. express the windspeed in miles per hour.",
602
+ "list the authors on the academic paper associated with the homezero project.",
603
+ "What are some good API services that i can use to help fetch relevant data for building automation purposes? include hyperlinks in your response.",
604
+ "show the first few rows of each of the uploaded csv files",
605
+ "What are the current maintenance protocols for HouseZero?",
606
+ "How do the maintenance protocols for HouseZero compare to industry best practices?",
607
+ "What are the most common maintenance challenges faced by net-zero energy buildings?",
608
+ "How does the Uponor Climate Control Network System contribute to building maintenance?",
609
+ "What role do smart systems play in the maintenance of sustainable buildings like HouseZero?",
610
+ "Can you provide data on the energy performance of HouseZero over the past year?",
611
+ "Tell me about the HouseZero dataset. Retrieve information from the publication you have access to. Use your file retrieval tool.",
612
+ "Describe in detail the relationshp between the columns and values in the uploaded CSV files and the information you have access to regarding the HouseZero dataset. Be verbose. Use your file retrieval tool.",
613
+ "Please comment on the zone relative humidity features, specifically if they indicate a problem withthe building",
614
+ "Give me in great detail any advice you have to maintain a small to midsize office building, like the HouseZero data corresponds to. Be verbose. Use your file retrieval tool.",
615
+ "Is there any information in the datafiles that indicates a problem with the building?",
616
+ "Show Massachusetts electricity billing rates during the same time span as the CSV data",
617
+ "Use those rates and the relevant columns in the CSV files to estimate how much it costs to operate this building per month.",
618
+ "What is the estimated average electricity cost for operating the building using massachusetts energy rates. use your file retrieval tool. use data csv files for building data. Limit your response to 140 characters. Use your file retrieval tool.",
619
+ "Based on the data in these CSV files, can you assign an EnergyIQ score from 1-10 that reflects how well the building is operating? Explain the reason for your score and provide any recommendations on actions to take that can improve it in the future. Be verbose. Use your file retrieval tool.",
620
+ "Please summarize information concerning sensor networks that may be leading to faulty meaurements.",
621
+ "Tell me how to properly install the PVC sky lights.",
622
+ "Based on data and insights, what specific changes should be made to HouseZero's maintenance protocols?",
623
+ "what recommendations do you have to mitigate against high relative humidity zone measurements in structures like the housezero building?"
624
+ ],
625
+ fill_height=True,
626
+ )
627
+
628
+ gr.Markdown("---")
629
+ with gr.Accordion("Example Plots Section", open=False):
630
+ with gr.Column():
631
+ # with gr.Column():
632
+ # Define the three ScatterPlot components
633
+ anomaly_plot = gr.ScatterPlot(
634
+ dfcleaned,
635
+ x="Timestamp",
636
+ y="Z5_RH",
637
+ color="off-nominal",
638
+ title="Anomaly Score"
639
+ )
640
+
641
+ zone3_plot = gr.ScatterPlot(
642
+ dfcleaned,
643
+ x="Timestamp",
644
+ y="Z3_RH",
645
+ color="off-nominal",
646
+ title="Zone 3 Relative Humidity",
647
+ )
648
+
649
+ zone4_plot = gr.ScatterPlot(
650
+ dfcleaned,
651
+ x="Timestamp",
652
+ y="Z4_RH",
653
+ color="off-nominal",
654
+ title="Zone 4 Relative Humidity",
655
+ )
656
+
657
+ # Group all plots into a list for easy management
658
+ plots = [anomaly_plot, zone3_plot, zone4_plot]
659
+
660
+ def select_region(selection: gr.SelectData):
661
+ """
662
+ Handles the region selection event.
663
+
664
+ Args:
665
+ selection (gr.SelectData): The data from the selection event.
666
+
667
+ Returns:
668
+ List[gr.Plot.update]: A list of update instructions for each plot.
669
+ """
670
+ if selection is None or selection.index is None:
671
+ return [gr.Plot.update() for _ in plots]
672
+
673
+ min_x, max_x = selection.index
674
+ # Update the x_lim for each plot
675
+ return [gr.ScatterPlot(x_lim=(min_x, max_x)) for _ in plots]
676
+
677
+ def reset_region():
678
+ """
679
+ Resets the x-axis limits for all plots.
680
+
681
+ Returns:
682
+ List[gr.Plot.update]: A list of update instructions to reset x_lim.
683
+ """
684
+ return [gr.ScatterPlot(x_lim=None) for _ in plots]
685
+
686
+ # Attach event listeners to each plot
687
+ for plot in plots:
688
+ plot.select(
689
+ select_region,
690
+ inputs=None,
691
+ outputs=plots # Update all plots
692
+ )
693
+ plot.double_click(
694
+ reset_region,
695
+ inputs=None,
696
+ outputs=plots # Reset all plots
697
+ )
698
+
699
+ # plots = [plt, first_plot, second_plot]
700
+
701
+ # def select_region(selection: gr.SelectData):
702
+ # min_w, max_w = selection.index
703
+ # return gr.ScatterPlot(x_lim=(min_w, max_w))
704
+
705
+ # for p in plots:
706
+ # p.select(select_region, None, plots)
707
+ # p.double_click(lambda: [gr.LinePlot(x_lim=None)] * len(plots), None, plots)
708
+
709
+ # second_plot.select(select_second_region, None, plt)
710
+ # second_plot.double_click(lambda: gr.ScatterPlot(x_lim=None), None, plt)
711
+ # gr.Column([anomaly_plot, first_plot, second_plot])
712
+
713
+ # anomaly_info = gr.Markdown("Anomaly detected around October 15, 2023")
714
+ with gr.Column():
715
+ query = gr.Textbox(label="Enter your question about the data",
716
+ value="Plot the anomaly_score as a function of time and highlight the highest 20 values")
717
+ query_button = gr.Button("Submit Data Query")
718
+ with gr.Row():
719
+ with gr.Column(visible=False) as output_col1:
720
+ out1 = gr.Textbox(label="Response")
721
+ with gr.Column(visible=False) as output_col2:
722
+ out2 = gr.Image(label="Plot")
723
+ with gr.Column(visible=False) as output_col3:
724
+ out3 = gr.DataFrame(label="DataFrame")
725
+ query_button.click(
726
+ fn=process_query,
727
+ inputs=query,
728
+ outputs=[
729
+ out1, # Text output
730
+ out2, # Image output
731
+ out3, # DataFrame output
732
+ output_col1, # Visibility for Text output
733
+ output_col2, # Visibility for Image output
734
+ output_col3 # Visibility for DataFrame output
735
+ ],
736
+ api_name="process_query"
737
+ )
738
+
739
+ # hide visibility until its ready
740
+
741
+
742
+ # Weather input
743
+ # with gr.Row():
744
+ # iface = gradio_app()
745
+
746
+
747
+ demo.launch(share=True)
.ipynb_checkpoints/requirements-checkpoint.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio==5.0.0
2
+ gradio_datetimerange==0.0.1
3
+ gradio_pdf==0.0.16
4
+ matplotlib==3.7.5
5
+ numpy==1.23.5
6
+ openai==1.51.2
7
+ pandas==2.2.3
8
+ pandasai==2.2.15
9
+ pyautogen==0.3.0
10
+ python-dotenv==1.0.1
11
+ Requests==2.32.3
12
+ tavily_python==0.5.0
13
+ typing_extensions==3.10.0.2
app.py CHANGED
@@ -46,15 +46,15 @@ PDF_DIR = "usedpdfs" # Replace with your directory path
46
  DEFAULT_PDF = "s41597-024-03770-7.pdf" # Replace with your actual PDF filename
47
 
48
 
49
-
50
  # Ensure the PDF_DIR exists
51
  if not os.path.isdir(PDF_DIR):
52
- raise ValueError(f"The directory '{PDF_DIR}' does not exist. Please check the path.")
53
-
 
54
 
55
 
56
  # Get list of PDF files in the directory
57
- pdf_files = [f for f in os.listdir(PDF_DIR) if f.lower().endswith('.pdf')]
58
 
59
  if DEFAULT_PDF not in pdf_files:
60
  raise ValueError(f"Default PDF '{DEFAULT_PDF}' not found in '{PDF_DIR}'.")
@@ -63,6 +63,7 @@ if DEFAULT_PDF not in pdf_files:
63
  if not pdf_files:
64
  raise ValueError(f"No PDF files found in the directory '{PDF_DIR}'.")
65
 
 
66
  def display_pdf(selected_file):
67
  """
68
  Given the selected file name, return the full path to display in the PDF viewer.
@@ -71,9 +72,6 @@ def display_pdf(selected_file):
71
  return file_path
72
 
73
 
74
-
75
-
76
-
77
  def web_search(query: str) -> str:
78
  """
79
  Performs a web search using the Tavily API and returns the context string.
@@ -97,18 +95,20 @@ def web_search(query: str) -> str:
97
  return f"Error performing web search: {str(e)}"
98
 
99
 
100
-
101
  # Ensure the PDF_DIR exists
102
  if not os.path.isdir(PDF_DIR):
103
- raise ValueError(f"The directory '{PDF_DIR}' does not exist. Please check the path.")
 
 
104
 
105
  # Get list of PDF files in the directory
106
- pdf_files = [f for f in os.listdir(PDF_DIR) if f.lower().endswith('.pdf')]
107
 
108
  # Check if there are PDF files in the directory
109
  if not pdf_files:
110
  raise ValueError(f"No PDF files found in the directory '{PDF_DIR}'.")
111
 
 
112
  def display_pdf(selected_file):
113
  """
114
  Given the selected file name, return the full path to display in the PDF viewer.
@@ -117,7 +117,6 @@ def display_pdf(selected_file):
117
  return file_path
118
 
119
 
120
-
121
  # Function to generate a date range
122
  def generate_date_range(start_date, end_date, freq="D"):
123
  return pd.date_range(start=start_date, end=end_date, freq=freq)
@@ -189,20 +188,21 @@ synthetic_dataset["time"] = [
189
  ]
190
 
191
  # something whcky happened with the vector store. i don't know what the fuck happened.
192
- # have to create a new assistant.
193
 
194
  # you need to have system instructions ilke this
195
- # You are a helpful assistant and expert at ansewring building automation questions. Always carry out a file search for the desired information. You can augment that information with your general knowledge, but alwasy carry out a file seaach with every query first to see if the relevant information is there, and then add to that afterwards.
196
 
197
  # name : Building Energy and Efficiency Expert
198
 
199
  # And also added repitiion of the instructions in the thread / run creation.
200
 
201
- VECTOR_STORE_ID = os.environ["VECTOR_STORE_ID"] # will need to be updated. what the hell happened??
 
 
202
  ASSISTANT_ID = os.environ["ASSISTANT_ID"]
203
 
204
 
205
-
206
  # small medium offices are waht is relevant to this dataset.
207
 
208
  # Initialize the client
@@ -228,37 +228,43 @@ class EventHandler(AssistantEventHandler):
228
  def on_text_delta(self, delta, snapshot):
229
  text = delta.value
230
  self.response_queue.put(text)
231
-
232
  @override
233
  def on_event(self, event):
234
- # Retrieve events that are denoted with 'requires_action'
235
- # since these will have our tool_calls
236
- if event.event == 'thread.run.requires_action':
237
- run_id = event.data.id # Retrieve the run ID from the event data
238
- self.handle_requires_action(event.data, run_id)
239
-
240
  def handle_requires_action(self, data, run_id):
241
- tool_outputs = []
242
-
243
- for tool in data.required_action.submit_tool_outputs.tool_calls:
244
- if tool.function.name == "update_weather_forecast":
245
- print(tool.function.arguments)
246
- args = json.loads(tool.function.arguments)
247
- loc = args["location"]
248
- tool_outputs.append({"tool_call_id": tool.id, "output": update_weather_forecast(loc)})
249
- elif tool.function.name == "update_weather":
250
- print(tool.function.arguments)
251
- args = json.loads(tool.function.arguments)
252
- loc = args["location"]
253
- tool_outputs.append({"tool_call_id": tool.id, "output": update_weather(loc)})
254
- elif tool.function.name == "web_search":
255
- print(tool.function.arguments)
256
- args = json.loads(tool.function.arguments)
257
- query = args["query"]
258
- tool_outputs.append({"tool_call_id": tool.id, "output": web_search(query)})
259
-
260
- # Submit all tool_outputs at the same time
261
- self.submit_tool_outputs(tool_outputs, run_id)
 
 
 
 
 
 
262
 
263
  def submit_tool_outputs(self, tool_outputs, run_id):
264
  # Use the submit_tool_outputs_stream helper
@@ -301,7 +307,7 @@ def chat(usr_message, history):
301
  with client.beta.threads.runs.stream(
302
  thread_id=thread_id,
303
  assistant_id=ASSISTANT_ID,
304
- tool_choice = "required",
305
  event_handler=EventHandler(response_queue),
306
  ) as stream:
307
  stream.until_done()
@@ -345,8 +351,10 @@ def update_weather(location):
345
  visibility = weather_data["visibility"]
346
  wind_speed = weather_data["wind"]["speed"]
347
  wind_deg = weather_data["wind"]["deg"]
348
- sunrise = datetime.fromtimestamp(weather_data["sys"]["sunrise"]).strftime('%H:%M:%S')
349
- sunset = datetime.fromtimestamp(weather_data["sys"]["sunset"]).strftime('%H:%M:%S')
 
 
350
  temp = weather_data["main"]["temp"]
351
  humidity = weather_data["main"]["humidity"]
352
  condition = weather_data["weather"][0]["description"]
@@ -363,9 +371,8 @@ def update_weather(location):
363
  - **Sunrise:** {sunrise}, **Sunset:** {sunset}"""
364
 
365
 
366
-
367
  def update_weather_forecast(location: str) -> str:
368
- """ Fetches the weather forecast for a given location and returns a formatted string
369
  Parameters:
370
  - location: the search term to find weather information
371
  Returns:
@@ -378,7 +385,7 @@ def update_weather_forecast(location: str) -> str:
378
  "q": location,
379
  "appid": api_key,
380
  "units": "imperial",
381
- "cnt": 40 # Request 40 data points (5 days * 8 three-hour periods)
382
  }
383
  response = requests.get(base_url, params=params)
384
  weather_data = response.json()
@@ -387,32 +394,36 @@ def update_weather_forecast(location: str) -> str:
387
 
388
  # Organize forecast data per date
389
  forecast_data = {}
390
- for item in weather_data['list']:
391
- dt_txt = item['dt_txt'] # 'YYYY-MM-DD HH:MM:SS'
392
- date_str = dt_txt.split(' ')[0] # 'YYYY-MM-DD'
393
- time_str = dt_txt.split(' ')[1] # 'HH:MM:SS'
394
  forecast_data.setdefault(date_str, [])
395
- forecast_data[date_str].append({
396
- 'time': time_str,
397
- 'temp': item['main']['temp'],
398
- 'feels_like': item['main']['feels_like'],
399
- 'humidity': item['main']['humidity'],
400
- 'pressure': item['main']['pressure'],
401
- 'wind_speed': item['wind']['speed'],
402
- 'wind_deg': item['wind']['deg'],
403
- 'condition': item['weather'][0]['description'],
404
- 'visibility': item.get('visibility', 'N/A'), # sometimes visibility may be missing
405
- })
 
 
 
 
406
 
407
  # Process data to create daily summaries
408
  daily_summaries = {}
409
  for date_str, forecasts in forecast_data.items():
410
- temps = [f['temp'] for f in forecasts]
411
- feels_likes = [f['feels_like'] for f in forecasts]
412
- humidities = [f['humidity'] for f in forecasts]
413
- pressures = [f['pressure'] for f in forecasts]
414
- wind_speeds = [f['wind_speed'] for f in forecasts]
415
- conditions = [f['condition'] for f in forecasts]
416
 
417
  min_temp = min(temps)
418
  max_temp = max(temps)
@@ -427,18 +438,18 @@ def update_weather_forecast(location: str) -> str:
427
  most_common_condition = condition_counts.most_common(1)[0][0]
428
 
429
  daily_summaries[date_str] = {
430
- 'min_temp': min_temp,
431
- 'max_temp': max_temp,
432
- 'avg_temp': avg_temp,
433
- 'avg_feels_like': avg_feels_like,
434
- 'avg_humidity': avg_humidity,
435
- 'avg_pressure': avg_pressure,
436
- 'avg_wind_speed': avg_wind_speed,
437
- 'condition': most_common_condition,
438
  }
439
 
440
  # Build the formatted string
441
- city_name = weather_data['city']['name']
442
  ret_str = f"**5-Day Weather Forecast for {city_name}:**\n"
443
 
444
  for date_str in sorted(daily_summaries.keys()):
@@ -455,14 +466,14 @@ def update_weather_forecast(location: str) -> str:
455
  return ret_str
456
 
457
 
458
- llmmodel = OpenAI(api_token=os.environ["OPENAI_API_KEY"], model='gpt-4o')
459
 
460
  # Load dataframes
461
  dfcleaned = pd.read_csv("dfcleaned.csv")
462
- dfcleaned['Timestamp'] = pd.to_datetime(dfcleaned['Timestamp'])
463
- dfcleaned['off-nominal'] = dfcleaned['off-nominal'].apply(str)
464
  dfshaps = pd.read_csv("shaps.csv")
465
- dfshaps['Timestamp'] = pd.to_datetime(dfshaps['Timestamp'])
466
 
467
  # Initialize Agent
468
  agent = Agent([dfcleaned, dfshaps], config={"llm": llmmodel})
@@ -471,11 +482,10 @@ sdfshaps = SmartDataframe(dfshaps, config={"llm": llmmodel})
471
  sdfcleaned = SmartDataframe(dfcleaned, config={"llm": llmmodel})
472
 
473
 
474
-
475
  def process_query(query):
476
  response = agent.chat(query) # Replace with your actual agent chat implementation
477
  print(response)
478
-
479
  # Initialize outputs and visibility flags
480
  text_output = None
481
  image_output = None
@@ -483,28 +493,27 @@ def process_query(query):
483
  text_visible = False
484
  image_visible = False
485
  dataframe_visible = False
486
-
487
  if isinstance(response, str) and ".png" not in response:
488
  text_output = response
489
  text_visible = True
490
  elif isinstance(response, str) and ".png" in response:
491
- image_output = response # Assuming response is a filepath or URL to the image
492
- image_visible = True
493
  elif isinstance(response, pd.DataFrame):
494
  dataframe_output = response
495
  dataframe_visible = True
496
-
497
  return (
498
  text_output,
499
  image_output,
500
  dataframe_output,
501
  gr.update(visible=text_visible),
502
  gr.update(visible=image_visible),
503
- gr.update(visible=dataframe_visible)
504
  )
505
 
506
 
507
-
508
  def gradio_app():
509
  iface = gr.Interface(
510
  fn=process_query,
@@ -512,24 +521,33 @@ def gradio_app():
512
  outputs=[
513
  gr.Textbox(label="Response"),
514
  gr.Image(label="Plot"),
515
- gr.DataFrame(label="Dataframe")
516
  ],
517
  title="pandasai Query Processor",
518
- description="Enter your query related to the csv data files."
519
  )
520
  return iface
521
 
 
522
  with gr.Blocks(
523
- # theme=gr.themes.Monochrome(primary_hue="green"),
524
- theme = gr.themes.Soft(),
525
  ) as demo:
526
  with gr.Row(): # Combine the two weather functions into a single row
527
  with gr.Column():
528
- location1 = gr.Textbox(label="Enter location for weather (e.g., Rio Rancho, New Mexico)",
529
- value="Cambridge, Massachusetts")
 
 
530
  weather_button = gr.Button("Get Weather")
531
- # output1 = gr.Markdown(label="Weather Information")
532
- output1 = gr.Textbox(label="Weather Information", lines=8, max_lines=8, show_label=True, show_copy_button=True)
 
 
 
 
 
 
533
  weather_button.click(
534
  fn=update_weather,
535
  inputs=location1,
@@ -537,12 +555,19 @@ with gr.Blocks(
537
  api_name="update_weather",
538
  )
539
  with gr.Column():
540
- location2 = gr.Textbox(label="Enter location for weather forecast (e.g., Rio Rancho, New Mexico)",
541
- value="Cambridge, Massachusetts")
 
 
542
  weather_forecast_button = gr.Button("Get 5-Day Weather Forecast")
543
- # output2 = gr.Markdown(label="Weather Forecast Information")
544
- output2 = gr.Textbox(label="Weather 5-Day Forecast Information", lines=8, max_lines=8,
545
- show_label=True, show_copy_button=True)
 
 
 
 
 
546
  weather_forecast_button.click(
547
  fn=update_weather_forecast,
548
  inputs=location2,
@@ -551,7 +576,7 @@ with gr.Blocks(
551
  )
552
  gr.Markdown("# 📄 PDF Viewer Section")
553
  gr.Markdown("Select a PDF from the dropdown below to view it.")
554
-
555
  with gr.Accordion("Open PDF Selection", open=False):
556
  with gr.Row():
557
  # Assign a larger scale to the dropdown
@@ -559,22 +584,20 @@ with gr.Blocks(
559
  choices=pdf_files,
560
  label="Select a PDF",
561
  value=DEFAULT_PDF, # Set a default value
562
- scale=1 # This component takes twice the space
563
  )
564
  # Assign a smaller scale to the PDF viewer
565
  pdf_viewer = PDF(
566
  label="PDF Viewer",
567
  interactive=True,
568
- scale=3 ,
569
- value=display_pdf(DEFAULT_PDF)# This component takes half the space compared to dropdown
 
 
570
  )
571
-
572
  # Set up the event: when dropdown changes, update the PDF viewer
573
- dropdown.change(
574
- fn=display_pdf,
575
- inputs=dropdown,
576
- outputs=pdf_viewer
577
- )
578
  with gr.Row():
579
  with gr.Column(scale=1):
580
  gr.Markdown("# Building Automation Assistant")
@@ -588,13 +611,17 @@ with gr.Blocks(
588
  # Update the ChatInterface to handle streaming
589
  chat_interface = gr.ChatInterface(
590
  chat,
591
- #show_label=True,
592
- # show_copy_button=True,
593
- chatbot=gr.Chatbot(height=750, show_copy_button=True, show_copy_all_button=True,
594
- avatar_images=("user_avatar.png", "assistant_avatar.png")),
 
 
 
 
595
  title="Ask Me Anything",
596
- examples_per_page= 5,
597
- # theme="soft", # glass
598
  description="Type your question about building automation here.",
599
  examples=[
600
  "Give the weather forecast for Cambridge, MA",
@@ -607,20 +634,20 @@ with gr.Blocks(
607
  "What are the most common maintenance challenges faced by net-zero energy buildings?",
608
  "How does the Uponor Climate Control Network System contribute to building maintenance?",
609
  "What role do smart systems play in the maintenance of sustainable buildings like HouseZero?",
610
- "Can you provide data on the energy performance of HouseZero over the past year?",
611
- "Tell me about the HouseZero dataset. Retrieve information from the publication you have access to. Use your file retrieval tool.",
612
  "Describe in detail the relationshp between the columns and values in the uploaded CSV files and the information you have access to regarding the HouseZero dataset. Be verbose. Use your file retrieval tool.",
613
  "Please comment on the zone relative humidity features, specifically if they indicate a problem withthe building",
614
  "Give me in great detail any advice you have to maintain a small to midsize office building, like the HouseZero data corresponds to. Be verbose. Use your file retrieval tool.",
615
  "Is there any information in the datafiles that indicates a problem with the building?",
616
  "Show Massachusetts electricity billing rates during the same time span as the CSV data",
617
  "Use those rates and the relevant columns in the CSV files to estimate how much it costs to operate this building per month.",
618
- "What is the estimated average electricity cost for operating the building using massachusetts energy rates. use your file retrieval tool. use data csv files for building data. Limit your response to 140 characters. Use your file retrieval tool.",
619
  "Based on the data in these CSV files, can you assign an EnergyIQ score from 1-10 that reflects how well the building is operating? Explain the reason for your score and provide any recommendations on actions to take that can improve it in the future. Be verbose. Use your file retrieval tool.",
620
  "Please summarize information concerning sensor networks that may be leading to faulty meaurements.",
621
  "Tell me how to properly install the PVC sky lights.",
622
  "Based on data and insights, what specific changes should be made to HouseZero's maintenance protocols?",
623
- "what recommendations do you have to mitigate against high relative humidity zone measurements in structures like the housezero building?"
624
  ],
625
  fill_height=True,
626
  )
@@ -631,13 +658,13 @@ with gr.Blocks(
631
  # with gr.Column():
632
  # Define the three ScatterPlot components
633
  anomaly_plot = gr.ScatterPlot(
634
- dfcleaned,
635
- x="Timestamp",
636
- y="Z5_RH",
637
  color="off-nominal",
638
- title="Anomaly Score"
639
  )
640
-
641
  zone3_plot = gr.ScatterPlot(
642
  dfcleaned,
643
  x="Timestamp",
@@ -653,8 +680,8 @@ with gr.Blocks(
653
  color="off-nominal",
654
  title="Zone 4 Relative Humidity",
655
  )
656
-
657
- # Group all plots into a list for easy management
658
  plots = [anomaly_plot, zone3_plot, zone4_plot]
659
 
660
  def select_region(selection: gr.SelectData):
@@ -669,9 +696,9 @@ with gr.Blocks(
669
  """
670
  if selection is None or selection.index is None:
671
  return [gr.Plot.update() for _ in plots]
672
-
673
  min_x, max_x = selection.index
674
- # Update the x_lim for each plot
675
  return [gr.ScatterPlot(x_lim=(min_x, max_x)) for _ in plots]
676
 
677
  def reset_region():
@@ -683,37 +710,35 @@ with gr.Blocks(
683
  """
684
  return [gr.ScatterPlot(x_lim=None) for _ in plots]
685
 
686
- # Attach event listeners to each plot
687
  for plot in plots:
688
  plot.select(
689
- select_region,
690
- inputs=None,
691
- outputs=plots # Update all plots
692
  )
693
  plot.double_click(
694
- reset_region,
695
- inputs=None,
696
- outputs=plots # Reset all plots
697
  )
698
 
699
- # plots = [plt, first_plot, second_plot]
 
 
 
 
700
 
701
- # def select_region(selection: gr.SelectData):
702
- # min_w, max_w = selection.index
703
- # return gr.ScatterPlot(x_lim=(min_w, max_w))
704
 
705
- # for p in plots:
706
- # p.select(select_region, None, plots)
707
- # p.double_click(lambda: [gr.LinePlot(x_lim=None)] * len(plots), None, plots)
708
-
709
- # second_plot.select(select_second_region, None, plt)
710
- # second_plot.double_click(lambda: gr.ScatterPlot(x_lim=None), None, plt)
711
- # gr.Column([anomaly_plot, first_plot, second_plot])
712
 
713
- # anomaly_info = gr.Markdown("Anomaly detected around October 15, 2023")
714
  with gr.Column():
715
- query = gr.Textbox(label="Enter your question about the data",
716
- value="Plot the anomaly_score as a function of time and highlight the highest 20 values")
 
 
717
  query_button = gr.Button("Submit Data Query")
718
  with gr.Row():
719
  with gr.Column(visible=False) as output_col1:
@@ -726,22 +751,21 @@ with gr.Blocks(
726
  fn=process_query,
727
  inputs=query,
728
  outputs=[
729
- out1, # Text output
730
- out2, # Image output
731
- out3, # DataFrame output
732
- output_col1, # Visibility for Text output
733
- output_col2, # Visibility for Image output
734
- output_col3 # Visibility for DataFrame output
735
  ],
736
- api_name="process_query"
737
  )
738
-
739
  # hide visibility until its ready
740
-
741
-
742
  # Weather input
743
- # with gr.Row():
744
- # iface = gradio_app()
745
 
746
 
747
- demo.launch(share=True)
 
46
  DEFAULT_PDF = "s41597-024-03770-7.pdf" # Replace with your actual PDF filename
47
 
48
 
 
49
  # Ensure the PDF_DIR exists
50
  if not os.path.isdir(PDF_DIR):
51
+ raise ValueError(
52
+ f"The directory '{PDF_DIR}' does not exist. Please check the path."
53
+ )
54
 
55
 
56
  # Get list of PDF files in the directory
57
+ pdf_files = [f for f in os.listdir(PDF_DIR) if f.lower().endswith(".pdf")]
58
 
59
  if DEFAULT_PDF not in pdf_files:
60
  raise ValueError(f"Default PDF '{DEFAULT_PDF}' not found in '{PDF_DIR}'.")
 
63
  if not pdf_files:
64
  raise ValueError(f"No PDF files found in the directory '{PDF_DIR}'.")
65
 
66
+
67
  def display_pdf(selected_file):
68
  """
69
  Given the selected file name, return the full path to display in the PDF viewer.
 
72
  return file_path
73
 
74
 
 
 
 
75
  def web_search(query: str) -> str:
76
  """
77
  Performs a web search using the Tavily API and returns the context string.
 
95
  return f"Error performing web search: {str(e)}"
96
 
97
 
 
98
  # Ensure the PDF_DIR exists
99
  if not os.path.isdir(PDF_DIR):
100
+ raise ValueError(
101
+ f"The directory '{PDF_DIR}' does not exist. Please check the path."
102
+ )
103
 
104
  # Get list of PDF files in the directory
105
+ pdf_files = [f for f in os.listdir(PDF_DIR) if f.lower().endswith(".pdf")]
106
 
107
  # Check if there are PDF files in the directory
108
  if not pdf_files:
109
  raise ValueError(f"No PDF files found in the directory '{PDF_DIR}'.")
110
 
111
+
112
  def display_pdf(selected_file):
113
  """
114
  Given the selected file name, return the full path to display in the PDF viewer.
 
117
  return file_path
118
 
119
 
 
120
  # Function to generate a date range
121
  def generate_date_range(start_date, end_date, freq="D"):
122
  return pd.date_range(start=start_date, end=end_date, freq=freq)
 
188
  ]
189
 
190
  # something whcky happened with the vector store. i don't know what the fuck happened.
191
+ # have to create a new assistant.
192
 
193
  # you need to have system instructions ilke this
194
+ # You are a helpful assistant and expert at ansewring building automation questions. Always carry out a file search for the desired information. You can augment that information with your general knowledge, but alwasy carry out a file seaach with every query first to see if the relevant information is there, and then add to that afterwards.
195
 
196
  # name : Building Energy and Efficiency Expert
197
 
198
  # And also added repitiion of the instructions in the thread / run creation.
199
 
200
+ VECTOR_STORE_ID = os.environ[
201
+ "VECTOR_STORE_ID"
202
+ ] # will need to be updated. what the hell happened??
203
  ASSISTANT_ID = os.environ["ASSISTANT_ID"]
204
 
205
 
 
206
  # small medium offices are waht is relevant to this dataset.
207
 
208
  # Initialize the client
 
228
  def on_text_delta(self, delta, snapshot):
229
  text = delta.value
230
  self.response_queue.put(text)
231
+
232
  @override
233
  def on_event(self, event):
234
+ # Retrieve events that are denoted with 'requires_action'
235
+ # since these will have our tool_calls
236
+ if event.event == "thread.run.requires_action":
237
+ run_id = event.data.id # Retrieve the run ID from the event data
238
+ self.handle_requires_action(event.data, run_id)
239
+
240
  def handle_requires_action(self, data, run_id):
241
+ tool_outputs = []
242
+
243
+ for tool in data.required_action.submit_tool_outputs.tool_calls:
244
+ if tool.function.name == "update_weather_forecast":
245
+ print(tool.function.arguments)
246
+ args = json.loads(tool.function.arguments)
247
+ loc = args["location"]
248
+ tool_outputs.append(
249
+ {"tool_call_id": tool.id, "output": update_weather_forecast(loc)}
250
+ )
251
+ elif tool.function.name == "update_weather":
252
+ print(tool.function.arguments)
253
+ args = json.loads(tool.function.arguments)
254
+ loc = args["location"]
255
+ tool_outputs.append(
256
+ {"tool_call_id": tool.id, "output": update_weather(loc)}
257
+ )
258
+ elif tool.function.name == "web_search":
259
+ print(tool.function.arguments)
260
+ args = json.loads(tool.function.arguments)
261
+ query = args["query"]
262
+ tool_outputs.append(
263
+ {"tool_call_id": tool.id, "output": web_search(query)}
264
+ )
265
+
266
+ # Submit all tool_outputs at the same time
267
+ self.submit_tool_outputs(tool_outputs, run_id)
268
 
269
  def submit_tool_outputs(self, tool_outputs, run_id):
270
  # Use the submit_tool_outputs_stream helper
 
307
  with client.beta.threads.runs.stream(
308
  thread_id=thread_id,
309
  assistant_id=ASSISTANT_ID,
310
+ tool_choice="required",
311
  event_handler=EventHandler(response_queue),
312
  ) as stream:
313
  stream.until_done()
 
351
  visibility = weather_data["visibility"]
352
  wind_speed = weather_data["wind"]["speed"]
353
  wind_deg = weather_data["wind"]["deg"]
354
+ sunrise = datetime.fromtimestamp(weather_data["sys"]["sunrise"]).strftime(
355
+ "%H:%M:%S"
356
+ )
357
+ sunset = datetime.fromtimestamp(weather_data["sys"]["sunset"]).strftime("%H:%M:%S")
358
  temp = weather_data["main"]["temp"]
359
  humidity = weather_data["main"]["humidity"]
360
  condition = weather_data["weather"][0]["description"]
 
371
  - **Sunrise:** {sunrise}, **Sunset:** {sunset}"""
372
 
373
 
 
374
  def update_weather_forecast(location: str) -> str:
375
+ """Fetches the weather forecast for a given location and returns a formatted string
376
  Parameters:
377
  - location: the search term to find weather information
378
  Returns:
 
385
  "q": location,
386
  "appid": api_key,
387
  "units": "imperial",
388
+ "cnt": 40, # Request 40 data points (5 days * 8 three-hour periods)
389
  }
390
  response = requests.get(base_url, params=params)
391
  weather_data = response.json()
 
394
 
395
  # Organize forecast data per date
396
  forecast_data = {}
397
+ for item in weather_data["list"]:
398
+ dt_txt = item["dt_txt"] # 'YYYY-MM-DD HH:MM:SS'
399
+ date_str = dt_txt.split(" ")[0] # 'YYYY-MM-DD'
400
+ time_str = dt_txt.split(" ")[1] # 'HH:MM:SS'
401
  forecast_data.setdefault(date_str, [])
402
+ forecast_data[date_str].append(
403
+ {
404
+ "time": time_str,
405
+ "temp": item["main"]["temp"],
406
+ "feels_like": item["main"]["feels_like"],
407
+ "humidity": item["main"]["humidity"],
408
+ "pressure": item["main"]["pressure"],
409
+ "wind_speed": item["wind"]["speed"],
410
+ "wind_deg": item["wind"]["deg"],
411
+ "condition": item["weather"][0]["description"],
412
+ "visibility": item.get(
413
+ "visibility", "N/A"
414
+ ), # sometimes visibility may be missing
415
+ }
416
+ )
417
 
418
  # Process data to create daily summaries
419
  daily_summaries = {}
420
  for date_str, forecasts in forecast_data.items():
421
+ temps = [f["temp"] for f in forecasts]
422
+ feels_likes = [f["feels_like"] for f in forecasts]
423
+ humidities = [f["humidity"] for f in forecasts]
424
+ pressures = [f["pressure"] for f in forecasts]
425
+ wind_speeds = [f["wind_speed"] for f in forecasts]
426
+ conditions = [f["condition"] for f in forecasts]
427
 
428
  min_temp = min(temps)
429
  max_temp = max(temps)
 
438
  most_common_condition = condition_counts.most_common(1)[0][0]
439
 
440
  daily_summaries[date_str] = {
441
+ "min_temp": min_temp,
442
+ "max_temp": max_temp,
443
+ "avg_temp": avg_temp,
444
+ "avg_feels_like": avg_feels_like,
445
+ "avg_humidity": avg_humidity,
446
+ "avg_pressure": avg_pressure,
447
+ "avg_wind_speed": avg_wind_speed,
448
+ "condition": most_common_condition,
449
  }
450
 
451
  # Build the formatted string
452
+ city_name = weather_data["city"]["name"]
453
  ret_str = f"**5-Day Weather Forecast for {city_name}:**\n"
454
 
455
  for date_str in sorted(daily_summaries.keys()):
 
466
  return ret_str
467
 
468
 
469
+ llmmodel = OpenAI(api_token=os.environ["OPENAI_API_KEY"], model="gpt-4o")
470
 
471
  # Load dataframes
472
  dfcleaned = pd.read_csv("dfcleaned.csv")
473
+ dfcleaned["Timestamp"] = pd.to_datetime(dfcleaned["Timestamp"])
474
+ dfcleaned["off-nominal"] = dfcleaned["off-nominal"].apply(str)
475
  dfshaps = pd.read_csv("shaps.csv")
476
+ dfshaps["Timestamp"] = pd.to_datetime(dfshaps["Timestamp"])
477
 
478
  # Initialize Agent
479
  agent = Agent([dfcleaned, dfshaps], config={"llm": llmmodel})
 
482
  sdfcleaned = SmartDataframe(dfcleaned, config={"llm": llmmodel})
483
 
484
 
 
485
  def process_query(query):
486
  response = agent.chat(query) # Replace with your actual agent chat implementation
487
  print(response)
488
+
489
  # Initialize outputs and visibility flags
490
  text_output = None
491
  image_output = None
 
493
  text_visible = False
494
  image_visible = False
495
  dataframe_visible = False
496
+
497
  if isinstance(response, str) and ".png" not in response:
498
  text_output = response
499
  text_visible = True
500
  elif isinstance(response, str) and ".png" in response:
501
+ image_output = response # Assuming response is a filepath or URL to the image
502
+ image_visible = True
503
  elif isinstance(response, pd.DataFrame):
504
  dataframe_output = response
505
  dataframe_visible = True
506
+
507
  return (
508
  text_output,
509
  image_output,
510
  dataframe_output,
511
  gr.update(visible=text_visible),
512
  gr.update(visible=image_visible),
513
+ gr.update(visible=dataframe_visible),
514
  )
515
 
516
 
 
517
  def gradio_app():
518
  iface = gr.Interface(
519
  fn=process_query,
 
521
  outputs=[
522
  gr.Textbox(label="Response"),
523
  gr.Image(label="Plot"),
524
+ gr.DataFrame(label="Dataframe"),
525
  ],
526
  title="pandasai Query Processor",
527
+ description="Enter your query related to the csv data files.",
528
  )
529
  return iface
530
 
531
+
532
  with gr.Blocks(
533
+ # theme=gr.themes.Monochrome(primary_hue="green"),
534
+ theme=gr.themes.Soft(),
535
  ) as demo:
536
  with gr.Row(): # Combine the two weather functions into a single row
537
  with gr.Column():
538
+ location1 = gr.Textbox(
539
+ label="Enter location for weather (e.g., Rio Rancho, New Mexico)",
540
+ value="Cambridge, Massachusetts",
541
+ )
542
  weather_button = gr.Button("Get Weather")
543
+ # output1 = gr.Markdown(label="Weather Information")
544
+ output1 = gr.Textbox(
545
+ label="Weather Information",
546
+ lines=8,
547
+ max_lines=8,
548
+ show_label=True,
549
+ show_copy_button=True,
550
+ )
551
  weather_button.click(
552
  fn=update_weather,
553
  inputs=location1,
 
555
  api_name="update_weather",
556
  )
557
  with gr.Column():
558
+ location2 = gr.Textbox(
559
+ label="Enter location for weather forecast (e.g., Rio Rancho, New Mexico)",
560
+ value="Cambridge, Massachusetts",
561
+ )
562
  weather_forecast_button = gr.Button("Get 5-Day Weather Forecast")
563
+ # output2 = gr.Markdown(label="Weather Forecast Information")
564
+ output2 = gr.Textbox(
565
+ label="Weather 5-Day Forecast Information",
566
+ lines=8,
567
+ max_lines=8,
568
+ show_label=True,
569
+ show_copy_button=True,
570
+ )
571
  weather_forecast_button.click(
572
  fn=update_weather_forecast,
573
  inputs=location2,
 
576
  )
577
  gr.Markdown("# 📄 PDF Viewer Section")
578
  gr.Markdown("Select a PDF from the dropdown below to view it.")
579
+
580
  with gr.Accordion("Open PDF Selection", open=False):
581
  with gr.Row():
582
  # Assign a larger scale to the dropdown
 
584
  choices=pdf_files,
585
  label="Select a PDF",
586
  value=DEFAULT_PDF, # Set a default value
587
+ scale=1, # This component takes twice the space
588
  )
589
  # Assign a smaller scale to the PDF viewer
590
  pdf_viewer = PDF(
591
  label="PDF Viewer",
592
  interactive=True,
593
+ scale=3,
594
+ value=display_pdf(
595
+ DEFAULT_PDF
596
+ ), # This component takes half the space compared to dropdown
597
  )
598
+
599
  # Set up the event: when dropdown changes, update the PDF viewer
600
+ dropdown.change(fn=display_pdf, inputs=dropdown, outputs=pdf_viewer)
 
 
 
 
601
  with gr.Row():
602
  with gr.Column(scale=1):
603
  gr.Markdown("# Building Automation Assistant")
 
611
  # Update the ChatInterface to handle streaming
612
  chat_interface = gr.ChatInterface(
613
  chat,
614
+ # show_label=True,
615
+ # show_copy_button=True,
616
+ chatbot=gr.Chatbot(
617
+ height=750,
618
+ show_copy_button=True,
619
+ show_copy_all_button=True,
620
+ avatar_images=("user_avatar.png", "assistant_avatar.png"),
621
+ ),
622
  title="Ask Me Anything",
623
+ examples_per_page=5,
624
+ # theme="soft", # glass
625
  description="Type your question about building automation here.",
626
  examples=[
627
  "Give the weather forecast for Cambridge, MA",
 
634
  "What are the most common maintenance challenges faced by net-zero energy buildings?",
635
  "How does the Uponor Climate Control Network System contribute to building maintenance?",
636
  "What role do smart systems play in the maintenance of sustainable buildings like HouseZero?",
637
+ "Can you provide data on the energy performance of HouseZero over the past year?",
638
+ "Tell me about the HouseZero dataset. Retrieve information from the publication you have access to. Use your file retrieval tool.",
639
  "Describe in detail the relationshp between the columns and values in the uploaded CSV files and the information you have access to regarding the HouseZero dataset. Be verbose. Use your file retrieval tool.",
640
  "Please comment on the zone relative humidity features, specifically if they indicate a problem withthe building",
641
  "Give me in great detail any advice you have to maintain a small to midsize office building, like the HouseZero data corresponds to. Be verbose. Use your file retrieval tool.",
642
  "Is there any information in the datafiles that indicates a problem with the building?",
643
  "Show Massachusetts electricity billing rates during the same time span as the CSV data",
644
  "Use those rates and the relevant columns in the CSV files to estimate how much it costs to operate this building per month.",
645
+ "What is the estimated average electricity cost for operating the building using massachusetts energy rates. use your file retrieval tool. use data csv files for building data. Limit your response to 140 characters. Use your file retrieval tool.",
646
  "Based on the data in these CSV files, can you assign an EnergyIQ score from 1-10 that reflects how well the building is operating? Explain the reason for your score and provide any recommendations on actions to take that can improve it in the future. Be verbose. Use your file retrieval tool.",
647
  "Please summarize information concerning sensor networks that may be leading to faulty meaurements.",
648
  "Tell me how to properly install the PVC sky lights.",
649
  "Based on data and insights, what specific changes should be made to HouseZero's maintenance protocols?",
650
+ "what recommendations do you have to mitigate against high relative humidity zone measurements in structures like the housezero building?",
651
  ],
652
  fill_height=True,
653
  )
 
658
  # with gr.Column():
659
  # Define the three ScatterPlot components
660
  anomaly_plot = gr.ScatterPlot(
661
+ dfcleaned,
662
+ x="Timestamp",
663
+ y="Z5_RH",
664
  color="off-nominal",
665
+ title="Anomaly Score",
666
  )
667
+
668
  zone3_plot = gr.ScatterPlot(
669
  dfcleaned,
670
  x="Timestamp",
 
680
  color="off-nominal",
681
  title="Zone 4 Relative Humidity",
682
  )
683
+
684
+ # Group all plots into a list for easy management
685
  plots = [anomaly_plot, zone3_plot, zone4_plot]
686
 
687
  def select_region(selection: gr.SelectData):
 
696
  """
697
  if selection is None or selection.index is None:
698
  return [gr.Plot.update() for _ in plots]
699
+
700
  min_x, max_x = selection.index
701
+ # Update the x_lim for each plot
702
  return [gr.ScatterPlot(x_lim=(min_x, max_x)) for _ in plots]
703
 
704
  def reset_region():
 
710
  """
711
  return [gr.ScatterPlot(x_lim=None) for _ in plots]
712
 
713
+ # Attach event listeners to each plot
714
  for plot in plots:
715
  plot.select(
716
+ select_region, inputs=None, outputs=plots # Update all plots
 
 
717
  )
718
  plot.double_click(
719
+ reset_region, inputs=None, outputs=plots # Reset all plots
 
 
720
  )
721
 
722
+ # plots = [plt, first_plot, second_plot]
723
+
724
+ # def select_region(selection: gr.SelectData):
725
+ # min_w, max_w = selection.index
726
+ # return gr.ScatterPlot(x_lim=(min_w, max_w))
727
 
728
+ # for p in plots:
729
+ # p.select(select_region, None, plots)
730
+ # p.double_click(lambda: [gr.LinePlot(x_lim=None)] * len(plots), None, plots)
731
 
732
+ # second_plot.select(select_second_region, None, plt)
733
+ # second_plot.double_click(lambda: gr.ScatterPlot(x_lim=None), None, plt)
734
+ # gr.Column([anomaly_plot, first_plot, second_plot])
 
 
 
 
735
 
736
+ # anomaly_info = gr.Markdown("Anomaly detected around October 15, 2023")
737
  with gr.Column():
738
+ query = gr.Textbox(
739
+ label="Enter your question about the data",
740
+ value="Plot the anomaly_score as a function of time and highlight the highest 20 values",
741
+ )
742
  query_button = gr.Button("Submit Data Query")
743
  with gr.Row():
744
  with gr.Column(visible=False) as output_col1:
 
751
  fn=process_query,
752
  inputs=query,
753
  outputs=[
754
+ out1, # Text output
755
+ out2, # Image output
756
+ out3, # DataFrame output
757
+ output_col1, # Visibility for Text output
758
+ output_col2, # Visibility for Image output
759
+ output_col3, # Visibility for DataFrame output
760
  ],
761
+ api_name="process_query",
762
  )
763
+
764
  # hide visibility until its ready
765
+
 
766
  # Weather input
767
+ # with gr.Row():
768
+ # iface = gradio_app()
769
 
770
 
771
+ demo.launch(share=True)
requirements.txt CHANGED
@@ -1,14 +1,13 @@
1
- gradio
2
- gradio_datetimerange
3
- gradio_pdf
4
- matplotlib
5
- numpy
6
- openai
7
- pandas
8
- pandasai
9
- pyautogen
10
- python-dotenv
11
- Requests
12
- typing_extensions
13
- flaml[automl]
14
- tavily-python
 
1
+ gradio==5.0.0
2
+ gradio_datetimerange==0.0.1
3
+ gradio_pdf==0.0.16
4
+ matplotlib==3.7.5
5
+ numpy==1.23.5
6
+ openai==1.51.2
7
+ pandas==2.2.3
8
+ pandasai==2.2.15
9
+ pyautogen==0.3.0
10
+ python-dotenv==1.0.1
11
+ Requests==2.32.3
12
+ tavily_python==0.5.0
13
+ typing_extensions==3.10.0.2
 
shaps.csv CHANGED
The diff for this file is too large to render. See raw diff
 
usedpdfs/resitable.pdf CHANGED
Binary files a/usedpdfs/resitable.pdf and b/usedpdfs/resitable.pdf differ