Kasualdad commited on
Commit
2eccdc1
·
1 Parent(s): e8c46ef

perf: stream SQL to UI, trim few-shots 7→4, GPU duration 30s

Browse files

- handle_query is now a generator: tokens stream into the SQL panel
within seconds instead of a blank wait
- prompts.py: drop 3 redundant few-shot examples (simple patterns
covered by remaining 4) to cut bnb-4bit prefill time
- spaces.GPU(duration=30): shorter durations get ZeroGPU queue priority
- max_tokens 192 (observed outputs are ~140-170 chars)

Files changed (2) hide show
  1. app.py +21 -12
  2. prompts.py +0 -12
app.py CHANGED
@@ -12,11 +12,13 @@ import gradio as gr
12
  # spaces.GPU is only available on HF Spaces — use a no-op locally
13
  try:
14
  import spaces
15
- _gpu_decorator = spaces.GPU(duration=120)
 
 
16
  except ImportError:
17
  _gpu_decorator = lambda fn: fn # no-op for local dev
18
 
19
- from model_inference import load_model, generate_sql
20
  from data_engine import create_session, execute_safe, QueryTimeoutError
21
 
22
  # ── Startup ───────────────────────────────────────────────────────────
@@ -60,32 +62,39 @@ EXAMPLE_QUERIES = [
60
  @_gpu_decorator
61
  def handle_query(user_question: str):
62
  """
63
- Process an admin's question end-to-end.
64
 
65
- 1. Generate SQL via local LLM (blocking)
66
  2. Execute validated SQL on a fresh per-request DB
67
- 3. Return (sql_text, dataframe, status_message)
68
  """
69
  if not user_question or not user_question.strip():
70
- return "", None, "⚠️ Please enter a question."
 
71
 
 
72
  try:
73
- raw_output, _ = generate_sql(user_question, llm=llm)
 
 
 
74
  except Exception as e:
75
- return "", None, f"❌ Model error: {e}"
 
76
 
77
  try:
 
78
  conn = create_session()
79
  clean_sql, df = execute_safe(conn, raw_output, timeout_sec=30)
80
  conn.close()
81
  row_count = len(df)
82
- return clean_sql, df, f"✅ Done — {row_count} row{'s' if row_count != 1 else ''} returned"
83
  except ValueError as e:
84
- return raw_output, None, f"⚠️ Validation: {e}"
85
  except QueryTimeoutError as e:
86
- return raw_output, None, f"⏱️ Timeout: {e}"
87
  except Exception as e:
88
- return raw_output, None, f"❌ Error: {e}"
89
 
90
  # ── UI ─────────────────────────────────────────────────────────────────
91
 
 
12
  # spaces.GPU is only available on HF Spaces — use a no-op locally
13
  try:
14
  import spaces
15
+ # Short duration = higher priority in the ZeroGPU queue. Generation
16
+ # takes ~5s; 30s leaves ample headroom.
17
+ _gpu_decorator = spaces.GPU(duration=30)
18
  except ImportError:
19
  _gpu_decorator = lambda fn: fn # no-op for local dev
20
 
21
+ from model_inference import load_model, generate_sql_streaming
22
  from data_engine import create_session, execute_safe, QueryTimeoutError
23
 
24
  # ── Startup ───────────────────────────────────────────────────────────
 
62
  @_gpu_decorator
63
  def handle_query(user_question: str):
64
  """
65
+ Process an admin's question end-to-end, streaming SQL as it generates.
66
 
67
+ 1. Stream SQL tokens from the LLM into the SQL panel (live)
68
  2. Execute validated SQL on a fresh per-request DB
69
+ 3. Yield (sql_text, dataframe, status_message)
70
  """
71
  if not user_question or not user_question.strip():
72
+ yield "", None, "⚠️ Please enter a question."
73
+ return
74
 
75
+ raw_output = ""
76
  try:
77
+ yield "", None, "🤖 Generating SQL…"
78
+ for accumulated in generate_sql_streaming(user_question, llm=llm, max_tokens=192):
79
+ raw_output = accumulated
80
+ yield raw_output, None, "🤖 Generating SQL…"
81
  except Exception as e:
82
+ yield raw_output, None, f"❌ Model error: {e}"
83
+ return
84
 
85
  try:
86
+ yield raw_output, None, "🦆 Running query…"
87
  conn = create_session()
88
  clean_sql, df = execute_safe(conn, raw_output, timeout_sec=30)
89
  conn.close()
90
  row_count = len(df)
91
+ yield clean_sql, df, f"✅ Done — {row_count} row{'s' if row_count != 1 else ''} returned"
92
  except ValueError as e:
93
+ yield raw_output, None, f"⚠️ Validation: {e}"
94
  except QueryTimeoutError as e:
95
+ yield raw_output, None, f"⏱️ Timeout: {e}"
96
  except Exception as e:
97
+ yield raw_output, None, f"❌ Error: {e}"
98
 
99
  # ── UI ─────────────────────────────────────────────────────────────────
100
 
prompts.py CHANGED
@@ -105,14 +105,6 @@ FEW_SHOT_EXAMPLES = [
105
  "question": "Show total enrollment per school for 2024-2025, sorted highest first.",
106
  "sql": "SELECT school_name, SUM(student_count) AS total_enrollment\nFROM enrollment\nWHERE school_year = '2024-2025'\nGROUP BY school_name\nORDER BY total_enrollment DESC;",
107
  },
108
- {
109
- "question": "What percentage of students at Lincoln Elementary were chronically absent in 2023-2024?",
110
- "sql": "SELECT\n COUNT(CASE WHEN is_chronically_absent THEN 1 END) * 100.0 / COUNT(*) AS chronic_absence_pct\nFROM attendance\nWHERE school_year = '2023-2024' AND school_name = 'Lincoln Elementary';",
111
- },
112
- {
113
- "question": "Show me the enrollment trend for all schools since 2021.",
114
- "sql": "SELECT school_year, SUM(student_count) AS total_enrollment\nFROM enrollment\nWHERE school_year >= '2021-2022'\nGROUP BY school_year\nORDER BY school_year;",
115
- },
116
  {
117
  "question": "How many chronically absent students are English Learners in 2023-2024?",
118
  "sql": "SELECT COUNT(DISTINCT a.student_id) AS chronic_ell_count\nFROM attendance a\nJOIN students s ON a.student_id = s.student_id\nWHERE a.school_year = '2023-2024'\n AND a.is_chronically_absent = TRUE\n AND s.english_learner = TRUE;",
@@ -121,10 +113,6 @@ FEW_SHOT_EXAMPLES = [
121
  "question": "What's the average GPA for chronically absent students vs non-chronic students in 2023-2024?",
122
  "sql": "SELECT\n a.is_chronically_absent,\n ROUND(AVG(g.gpa), 2) AS avg_gpa\nFROM attendance a\nJOIN grades g ON a.student_id = g.student_id AND a.school_year = g.school_year\nWHERE a.school_year = '2023-2024'\nGROUP BY a.is_chronically_absent;",
123
  },
124
- {
125
- "question": "How many discipline incidents were recorded at each school in 2023-2024?",
126
- "sql": "SELECT school_name, COUNT(*) AS incident_count\nFROM discipline\nWHERE school_year = '2023-2024'\nGROUP BY school_name\nORDER BY incident_count DESC;",
127
- },
128
  ]
129
 
130
 
 
105
  "question": "Show total enrollment per school for 2024-2025, sorted highest first.",
106
  "sql": "SELECT school_name, SUM(student_count) AS total_enrollment\nFROM enrollment\nWHERE school_year = '2024-2025'\nGROUP BY school_name\nORDER BY total_enrollment DESC;",
107
  },
 
 
 
 
 
 
 
 
108
  {
109
  "question": "How many chronically absent students are English Learners in 2023-2024?",
110
  "sql": "SELECT COUNT(DISTINCT a.student_id) AS chronic_ell_count\nFROM attendance a\nJOIN students s ON a.student_id = s.student_id\nWHERE a.school_year = '2023-2024'\n AND a.is_chronically_absent = TRUE\n AND s.english_learner = TRUE;",
 
113
  "question": "What's the average GPA for chronically absent students vs non-chronic students in 2023-2024?",
114
  "sql": "SELECT\n a.is_chronically_absent,\n ROUND(AVG(g.gpa), 2) AS avg_gpa\nFROM attendance a\nJOIN grades g ON a.student_id = g.student_id AND a.school_year = g.school_year\nWHERE a.school_year = '2023-2024'\nGROUP BY a.is_chronically_absent;",
115
  },
 
 
 
 
116
  ]
117
 
118