P-Karthik-Mohan commited on
Commit
ee70dbf
Β·
1 Parent(s): 2c0f06f

Remove unused files... final clean submission:)

Browse files
Files changed (2) hide show
  1. make_awesome.py +0 -398
  2. ui.py +0 -86
make_awesome.py DELETED
@@ -1,398 +0,0 @@
1
- import os
2
- import re
3
-
4
- # 1. Update requirements.txt
5
- req_txt = "requirements.txt"
6
- with open(req_txt, "r") as f:
7
- reqs = f.read()
8
- if "gradio" not in reqs:
9
- with open(req_txt, "a") as f:
10
- f.write("\ngradio==4.44.0\npandas\n")
11
-
12
- # 2. Create the Gradio UI file (ui.py)
13
- ui_code = """
14
- import gradio as gr
15
- import requests
16
- import pandas as pd
17
- import json
18
- import uuid
19
-
20
- ENV_BASE_URL = "http://127.0.0.1:7860"
21
-
22
- def new_session():
23
- return str(uuid.uuid4())
24
-
25
- def load_task(task_id, sid):
26
- try:
27
- task_num = int(task_id.split()[1])
28
- r = requests.post(f"{ENV_BASE_URL}/api/reset", json={"task_id": task_num, "session_id": sid})
29
- if r.status_code != 200:
30
- return f"Error: {r.text}", "", "", pd.DataFrame(), f"Error loading task {task_num}"
31
-
32
- data = r.json()
33
- obs = data["observation"]
34
- return obs["task_description"], obs["schema"], obs["hint"], pd.DataFrame(), "Task loaded. Write SQL below."
35
- except Exception as e:
36
- return str(e), "", "", pd.DataFrame(), "Error loading task"
37
-
38
- def run_sql(sql, sid):
39
- if not sql.strip():
40
- return pd.DataFrame(), "Please enter a SQL query.", "Error"
41
- try:
42
- r = requests.post(f"{ENV_BASE_URL}/api/step", json={"action": sql, "session_id": sid})
43
- data = r.json()
44
- obs = data.get("observation", {})
45
- reward = data.get("reward", 0.0)
46
- done = data.get("done", False)
47
-
48
- df = pd.DataFrame(obs.get("result_preview", []))
49
- breakdown = obs.get("reward_breakdown", {})
50
-
51
- feedback = f"🎯 Reward: {reward:.2f} / 1.0\\n"
52
- if breakdown:
53
- feedback += f"Columns: {breakdown.get('column_score',0):.2f}, Rows: {breakdown.get('row_score',0):.2f}, Values: {breakdown.get('value_score',0):.2f}"
54
- if "error" in obs:
55
- feedback += f"\\n\\n⚠️ Error: {obs['error']}"
56
-
57
- return df, feedback, "βœ… SOLVED!" if done else "Keep trying!"
58
- except Exception as e:
59
- return pd.DataFrame(), str(e), "Error"
60
-
61
- def build_ui():
62
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as demo:
63
- gr.Markdown("# πŸ“Š SQL Analyst OpenEnv - Hackathon Edition")
64
- gr.Markdown("Test Human or AI performance on realistic E-Commerce SQL Data tasks. [API served at `/api`]")
65
-
66
- sid = gr.State(new_session)
67
-
68
- with gr.Row():
69
- with gr.Column(scale=1):
70
- task_dropdown = gr.Dropdown(choices=["Task 1 (Easy)", "Task 2 (Medium)", "Task 3 (Hard)", "Task 4 (Medium)", "Task 5 (Hard)"], value="Task 1 (Easy)", label="Select Task")
71
- btn_load = gr.Button("πŸ”„ Load Task")
72
-
73
- desc = gr.Textbox(label="Business Question", interactive=False, lines=2)
74
- hint = gr.Textbox(label="Hint", interactive=False)
75
- schema = gr.Code(label="Database Schema", language="sql", interactive=False)
76
-
77
- with gr.Column(scale=2):
78
- sql_input = gr.Code(label="SQL Editor", language="sql", lines=10)
79
- btn_run = gr.Button("πŸš€ Run SQL", variant="primary")
80
-
81
- status_out = gr.Markdown("Ready.")
82
- feedback_out = gr.Textbox(label="Feedback & Score", interactive=False)
83
- grid_out = gr.Dataframe(label="Result Preview (First 5 Rows)")
84
-
85
- btn_load.click(load_task, inputs=[task_dropdown, sid], outputs=[desc, schema, hint, grid_out, feedback_out])
86
- btn_run.click(run_sql, inputs=[sql_input, sid], outputs=[grid_out, feedback_out, status_out])
87
-
88
- return demo
89
- """
90
- with open("ui.py", "w", encoding="utf-8") as f:
91
- f.write(ui_code.strip() + "\n")
92
-
93
- # 3. Rewrite main.py (adding concurrency fixes, security, and mounting gradio)
94
- main_py_code = """
95
- import sqlite3
96
- import os
97
- import json
98
- import re
99
- from datetime import datetime
100
- from typing import Any, Optional
101
- import uuid
102
-
103
- from fastapi import FastAPI, HTTPException
104
- from pydantic import BaseModel, Field
105
- import gradio as gr
106
- from ui import build_ui
107
-
108
- # ── Config ────────────────────────────────────────────────────────────────────
109
- DB_PATH = os.path.join("data", "ecommerce.db")
110
- # Under /api for direct agent access, root for UI
111
- api_app = FastAPI(title="SQL Analyst OpenEnv API", version="1.1.0")
112
-
113
- # ── Pydantic Models ───────────────────────────────────────────────────────────
114
-
115
- class StepRequest(BaseModel):
116
- session_id: str = "default"
117
- action: str
118
-
119
- class StepResponse(BaseModel):
120
- observation: dict
121
- reward: float
122
- done: bool
123
- info: dict
124
-
125
- class ResetRequest(BaseModel):
126
- task_id: int
127
- session_id: str = "default"
128
-
129
- class ResetResponse(BaseModel):
130
- observation: dict
131
- info: dict
132
-
133
- class StateRequest(BaseModel):
134
- session_id: str = "default"
135
-
136
- class StateResponse(BaseModel):
137
- session_id: str
138
- task_id: Optional[int]
139
- task_description: Optional[str]
140
- schema_info: str
141
- attempts: int
142
- best_reward: float
143
- history: list
144
-
145
- # ── Task Definitions ──────────────────────────────────────────────────────────
146
-
147
- TASKS = {
148
- 1: {
149
- "description": "Find the total number of completed orders placed in the year 2024. Return a single number with column name: total_orders",
150
- "difficulty": "easy",
151
- "hint": "Use COUNT with WHERE filters on status and order_date",
152
- "answer_query": "SELECT COUNT(*) AS total_orders FROM orders WHERE status = 'completed' AND order_date LIKE '2024%'",
153
- },
154
- 2: {
155
- "description": "Find the top 5 customers by total revenue (sum of total_amount for completed orders only). Return columns: first_name, last_name, total_revenue. Order by total_revenue descending.",
156
- "difficulty": "medium",
157
- "hint": "JOIN orders with customers, GROUP BY customer, filter completed, ORDER and LIMIT",
158
- "answer_query": "SELECT c.first_name, c.last_name, ROUND(SUM(o.total_amount), 2) AS total_revenue FROM orders o JOIN customers c ON o.customer_id = c.customer_id WHERE o.status = 'completed' GROUP BY o.customer_id ORDER BY total_revenue DESC LIMIT 5",
159
- },
160
- 3: {
161
- "description": "For each product category, calculate the total revenue (completed orders only) and rank categories by revenue using a window function. Return columns: category, total_revenue, revenue_rank. Order by revenue_rank ascending.",
162
- "difficulty": "hard",
163
- "hint": "Use SUM with GROUP BY inside a CTE, then apply RANK() OVER (ORDER BY ...) on the result",
164
- "answer_query": "WITH category_revenue AS ( SELECT p.category, SUM(o.total_amount) AS total_revenue FROM orders o JOIN products p ON o.product_id = p.product_id WHERE o.status = 'completed' GROUP BY p.category ) SELECT category, total_revenue, RANK() OVER (ORDER BY total_revenue DESC) AS revenue_rank FROM category_revenue ORDER BY revenue_rank ASC",
165
- },
166
- 4: {
167
- "description": "Find the average price of products in each category, but only for categories that have more than 2 products. Return columns: category, avg_price.",
168
- "difficulty": "medium",
169
- "hint": "Use GROUP BY with HAVING COUNT(...) > 2.",
170
- "answer_query": "SELECT category, ROUND(AVG(price), 2) AS avg_price FROM products GROUP BY category HAVING COUNT(product_id) > 2",
171
- },
172
- 5: {
173
- "description": "Identify customers who have ordered products from both the 'Electronics' and 'Clothing' categories. Return columns: customer_id, first_name.",
174
- "difficulty": "hard",
175
- "hint": "Use INTERSECT on two queries, or GROUP BY customer HAVING COUNT(DISTINCT category) = 2.",
176
- "answer_query": "SELECT DISTINCT c.customer_id, c.first_name FROM customers c JOIN orders o ON c.customer_id = o.customer_id JOIN products p ON o.product_id = p.product_id WHERE p.category = 'Electronics' INTERSECT SELECT DISTINCT c.customer_id, c.first_name FROM customers c JOIN orders o ON c.customer_id = o.customer_id JOIN products p ON o.product_id = p.product_id WHERE p.category = 'Clothing'",
177
- },
178
- }
179
-
180
- # ── Sessions ──────────────────────────────────────────────────────────────────
181
-
182
- sessions = {}
183
-
184
- def get_session(sid: str):
185
- if sid not in sessions:
186
- sessions[sid] = {
187
- "task_id": None, "task": None,
188
- "expected_rows": None, "expected_columns": None,
189
- "attempts": 0, "best_reward": 0.0, "history": []
190
- }
191
- return sessions[sid]
192
-
193
- # ── Database Helpers ──────────────────────────────────────────────────────────
194
-
195
- def progress_handler():
196
- raise sqlite3.OperationalError("Query execution aborted: Timed out or exceeded instruction limits. Hint: Too complex CROSS JOIN?")
197
-
198
- def get_connection():
199
- if not os.path.exists(DB_PATH):
200
- raise HTTPException(status_code=500, detail=f"Database not found at {DB_PATH}.")
201
- conn = sqlite3.connect(DB_PATH)
202
- conn.row_factory = sqlite3.Row
203
- # Security feature: Prevent DOS
204
- conn.set_progress_handler(progress_handler, 500000)
205
- return conn
206
-
207
- def get_schema_info() -> str:
208
- conn = get_connection()
209
- cur = conn.cursor()
210
- schema_parts = []
211
- cur.execute("SELECT name FROM sqlite_master WHERE type='table'")
212
- tables = [r["name"] for r in cur.fetchall()]
213
- for table in tables:
214
- cur.execute(f"PRAGMA table_info({table})")
215
- cols = cur.fetchall()
216
- col_defs = ", ".join(f"{c['name']} {c['type']}" for c in cols)
217
- cur.execute(f"SELECT COUNT(*) AS n FROM {table}")
218
- count = cur.fetchone()["n"]
219
- schema_parts.append(f" {table} ({col_defs}) -- {count} rows")
220
- conn.close()
221
- return "Tables:\\n" + "\\n".join(schema_parts)
222
-
223
- def run_query(sql: str) -> tuple[list[dict], list[str]]:
224
- conn = get_connection()
225
- cur = conn.cursor()
226
- cur.execute(sql)
227
- columns = [d[0] for d in cur.description] if cur.description else []
228
- rows = [dict(zip(columns, row)) for row in cur.fetchall()]
229
- conn.close()
230
- return rows, columns
231
-
232
- def compute_expected(sid: str):
233
- session = get_session(sid)
234
- task = session["task"]
235
- rows, columns = run_query(task["answer_query"])
236
- session["expected_rows"] = rows
237
- session["expected_columns"] = columns
238
-
239
- # ── Reward Function ───────────────────────────────────────────────────────────
240
-
241
- def compute_reward(sid: str, agent_rows: list[dict], agent_cols: list[str]) -> tuple[float, dict]:
242
- session = get_session(sid)
243
- expected_rows = session["expected_rows"]
244
- expected_cols = session["expected_columns"]
245
- details = {}
246
-
247
- agent_cols_lower = [c.lower() for c in agent_cols]
248
- expected_cols_lower = [c.lower() for c in expected_cols]
249
- col_matches = sum(1 for c in expected_cols_lower if c in agent_cols_lower)
250
- col_score = (col_matches / len(expected_cols_lower)) * 0.30 if expected_cols_lower else 0.0
251
- details["column_score"] = round(col_score, 3)
252
-
253
- expected_count = len(expected_rows)
254
- agent_count = len(agent_rows)
255
- if expected_count == 0:
256
- row_score = 0.30 if agent_count == 0 else 0.0
257
- else:
258
- row_ratio = min(agent_count, expected_count) / max(agent_count, expected_count)
259
- row_score = row_ratio * 0.30
260
- details["row_score"] = round(row_score, 3)
261
-
262
- if not expected_rows or not agent_rows:
263
- value_score = 0.0
264
- else:
265
- def normalize(v):
266
- if v is None: return ""
267
- try: return str(round(float(v), 1))
268
- except: return str(v).strip().lower()
269
-
270
- matched_cells = 0
271
- total_cells = len(expected_rows) * len(expected_cols_lower)
272
-
273
- for exp_row, agt_row in zip(expected_rows, agent_rows):
274
- for col in expected_cols_lower:
275
- exp_val = normalize(exp_row.get(col) or exp_row.get(col.upper()))
276
- agt_val = normalize(agt_row.get(col) or agt_row.get(col.upper()))
277
- if not agt_val:
278
- exp_idx = expected_cols_lower.index(col)
279
- if exp_idx < len(agent_cols):
280
- pos_col = agent_cols[exp_idx]
281
- agt_val = normalize(agt_row.get(pos_col))
282
- if exp_val == agt_val:
283
- matched_cells += 1
284
-
285
- value_score = (matched_cells / total_cells) * 0.40 if total_cells > 0 else 0.0
286
- details["value_score"] = round(value_score, 3)
287
-
288
- total = round(col_score + row_score + value_score, 3)
289
- details["total_reward"] = total
290
- return total, details
291
-
292
- # ── Endpoints ─────────────────────────────────────────────────────────────────
293
-
294
- @api_app.post("/reset", response_model=ResetResponse)
295
- def reset(req: ResetRequest):
296
- if req.task_id not in TASKS: raise HTTPException(status_code=400, detail="Invalid task_id")
297
- session = get_session(req.session_id)
298
- session["task_id"] = req.task_id
299
- session["task"] = TASKS[req.task_id]
300
- session["attempts"] = 0
301
- session["best_reward"] = 0.0
302
- session["history"] = []
303
- compute_expected(req.session_id)
304
- observation = {
305
- "task_id": req.task_id,
306
- "difficulty": session["task"]["difficulty"],
307
- "task_description": session["task"]["description"],
308
- "schema": get_schema_info(),
309
- "hint": session["task"]["hint"],
310
- }
311
- return ResetResponse(observation=observation, info={"message": f"Task {req.task_id} loaded."})
312
-
313
- @api_app.post("/step", response_model=StepResponse)
314
- def step(req: StepRequest):
315
- session = get_session(req.session_id)
316
- if session["task_id"] is None: raise HTTPException(status_code=400, detail="Call /reset first.")
317
- session["attempts"] += 1
318
- sql = req.action.strip()
319
-
320
- if not re.match(r"^\\s*(SELECT|WITH)\\b", sql, re.IGNORECASE):
321
- return StepResponse(
322
- observation={"error": "Only SELECT or WITH allowed."}, reward=0.0, done=False,
323
- info={"attempt": session["attempts"], "message": "Rejected"}
324
- )
325
-
326
- try:
327
- agent_rows, agent_cols = run_query(sql)
328
- except Exception as e:
329
- session["history"].append({"attempt": session["attempts"], "sql": sql, "reward": 0.0, "error": str(e)})
330
- return StepResponse(
331
- observation={"error": str(e), "sql_submitted": sql}, reward=0.0, done=False,
332
- info={"attempt": session["attempts"], "message": "SQL Error"}
333
- )
334
-
335
- reward, details = compute_reward(req.session_id, agent_rows, agent_cols)
336
- session["best_reward"] = max(session["best_reward"], reward)
337
- done = reward >= 1.0
338
- session["history"].append({"attempt": session["attempts"], "sql": sql, "reward": reward, "details": details})
339
-
340
- observation = {
341
- "task_id": session["task_id"], "task_description": session["task"]["description"],
342
- "sql_submitted": sql, "result_preview": agent_rows[:5], "result_row_count": len(agent_rows),
343
- "reward_breakdown": details,
344
- }
345
- return StepResponse(
346
- observation=observation, reward=reward, done=done,
347
- info={"attempt": session["attempts"], "best_reward": session["best_reward"]}
348
- )
349
-
350
- @api_app.get("/state", response_model=StateResponse)
351
- def state(req: StateRequest):
352
- session = get_session(req.session_id)
353
- return StateResponse(
354
- session_id=req.session_id,
355
- task_id=session["task_id"],
356
- task_description=session["task"]["description"] if session["task"] else None,
357
- schema_info=get_schema_info(),
358
- attempts=session["attempts"],
359
- best_reward=session["best_reward"],
360
- history=session["history"],
361
- )
362
-
363
- @api_app.get("/")
364
- def root():
365
- return {"message": "API running at /api. Try the UI at root (handled by wrapper)!"}
366
-
367
- # ── Server Setup ──────────────────────────────────────────────────────────────
368
-
369
- demo = build_ui()
370
- app = gr.mount_gradio_app(api_app, demo, path="/")
371
- """
372
- with open("main.py", "w", encoding="utf-8") as f:
373
- f.write(main_py_code.strip() + "\n")
374
-
375
- # 4. Modify inference.py to use session IDs
376
- with open("inference.py", "r", encoding="utf-8") as f:
377
- inf = f.read()
378
-
379
- inf = inf.replace('ENV_BASE_URL = "http://127.0.0.1:7860"', 'ENV_BASE_URL = "http://127.0.0.1:7860/api"')
380
- inf = inf.replace("TASK_IDS = [1, 2, 3]", "TASK_IDS = [1, 2, 3, 4, 5]")
381
- inf = inf.replace('def env_reset(task_id: int) -> dict:', 'def env_reset(task_id: int, session_id: str) -> dict:')
382
- inf = inf.replace('json={"task_id": task_id}', 'json={"task_id": task_id, "session_id": session_id}')
383
-
384
- inf = inf.replace('def env_step(sql: str) -> dict:', 'def env_step(sql: str, session_id: str) -> dict:')
385
- inf = inf.replace('json={"action": sql}', 'json={"action": sql, "session_id": session_id}')
386
-
387
- inf = inf.replace("reset_resp = env_reset(task_id)", 'session_id = f"baseline_{task_id}"\n reset_resp = env_reset(task_id, session_id)')
388
- inf = inf.replace("step_resp = env_step(sql)", 'step_resp = env_step(sql, session_id)')
389
-
390
- inf = inf.replace('r = requests.get(f"{ENV_BASE_URL}/state")', 'r = requests.get(f"{ENV_BASE_URL}/state", json={"session_id": "baseline_1"})')
391
-
392
- # health check fix for inference wait_for_server
393
- inf = re.sub(r'requests\.get\(f"\{ENV_BASE_URL\}/health", timeout=3\)', 'requests.get(f"{ENV_BASE_URL}/", timeout=3)', inf)
394
-
395
- with open("inference.py", "w", encoding="utf-8") as f:
396
- f.write(inf)
397
-
398
- print("Done generating make_awesome.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ui.py DELETED
@@ -1,86 +0,0 @@
1
- import gradio as gr
2
- import requests
3
- import pandas as pd
4
- import json
5
- import uuid
6
-
7
- ENV_BASE_URL = "http://127.0.0.1:7860"
8
-
9
- def new_session():
10
- return str(uuid.uuid4())
11
-
12
- def load_task(task_id, sid):
13
- try:
14
- task_num = int(task_id.split()[1])
15
- r = requests.post(f"{ENV_BASE_URL}/api/reset", json={"task_id": task_num, "session_id": sid})
16
- if r.status_code != 200:
17
- return f"Error: {r.text}", "", "", pd.DataFrame(), f"Error loading task {task_num}"
18
-
19
- data = r.json()
20
- obs = data["observation"]
21
- return obs["task_description"], obs["schema"], obs["hint"], pd.DataFrame(), "Task loaded. Write SQL below."
22
- except Exception as e:
23
- return str(e), "", "", pd.DataFrame(), "Error loading task"
24
-
25
- def run_sql(sql, sid):
26
- if not sql.strip():
27
- return pd.DataFrame(), "Please enter a SQL query.", "Error"
28
- try:
29
- r = requests.post(f"{ENV_BASE_URL}/api/step", json={"action": sql, "session_id": sid})
30
- data = r.json()
31
- obs = data.get("observation", {})
32
- reward = data.get("reward", 0.0)
33
- done = data.get("done", False)
34
-
35
- df = pd.DataFrame(obs.get("result_preview", []))
36
- breakdown = obs.get("reward_breakdown", {})
37
-
38
- feedback = f"🎯 Reward: {reward:.2f} / 1.0\n"
39
- if breakdown:
40
- feedback += f"Columns: {breakdown.get('column_score',0):.2f}, Rows: {breakdown.get('row_score',0):.2f}, Values: {breakdown.get('value_score',0):.2f}"
41
- if "error" in obs:
42
- feedback += f"\n\n⚠️ Error: {obs['error']}"
43
-
44
- return df, feedback, "βœ… SOLVED!" if done else "Keep trying!"
45
- except Exception as e:
46
- return pd.DataFrame(), str(e), "Error"
47
-
48
- def build_ui():
49
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as demo:
50
- gr.Markdown("# πŸ“Š SQL Analyst OpenEnv")
51
- gr.Markdown("An interactive environment to test SQL generation. Load a task, read the schema, and write a query answering the business question.")
52
-
53
- sid = gr.State(new_session)
54
-
55
- with gr.Group():
56
- gr.Markdown("### Step 1: Select a Task")
57
- with gr.Row():
58
- task_dropdown = gr.Dropdown(choices=["Task 1 (Easy)", "Task 2 (Medium)", "Task 3 (Hard)", "Task 4 (Medium)", "Task 5 (Hard)"], value="Task 1 (Easy)", label="Available Tasks", show_label=False)
59
- btn_load = gr.Button("πŸ”„ Load Task", variant="primary")
60
-
61
- with gr.Row():
62
- desc = gr.Textbox(label="🎯 Business Question", interactive=False, lines=2)
63
-
64
- with gr.Row():
65
- with gr.Column():
66
- gr.Markdown("### Step 2: Understand the Data")
67
- schema = gr.Code(label="Database Schema", language="sql", interactive=False)
68
- with gr.Accordion("πŸ’‘ Need a hint?", open=False):
69
- hint = gr.Textbox(show_label=False, interactive=False)
70
-
71
- with gr.Column():
72
- gr.Markdown("### Step 3: Write & Execute SQL")
73
- sql_input = gr.Code(label="SQL Editor", language="sql", lines=12)
74
- btn_run = gr.Button("πŸš€ Execute Query", variant="primary")
75
-
76
- status_out = gr.Markdown("Waiting for query...")
77
- feedback_out = gr.Textbox(label="Evaluation Score & Feedback", interactive=False, lines=3)
78
-
79
- with gr.Group():
80
- gr.Markdown("### Step 4: Review Results")
81
- grid_out = gr.Dataframe(label="Result Preview (First 5 Rows)", interactive=False)
82
-
83
- btn_load.click(load_task, inputs=[task_dropdown, sid], outputs=[desc, schema, hint, grid_out, feedback_out])
84
- btn_run.click(run_sql, inputs=[sql_input, sid], outputs=[grid_out, feedback_out, status_out])
85
-
86
- return demo