jzou19950715 commited on
Commit
224e4cc
·
verified ·
1 Parent(s): e742aa1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +391 -88
app.py CHANGED
@@ -1,4 +1,7 @@
 
 
1
  import os
 
2
  from typing import List, Optional, Tuple, Dict, Any
3
  import json
4
 
@@ -11,61 +14,149 @@ from plotly.subplots import make_subplots
11
  from litellm import completion
12
 
13
  class DataAnalyzer:
 
 
14
  def __init__(self):
15
  self.data: Optional[pd.DataFrame] = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
- def create_plot(self, plot_type: str, **kwargs) -> str:
18
- """Create plot and return HTML string"""
19
- if self.data is None:
20
- raise ValueError("No data loaded")
21
-
22
- if plot_type == "scatter":
23
- fig = px.scatter(
24
- self.data,
25
- x=kwargs.get('x'),
26
- y=kwargs.get('y'),
27
- title=kwargs.get('title', 'Scatter Plot'),
28
- color=kwargs.get('color')
29
- )
30
- elif plot_type == "line":
31
- fig = px.line(
32
- self.data,
33
- x=kwargs.get('x'),
34
- y=kwargs.get('y'),
35
- title=kwargs.get('title', 'Line Plot')
36
- )
37
- elif plot_type == "bar":
38
- fig = px.bar(
39
- self.data,
40
- x=kwargs.get('x'),
41
- y=kwargs.get('y'),
42
- title=kwargs.get('title', 'Bar Plot')
43
- )
44
- elif plot_type == "histogram":
45
- fig = px.histogram(
46
- self.data,
47
- x=kwargs.get('x'),
48
- title=kwargs.get('title', 'Distribution')
49
- )
50
- elif plot_type == "box":
51
- fig = px.box(
52
- self.data,
53
- x=kwargs.get('x'),
54
- y=kwargs.get('y'),
55
- title=kwargs.get('title', 'Box Plot')
56
  )
57
- else:
58
- raise ValueError(f"Unknown plot type: {plot_type}")
59
 
60
- # Convert plot to HTML string
61
- return fig.to_html(include_plotlyjs=True, full_html=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  class ChatAnalyzer:
 
 
64
  def __init__(self):
65
  self.analyzer = DataAnalyzer()
66
  self.history: List[Tuple[str, str]] = []
67
-
68
  def process_file(self, file: gr.File) -> List[Tuple[str, str]]:
 
69
  try:
70
  if file.name.endswith('.csv'):
71
  self.analyzer.data = pd.read_csv(file.name)
@@ -74,9 +165,22 @@ class ChatAnalyzer:
74
  else:
75
  return [("System", "Error: Please upload a CSV or Excel file.")]
76
 
 
 
 
 
 
 
 
 
77
  info = f"""Data loaded successfully!
78
  Shape: {self.analyzer.data.shape}
79
- Columns: {', '.join(self.analyzer.data.columns)}"""
 
 
 
 
 
80
 
81
  self.history = [("System", info)]
82
  return self.history
@@ -86,6 +190,7 @@ class ChatAnalyzer:
86
  return self.history
87
 
88
  def chat(self, message: str, api_key: str) -> Tuple[List[Tuple[str, str]], str]:
 
89
  if self.analyzer.data is None:
90
  return [(message, "Please upload a data file first.")], ""
91
 
@@ -111,120 +216,318 @@ class ChatAnalyzer:
111
  analysis = completion_response.choices[0].message.content
112
 
113
  # Create visualizations
114
- plot_html = ""
115
  try:
116
- # Execute any visualization commands in the analysis
117
- exec_globals = {
118
- 'analyzer': self.analyzer,
119
- 'df': self.analyzer.data,
120
- 'px': px,
121
- 'go': go,
122
- 'print': lambda x: x # Will be used to capture plot output
123
- }
124
-
125
  # Extract code blocks
126
  import re
127
  code_blocks = re.findall(r'```python\n(.*?)```', analysis, re.DOTALL)
128
 
129
  for code in code_blocks:
130
- result = exec(code, exec_globals)
131
- if isinstance(result, (go.Figure, px.Figure)):
132
- plot_html += result.to_html(include_plotlyjs=True, full_html=False)
 
 
 
 
 
 
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  except Exception as e:
135
  analysis += f"\n\nError creating visualization: {str(e)}"
136
 
137
  # Update chat history
138
  self.history.append((message, analysis))
139
 
140
- return self.history, plot_html
141
 
142
  except Exception as e:
143
  self.history.append((message, f"Error: {str(e)}"))
144
  return self.history, ""
145
 
146
  def _get_data_context(self) -> str:
 
147
  df = self.analyzer.data
148
  numeric_cols = df.select_dtypes(include=[np.number]).columns
149
- categorical_cols = df.select_dtypes(include=['object', 'category']).columns
 
 
 
 
150
 
151
  return f"""
152
  Data Information:
153
  - Shape: {df.shape}
154
  - Numeric columns: {', '.join(numeric_cols)}
 
155
  - Categorical columns: {', '.join(categorical_cols)}
 
 
 
 
 
 
 
 
 
 
 
156
  """
157
 
158
  def _get_system_prompt(self) -> str:
159
- return """You are a data analysis assistant. To create visualizations, use Python code blocks with Plotly.
 
 
 
 
 
 
 
 
 
160
 
161
- Example commands:
 
 
 
 
 
 
162
  ```python
163
  # Create scatter plot
164
- fig = px.scatter(df, x='column1', y='column2', title='Analysis')
165
- fig # Return the figure object
 
 
 
 
 
 
 
 
 
 
 
 
 
166
 
167
- # Create histogram
168
- fig = px.histogram(df, x='column', title='Distribution')
169
- fig # Return the figure object
 
 
 
170
  ```
171
 
172
- Provide analysis and insights along with visualizations."""
173
 
174
  def create_interface():
 
 
175
  analyzer = ChatAnalyzer()
176
 
177
- with gr.Blocks(css="footer {visibility: hidden}") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  gr.Markdown("""
179
  # Interactive Data Analysis Chat
180
- Upload your data and chat with AI to analyze it!
 
 
 
 
 
 
 
181
  """)
182
 
183
  with gr.Row():
184
  with gr.Column(scale=1):
185
- file = gr.File(label="Upload Data (CSV or Excel)")
 
 
 
 
186
  api_key = gr.Textbox(
187
  label="OpenAI API Key",
188
  type="password",
189
- placeholder="Enter your API key"
 
190
  )
191
 
192
  with gr.Column(scale=2):
193
- chatbot = gr.Chatbot(height=400)
194
- message = gr.Textbox(
195
- label="Ask about your data",
196
- placeholder="e.g., Show me a scatter plot of X vs Y"
197
  )
198
- send = gr.Button("Send")
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
- # Plot output area (using HTML for interactive plots)
201
- plot_output = gr.HTML(label="Visualization")
 
 
 
 
202
 
203
  # Event handlers
204
  file.change(
205
- analyzer.process_file,
206
  inputs=[file],
207
- outputs=[chatbot]
 
 
 
 
 
 
 
 
 
208
  )
209
 
210
- send.click(
211
- analyzer.chat,
212
  inputs=[message, api_key],
213
  outputs=[chatbot, plot_output]
214
  )
215
 
 
 
 
 
 
 
 
216
  # Example queries
217
  gr.Examples(
218
  examples=[
219
- ["Show me a scatter plot of the numerical variables"],
220
- ["Create a histogram of the distribution"],
221
- ["Analyze trends in the data"],
 
 
 
 
 
222
  ],
223
- inputs=message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  )
225
 
226
  return demo
227
 
228
  if __name__ == "__main__":
229
  demo = create_interface()
230
- demo.launch()
 
 
 
 
 
 
1
+ import base64
2
+ import io
3
  import os
4
+ from dataclasses import dataclass
5
  from typing import List, Optional, Tuple, Dict, Any
6
  import json
7
 
 
14
  from litellm import completion
15
 
16
  class DataAnalyzer:
17
+ """Handles data analysis and visualization"""
18
+
19
  def __init__(self):
20
  self.data: Optional[pd.DataFrame] = None
21
+ self.width = 800
22
+ self.height = 500
23
+ self.template = "plotly_white"
24
+
25
+ def create_scatter(self, x_col: str, y_col: str, color_col: Optional[str] = None,
26
+ title: str = "") -> go.Figure:
27
+ """Create scatter plot"""
28
+ fig = px.scatter(
29
+ self.data,
30
+ x=x_col,
31
+ y=y_col,
32
+ color=color_col,
33
+ title=title,
34
+ template=self.template,
35
+ height=self.height,
36
+ width=self.width
37
+ )
38
+ fig.update_layout(
39
+ hovermode='closest',
40
+ showlegend=True if color_col else False
41
+ )
42
+ return fig
43
+
44
+ def create_line(self, x_col: str, y_cols: List[str], title: str = "") -> go.Figure:
45
+ """Create line plot"""
46
+ fig = go.Figure()
47
 
48
+ for y_col in y_cols:
49
+ fig.add_trace(
50
+ go.Scatter(
51
+ x=self.data[x_col],
52
+ y=self.data[y_col],
53
+ name=y_col,
54
+ mode='lines+markers'
55
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  )
 
 
57
 
58
+ fig.update_layout(
59
+ title=title,
60
+ template=self.template,
61
+ height=self.height,
62
+ width=self.width,
63
+ hovermode='x unified',
64
+ showlegend=True
65
+ )
66
+ return fig
67
+
68
+ def create_bar(self, x_col: str, y_col: str, color_col: Optional[str] = None,
69
+ title: str = "") -> go.Figure:
70
+ """Create bar plot"""
71
+ fig = px.bar(
72
+ self.data,
73
+ x=x_col,
74
+ y=y_col,
75
+ color=color_col,
76
+ title=title,
77
+ template=self.template,
78
+ height=self.height,
79
+ width=self.width
80
+ )
81
+ fig.update_layout(
82
+ hovermode='closest',
83
+ showlegend=True if color_col else False
84
+ )
85
+ return fig
86
+
87
+ def create_histogram(self, column: str, bins: int = 30,
88
+ title: str = "") -> go.Figure:
89
+ """Create histogram"""
90
+ fig = px.histogram(
91
+ self.data,
92
+ x=column,
93
+ nbins=bins,
94
+ title=title,
95
+ template=self.template,
96
+ height=self.height,
97
+ width=self.width,
98
+ marginal="box" # Add box plot on the margin
99
+ )
100
+ fig.update_layout(
101
+ hovermode='closest',
102
+ showlegend=False
103
+ )
104
+ return fig
105
+
106
+ def create_box(self, x_col: str, y_col: str, color_col: Optional[str] = None,
107
+ title: str = "") -> go.Figure:
108
+ """Create box plot"""
109
+ fig = px.box(
110
+ self.data,
111
+ x=x_col,
112
+ y=y_col,
113
+ color=color_col,
114
+ title=title,
115
+ template=self.template,
116
+ height=self.height,
117
+ width=self.width,
118
+ points="all" # Show all points
119
+ )
120
+ fig.update_layout(
121
+ hovermode='closest',
122
+ showlegend=True if color_col else False
123
+ )
124
+ return fig
125
+
126
+ def create_correlation_matrix(self, title: str = "") -> go.Figure:
127
+ """Create correlation matrix"""
128
+ # Get numeric columns
129
+ numeric_cols = self.data.select_dtypes(include=[np.number]).columns
130
+ corr_matrix = self.data[numeric_cols].corr()
131
+
132
+ fig = px.imshow(
133
+ corr_matrix,
134
+ title=title,
135
+ template=self.template,
136
+ height=self.height,
137
+ width=self.width,
138
+ color_continuous_scale="RdBu",
139
+ aspect="auto",
140
+ labels=dict(color="Correlation")
141
+ )
142
+
143
+ # Update layout for better readability
144
+ fig.update_traces(text=corr_matrix.round(2), texttemplate="%{text}")
145
+ fig.update_layout(
146
+ xaxis_title="",
147
+ yaxis_title=""
148
+ )
149
+ return fig
150
 
151
  class ChatAnalyzer:
152
+ """Handles chat-based analysis with visualization"""
153
+
154
  def __init__(self):
155
  self.analyzer = DataAnalyzer()
156
  self.history: List[Tuple[str, str]] = []
157
+
158
  def process_file(self, file: gr.File) -> List[Tuple[str, str]]:
159
+ """Process uploaded file and initialize analyzer"""
160
  try:
161
  if file.name.endswith('.csv'):
162
  self.analyzer.data = pd.read_csv(file.name)
 
165
  else:
166
  return [("System", "Error: Please upload a CSV or Excel file.")]
167
 
168
+ # Convert date columns to datetime
169
+ date_cols = self.analyzer.data.select_dtypes(include=['object']).columns
170
+ for col in date_cols:
171
+ try:
172
+ self.analyzer.data[col] = pd.to_datetime(self.analyzer.data[col])
173
+ except:
174
+ continue
175
+
176
  info = f"""Data loaded successfully!
177
  Shape: {self.analyzer.data.shape}
178
+ Columns: {', '.join(self.analyzer.data.columns)}
179
+
180
+ Numeric columns: {', '.join(self.analyzer.data.select_dtypes(include=[np.number]).columns)}
181
+ Date columns: {', '.join(self.analyzer.data.select_dtypes(include=['datetime64']).columns)}
182
+ Categorical columns: {', '.join(self.analyzer.data.select_dtypes(include=['object']).columns)}
183
+ """
184
 
185
  self.history = [("System", info)]
186
  return self.history
 
190
  return self.history
191
 
192
  def chat(self, message: str, api_key: str) -> Tuple[List[Tuple[str, str]], str]:
193
+ """Process chat message and generate visualizations"""
194
  if self.analyzer.data is None:
195
  return [(message, "Please upload a data file first.")], ""
196
 
 
216
  analysis = completion_response.choices[0].message.content
217
 
218
  # Create visualizations
219
+ plot_output = ""
220
  try:
 
 
 
 
 
 
 
 
 
221
  # Extract code blocks
222
  import re
223
  code_blocks = re.findall(r'```python\n(.*?)```', analysis, re.DOTALL)
224
 
225
  for code in code_blocks:
226
+ # Create namespace for execution
227
+ namespace = {
228
+ 'df': self.analyzer.data,
229
+ 'px': px,
230
+ 'go': go,
231
+ 'pd': pd,
232
+ 'np': np,
233
+ 'analyzer': self.analyzer
234
+ }
235
 
236
+ # Execute the code
237
+ exec(code, namespace)
238
+
239
+ # Look for figure object in namespace
240
+ for var in namespace.values():
241
+ if isinstance(var, (go.Figure, px.Figure)):
242
+ try:
243
+ # Try interactive HTML first
244
+ html = var.to_html(
245
+ include_plotlyjs=True,
246
+ full_html=False,
247
+ config={
248
+ 'displayModeBar': True,
249
+ 'responsive': True
250
+ }
251
+ )
252
+ plot_output += f'''
253
+ <div class="plot-container">
254
+ <div style="overflow-x: auto;">{html}</div>
255
+ </div>
256
+ '''
257
+ except Exception as e:
258
+ # Fallback to static image
259
+ buffer = io.BytesIO()
260
+ var.write_image(buffer, format='png')
261
+ buffer.seek(0)
262
+ image = base64.b64encode(buffer.read()).decode()
263
+ plot_output += f'''
264
+ <div class="plot-container">
265
+ <img src="data:image/png;base64,{image}"
266
+ style="max-width: 100%; height: auto;">
267
+ </div>
268
+ '''
269
+
270
  except Exception as e:
271
  analysis += f"\n\nError creating visualization: {str(e)}"
272
 
273
  # Update chat history
274
  self.history.append((message, analysis))
275
 
276
+ return self.history, plot_output
277
 
278
  except Exception as e:
279
  self.history.append((message, f"Error: {str(e)}"))
280
  return self.history, ""
281
 
282
  def _get_data_context(self) -> str:
283
+ """Get current data context for AI"""
284
  df = self.analyzer.data
285
  numeric_cols = df.select_dtypes(include=[np.number]).columns
286
+ date_cols = df.select_dtypes(include=['datetime64']).columns
287
+ categorical_cols = df.select_dtypes(include=['object']).columns
288
+
289
+ # Get basic statistics
290
+ stats = df[numeric_cols].describe().to_string() if len(numeric_cols) > 0 else "No numeric columns"
291
 
292
  return f"""
293
  Data Information:
294
  - Shape: {df.shape}
295
  - Numeric columns: {', '.join(numeric_cols)}
296
+ - Date columns: {', '.join(date_cols)}
297
  - Categorical columns: {', '.join(categorical_cols)}
298
+
299
+ Basic Statistics:
300
+ {stats}
301
+
302
+ Available visualization functions:
303
+ - analyzer.create_scatter(x_col, y_col, color_col, title)
304
+ - analyzer.create_line(x_col, y_cols, title)
305
+ - analyzer.create_bar(x_col, y_col, color_col, title)
306
+ - analyzer.create_histogram(column, bins, title)
307
+ - analyzer.create_box(x_col, y_col, color_col, title)
308
+ - analyzer.create_correlation_matrix(title)
309
  """
310
 
311
  def _get_system_prompt(self) -> str:
312
+ """Get system prompt for AI"""
313
+ return """You are a data analysis assistant specialized in creating interactive visualizations.
314
+
315
+ Available visualization functions:
316
+ 1. analyzer.create_scatter(x_col, y_col, color_col, title)
317
+ 2. analyzer.create_line(x_col, y_cols, title)
318
+ 3. analyzer.create_bar(x_col, y_col, color_col, title)
319
+ 4. analyzer.create_histogram(column, bins, title)
320
+ 5. analyzer.create_box(x_col, y_col, color_col, title)
321
+ 6. analyzer.create_correlation_matrix(title)
322
 
323
+ When analyzing data:
324
+ 1. First understand the data type and relationships
325
+ 2. Choose appropriate visualizations
326
+ 3. Provide insights and analysis
327
+ 4. Suggest follow-up analyses
328
+
329
+ Example usage:
330
  ```python
331
  # Create scatter plot
332
+ fig = analyzer.create_scatter(
333
+ x_col='Date',
334
+ y_col='Value',
335
+ color_col='Category',
336
+ title='Value Trends by Category'
337
+ )
338
+ print(fig)
339
+
340
+ # Create multiple visualizations
341
+ fig1 = analyzer.create_histogram(
342
+ column='Value',
343
+ bins=30,
344
+ title='Value Distribution'
345
+ )
346
+ print(fig1)
347
 
348
+ fig2 = analyzer.create_box(
349
+ x_col='Category',
350
+ y_col='Value',
351
+ title='Value Distribution by Category'
352
+ )
353
+ print(fig2)
354
  ```
355
 
356
+ Always wrap code in Python code blocks and print the figures to display them."""
357
 
358
  def create_interface():
359
+ """Create Gradio interface"""
360
+
361
  analyzer = ChatAnalyzer()
362
 
363
+ # Custom CSS for better visualization display
364
+ css = """
365
+ .container { max-width: 1200px; margin: auto; }
366
+ .plot-container {
367
+ margin: 20px 0;
368
+ padding: 15px;
369
+ border: 1px solid #e0e0e0;
370
+ border-radius: 8px;
371
+ background: white;
372
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
373
+ }
374
+ .chat-message {
375
+ margin-bottom: 15px;
376
+ padding: 10px;
377
+ border-radius: 8px;
378
+ background: #f8f9fa;
379
+ }
380
+ .title {
381
+ text-align: center;
382
+ margin-bottom: 20px;
383
+ }
384
+ .footer {
385
+ text-align: center;
386
+ margin-top: 20px;
387
+ font-size: 0.9em;
388
+ color: #666;
389
+ }
390
+ """
391
+
392
+ with gr.Blocks(css=css, title="Interactive Data Analysis Chat") as demo:
393
  gr.Markdown("""
394
  # Interactive Data Analysis Chat
395
+
396
+ Upload your data and chat with AI to analyze it! Features:
397
+ - Interactive visualizations with zoom, pan, and hover capabilities
398
+ - Natural language analysis and insights
399
+ - Statistical analysis and summaries
400
+ - Trend detection and pattern analysis
401
+
402
+ Start by uploading a CSV or Excel file.
403
  """)
404
 
405
  with gr.Row():
406
  with gr.Column(scale=1):
407
+ file = gr.File(
408
+ label="Upload Data (CSV or Excel)",
409
+ file_types=[".csv", ".xlsx", ".xls"],
410
+ elem_classes="file-upload"
411
+ )
412
  api_key = gr.Textbox(
413
  label="OpenAI API Key",
414
  type="password",
415
+ placeholder="Enter your API key",
416
+ elem_classes="api-input"
417
  )
418
 
419
  with gr.Column(scale=2):
420
+ chatbot = gr.Chatbot(
421
+ height=400,
422
+ elem_classes="chat-message",
423
+ show_label=False
424
  )
425
+ with gr.Row():
426
+ message = gr.Textbox(
427
+ label="Ask about your data",
428
+ placeholder="e.g., Show me trends in the data",
429
+ lines=2,
430
+ elem_classes="message-input",
431
+ scale=4
432
+ )
433
+ send = gr.Button(
434
+ "Send",
435
+ scale=1,
436
+ elem_classes="send-button"
437
+ )
438
 
439
+ # Plot output area
440
+ plot_output = gr.HTML(
441
+ label="Visualizations",
442
+ elem_classes="plot-container",
443
+ visible=True # Always show container even when empty
444
+ )
445
 
446
  # Event handlers
447
  file.change(
448
+ fn=analyzer.process_file,
449
  inputs=[file],
450
+ outputs=[chatbot],
451
+ api_name="upload"
452
+ )
453
+
454
+ # Handle both click and enter key
455
+ msg_handler = send.click(
456
+ fn=analyzer.chat,
457
+ inputs=[message, api_key],
458
+ outputs=[chatbot, plot_output],
459
+ api_name="chat"
460
  )
461
 
462
+ message.submit(
463
+ fn=analyzer.chat,
464
  inputs=[message, api_key],
465
  outputs=[chatbot, plot_output]
466
  )
467
 
468
+ # Clear message after sending
469
+ msg_handler.then(
470
+ fn=lambda: "",
471
+ inputs=[],
472
+ outputs=[message]
473
+ )
474
+
475
  # Example queries
476
  gr.Examples(
477
  examples=[
478
+ ["Show me a scatter plot of the main numerical variables and explain any patterns you see"],
479
+ ["Create a correlation analysis with heatmap and highlight the strongest relationships"],
480
+ ["Show the distribution of values using histograms and describe the shapes"],
481
+ ["Create box plots to analyze categories and identify any outliers"],
482
+ ["Show trends over time using line plots and explain the patterns"],
483
+ ["Generate a comprehensive analysis with multiple visualizations"],
484
+ ["Compare the distribution across different categories using appropriate plots"],
485
+ ["Identify and visualize any seasonal patterns or cycles in the data"],
486
  ],
487
+ inputs=[message],
488
+ label="Example Analysis Queries"
489
+ )
490
+
491
+ # Tips section
492
+ gr.Markdown("""
493
+ ### Tips for better analysis:
494
+ 1. **Data Preparation**: Upload clean CSV or Excel files with clear column names
495
+ 2. **Specific Questions**: Ask clear, specific questions about your data
496
+ 3. **Interactive Features**: Use zoom, pan, and hover on visualizations
497
+ 4. **Follow-up Questions**: Ask for deeper analysis of interesting patterns
498
+ 5. **Multiple Views**: Request different visualization types for better insights
499
+
500
+ ### Available Visualization Types:
501
+ - Scatter plots for relationships
502
+ - Line plots for trends
503
+ - Bar charts for comparisons
504
+ - Histograms for distributions
505
+ - Box plots for statistical summaries
506
+ - Correlation matrices for relationship analysis
507
+ """)
508
+
509
+ # Footer
510
+ gr.Markdown("""
511
+ <div class="footer">
512
+ Built with Gradio • Powered by OpenAI • Interactive Visualizations
513
+ </div>
514
+ """)
515
+
516
+ # Theme customization
517
+ demo.theme = gr.themes.Soft(
518
+ primary_hue="blue",
519
+ secondary_hue="gray",
520
+ neutral_hue="gray",
521
+ text_size=gr.themes.sizes.text_md
522
  )
523
 
524
  return demo
525
 
526
  if __name__ == "__main__":
527
  demo = create_interface()
528
+ demo.launch(
529
+ share=False, # Set to True to create a public link
530
+ debug=True, # Set to False in production
531
+ show_error=True, # Show detailed error messages
532
+ server_port=7860 # Specify port number
533
+ )