Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -7,6 +7,7 @@ import json
|
|
| 7 |
import time
|
| 8 |
import traceback
|
| 9 |
from PIL import Image
|
|
|
|
| 10 |
# 🔧 CONFIGURE: Your Flask API URL (Public URL)
|
| 11 |
FLASK_API_URL = "http://3.16.57.66:5000"
|
| 12 |
|
|
@@ -20,7 +21,6 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 20 |
print("=== NEW QUERY REQUEST ===")
|
| 21 |
print(f"Time: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
| 22 |
print(f"Question: {question}")
|
| 23 |
-
print(f"Dashboard mode: {dashboard_mode}")
|
| 24 |
print(f"Chart type: {chart_type}")
|
| 25 |
print("="*50)
|
| 26 |
|
|
@@ -30,10 +30,6 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 30 |
"visualize": True
|
| 31 |
}
|
| 32 |
|
| 33 |
-
# Add dashboard_mode if specified
|
| 34 |
-
if dashboard_mode:
|
| 35 |
-
payload["dashboard_mode"] = dashboard_mode
|
| 36 |
-
|
| 37 |
# Add chart_type if specified
|
| 38 |
if chart_type and chart_type != "auto":
|
| 39 |
payload["viz_type"] = chart_type
|
|
@@ -59,7 +55,7 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 59 |
if not response.text:
|
| 60 |
error_msg = "Empty response from server"
|
| 61 |
print(f"ERROR: {error_msg}")
|
| 62 |
-
return "", None, None, "⚠️ Please enter a question.", "",
|
| 63 |
|
| 64 |
# Try to parse JSON response
|
| 65 |
try:
|
|
@@ -69,7 +65,7 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 69 |
error_msg = f"Invalid JSON response: {str(e)}"
|
| 70 |
print(f"ERROR: {error_msg}")
|
| 71 |
print(f"Response text (first 1000 chars): {response.text[:1000]}")
|
| 72 |
-
return "", None, None, "⚠️ Please enter a question.", "",
|
| 73 |
|
| 74 |
# Check HTTP status
|
| 75 |
if response.status_code != 200:
|
|
@@ -80,21 +76,24 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 80 |
if response.status_code == 500:
|
| 81 |
error_details = f"Server Error (500): {error_msg}\n"
|
| 82 |
error_details += f"Response: {json.dumps(result, indent=2)}"
|
| 83 |
-
return "", None, None, "⚠️ Please enter a question.", "",
|
| 84 |
|
| 85 |
-
return "", None, None, "⚠️ Please enter a question.", "",
|
| 86 |
|
| 87 |
-
# Extract data
|
| 88 |
sql = result.get("sql", "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
rows = result.get("result", [])
|
| 90 |
-
visualization = result.get("visualization", {})
|
| 91 |
-
row_count = result.get("row_count", len(rows))
|
| 92 |
|
| 93 |
print(f"\n=== EXTRACTED DATA ===")
|
| 94 |
print(f"SQL: {sql[:100] if sql else 'None'}...")
|
| 95 |
-
print(f"
|
| 96 |
-
print(f"
|
| 97 |
-
print(f"
|
| 98 |
|
| 99 |
# Create DataFrame
|
| 100 |
df = pd.DataFrame(rows) if rows else pd.DataFrame()
|
|
@@ -110,21 +109,22 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 110 |
show_image = True
|
| 111 |
show_html = False
|
| 112 |
|
| 113 |
-
if
|
|
|
|
| 114 |
try:
|
| 115 |
-
if isinstance(
|
| 116 |
# Check if it's an error response
|
| 117 |
-
if "error" in
|
| 118 |
-
chart_error =
|
| 119 |
print(f"Chart error: {chart_error}")
|
| 120 |
else:
|
| 121 |
# Extract the base64 image string
|
| 122 |
-
chart_image_b64 =
|
| 123 |
if chart_image_b64:
|
| 124 |
-
# Handle base64 prefix
|
| 125 |
-
if chart_image_b64.startswith("data:image/"):
|
| 126 |
-
chart_image_b64 = chart_image_b64.split(",")[1]
|
| 127 |
try:
|
|
|
|
|
|
|
|
|
|
| 128 |
image_bytes = base64.b64decode(chart_image_b64)
|
| 129 |
chart_image = Image.open(BytesIO(image_bytes))
|
| 130 |
print("Chart decoded successfully")
|
|
@@ -135,28 +135,20 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 135 |
print(f"Error decoding chart: {e}")
|
| 136 |
chart_error = f"Chart decoding error: {str(e)}"
|
| 137 |
|
| 138 |
-
# If no image, check for HTML fallback
|
| 139 |
-
if not chart_image and "html" in visualization:
|
| 140 |
-
chart_html = visualization["html"]
|
| 141 |
-
print("HTML chart fallback available")
|
| 142 |
-
chart_format = "html"
|
| 143 |
-
show_image = False
|
| 144 |
-
show_html = True
|
| 145 |
-
|
| 146 |
# Extract chart metadata
|
| 147 |
-
chart_title =
|
| 148 |
-
chart_type_result =
|
| 149 |
-
chart_format =
|
| 150 |
print(f"Chart type: {chart_type_result}")
|
| 151 |
print(f"Chart title: {chart_title}")
|
| 152 |
print(f"Chart format: {chart_format}")
|
| 153 |
-
elif isinstance(
|
| 154 |
# Fallback for backward compatibility
|
| 155 |
try:
|
| 156 |
# Handle base64 prefix
|
| 157 |
-
if
|
| 158 |
-
|
| 159 |
-
image_bytes = base64.b64decode(
|
| 160 |
chart_image = Image.open(BytesIO(image_bytes))
|
| 161 |
print("Chart decoded successfully (fallback)")
|
| 162 |
chart_format = "png"
|
|
@@ -166,22 +158,26 @@ def query_database(question, dashboard_mode=False, chart_type=None):
|
|
| 166 |
print(f"Error decoding chart (fallback): {e}")
|
| 167 |
chart_error = f"Chart decoding error: {str(e)}"
|
| 168 |
except Exception as e:
|
| 169 |
-
print(f"Error processing
|
| 170 |
-
chart_error = f"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
# Prepare details
|
| 173 |
details = f"Request time: {elapsed_time:.2f}s\n"
|
| 174 |
details += f"Status code: {response.status_code}\n"
|
| 175 |
details += f"Rows returned: {row_count}\n"
|
| 176 |
-
details += f"Chart generated: {
|
| 177 |
if chart_type_result:
|
| 178 |
details += f"Chart type: {chart_type_result}\n"
|
| 179 |
if chart_title:
|
| 180 |
details += f"Chart title: {chart_title}\n"
|
| 181 |
if chart_format:
|
| 182 |
details += f"Chart format: {chart_format}\n"
|
| 183 |
-
if dashboard_mode:
|
| 184 |
-
details += f"Dashboard mode: Enabled\n"
|
| 185 |
details += f"Response size: {len(response.text)} bytes"
|
| 186 |
|
| 187 |
print(f"=== REQUEST COMPLETED SUCCESSFULLY ===")
|
|
@@ -417,12 +413,7 @@ with gr.Blocks(theme=theme, title="Enterprise SQL Assistant", css="""
|
|
| 417 |
)
|
| 418 |
|
| 419 |
with gr.Row():
|
| 420 |
-
|
| 421 |
-
label="Dashboard Mode",
|
| 422 |
-
value=False,
|
| 423 |
-
info="Generate multiple charts (only primary will be shown)"
|
| 424 |
-
)
|
| 425 |
-
|
| 426 |
chart_type_dropdown = gr.Dropdown(
|
| 427 |
label="Chart Type (Optional)",
|
| 428 |
choices=[
|
|
@@ -529,10 +520,10 @@ with gr.Blocks(theme=theme, title="Enterprise SQL Assistant", css="""
|
|
| 529 |
outputs=[question_input]
|
| 530 |
)
|
| 531 |
|
| 532 |
-
# Submit button
|
| 533 |
submit_btn.click(
|
| 534 |
fn=query_database,
|
| 535 |
-
inputs=[question_input,
|
| 536 |
outputs=[sql_output, results_output, chart_output, html_output, gr.Number(visible=False, value=1), gr.Number(visible=False, value=0), chatbot_output, request_details, error_details, chart_type_output, chart_title_output, chart_format_output, chart_error_output]
|
| 537 |
)
|
| 538 |
|
|
|
|
| 7 |
import time
|
| 8 |
import traceback
|
| 9 |
from PIL import Image
|
| 10 |
+
|
| 11 |
# 🔧 CONFIGURE: Your Flask API URL (Public URL)
|
| 12 |
FLASK_API_URL = "http://3.16.57.66:5000"
|
| 13 |
|
|
|
|
| 21 |
print("=== NEW QUERY REQUEST ===")
|
| 22 |
print(f"Time: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
| 23 |
print(f"Question: {question}")
|
|
|
|
| 24 |
print(f"Chart type: {chart_type}")
|
| 25 |
print("="*50)
|
| 26 |
|
|
|
|
| 30 |
"visualize": True
|
| 31 |
}
|
| 32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
# Add chart_type if specified
|
| 34 |
if chart_type and chart_type != "auto":
|
| 35 |
payload["viz_type"] = chart_type
|
|
|
|
| 55 |
if not response.text:
|
| 56 |
error_msg = "Empty response from server"
|
| 57 |
print(f"ERROR: {error_msg}")
|
| 58 |
+
return "", None, None, "⚠️ Please enter a question.", "", "", "", "", "", ""
|
| 59 |
|
| 60 |
# Try to parse JSON response
|
| 61 |
try:
|
|
|
|
| 65 |
error_msg = f"Invalid JSON response: {str(e)}"
|
| 66 |
print(f"ERROR: {error_msg}")
|
| 67 |
print(f"Response text (first 1000 chars): {response.text[:1000]}")
|
| 68 |
+
return "", None, None, "⚠️ Please enter a question.", "", "", "", "", "", ""
|
| 69 |
|
| 70 |
# Check HTTP status
|
| 71 |
if response.status_code != 200:
|
|
|
|
| 76 |
if response.status_code == 500:
|
| 77 |
error_details = f"Server Error (500): {error_msg}\n"
|
| 78 |
error_details += f"Response: {json.dumps(result, indent=2)}"
|
| 79 |
+
return "", None, None, "⚠️ Please enter a question.", "", "", "", error_details, "", "", ""
|
| 80 |
|
| 81 |
+
return "", None, None, "⚠️ Please enter a question.", "", "", "", f"HTTP error: {error_msg}", "", "", ""
|
| 82 |
|
| 83 |
+
# Extract data - Updated to match new response structure
|
| 84 |
sql = result.get("sql", "")
|
| 85 |
+
chart = result.get("chart", {}) # Changed from "visualization" to "chart"
|
| 86 |
+
chart_generated = result.get("chart_generated", False) # New field
|
| 87 |
+
row_count = result.get("row_count", 0)
|
| 88 |
+
|
| 89 |
+
# Extract result data if available (for backward compatibility)
|
| 90 |
rows = result.get("result", [])
|
|
|
|
|
|
|
| 91 |
|
| 92 |
print(f"\n=== EXTRACTED DATA ===")
|
| 93 |
print(f"SQL: {sql[:100] if sql else 'None'}...")
|
| 94 |
+
print(f"Chart generated: {chart_generated}")
|
| 95 |
+
print(f"Row count: {row_count}")
|
| 96 |
+
print(f"Chart data: {chart}")
|
| 97 |
|
| 98 |
# Create DataFrame
|
| 99 |
df = pd.DataFrame(rows) if rows else pd.DataFrame()
|
|
|
|
| 109 |
show_image = True
|
| 110 |
show_html = False
|
| 111 |
|
| 112 |
+
# Only process chart if chart_generated is True
|
| 113 |
+
if chart_generated and chart:
|
| 114 |
try:
|
| 115 |
+
if isinstance(chart, dict):
|
| 116 |
# Check if it's an error response
|
| 117 |
+
if "error" in chart:
|
| 118 |
+
chart_error = chart["error"]
|
| 119 |
print(f"Chart error: {chart_error}")
|
| 120 |
else:
|
| 121 |
# Extract the base64 image string
|
| 122 |
+
chart_image_b64 = chart.get("image")
|
| 123 |
if chart_image_b64:
|
|
|
|
|
|
|
|
|
|
| 124 |
try:
|
| 125 |
+
# Handle base64 prefix
|
| 126 |
+
if chart_image_b64.startswith("data:image/"):
|
| 127 |
+
chart_image_b64 = chart_image_b64.split(",")[1]
|
| 128 |
image_bytes = base64.b64decode(chart_image_b64)
|
| 129 |
chart_image = Image.open(BytesIO(image_bytes))
|
| 130 |
print("Chart decoded successfully")
|
|
|
|
| 135 |
print(f"Error decoding chart: {e}")
|
| 136 |
chart_error = f"Chart decoding error: {str(e)}"
|
| 137 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
# Extract chart metadata
|
| 139 |
+
chart_title = chart.get("title", "")
|
| 140 |
+
chart_type_result = chart.get("type", "")
|
| 141 |
+
chart_format = chart.get("format", chart_format)
|
| 142 |
print(f"Chart type: {chart_type_result}")
|
| 143 |
print(f"Chart title: {chart_title}")
|
| 144 |
print(f"Chart format: {chart_format}")
|
| 145 |
+
elif isinstance(chart, str):
|
| 146 |
# Fallback for backward compatibility
|
| 147 |
try:
|
| 148 |
# Handle base64 prefix
|
| 149 |
+
if chart.startswith("data:image/"):
|
| 150 |
+
chart = chart.split(",")[1]
|
| 151 |
+
image_bytes = base64.b64decode(chart)
|
| 152 |
chart_image = Image.open(BytesIO(image_bytes))
|
| 153 |
print("Chart decoded successfully (fallback)")
|
| 154 |
chart_format = "png"
|
|
|
|
| 158 |
print(f"Error decoding chart (fallback): {e}")
|
| 159 |
chart_error = f"Chart decoding error: {str(e)}"
|
| 160 |
except Exception as e:
|
| 161 |
+
print(f"Error processing chart: {e}")
|
| 162 |
+
chart_error = f"Chart processing error: {str(e)}"
|
| 163 |
+
elif not chart_generated:
|
| 164 |
+
print("Chart was not generated")
|
| 165 |
+
chart_error = "Chart generation was not successful"
|
| 166 |
+
else:
|
| 167 |
+
print("No chart data available")
|
| 168 |
+
chart_error = "No chart data available"
|
| 169 |
|
| 170 |
# Prepare details
|
| 171 |
details = f"Request time: {elapsed_time:.2f}s\n"
|
| 172 |
details += f"Status code: {response.status_code}\n"
|
| 173 |
details += f"Rows returned: {row_count}\n"
|
| 174 |
+
details += f"Chart generated: {chart_generated}\n"
|
| 175 |
if chart_type_result:
|
| 176 |
details += f"Chart type: {chart_type_result}\n"
|
| 177 |
if chart_title:
|
| 178 |
details += f"Chart title: {chart_title}\n"
|
| 179 |
if chart_format:
|
| 180 |
details += f"Chart format: {chart_format}\n"
|
|
|
|
|
|
|
| 181 |
details += f"Response size: {len(response.text)} bytes"
|
| 182 |
|
| 183 |
print(f"=== REQUEST COMPLETED SUCCESSFULLY ===")
|
|
|
|
| 413 |
)
|
| 414 |
|
| 415 |
with gr.Row():
|
| 416 |
+
# Removed dashboard_mode as backend no longer supports it
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
chart_type_dropdown = gr.Dropdown(
|
| 418 |
label="Chart Type (Optional)",
|
| 419 |
choices=[
|
|
|
|
| 520 |
outputs=[question_input]
|
| 521 |
)
|
| 522 |
|
| 523 |
+
# Submit button - Updated to remove dashboard_mode parameter
|
| 524 |
submit_btn.click(
|
| 525 |
fn=query_database,
|
| 526 |
+
inputs=[question_input, chart_type_dropdown], # Removed dashboard_mode
|
| 527 |
outputs=[sql_output, results_output, chart_output, html_output, gr.Number(visible=False, value=1), gr.Number(visible=False, value=0), chatbot_output, request_details, error_details, chart_type_output, chart_title_output, chart_format_output, chart_error_output]
|
| 528 |
)
|
| 529 |
|