Update app.py
Browse files
app.py
CHANGED
@@ -4,6 +4,8 @@ import openai
|
|
4 |
import duckdb
|
5 |
import gradio as gr
|
6 |
from functools import lru_cache
|
|
|
|
|
7 |
|
8 |
# =========================
|
9 |
# Configuration and Setup
|
@@ -14,11 +16,8 @@ openai.api_key = os.getenv("OPENAI_API_KEY")
|
|
14 |
if not openai.api_key:
|
15 |
raise ValueError("Please set the OPENAI_API_KEY environment variable.")
|
16 |
|
17 |
-
from dotenv import load_dotenv
|
18 |
load_dotenv()
|
19 |
-
|
20 |
-
|
21 |
-
sbx = Sandbox() # By default the sandbox is alive for 5 minutes
|
22 |
|
23 |
# Path to your Parquet dataset
|
24 |
DATASET_PATH = 'hsas.parquet' # Update with your Parquet file path
|
@@ -175,7 +174,6 @@ with gr.Blocks(css="""
|
|
175 |
]
|
176 |
btn_queries = [gr.Button(q, variant="secondary", size="sm") for q in query_buttons]
|
177 |
|
178 |
-
# Removed gr.Box and used gr.Group as an alternative
|
179 |
with gr.Group():
|
180 |
query_input = gr.Textbox(
|
181 |
label="π Your Query",
|
@@ -194,6 +192,32 @@ with gr.Blocks(css="""
|
|
194 |
with gr.Column(scale=2, min_width=600):
|
195 |
gr.Markdown("### π Query Results", elem_classes="results")
|
196 |
results_out = gr.Dataframe(label="Query Results", interactive=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
|
198 |
with gr.Tab("π Dataset Schema", elem_classes="schema-tab"):
|
199 |
gr.Markdown("### Dataset Schema")
|
@@ -204,15 +228,6 @@ with gr.Blocks(css="""
|
|
204 |
# =========================
|
205 |
|
206 |
def generate_sql(nl_query):
|
207 |
-
"""
|
208 |
-
Generates SQL from a natural language query.
|
209 |
-
|
210 |
-
Args:
|
211 |
-
nl_query (str): The natural language query.
|
212 |
-
|
213 |
-
Returns:
|
214 |
-
tuple: The SQL query, error message (if any), and visibility update.
|
215 |
-
"""
|
216 |
if not nl_query.strip():
|
217 |
return "", "<p class='error-message'>Please enter a query.</p>", gr.update(visible=True)
|
218 |
sql_query, error = parse_query(nl_query)
|
@@ -222,15 +237,6 @@ with gr.Blocks(css="""
|
|
222 |
return sql_query, "", gr.update(visible=False)
|
223 |
|
224 |
def execute_query(sql_query):
|
225 |
-
"""
|
226 |
-
Executes the generated SQL query.
|
227 |
-
|
228 |
-
Args:
|
229 |
-
sql_query (str): The SQL query to execute.
|
230 |
-
|
231 |
-
Returns:
|
232 |
-
tuple: The result dataframe, error message (if any), and visibility update.
|
233 |
-
"""
|
234 |
if not sql_query.strip():
|
235 |
return None, "<p class='error-message'>No SQL query to execute.</p>", gr.update(visible=True)
|
236 |
result_df, error = execute_sql_query(sql_query)
|
@@ -240,15 +246,6 @@ with gr.Blocks(css="""
|
|
240 |
return result_df, "", gr.update(visible=False)
|
241 |
|
242 |
def handle_example_click(example_query):
|
243 |
-
"""
|
244 |
-
Handles clicks on example query buttons.
|
245 |
-
|
246 |
-
Args:
|
247 |
-
example_query (str): The example query text.
|
248 |
-
|
249 |
-
Returns:
|
250 |
-
tuple: The SQL query, error message (if any), result dataframe, and visibility update.
|
251 |
-
"""
|
252 |
if example_query.strip().upper().startswith("SELECT"):
|
253 |
sql_query = example_query
|
254 |
result_df, error = execute_sql_query(sql_query)
|
@@ -264,12 +261,9 @@ with gr.Blocks(css="""
|
|
264 |
if exec_error:
|
265 |
return sql_query, f"<p class='error-message'>{exec_error}</p>", None, gr.update(visible=True)
|
266 |
else:
|
267 |
-
return sql_query, "", result_df, gr.update(visible
|
268 |
|
269 |
-
# =========================
|
270 |
# Button Click Event Handlers
|
271 |
-
# =========================
|
272 |
-
|
273 |
btn_generate_sql.click(
|
274 |
fn=generate_sql,
|
275 |
inputs=query_input,
|
@@ -289,7 +283,6 @@ with gr.Blocks(css="""
|
|
289 |
outputs=[sql_query_out, error_out, results_out, error_out],
|
290 |
)
|
291 |
|
292 |
-
# Clear error messages when inputs change
|
293 |
query_input.change(fn=lambda: ("", gr.update(visible=False)), inputs=None, outputs=[error_out])
|
294 |
sql_query_out.change(fn=lambda: ("", gr.update(visible=False)), inputs=None, outputs=[error_out])
|
295 |
|
@@ -302,5 +295,5 @@ if __name__ == "__main__":
|
|
302 |
server_name="0.0.0.0",
|
303 |
server_port=7860,
|
304 |
share=False,
|
305 |
-
debug=True,
|
306 |
)
|
|
|
4 |
import duckdb
|
5 |
import gradio as gr
|
6 |
from functools import lru_cache
|
7 |
+
from dotenv import load_dotenv
|
8 |
+
from e2b_code_interpreter import Sandbox
|
9 |
|
10 |
# =========================
|
11 |
# Configuration and Setup
|
|
|
16 |
if not openai.api_key:
|
17 |
raise ValueError("Please set the OPENAI_API_KEY environment variable.")
|
18 |
|
|
|
19 |
load_dotenv()
|
20 |
+
sbx = Sandbox() # By default, the sandbox is alive for 5 minutes
|
|
|
|
|
21 |
|
22 |
# Path to your Parquet dataset
|
23 |
DATASET_PATH = 'hsas.parquet' # Update with your Parquet file path
|
|
|
174 |
]
|
175 |
btn_queries = [gr.Button(q, variant="secondary", size="sm") for q in query_buttons]
|
176 |
|
|
|
177 |
with gr.Group():
|
178 |
query_input = gr.Textbox(
|
179 |
label="π Your Query",
|
|
|
192 |
with gr.Column(scale=2, min_width=600):
|
193 |
gr.Markdown("### π Query Results", elem_classes="results")
|
194 |
results_out = gr.Dataframe(label="Query Results", interactive=False)
|
195 |
+
btn_copy_results = gr.Button("Copy to Clipboard", variant="secondary", size="sm")
|
196 |
+
|
197 |
+
# JavaScript for copying to clipboard
|
198 |
+
copy_script = gr.HTML("""
|
199 |
+
<script>
|
200 |
+
function copyToClipboard() {
|
201 |
+
const resultsTable = document.querySelector(".dataframe-output table");
|
202 |
+
if (resultsTable) {
|
203 |
+
const range = document.createRange();
|
204 |
+
range.selectNode(resultsTable);
|
205 |
+
window.getSelection().removeAllRanges();
|
206 |
+
window.getSelection().addRange(range);
|
207 |
+
document.execCommand("copy");
|
208 |
+
window.getSelection().removeAllRanges();
|
209 |
+
alert("Copied results to clipboard!");
|
210 |
+
} else {
|
211 |
+
alert("No results to copy!");
|
212 |
+
}
|
213 |
+
}
|
214 |
+
</script>
|
215 |
+
""")
|
216 |
+
|
217 |
+
# Connect JavaScript function to button
|
218 |
+
btn_copy_results.click(
|
219 |
+
None, None, None, _js="copyToClipboard"
|
220 |
+
)
|
221 |
|
222 |
with gr.Tab("π Dataset Schema", elem_classes="schema-tab"):
|
223 |
gr.Markdown("### Dataset Schema")
|
|
|
228 |
# =========================
|
229 |
|
230 |
def generate_sql(nl_query):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
if not nl_query.strip():
|
232 |
return "", "<p class='error-message'>Please enter a query.</p>", gr.update(visible=True)
|
233 |
sql_query, error = parse_query(nl_query)
|
|
|
237 |
return sql_query, "", gr.update(visible=False)
|
238 |
|
239 |
def execute_query(sql_query):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
if not sql_query.strip():
|
241 |
return None, "<p class='error-message'>No SQL query to execute.</p>", gr.update(visible=True)
|
242 |
result_df, error = execute_sql_query(sql_query)
|
|
|
246 |
return result_df, "", gr.update(visible=False)
|
247 |
|
248 |
def handle_example_click(example_query):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
if example_query.strip().upper().startswith("SELECT"):
|
250 |
sql_query = example_query
|
251 |
result_df, error = execute_sql_query(sql_query)
|
|
|
261 |
if exec_error:
|
262 |
return sql_query, f"<p class='error-message'>{exec_error}</p>", None, gr.update(visible=True)
|
263 |
else:
|
264 |
+
return sql_query, "", result_df, gr.update(visible=False)
|
265 |
|
|
|
266 |
# Button Click Event Handlers
|
|
|
|
|
267 |
btn_generate_sql.click(
|
268 |
fn=generate_sql,
|
269 |
inputs=query_input,
|
|
|
283 |
outputs=[sql_query_out, error_out, results_out, error_out],
|
284 |
)
|
285 |
|
|
|
286 |
query_input.change(fn=lambda: ("", gr.update(visible=False)), inputs=None, outputs=[error_out])
|
287 |
sql_query_out.change(fn=lambda: ("", gr.update(visible=False)), inputs=None, outputs=[error_out])
|
288 |
|
|
|
295 |
server_name="0.0.0.0",
|
296 |
server_port=7860,
|
297 |
share=False,
|
298 |
+
debug=True,
|
299 |
)
|