shukdevdattaEX commited on
Commit
9968ba2
·
verified ·
1 Parent(s): 0cd6cca

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -395
app.py CHANGED
@@ -1,407 +1,42 @@
1
- from groq import Groq
2
- from pydantic import BaseModel
3
- import json
4
- import gradio as gr
5
- import pandas as pd
6
- from datetime import datetime
7
- import tempfile
8
  import os
 
 
9
 
10
- class ValidationStatus(BaseModel):
11
- is_valid: bool
12
- syntax_errors: list[str]
13
- warnings: list[str] = []
14
-
15
- class SQLQueryGeneration(BaseModel):
16
- query: str
17
- query_type: str
18
- tables_used: list[str]
19
- estimated_complexity: str
20
- execution_notes: list[str]
21
- validation_status: ValidationStatus
22
- table_schema: str
23
- sample_data: str
24
- execution_results: str
25
- optimization_notes: list[str]
26
- explanation: str = ""
27
- alternative_queries: list[str] = []
28
-
29
- def parse_execution_results_to_dataframe(execution_results):
30
- """Convert text-based table results to pandas DataFrame"""
31
- try:
32
- lines = execution_results.strip().split('\n')
33
- if len(lines) < 3:
34
- return None
35
-
36
- header_line = lines[0]
37
- headers = [col.strip() for col in header_line.split('|')]
38
-
39
- data_rows = []
40
- for line in lines[2:]:
41
- if line.strip() and not line.strip().startswith('-'):
42
- row = [cell.strip() for cell in line.split('|')]
43
- if len(row) == len(headers):
44
- data_rows.append(row)
45
-
46
- if data_rows:
47
- df = pd.DataFrame(data_rows, columns=headers)
48
- return df
49
- return None
50
- except Exception as e:
51
- print(f"Error parsing results: {e}")
52
- return None
53
-
54
- def generate_sql_query(api_key, user_query, sql_dialect, include_comments, complexity_level):
55
- """Generate SQL query from natural language using GROQ API"""
56
- try:
57
- if not api_key:
58
- return "Error: Please enter your GROQ API key", "", "", "", None, "", "", ""
59
-
60
- if not user_query:
61
- return "Error: Please enter a query description", "", "", "", None, "", "", ""
62
-
63
- client = Groq(api_key=api_key)
64
-
65
- # Enhanced system prompt
66
- system_prompt = f"""You are an expert SQL database architect and query optimizer. Generate production-ready SQL queries from natural language descriptions.
67
-
68
- **SQL Dialect**: {sql_dialect}
69
- **Include Comments**: {include_comments}
70
- **Target Complexity**: {complexity_level}
71
-
72
- ## Core Requirements:
73
- 1. Generate syntactically correct {sql_dialect} queries
74
- 2. Follow {sql_dialect}-specific best practices and conventions
75
- 3. Use proper indexing hints where applicable
76
- 4. Include CTEs (Common Table Expressions) for complex queries when appropriate
77
- 5. Add inline comments explaining complex logic (if comments enabled)
78
- 6. Consider query performance and optimization
79
-
80
- ## Security Guidelines:
81
- - Use parameterized query patterns (e.g., WHERE id = $1)
82
- - Never include actual sensitive data in examples
83
- - Validate that queries follow principle of least privilege
84
- - Flag any potential SQL injection vulnerabilities
85
-
86
- ## Query Analysis:
87
- - Identify query type (SELECT, INSERT, UPDATE, DELETE, etc.)
88
- - Estimate complexity (Simple, Moderate, Complex, Advanced)
89
- - List all tables and joins involved
90
- - Provide optimization suggestions (indexes, query rewriting, etc.)
91
- - Warn about potential performance issues (N+1 queries, missing indexes, etc.)
92
-
93
- ## Sample Data Requirements:
94
- 1. Create realistic table schemas with appropriate:
95
- - Primary keys and foreign keys
96
- - Indexes on commonly queried columns
97
- - Constraints (NOT NULL, UNIQUE, CHECK)
98
- - Appropriate data types for {sql_dialect}
99
- 2. Generate 5-10 rows of realistic sample data
100
- 3. Execute the query against sample data
101
- 4. Show results in pipe-delimited table format:
102
-
103
- column1 | column2 | column3
104
- --------|---------|--------
105
- value1 | value2 | value3
106
-
107
- ## Additional Features:
108
- - Provide a clear explanation of what the query does
109
- - Suggest 1-2 alternative approaches if applicable
110
- - Include execution notes about assumptions made
111
- - List optimization opportunities
112
-
113
- ## Response Structure:
114
- Return a complete JSON object with all fields populated, including explanation and alternative_queries arrays."""
115
-
116
- response = client.chat.completions.create(
117
- model="moonshotai/kimi-k2-instruct-0905",
118
- messages=[
119
- {"role": "system", "content": system_prompt},
120
- {"role": "user", "content": user_query},
121
- ],
122
- response_format={
123
- "type": "json_schema",
124
- "json_schema": {
125
- "name": "sql_query_generation",
126
- "schema": SQLQueryGeneration.model_json_schema()
127
- }
128
- }
129
- )
130
-
131
- sql_query_generation = SQLQueryGeneration.model_validate(
132
- json.loads(response.choices[0].message.content)
133
- )
134
-
135
- # Format validation status with warnings
136
- validation_text = f"✓ Valid: {sql_query_generation.validation_status.is_valid}\n"
137
- if sql_query_generation.validation_status.syntax_errors:
138
- validation_text += "\n❌ Errors:\n" + "\n".join(
139
- f" • {error}" for error in sql_query_generation.validation_status.syntax_errors
140
- )
141
- else:
142
- validation_text += "✓ No syntax errors found"
143
-
144
- if sql_query_generation.validation_status.warnings:
145
- validation_text += "\n\n⚠️ Warnings:\n" + "\n".join(
146
- f" • {warning}" for warning in sql_query_generation.validation_status.warnings
147
- )
148
-
149
- # Format metadata
150
- metadata = f"""📊 Query Type: {sql_query_generation.query_type}
151
- 📁 Tables Used: {', '.join(sql_query_generation.tables_used)}
152
- ⚡ Complexity: {sql_query_generation.estimated_complexity}
153
-
154
- 🔍 Execution Notes:
155
- {chr(10).join(f" • {note}" for note in sql_query_generation.execution_notes)}
156
 
157
- ⚙️ Optimization Notes:
158
- {chr(10).join(f" • {note}" for note in sql_query_generation.optimization_notes)}"""
159
-
160
- # Format explanation
161
- explanation = sql_query_generation.explanation or "No explanation provided"
162
-
163
- # Format alternative queries
164
- alternatives = ""
165
- if sql_query_generation.alternative_queries:
166
- alternatives = "\n\n".join(
167
- f"Alternative {i+1}:\n{query}"
168
- for i, query in enumerate(sql_query_generation.alternative_queries)
169
- )
170
- else:
171
- alternatives = "No alternative approaches suggested"
172
-
173
- # Convert execution results to DataFrame
174
- results_df = parse_execution_results_to_dataframe(sql_query_generation.execution_results)
175
-
176
- return (
177
- sql_query_generation.query,
178
- metadata,
179
- sql_query_generation.table_schema,
180
- sql_query_generation.sample_data,
181
- results_df,
182
- validation_text,
183
- explanation,
184
- alternatives
185
- )
186
-
187
- except Exception as e:
188
- error_msg = f"❌ Error: {str(e)}"
189
- return error_msg, "", "", "", None, "", "", ""
190
 
191
- def export_query(sql_query, schema, sample_data):
192
- """Export query with schema and sample data as a complete SQL file"""
193
- if not sql_query or sql_query.startswith("Error"):
194
- return None
195
-
196
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
197
- content = f"""-- Generated SQL Query
198
- -- Timestamp: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
199
- --
200
- {'-' * 60}
201
 
202
- -- TABLE SCHEMA
203
- {schema}
204
 
205
- {'-' * 60}
 
206
 
207
- -- SAMPLE DATA
208
- {sample_data}
 
209
 
210
- {'-' * 60}
 
211
 
212
- -- QUERY
213
- {sql_query}
214
- """
215
-
216
- # Create a temporary file with proper naming
217
- temp_file = tempfile.NamedTemporaryFile(
218
- mode='w',
219
- suffix='.sql',
220
- prefix=f'sql_query_{timestamp}_',
221
- delete=False
222
- )
223
-
224
- try:
225
- temp_file.write(content)
226
- temp_file.flush()
227
- temp_file.close()
228
- return temp_file.name
229
- except Exception as e:
230
- print(f"Error creating file: {e}")
231
- if os.path.exists(temp_file.name):
232
- os.unlink(temp_file.name)
233
- return None
234
 
235
- # Create Gradio interface with enhanced features
236
- with gr.Blocks(title="SQL Query Generator Pro", theme=gr.themes.Ocean()) as demo:
237
- gr.Markdown(
238
- """
239
- # 🗄️ Natural Language to SQL Query Generator Pro
240
- Convert natural language descriptions into production-ready SQL queries with validation, optimization, and execution results.
241
- """
242
- )
243
-
244
- with gr.Row():
245
- with gr.Column(scale=1):
246
- api_key_input = gr.Textbox(
247
- label="🔑 GROQ API Key",
248
- type="password",
249
- placeholder="Enter your GROQ API key here...",
250
- info="Your API key is not stored and only used for this session"
251
- )
252
-
253
- sql_dialect = gr.Dropdown(
254
- label="SQL Dialect",
255
- choices=["PostgreSQL", "MySQL", "SQLite", "SQL Server", "Oracle"],
256
- value="PostgreSQL",
257
- info="Select your target database system"
258
- )
259
-
260
- with gr.Row():
261
- include_comments = gr.Checkbox(
262
- label="Include inline comments",
263
- value=True
264
- )
265
- complexity_level = gr.Radio(
266
- label="Target Complexity",
267
- choices=["Simple", "Moderate", "Advanced"],
268
- value="Moderate"
269
- )
270
-
271
- query_input = gr.Textbox(
272
- label="Natural Language Query",
273
- placeholder="e.g., Find all customers who made purchases over $1000 in the last quarter and group by region",
274
- lines=4,
275
- value="Find all the students who scored more than 90 out of 100"
276
- )
277
-
278
- generate_btn = gr.Button("🚀 Generate SQL Query", variant="primary", size="lg")
279
-
280
- gr.Examples(
281
- examples=[
282
- ["Find all the students who scored more than 90 out of 100"],
283
- ["Get the top 5 customers by total purchase amount with their contact info"],
284
- ["List all employees hired in the last 6 months with their department and salary"],
285
- ["Find products with price between $50 and $100 ordered by popularity"],
286
- ["Show average salary by department with employee count"],
287
- ["Get customers who haven't made a purchase in the last 90 days"],
288
- ["Find duplicate email addresses in the users table"],
289
- ["Calculate running total of sales by date for each product category"]
290
- ],
291
- inputs=query_input,
292
- label="📚 Example Queries"
293
- )
294
-
295
- with gr.Row():
296
- with gr.Column():
297
- sql_output = gr.Code(
298
- label="Generated SQL Query",
299
- language="sql",
300
- lines=10
301
- )
302
-
303
- explanation_output = gr.Textbox(
304
- label="📖 Query Explanation",
305
- lines=4
306
- )
307
-
308
- with gr.Row():
309
- with gr.Column():
310
- metadata_output = gr.Textbox(
311
- label="📊 Query Metadata",
312
- lines=10
313
- )
314
-
315
- with gr.Column():
316
- validation_output = gr.Textbox(
317
- label="✅ Validation Status",
318
- lines=10
319
- )
320
-
321
- with gr.Row():
322
- with gr.Column():
323
- schema_output = gr.Code(
324
- label="🏗️ Table Schema",
325
- language="sql",
326
- lines=10
327
- )
328
-
329
- with gr.Column():
330
- sample_data_output = gr.Code(
331
- label="📝 Sample Data",
332
- language="sql",
333
- lines=10
334
- )
335
-
336
- with gr.Row():
337
- execution_output = gr.Dataframe(
338
- label="📊 Execution Results",
339
- headers=None,
340
- datatype="str",
341
- row_count=10,
342
- col_count=None,
343
- wrap=True,
344
- interactive=False
345
- )
346
-
347
- with gr.Row():
348
- alternatives_output = gr.Code(
349
- label="🔄 Alternative Query Approaches",
350
- language="sql",
351
- lines=8
352
- )
353
-
354
- with gr.Row():
355
- export_btn = gr.Button("💾 Export Complete SQL File", variant="secondary")
356
- export_output = gr.File(label="Download SQL File")
357
-
358
- generate_btn.click(
359
- fn=generate_sql_query,
360
- inputs=[api_key_input, query_input, sql_dialect, include_comments, complexity_level],
361
- outputs=[
362
- sql_output,
363
- metadata_output,
364
- schema_output,
365
- sample_data_output,
366
- execution_output,
367
- validation_output,
368
- explanation_output,
369
- alternatives_output
370
- ]
371
- )
372
-
373
- export_btn.click(
374
- fn=export_query,
375
- inputs=[sql_output, schema_output, sample_data_output],
376
- outputs=export_output
377
- )
378
-
379
- gr.Markdown(
380
- """
381
- ---
382
- ### 📋 How to use:
383
- 1. **API Key**: Enter your GROQ API key (get one from [console.groq.com](https://console.groq.com))
384
- 2. **Configure**: Select your SQL dialect and preferences
385
- 3. **Query**: Type your natural language description
386
- 4. **Generate**: Click the button to get your SQL query
387
- 5. **Export**: Download the complete SQL file with schema and sample data
388
-
389
- ### ✨ Features:
390
- - ✅ Multi-dialect SQL support (PostgreSQL, MySQL, SQLite, SQL Server, Oracle)
391
- - 🔍 Syntax validation with warnings
392
- - ⚡ Performance optimization suggestions
393
- - 📊 Live query execution with sample data
394
- - 🔄 Alternative query approaches
395
- - 📖 Clear explanations of query logic
396
- - 💾 Export complete SQL files
397
- - 🎯 Complexity level control
398
-
399
- ### 🔒 Security:
400
- - Your API key is never stored
401
- - Queries use parameterized patterns
402
- - No sensitive data in examples
403
- """
404
- )
405
 
406
  if __name__ == "__main__":
407
- demo.launch(share=True)
 
 
 
 
1
+ from Crypto.Cipher import AES
2
+ from Crypto.Protocol.KDF import PBKDF2
 
 
 
 
 
3
  import os
4
+ import tempfile
5
+ from dotenv import load_dotenv
6
 
7
+ load_dotenv() # Load all environment variables
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ def unpad(data):
10
+ return data[:-data[-1]]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
+ def decrypt_and_run():
13
+ # Get password from Hugging Face Secrets environment variable
14
+ password = os.getenv("PASSWORD")
15
+ if not password:
16
+ raise ValueError("PASSWORD secret not found in environment variables")
 
 
 
 
 
17
 
18
+ password = password.encode()
 
19
 
20
+ with open("code.enc", "rb") as f:
21
+ encrypted = f.read()
22
 
23
+ salt = encrypted[:16]
24
+ iv = encrypted[16:32]
25
+ ciphertext = encrypted[32:]
26
 
27
+ key = PBKDF2(password, salt, dkLen=32, count=1000000)
28
+ cipher = AES.new(key, AES.MODE_CBC, iv)
29
 
30
+ plaintext = unpad(cipher.decrypt(ciphertext))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ with tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode='wb') as tmp:
33
+ tmp.write(plaintext)
34
+ tmp.flush()
35
+ print(f"[INFO] Running decrypted code from {tmp.name}")
36
+ os.system(f"python {tmp.name}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  if __name__ == "__main__":
39
+ decrypt_and_run()
40
+
41
+ # This script decrypts the encrypted code and runs it.
42
+ # Ensure you have the PASSWORD secret set in your Hugging Face Secrets