Sazzz02 commited on
Commit
985fc10
ยท
verified ยท
1 Parent(s): 3478eba

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +585 -0
app.py ADDED
@@ -0,0 +1,585 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pandas as pd
3
+ import sqlite3
4
+ import numpy as np
5
+ import json
6
+ import re
7
+ from typing import List, Dict, Tuple
8
+ from groq import Groq
9
+ import gradio as gr
10
+ from sklearn.metrics import accuracy_score
11
+ import warnings
12
+ warnings.filterwarnings('ignore')
13
+
14
+ # ------------------------------
15
+ # โœ… GROQ API KEY FROM ENVIRONMENT
16
+ # ------------------------------
17
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
18
+
19
+ if not GROQ_API_KEY:
20
+ print("โš ๏ธ WARNING: GROQ_API_KEY environment variable not set!")
21
+ print("Please add your Groq API key to your Hugging Face Space secrets.")
22
+ print("For demo purposes, the app will continue but API calls will fail.")
23
+ GROQ_API_KEY = "dummy-key-for-demo"
24
+
25
+ # ------------------------------
26
+ # SQL Converter Using Groq API
27
+ # ------------------------------
28
+
29
+ class EnhancedNL2SQLConverter:
30
+ def __init__(self, model_name: str = "llama3-70b-8192"):
31
+ self.model_name = model_name
32
+ self.client = None
33
+
34
+ try:
35
+ if GROQ_API_KEY and GROQ_API_KEY != "dummy-key-for-demo":
36
+ self.client = Groq(api_key=GROQ_API_KEY)
37
+ print(f"โœ… Successfully initialized Groq client with model: {self.model_name}")
38
+ else:
39
+ print("โš ๏ธ Groq client not initialized - API key missing")
40
+ except Exception as e:
41
+ print(f"โŒ Error initializing Groq client: {str(e)}")
42
+ self.client = None
43
+
44
+ self.default_schema = """
45
+ Table: employees
46
+ Columns:
47
+ - id (INTEGER) PRIMARY KEY
48
+ - name (TEXT) NOT NULL
49
+ - department (TEXT)
50
+ - salary (REAL)
51
+ - hire_date (TEXT)
52
+ - manager_id (INTEGER)
53
+ """
54
+
55
+ def generate_sql(self, query: str, schema: str = None) -> str:
56
+ try:
57
+ if not self.client:
58
+ return "ERROR: Groq API client not initialized. Please check your API key."
59
+
60
+ schema_to_use = schema or self.default_schema
61
+
62
+ system_prompt = """You are an expert SQL query generator. Convert natural language questions to SQL queries based on the provided database schema.
63
+
64
+ Rules:
65
+ 1. Only return the SQL query, nothing else
66
+ 2. Use proper SQL syntax
67
+ 3. Be precise with column names and table names
68
+ 4. Use appropriate WHERE clauses, JOINs, and aggregations as needed
69
+ 5. For date comparisons, use proper date format
70
+ 6. Don't include explanations, just the SQL query"""
71
+
72
+ user_prompt = f"""Database Schema:
73
+ {schema_to_use}
74
+
75
+ Natural Language Question: {query}
76
+
77
+ Generate the SQL query:"""
78
+
79
+ chat_completion = self.client.chat.completions.create(
80
+ messages=[
81
+ {"role": "system", "content": system_prompt},
82
+ {"role": "user", "content": user_prompt}
83
+ ],
84
+ model=self.model_name,
85
+ temperature=0.1,
86
+ max_tokens=200
87
+ )
88
+
89
+ sql_query = chat_completion.choices[0].message.content.strip()
90
+ return self._clean_sql(sql_query)
91
+
92
+ except Exception as e:
93
+ print(f"Error generating SQL: {str(e)}")
94
+ return f"ERROR: Could not generate SQL query - {str(e)}"
95
+
96
+ def _clean_sql(self, sql: str) -> str:
97
+ sql = sql.strip()
98
+ sql = re.sub(r'```sql\n?', '', sql)
99
+ sql = re.sub(r'```\n?', '', sql)
100
+ sql = re.sub(r'^["\']|["\']$', '', sql)
101
+ sql = sql.rstrip(';')
102
+
103
+ sql_keywords = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'ALTER']
104
+ if not any(sql.upper().startswith(keyword) for keyword in sql_keywords):
105
+ for keyword in sql_keywords:
106
+ if keyword in sql.upper():
107
+ sql = sql[sql.upper().find(keyword):]
108
+ break
109
+ return sql
110
+
111
+ # ------------------------------
112
+ # SQL Evaluator & Test Database
113
+ # ------------------------------
114
+
115
+ class SQLEvaluator:
116
+ def __init__(self):
117
+ self.db_path = "test_database.db"
118
+ self.setup_test_database()
119
+
120
+ def setup_test_database(self):
121
+ conn = sqlite3.connect(self.db_path)
122
+ cursor = conn.cursor()
123
+
124
+ cursor.execute('''
125
+ CREATE TABLE IF NOT EXISTS employees (
126
+ id INTEGER PRIMARY KEY,
127
+ name TEXT NOT NULL,
128
+ department TEXT,
129
+ salary REAL,
130
+ hire_date TEXT,
131
+ manager_id INTEGER
132
+ )''')
133
+
134
+ sample_data = [
135
+ (1, 'Alice Johnson', 'Engineering', 75000, '2022-01-15', None),
136
+ (2, 'Bob Smith', 'Sales', 65000, '2021-06-20', None),
137
+ (3, 'Charlie Brown', 'Engineering', 80000, '2020-03-10', 1),
138
+ (4, 'Diana Prince', 'HR', 60000, '2023-02-28', None),
139
+ (5, 'Eve Wilson', 'Sales', 70000, '2022-11-05', 2),
140
+ (6, 'Frank Miller', 'Engineering', 85000, '2019-08-12', 1),
141
+ (7, 'Grace Lee', 'Marketing', 55000, '2023-01-20', None),
142
+ (8, 'Henry Davis', 'Engineering', 72000, '2022-07-30', 1)
143
+ ]
144
+
145
+ cursor.executemany('''
146
+ INSERT OR REPLACE INTO employees (id, name, department, salary, hire_date, manager_id)
147
+ VALUES (?, ?, ?, ?, ?, ?)''', sample_data)
148
+
149
+ conn.commit()
150
+ conn.close()
151
+ print("โœ… Test database initialized successfully")
152
+
153
+ def execute_sql(self, sql_query: str) -> Tuple[bool, any]:
154
+ try:
155
+ conn = sqlite3.connect(self.db_path)
156
+ cursor = conn.cursor()
157
+ cursor.execute(sql_query)
158
+
159
+ if sql_query.strip().upper().startswith('SELECT'):
160
+ results = cursor.fetchall()
161
+ columns = [description[0] for description in cursor.description]
162
+ conn.close()
163
+ return True, {'columns': columns, 'data': results}
164
+ else:
165
+ conn.commit()
166
+ conn.close()
167
+ return True, "Query executed successfully"
168
+ except Exception as e:
169
+ return False, str(e)
170
+
171
+ # ------------------------------
172
+ # Initialize components
173
+ # ------------------------------
174
+ try:
175
+ converter = EnhancedNL2SQLConverter()
176
+ evaluator = SQLEvaluator()
177
+ print("โœ… Application components initialized successfully")
178
+ except Exception as e:
179
+ print(f"โŒ Error initializing components: {str(e)}")
180
+ converter = None
181
+ evaluator = SQLEvaluator()
182
+
183
+ # ------------------------------
184
+ # Enhanced UI Functions
185
+ # ------------------------------
186
+
187
+ def process_nl_query(nl_query: str) -> Tuple[str, str, str]:
188
+ """Process natural language query and return SQL + results"""
189
+ if not nl_query.strip():
190
+ return "", "", "โš ๏ธ Please enter a natural language query."
191
+
192
+ try:
193
+ if not converter:
194
+ return "", "", "โŒ Error: SQL converter not initialized. Please check API configuration."
195
+
196
+ generated_sql = converter.generate_sql(nl_query)
197
+
198
+ if generated_sql.startswith("ERROR"):
199
+ return generated_sql, "", "โŒ Failed to generate SQL query. Please check your API key."
200
+
201
+ success, result = evaluator.execute_sql(generated_sql)
202
+
203
+ if success and isinstance(result, dict):
204
+ df = pd.DataFrame(result['data'], columns=result['columns'])
205
+ if len(df) == 0:
206
+ formatted_output = "No results found."
207
+ else:
208
+ formatted_output = df.to_string(index=False)
209
+ return generated_sql, formatted_output, "โœ… Query executed successfully!"
210
+ elif success:
211
+ return generated_sql, str(result), "โœ… Query executed successfully!"
212
+ else:
213
+ return generated_sql, "", f"โŒ Error executing query: {result}"
214
+
215
+ except Exception as e:
216
+ return "", "", f"โŒ Unexpected error: {str(e)}"
217
+
218
+ def get_sample_queries():
219
+ return [
220
+ "Show all employees in the Engineering department",
221
+ "Find employees with salary greater than 70000",
222
+ "List all employees hired after 2022",
223
+ "Count employees by department",
224
+ "Show the highest paid employee in each department",
225
+ "Find employees who don't have a manager",
226
+ "Show average salary by department"
227
+ ]
228
+
229
+ # ------------------------------
230
+ # Beautiful Custom CSS
231
+ # ------------------------------
232
+
233
+ custom_css = """
234
+ /* Main container styling */
235
+ .gradio-container {
236
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
237
+ min-height: 100vh;
238
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
239
+ }
240
+
241
+ /* Header styling */
242
+ .header-container {
243
+ background: rgba(255, 255, 255, 0.1);
244
+ backdrop-filter: blur(20px);
245
+ border-radius: 20px;
246
+ padding: 2rem;
247
+ margin-bottom: 2rem;
248
+ border: 1px solid rgba(255, 255, 255, 0.2);
249
+ box-shadow: 0 8px 32px rgba(31, 38, 135, 0.37);
250
+ }
251
+
252
+ /* Card styling */
253
+ .card {
254
+ background: rgba(255, 255, 255, 0.95);
255
+ backdrop-filter: blur(20px);
256
+ border-radius: 16px;
257
+ padding: 1.5rem;
258
+ margin: 1rem 0;
259
+ border: 1px solid rgba(255, 255, 255, 0.3);
260
+ box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
261
+ transition: all 0.3s ease;
262
+ }
263
+
264
+ .card:hover {
265
+ transform: translateY(-2px);
266
+ box-shadow: 0 12px 40px rgba(31, 38, 135, 0.25);
267
+ }
268
+
269
+ /* Input styling */
270
+ .gr-textbox {
271
+ border-radius: 12px !important;
272
+ border: 2px solid rgba(103, 126, 234, 0.3) !important;
273
+ background: rgba(255, 255, 255, 0.9) !important;
274
+ transition: all 0.3s ease !important;
275
+ }
276
+
277
+ .gr-textbox:focus {
278
+ border-color: #667eea !important;
279
+ box-shadow: 0 0 0 3px rgba(103, 126, 234, 0.1) !important;
280
+ transform: scale(1.02);
281
+ }
282
+
283
+ /* Button styling */
284
+ .gr-button {
285
+ background: linear-gradient(45deg, #667eea, #764ba2) !important;
286
+ border: none !important;
287
+ border-radius: 12px !important;
288
+ padding: 12px 24px !important;
289
+ font-weight: 600 !important;
290
+ color: white !important;
291
+ transition: all 0.3s ease !important;
292
+ box-shadow: 0 4px 15px rgba(103, 126, 234, 0.4) !important;
293
+ }
294
+
295
+ .gr-button:hover {
296
+ transform: translateY(-2px) !important;
297
+ box-shadow: 0 8px 25px rgba(103, 126, 234, 0.6) !important;
298
+ }
299
+
300
+ .sample-btn {
301
+ background: linear-gradient(45deg, #f093fb, #f5576c) !important;
302
+ margin: 0.25rem !important;
303
+ font-size: 0.9rem !important;
304
+ padding: 8px 16px !important;
305
+ }
306
+
307
+ .sample-btn:hover {
308
+ background: linear-gradient(45deg, #f5576c, #f093fb) !important;
309
+ }
310
+
311
+ /* Results area styling */
312
+ .results-container {
313
+ background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
314
+ border-radius: 16px;
315
+ padding: 1.5rem;
316
+ margin-top: 1rem;
317
+ }
318
+
319
+ /* Status indicators */
320
+ .status-success {
321
+ color: #10b981 !important;
322
+ font-weight: 600 !important;
323
+ }
324
+
325
+ .status-error {
326
+ color: #ef4444 !important;
327
+ font-weight: 600 !important;
328
+ }
329
+
330
+ .status-warning {
331
+ color: #f59e0b !important;
332
+ font-weight: 600 !important;
333
+ }
334
+
335
+ /* Schema box */
336
+ .schema-box {
337
+ background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
338
+ border-radius: 12px;
339
+ padding: 1rem;
340
+ font-family: 'Monaco', 'Consolas', monospace;
341
+ border-left: 4px solid #f59e0b;
342
+ }
343
+
344
+ /* Animation keyframes */
345
+ @keyframes fadeInUp {
346
+ from {
347
+ opacity: 0;
348
+ transform: translateY(30px);
349
+ }
350
+ to {
351
+ opacity: 1;
352
+ transform: translateY(0);
353
+ }
354
+ }
355
+
356
+ .fade-in {
357
+ animation: fadeInUp 0.6s ease-out;
358
+ }
359
+
360
+ /* Responsive design */
361
+ @media (max-width: 768px) {
362
+ .gradio-container {
363
+ padding: 1rem;
364
+ }
365
+
366
+ .card {
367
+ padding: 1rem;
368
+ margin: 0.5rem 0;
369
+ }
370
+ }
371
+
372
+ /* Loading spinner */
373
+ .loading {
374
+ display: inline-block;
375
+ width: 20px;
376
+ height: 20px;
377
+ border: 3px solid rgba(255,255,255,.3);
378
+ border-radius: 50%;
379
+ border-top-color: #fff;
380
+ animation: spin 1s ease-in-out infinite;
381
+ }
382
+
383
+ @keyframes spin {
384
+ to { transform: rotate(360deg); }
385
+ }
386
+ """
387
+
388
+ # ------------------------------
389
+ # Enhanced Gradio Interface
390
+ # ------------------------------
391
+
392
+ with gr.Blocks(css=custom_css, title="AI-Powered NL2SQL Converter", theme=gr.themes.Glass()) as iface:
393
+ # Header Section
394
+ with gr.Row(elem_classes="header-container fade-in"):
395
+ gr.HTML("""
396
+ <div style="text-align: center; color: white;">
397
+ <h1 style="font-size: 3rem; margin-bottom: 0.5rem; background: linear-gradient(45deg, #fff, #f0f0f0); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">
398
+ ๐Ÿš€ AI-Powered NL2SQL Converter
399
+ </h1>
400
+ <p style="font-size: 1.2rem; opacity: 0.9; margin-bottom: 1rem;">
401
+ Transform natural language into powerful SQL queries using Groq's advanced AI
402
+ </p>
403
+ <div style="display: flex; justify-content: center; gap: 2rem; margin-top: 1rem;">
404
+ <div style="text-align: center;">
405
+ <div style="font-size: 2rem;">๐Ÿค–</div>
406
+ <div style="font-size: 0.9rem; opacity: 0.8;">AI-Powered</div>
407
+ </div>
408
+ <div style="text-align: center;">
409
+ <div style="font-size: 2rem;">โšก</div>
410
+ <div style="font-size: 0.9rem; opacity: 0.8;">Lightning Fast</div>
411
+ </div>
412
+ <div style="text-align: center;">
413
+ <div style="font-size: 2rem;">๐ŸŽฏ</div>
414
+ <div style="font-size: 0.9rem; opacity: 0.8;">Precise Results</div>
415
+ </div>
416
+ </div>
417
+ </div>
418
+ """)
419
+
420
+ # Database Schema Section
421
+ with gr.Row(elem_classes="card fade-in"):
422
+ gr.HTML("""
423
+ <div class="schema-box">
424
+ <h3 style="color: #d97706; margin-bottom: 1rem;">๐Ÿ“Š Database Schema</h3>
425
+ <div style="background: rgba(255,255,255,0.7); padding: 1rem; border-radius: 8px;">
426
+ <strong>employees</strong> table:<br>
427
+ โ€ข <code>id</code> (INTEGER) - Primary Key<br>
428
+ โ€ข <code>name</code> (TEXT) - Employee Name<br>
429
+ โ€ข <code>department</code> (TEXT) - Department<br>
430
+ โ€ข <code>salary</code> (REAL) - Salary Amount<br>
431
+ โ€ข <code>hire_date</code> (TEXT) - Hiring Date<br>
432
+ โ€ข <code>manager_id</code> (INTEGER) - Manager Reference
433
+ </div>
434
+ </div>
435
+ """)
436
+
437
+ # Main Input Section
438
+ with gr.Row(elem_classes="card fade-in"):
439
+ with gr.Column(scale=3):
440
+ nl_input = gr.Textbox(
441
+ label="๐Ÿ’ฌ Ask your question in plain English",
442
+ placeholder="e.g., Show me all engineers earning more than $75,000",
443
+ lines=3,
444
+ elem_classes="main-input"
445
+ )
446
+
447
+ with gr.Row():
448
+ submit_btn = gr.Button(
449
+ "๐Ÿ”ฎ Generate & Execute SQL",
450
+ variant="primary",
451
+ size="lg",
452
+ elem_classes="main-button"
453
+ )
454
+ clear_btn = gr.Button(
455
+ "๐Ÿ—‘๏ธ Clear",
456
+ variant="secondary",
457
+ size="lg"
458
+ )
459
+
460
+ with gr.Column(scale=2):
461
+ gr.HTML("<h3 style='color: #667eea; margin-bottom: 1rem;'>๐ŸŽฏ Try These Examples</h3>")
462
+
463
+ sample_queries = get_sample_queries()
464
+ for i, query in enumerate(sample_queries):
465
+ sample_btn = gr.Button(
466
+ f"๐Ÿ’ก {query}",
467
+ variant="secondary",
468
+ size="sm",
469
+ elem_classes="sample-btn"
470
+ )
471
+ sample_btn.click(
472
+ lambda q=query: q,
473
+ outputs=nl_input
474
+ )
475
+
476
+ # Results Section
477
+ with gr.Row(elem_classes="results-container fade-in"):
478
+ with gr.Column():
479
+ gr.HTML("<h3 style='color: #6366f1; margin-bottom: 1rem;'>๐Ÿ“ Generated SQL Query</h3>")
480
+ sql_output = gr.Code(
481
+ label="",
482
+ language="sql",
483
+ lines=4,
484
+ interactive=False,
485
+ elem_classes="sql-output"
486
+ )
487
+
488
+ status_output = gr.HTML(
489
+ "<div style='padding: 1rem; text-align: center; font-size: 1.1rem;'>Ready to process your query! ๐Ÿš€</div>"
490
+ )
491
+
492
+ with gr.Row(elem_classes="card fade-in"):
493
+ gr.HTML("<h3 style='color: #059669; margin-bottom: 1rem;'>๐Ÿ“Š Query Results</h3>")
494
+ results_output = gr.Code(
495
+ label="",
496
+ lines=12,
497
+ interactive=False,
498
+ elem_classes="results-output"
499
+ )
500
+
501
+ # Footer Section
502
+ with gr.Row(elem_classes="card fade-in"):
503
+ gr.HTML("""
504
+ <div style="text-align: center; padding: 1rem;">
505
+ <h3 style="color: #667eea; margin-bottom: 1rem;">๐Ÿ” About This Application</h3>
506
+ <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem; margin-top: 1rem;">
507
+ <div style="background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 1rem; border-radius: 12px;">
508
+ <h4>๐Ÿค– AI Model</h4>
509
+ <p>Powered by Groq's Llama3-70B for intelligent SQL generation</p>
510
+ </div>
511
+ <div style="background: linear-gradient(135deg, #f093fb, #f5576c); color: white; padding: 1rem; border-radius: 12px;">
512
+ <h4>๐Ÿ’พ Database</h4>
513
+ <p>SQLite with sample employee data for testing and learning</p>
514
+ </div>
515
+ <div style="background: linear-gradient(135deg, #a8edea, #fed6e3); color: #374151; padding: 1rem; border-radius: 12px;">
516
+ <h4>โœจ Features</h4>
517
+ <p>Natural language processing, SQL execution, and formatted results</p>
518
+ </div>
519
+ </div>
520
+ <div style="margin-top: 2rem; padding: 1rem; background: rgba(103, 126, 234, 0.1); border-radius: 12px;">
521
+ <h4 style="color: #667eea;">๐Ÿ’ก Pro Tips for Better Results</h4>
522
+ <ul style="text-align: left; display: inline-block; color: #4b5563;">
523
+ <li>Be specific and clear in your questions</li>
524
+ <li>Use column names mentioned in the schema</li>
525
+ <li>Try the sample queries to understand the format</li>
526
+ <li>Use natural language - no need for technical jargon</li>
527
+ </ul>
528
+ </div>
529
+ </div>
530
+ """)
531
+
532
+ # Event Handlers with Enhanced Feedback
533
+ def enhanced_process(query):
534
+ if not query.strip():
535
+ return "", "<div class='status-warning'>โš ๏ธ Please enter a question first!</div>", ""
536
+
537
+ # Show loading state
538
+ loading_html = "<div class='status-info'>๐Ÿ”„ Processing your query... <span class='loading'></span></div>"
539
+
540
+ try:
541
+ sql, results, status = process_nl_query(query)
542
+
543
+ # Enhanced status formatting
544
+ if "successfully" in status.lower():
545
+ status_html = f"<div class='status-success'>{status}</div>"
546
+ elif "error" in status.lower() or "failed" in status.lower():
547
+ status_html = f"<div class='status-error'>{status}</div>"
548
+ else:
549
+ status_html = f"<div class='status-warning'>{status}</div>"
550
+
551
+ return sql, status_html, results
552
+
553
+ except Exception as e:
554
+ return "", f"<div class='status-error'>โŒ Unexpected error: {str(e)}</div>", ""
555
+
556
+ def clear_all():
557
+ return "", "", "<div style='padding: 1rem; text-align: center; font-size: 1.1rem;'>Ready to process your query! ๐Ÿš€</div>", ""
558
+
559
+ # Connect events
560
+ submit_btn.click(
561
+ fn=enhanced_process,
562
+ inputs=[nl_input],
563
+ outputs=[sql_output, status_output, results_output]
564
+ )
565
+
566
+ nl_input.submit(
567
+ fn=enhanced_process,
568
+ inputs=[nl_input],
569
+ outputs=[sql_output, status_output, results_output]
570
+ )
571
+
572
+ clear_btn.click(
573
+ fn=clear_all,
574
+ outputs=[nl_input, sql_output, status_output, results_output]
575
+ )
576
+
577
+ # Launch the app
578
+ if __name__ == "__main__":
579
+ print("๐Ÿš€ Launching Enhanced NL2SQL Application...")
580
+ iface.launch(
581
+ server_name="0.0.0.0",
582
+ server_port=7860,
583
+ share=True,
584
+ show_error=True
585
+ )