9
9
10
10
from sql import inspect
11
11
from sql .run import run
12
- from sql .connection import ConnectionManager
12
+ from sqlalchemy import create_engine
13
+ from sql .connection import SQLAlchemyConnection
13
14
from sql .magic import SqlMagic , load_ipython_extension
14
15
from IPython .core .interactiveshell import InteractiveShell
15
16
from sql .plot import boxplot , histogram
18
19
from chat import *
19
20
20
21
from matplotlib import pyplot as plt
22
+
21
23
plt .switch_backend ("agg" )
22
24
23
25
css = """
51
53
52
54
53
55
def gen_name ():
54
- return str (uuid .uuid4 ())[:8 ] + ' .csv'
56
+ return str (uuid .uuid4 ())[:8 ] + " .csv"
55
57
56
58
57
59
def load_data (name ):
58
60
run .run_statements (conn , "drop table if exists my_data" , sqlmagic )
59
- run .run_statements (conn , f"create table my_data as (select * from '{ name } ')" , sqlmagic )
61
+ run .run_statements (
62
+ conn , f"create table my_data as (select * from '{ name } ')" , sqlmagic
63
+ )
60
64
cols = inspect .get_columns ("my_data" )
61
65
return cols
62
66
63
67
64
68
def delete_data ():
65
69
run .run_statements (conn , "drop table if exists my_data" , sqlmagic )
66
70
71
+
67
72
ip = InteractiveShell ()
68
73
69
74
sqlmagic = SqlMagic (shell = ip )
70
75
sqlmagic .feedback = 1
71
76
sqlmagic .autopandas = True
72
77
load_ipython_extension (ip )
73
78
74
- conn = ConnectionManager .set (
75
- "duckdb://" ,
76
- displaycon = True ,
77
- connect_args = {},
78
- creator = None ,
79
- alias = None ,
80
- config = sqlmagic ,
81
- )
79
+ conn = SQLAlchemyConnection (create_engine ("duckdb://" ), config = sqlmagic )
82
80
83
81
84
82
class State :
@@ -95,7 +93,9 @@ def load_sample():
95
93
State .reset ()
96
94
name = gen_name ()
97
95
State .loading_data .value = True
98
- url = "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
96
+ url = (
97
+ "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv"
98
+ )
99
99
response = requests .get (url )
100
100
if response .status_code == 200 :
101
101
with open (name , "wb" ) as f :
@@ -118,7 +118,7 @@ def load_from_file(file):
118
118
try :
119
119
df = pd .read_csv (file ["file_obj" ])
120
120
df .columns = df .columns .str .strip ()
121
- df .columns = df .columns .str .replace (' ' , '_' )
121
+ df .columns = df .columns .str .replace (" " , "_" )
122
122
df .to_csv (name , index = False )
123
123
cols = load_data (name )
124
124
State .upload_data .value = True
@@ -145,33 +145,38 @@ def chat_with_gpt3(prompts):
145
145
{"role" : "system" , "content" : State .initial_prompt .value },
146
146
{"role" : "user" , "content" : "Show me the first 5 rows" },
147
147
{"role" : "assistant" , "content" : "SELECT * FROM my_data LIMIT 5" },
148
- ] + [{"role" : prompt .role , "content" : prompt .content } for prompt in prompts ],
148
+ ]
149
+ + [{"role" : prompt .role , "content" : prompt .content } for prompt in prompts ],
149
150
temperature = 0.1 ,
150
- stream = True
151
+ stream = True ,
151
152
)
152
153
153
154
total = ""
154
155
for chunk in response :
155
- part = chunk [' choices' ][0 ][' delta' ].get ("content" , "" )
156
+ part = chunk [" choices" ][0 ][" delta" ].get ("content" , "" )
156
157
total += part
157
158
yield total
158
159
159
160
160
161
@solara .component
161
162
def Chat () -> None :
162
- solara .Style ("""
163
+ solara .Style (
164
+ """
163
165
.chat-input {
164
166
max-width: 800px;
165
167
})
166
- """ )
167
-
168
- messages , set_messages = solara .use_state ([
169
- Message (
170
- role = "assistant" ,
171
- content = f"Welcome. Please post your queries!" ,
172
- df = None ,
173
- fig = None )
174
- ]
168
+ """
169
+ )
170
+
171
+ messages , set_messages = solara .use_state (
172
+ [
173
+ Message (
174
+ role = "assistant" ,
175
+ content = f"Welcome. Please post your queries!" ,
176
+ df = None ,
177
+ fig = None ,
178
+ )
179
+ ]
175
180
)
176
181
input , set_input = solara .use_state ("" )
177
182
@@ -184,46 +189,91 @@ def ask_chatgpt():
184
189
set_messages (_messages )
185
190
if State .initial_prompt .value :
186
191
final = None
187
- for command in State .chat_with_gpt3 ([Message (role = "user" , content = user_input , df = None , fig = None )]):
192
+ for command in State .chat_with_gpt3 (
193
+ [Message (role = "user" , content = user_input , df = None , fig = None )]
194
+ ):
188
195
final = command
189
196
190
197
if final .startswith ("%sqlplot" ):
191
198
try :
192
199
_ , name , column = final .split (" " )
193
200
except Exception as e :
194
- error_message = "Sorry, we couldn't run your query on the data. " \
195
- "Please ensure you specify a relevant column."
196
- set_messages (_messages + [Message (role = "assistant" , content = error_message , df = None , fig = None )])
201
+ error_message = (
202
+ "Sorry, we couldn't run your query on the data. "
203
+ "Please ensure you specify a relevant column."
204
+ )
205
+ set_messages (
206
+ _messages
207
+ + [
208
+ Message (
209
+ role = "assistant" ,
210
+ content = error_message ,
211
+ df = None ,
212
+ fig = None ,
213
+ )
214
+ ]
215
+ )
197
216
return
198
217
199
218
fig = Figure ()
200
219
ax = fig .subplots ()
201
220
202
- fn_map = {"histogram" : partial (histogram , bins = 50 ),
203
- "boxplot" : boxplot }
221
+ fn_map = {"histogram" : partial (histogram , bins = 50 ), "boxplot" : boxplot }
204
222
205
223
fn = fn_map [name ]
206
224
try :
207
225
ax = fn ("my_data" , column , ax = ax )
208
- set_messages (_messages + [Message (role = "assistant" , content = "" , df = None , fig = fig )])
226
+ set_messages (
227
+ _messages
228
+ + [Message (role = "assistant" , content = "" , df = None , fig = fig )]
229
+ )
209
230
except Exception as e :
210
- set_messages (_messages + [
211
- Message (role = "assistant" , content = "Please pass relevant columns" , df = None , fig = None )])
231
+ set_messages (
232
+ _messages
233
+ + [
234
+ Message (
235
+ role = "assistant" ,
236
+ content = "Please pass relevant columns" ,
237
+ df = None ,
238
+ fig = None ,
239
+ )
240
+ ]
241
+ )
212
242
else :
213
243
error = "Sorry, we couldn't run your query on the data"
214
244
try :
215
245
query_result = run .run_statements (conn , final , sqlmagic )
216
- set_messages (_messages + [Message (role = "assistant" , content = "" , df = query_result , fig = None )])
246
+ set_messages (
247
+ _messages
248
+ + [
249
+ Message (
250
+ role = "assistant" , content = "" , df = query_result , fig = None
251
+ )
252
+ ]
253
+ )
217
254
except ProgrammingError as e :
218
- set_messages (_messages + [
219
- Message (role = "assistant" , content = error , df = None , fig = None )])
255
+ set_messages (
256
+ _messages
257
+ + [Message (role = "assistant" , content = error , df = None , fig = None )]
258
+ )
220
259
except Exception as e :
221
- set_messages (_messages + [
222
- Message (role = "assistant" , content = error , df = None , fig = None )])
260
+ set_messages (
261
+ _messages
262
+ + [Message (role = "assistant" , content = error , df = None , fig = None )]
263
+ )
223
264
224
265
else :
225
- set_messages (_messages + [Message (role = "assistant" ,
226
- content = "Please load some data first!" , df = None , fig = None )])
266
+ set_messages (
267
+ _messages
268
+ + [
269
+ Message (
270
+ role = "assistant" ,
271
+ content = "Please load some data first!" ,
272
+ df = None ,
273
+ fig = None ,
274
+ )
275
+ ]
276
+ )
227
277
228
278
with solara .VBox ():
229
279
for message in messages :
@@ -249,40 +299,64 @@ def Page():
249
299
solara .Text ("Data Querying and Visualisation App" )
250
300
251
301
with solara .Card (title = "About" , elevation = 6 , style = "background-color: #f5f5f5;" ):
252
- solara .Markdown ("""
302
+ solara .Markdown (
303
+ """
253
304
Interact with your data using natural language.
254
305
255
306
Examples: <br>
256
307
- show me the unique values of column {column name} <br>
257
308
- create a histogram of {column name} <br>
258
- - create a boxplot of {column name}""" )
309
+ - create a boxplot of {column name}"""
310
+ )
259
311
260
312
with solara .Sidebar ():
261
313
with solara .Card ("Controls" , margin = 0 , elevation = 0 ):
262
314
with solara .Column ():
263
315
with solara .Row ():
264
- solara .Button ("Sample dataset" , color = "primary" , text = True , outlined = True ,
265
- on_click = State .load_sample )
266
- solara .Button ("Clear dataset" , color = "primary" , text = True , outlined = True , on_click = State .reset )
267
- FileDrop (on_file = State .load_from_file , on_total_progress = lambda * args : None ,
268
- label = "Drag a .csv file here" )
316
+ solara .Button (
317
+ "Sample dataset" ,
318
+ color = "primary" ,
319
+ text = True ,
320
+ outlined = True ,
321
+ on_click = State .load_sample ,
322
+ )
323
+ solara .Button (
324
+ "Clear dataset" ,
325
+ color = "primary" ,
326
+ text = True ,
327
+ outlined = True ,
328
+ on_click = State .reset ,
329
+ )
330
+ FileDrop (
331
+ on_file = State .load_from_file ,
332
+ on_total_progress = lambda * args : None ,
333
+ label = "Drag a .csv file here" ,
334
+ )
269
335
if State .loading_data .value :
270
336
with solara .Div ():
271
337
solara .Text ("Loading csv..." )
272
338
solara .ProgressLinear (True )
273
339
if initial_prompt :
274
- solara .InputInt ("Number of preview rows" , value = State .results , continuous_update = True )
340
+ solara .InputInt (
341
+ "Number of preview rows" ,
342
+ value = State .results ,
343
+ continuous_update = True ,
344
+ )
275
345
276
346
solara .Markdown ("Hosted in [Ploomber Cloud](https://ploomber.io/)" )
277
347
278
348
if sample_data_loaded :
279
349
solara .Info ("Sample data is loaded" )
280
- sql_output = run .run_statements (conn , f"select * from my_data limit { results } " , sqlmagic )
350
+ sql_output = run .run_statements (
351
+ conn , f"select * from my_data limit { results } " , sqlmagic
352
+ )
281
353
solara .DataFrame (sql_output , items_per_page = 10 )
282
354
283
355
if upload_data :
284
356
solara .Info ("Data is successfully uploaded" )
285
- sql_output = run .run_statements (conn , f"select * from my_data limit { results } " , sqlmagic )
357
+ sql_output = run .run_statements (
358
+ conn , f"select * from my_data limit { results } " , sqlmagic
359
+ )
286
360
solara .DataFrame (sql_output , items_per_page = 10 )
287
361
288
362
if upload_data_error :
@@ -293,7 +367,9 @@ def Page():
293
367
294
368
solara .Style (css )
295
369
with solara .VBox (classes = ["main" ]):
296
- solara .HTML (tag = "h3" , style = "margin: auto;" , unsafe_innerHTML = "Chat with your data" )
370
+ solara .HTML (
371
+ tag = "h3" , style = "margin: auto;" , unsafe_innerHTML = "Chat with your data"
372
+ )
297
373
298
374
Chat ()
299
375
@@ -302,4 +378,3 @@ def Page():
302
378
def Layout (children ):
303
379
route , routes = solara .use_route ()
304
380
return solara .AppLayout (children = children )
305
-
0 commit comments