shukdevdatta123 commited on
Commit
6aa4b02
·
verified ·
1 Parent(s): 8858024

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -495
app.py CHANGED
@@ -4,20 +4,10 @@ import re
4
  from groq import Groq
5
  import pandas as pd
6
  import matplotlib.pyplot as plt
7
- import seaborn as sns
8
  import io
9
  import base64
10
  from datetime import datetime, timedelta
11
  import json
12
- import numpy as np
13
- from statsmodels.tsa.arima.model import ARIMA
14
- from sklearn.linear_model import LinearRegression
15
- import calendar
16
- import matplotlib.dates as mdates
17
-
18
- # Set the style for better looking charts
19
- plt.style.use('ggplot')
20
- sns.set_palette("pastel")
21
 
22
  def validate_api_key(api_key):
23
  """Validate if the API key has the correct format."""
@@ -51,44 +41,18 @@ def test_api_connection(api_key):
51
  # Ensure analytics directory exists
52
  os.makedirs("analytics", exist_ok=True)
53
 
54
- def log_chat_interaction(model, tokens_used, response_time, user_message_length, message_type, session_id=None):
55
- """Enhanced log chat interactions for analytics"""
56
  timestamp = datetime.now().isoformat()
57
 
58
- # Generate a session ID if none is provided
59
- if session_id is None:
60
- session_id = f"session_{datetime.now().strftime('%Y%m%d%H%M%S')}_{hash(timestamp) % 1000}"
61
-
62
  log_file = "analytics/chat_log.json"
63
 
64
- # Extract message intent/category through simple keyword matching
65
- intent_categories = {
66
- "code": ["code", "programming", "function", "class", "algorithm", "debug"],
67
- "creative": ["story", "poem", "creative", "imagine", "write", "generate"],
68
- "technical": ["explain", "how does", "technical", "details", "documentation"],
69
- "data": ["data", "analysis", "statistics", "graph", "chart", "dataset"],
70
- "general": [] # Default category
71
- }
72
-
73
- message_content = user_message_length.lower() if isinstance(user_message_length, str) else ""
74
- message_intent = "general"
75
-
76
- for intent, keywords in intent_categories.items():
77
- if any(keyword in message_content for keyword in keywords):
78
- message_intent = intent
79
- break
80
-
81
  log_entry = {
82
  "timestamp": timestamp,
83
  "model": model,
84
  "tokens_used": tokens_used,
85
  "response_time_sec": response_time,
86
- "message_length": len(message_content) if isinstance(message_content, str) else user_message_length,
87
- "message_type": message_type,
88
- "message_intent": message_intent,
89
- "session_id": session_id,
90
- "day_of_week": datetime.now().strftime("%A"),
91
- "hour_of_day": datetime.now().hour
92
  }
93
 
94
  # Append to existing log or create new file
@@ -105,8 +69,6 @@ def log_chat_interaction(model, tokens_used, response_time, user_message_length,
105
 
106
  with open(log_file, "w") as f:
107
  json.dump(logs, f, indent=2)
108
-
109
- return session_id
110
 
111
  def get_template_prompt(template_name):
112
  """Get system prompt for a given template name"""
@@ -120,7 +82,7 @@ def get_template_prompt(template_name):
120
 
121
  return templates.get(template_name, "")
122
 
123
- def enhanced_chat_with_groq(api_key, model, user_message, temperature, max_tokens, top_p, chat_history, template_name="", session_id=None):
124
  """Enhanced chat function with analytics logging"""
125
  start_time = datetime.now()
126
 
@@ -130,11 +92,11 @@ def enhanced_chat_with_groq(api_key, model, user_message, temperature, max_token
130
  # Validate and process as before
131
  is_valid, message = validate_api_key(api_key)
132
  if not is_valid:
133
- return chat_history + [[user_message, f"Error: {message}"]], session_id
134
 
135
  connection_valid, connection_message = test_api_connection(api_key)
136
  if not connection_valid:
137
- return chat_history + [[user_message, f"Error: {connection_message}"]], session_id
138
 
139
  try:
140
  # Format history
@@ -164,137 +126,55 @@ def enhanced_chat_with_groq(api_key, model, user_message, temperature, max_token
164
  response_time = (end_time - start_time).total_seconds()
165
  tokens_used = response.usage.total_tokens
166
 
167
- # Determine message type based on template or content
168
- message_type = template_name if template_name else "general"
169
-
170
  # Log the interaction
171
- session_id = log_chat_interaction(
172
  model=model,
173
  tokens_used=tokens_used,
174
  response_time=response_time,
175
- user_message_length=user_message,
176
- message_type=message_type,
177
- session_id=session_id
178
  )
179
 
180
  # Extract response
181
  assistant_response = response.choices[0].message.content
182
 
183
- return chat_history + [[user_message, assistant_response]], session_id
184
 
185
  except Exception as e:
186
  error_message = f"Error: {str(e)}"
187
- return chat_history + [[user_message, error_message]], session_id
188
 
189
  def clear_conversation():
190
  """Clear the conversation history."""
191
- return [], None # Return empty chat history and reset session ID
192
 
193
  def plt_to_html(fig):
194
  """Convert matplotlib figure to HTML img tag"""
195
  buf = io.BytesIO()
196
- fig.savefig(buf, format="png", bbox_inches="tight", dpi=100)
197
  buf.seek(0)
198
  img_str = base64.b64encode(buf.read()).decode("utf-8")
199
  plt.close(fig)
200
  return f'<img src="data:image/png;base64,{img_str}" alt="Chart">'
201
 
202
- def predict_future_usage(df, days_ahead=7):
203
- """Predict future token usage based on historical data"""
204
- if len(df) < 5: # Need a minimum amount of data for prediction
205
- return None, "Insufficient data for prediction"
206
-
207
- # Group by date and get total tokens per day
208
- df['date'] = pd.to_datetime(df['timestamp']).dt.date
209
- daily_data = df.groupby('date')['tokens_used'].sum().reset_index()
210
- daily_data['date'] = pd.to_datetime(daily_data['date'])
211
-
212
- # Sort by date
213
- daily_data = daily_data.sort_values('date')
214
-
215
- try:
216
- # Simple linear regression for prediction
217
- X = np.array(range(len(daily_data))).reshape(-1, 1)
218
- y = daily_data['tokens_used'].values
219
-
220
- model = LinearRegression()
221
- model.fit(X, y)
222
-
223
- # Predict future days
224
- future_days = pd.date_range(
225
- start=daily_data['date'].max() + timedelta(days=1),
226
- periods=days_ahead
227
- )
228
-
229
- future_X = np.array(range(len(daily_data), len(daily_data) + days_ahead)).reshape(-1, 1)
230
- predictions = model.predict(future_X)
231
-
232
- # Create prediction dataframe
233
- prediction_df = pd.DataFrame({
234
- 'date': future_days,
235
- 'predicted_tokens': np.maximum(predictions, 0) # Ensure no negative predictions
236
- })
237
-
238
- # Create visualization
239
- fig = plt.figure(figsize=(12, 6))
240
- plt.plot(daily_data['date'], daily_data['tokens_used'], 'o-', label='Historical Usage')
241
- plt.plot(prediction_df['date'], prediction_df['predicted_tokens'], 'o--', label='Predicted Usage')
242
- plt.title('Token Usage Forecast (Next 7 Days)')
243
- plt.xlabel('Date')
244
- plt.ylabel('Token Usage')
245
- plt.legend()
246
- plt.grid(True)
247
- plt.xticks(rotation=45)
248
- plt.tight_layout()
249
-
250
- return plt_to_html(fig), prediction_df
251
-
252
- except Exception as e:
253
- return None, f"Error in prediction: {str(e)}"
254
-
255
- def export_analytics_csv(df):
256
- """Export analytics data to CSV"""
257
- try:
258
- output_path = "analytics/export_" + datetime.now().strftime("%Y%m%d_%H%M%S") + ".csv"
259
- df.to_csv(output_path, index=False)
260
- return f"Data exported to {output_path}"
261
- except Exception as e:
262
- return f"Error exporting data: {str(e)}"
263
-
264
- def generate_enhanced_analytics(date_range=None):
265
- """Generate enhanced analytics from the chat log"""
266
  log_file = "analytics/chat_log.json"
267
 
268
  if not os.path.exists(log_file):
269
- return "No analytics data available yet.", None, None, None, None, None, None, None, None, []
270
 
271
  try:
272
  with open(log_file, "r") as f:
273
  logs = json.load(f)
274
 
275
  if not logs:
276
- return "No analytics data available yet.", None, None, None, None, None, None, None, None, []
277
 
278
  # Convert to DataFrame
279
  df = pd.DataFrame(logs)
280
  df["timestamp"] = pd.to_datetime(df["timestamp"])
281
 
282
- # Apply date filter if provided
283
- if date_range and date_range != "all":
284
- end_date = datetime.now()
285
-
286
- if date_range == "last_7_days":
287
- start_date = end_date - timedelta(days=7)
288
- elif date_range == "last_30_days":
289
- start_date = end_date - timedelta(days=30)
290
- elif date_range == "last_90_days":
291
- start_date = end_date - timedelta(days=90)
292
- else: # Default to all time if unrecognized option
293
- start_date = df["timestamp"].min()
294
-
295
- df = df[(df["timestamp"] >= start_date) & (df["timestamp"] <= end_date)]
296
-
297
- # 1. Generate usage by model chart
298
  model_usage = df.groupby("model").agg({
299
  "tokens_used": "sum",
300
  "timestamp": "count"
@@ -302,266 +182,69 @@ def generate_enhanced_analytics(date_range=None):
302
  model_usage.columns = ["model", "total_tokens", "request_count"]
303
 
304
  fig1 = plt.figure(figsize=(10, 6))
305
- ax1 = sns.barplot(x="model", y="total_tokens", data=model_usage)
306
- plt.title("Token Usage by Model", fontsize=14)
307
- plt.xlabel("Model", fontsize=12)
308
- plt.ylabel("Total Tokens Used", fontsize=12)
309
  plt.xticks(rotation=45)
310
-
311
- # Add values on top of bars
312
- for i, v in enumerate(model_usage["total_tokens"]):
313
- ax1.text(i, v + 0.1, f"{v:,}", ha='center')
314
-
315
  plt.tight_layout()
316
  model_usage_img = plt_to_html(fig1)
317
 
318
- # 2. Generate usage over time chart
319
  df["date"] = df["timestamp"].dt.date
320
  daily_usage = df.groupby("date").agg({
321
  "tokens_used": "sum"
322
  }).reset_index()
323
 
324
  fig2 = plt.figure(figsize=(10, 6))
325
- plt.plot(daily_usage["date"], daily_usage["tokens_used"], marker="o", linestyle="-", linewidth=2)
326
- plt.title("Daily Token Usage", fontsize=14)
327
- plt.xlabel("Date", fontsize=12)
328
- plt.ylabel("Tokens Used", fontsize=12)
329
- plt.grid(True, alpha=0.3)
330
-
331
- # Format x-axis dates
332
- plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
333
- plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator())
334
-
335
- plt.xticks(rotation=45)
336
  plt.tight_layout()
337
  daily_usage_img = plt_to_html(fig2)
338
 
339
- # 3. Generate response time chart by model
340
  model_response_time = df.groupby("model").agg({
341
- "response_time_sec": ["mean", "median", "std"]
342
  }).reset_index()
343
- model_response_time.columns = ["model", "mean_time", "median_time", "std_time"]
344
 
345
  fig3 = plt.figure(figsize=(10, 6))
346
- ax3 = sns.barplot(x="model", y="mean_time", data=model_response_time)
347
-
348
- # Add error bars
349
- for i, v in enumerate(model_response_time["mean_time"]):
350
- std = model_response_time.iloc[i]["std_time"]
351
- if not np.isnan(std):
352
- plt.errorbar(i, v, yerr=std, fmt='none', color='black', capsize=5)
353
-
354
- plt.title("Response Time by Model", fontsize=14)
355
- plt.xlabel("Model", fontsize=12)
356
- plt.ylabel("Average Response Time (seconds)", fontsize=12)
357
  plt.xticks(rotation=45)
358
-
359
- # Add values on top of bars
360
- for i, v in enumerate(model_response_time["mean_time"]):
361
- ax3.text(i, v + 0.1, f"{v:.2f}s", ha='center')
362
-
363
  plt.tight_layout()
364
  response_time_img = plt_to_html(fig3)
365
 
366
- # 4. Usage by time of day and day of week
367
- if "hour_of_day" in df.columns and "day_of_week" in df.columns:
368
- # Map day of week to ensure correct order
369
- day_order = {day: i for i, day in enumerate(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'])}
370
- df['day_num'] = df['day_of_week'].map(day_order)
371
-
372
- hourly_usage = df.groupby("hour_of_day").agg({
373
- "tokens_used": "sum"
374
- }).reset_index()
375
-
376
- daily_usage_by_weekday = df.groupby("day_of_week").agg({
377
- "tokens_used": "sum"
378
- }).reset_index()
379
-
380
- # Sort by day of week
381
- daily_usage_by_weekday['day_num'] = daily_usage_by_weekday['day_of_week'].map(day_order)
382
- daily_usage_by_weekday = daily_usage_by_weekday.sort_values('day_num')
383
-
384
- fig4 = plt.figure(figsize=(18, 8))
385
-
386
- # Hourly usage chart
387
- plt.subplot(1, 2, 1)
388
- sns.barplot(x="hour_of_day", y="tokens_used", data=hourly_usage)
389
- plt.title("Token Usage by Hour of Day", fontsize=14)
390
- plt.xlabel("Hour of Day", fontsize=12)
391
- plt.ylabel("Total Tokens Used", fontsize=12)
392
- plt.xticks(ticks=range(0, 24, 2))
393
-
394
- # Daily usage chart
395
- plt.subplot(1, 2, 2)
396
- sns.barplot(x="day_of_week", y="tokens_used", data=daily_usage_by_weekday)
397
- plt.title("Token Usage by Day of Week", fontsize=14)
398
- plt.xlabel("Day of Week", fontsize=12)
399
- plt.ylabel("Total Tokens Used", fontsize=12)
400
- plt.xticks(rotation=45)
401
-
402
- plt.tight_layout()
403
- time_pattern_img = plt_to_html(fig4)
404
- else:
405
- time_pattern_img = None
406
-
407
- # 5. Message intent/type analysis
408
- if "message_intent" in df.columns:
409
- intent_usage = df.groupby("message_intent").agg({
410
- "tokens_used": "sum",
411
- "timestamp": "count"
412
- }).reset_index()
413
- intent_usage.columns = ["intent", "total_tokens", "request_count"]
414
-
415
- fig5 = plt.figure(figsize=(12, 10))
416
-
417
- # Pie chart for intent distribution
418
- plt.subplot(2, 1, 1)
419
- plt.pie(intent_usage["request_count"], labels=intent_usage["intent"], autopct='%1.1f%%', startangle=90)
420
- plt.axis('equal')
421
- plt.title("Message Intent Distribution", fontsize=14)
422
-
423
- # Bar chart for tokens by intent
424
- plt.subplot(2, 1, 2)
425
- sns.barplot(x="intent", y="total_tokens", data=intent_usage)
426
- plt.title("Token Usage by Message Intent", fontsize=14)
427
- plt.xlabel("Intent", fontsize=12)
428
- plt.ylabel("Total Tokens Used", fontsize=12)
429
-
430
- plt.tight_layout()
431
- intent_analysis_img = plt_to_html(fig5)
432
- else:
433
- intent_analysis_img = None
434
-
435
- # 6. Model comparison chart
436
- if len(model_usage) > 1:
437
- fig6 = plt.figure(figsize=(12, 8))
438
-
439
- # Create metrics for comparison
440
- model_comparison = df.groupby("model").agg({
441
- "tokens_used": ["mean", "median", "sum"],
442
- "response_time_sec": ["mean", "median"]
443
- }).reset_index()
444
-
445
- # Flatten column names
446
- model_comparison.columns = [
447
- f"{col[0]}_{col[1]}" if col[1] else col[0]
448
- for col in model_comparison.columns
449
- ]
450
-
451
- # Calculate token efficiency (tokens per second)
452
- model_comparison["tokens_per_second"] = model_comparison["tokens_used_mean"] / model_comparison["response_time_sec_mean"]
453
-
454
- # Normalize for radar chart
455
- metrics = ['tokens_used_mean', 'response_time_sec_mean', 'tokens_per_second']
456
- model_comparison_norm = model_comparison.copy()
457
-
458
- for metric in metrics:
459
- max_val = model_comparison[metric].max()
460
- if max_val > 0: # Avoid division by zero
461
- model_comparison_norm[f"{metric}_norm"] = model_comparison[metric] / max_val
462
-
463
- # Bar chart comparison
464
- plt.subplot(1, 2, 1)
465
- x = np.arange(len(model_comparison["model"]))
466
- width = 0.35
467
-
468
- plt.bar(x - width/2, model_comparison["tokens_used_mean"], width, label="Avg Tokens")
469
- plt.bar(x + width/2, model_comparison["response_time_sec_mean"], width, label="Avg Time (s)")
470
-
471
- plt.xlabel("Model")
472
- plt.ylabel("Value")
473
- plt.title("Model Performance Comparison")
474
- plt.xticks(x, model_comparison["model"], rotation=45)
475
- plt.legend()
476
-
477
- # Scatter plot for efficiency
478
- plt.subplot(1, 2, 2)
479
- sns.scatterplot(
480
- x="response_time_sec_mean",
481
- y="tokens_used_mean",
482
- size="tokens_per_second",
483
- hue="model",
484
- data=model_comparison,
485
- sizes=(100, 500)
486
- )
487
-
488
- plt.xlabel("Average Response Time (s)")
489
- plt.ylabel("Average Tokens Used")
490
- plt.title("Model Efficiency")
491
-
492
- plt.tight_layout()
493
- model_comparison_img = plt_to_html(fig6)
494
- else:
495
- model_comparison_img = None
496
-
497
- # 7. Usage prediction chart
498
- forecast_chart, prediction_data = predict_future_usage(df)
499
-
500
  # Summary statistics
501
  total_tokens = df["tokens_used"].sum()
502
  total_requests = len(df)
503
  avg_response_time = df["response_time_sec"].mean()
504
 
505
- # Cost estimation (assuming average pricing)
506
- # These rates are estimates and should be updated with actual rates
507
- estimated_cost_rates = {
508
- "llama3-70b-8192": 0.0001, # per token
509
- "llama3-8b-8192": 0.00005,
510
- "mistral-saba-24b": 0.00008,
511
- "gemma2-9b-it": 0.00006,
512
- "allam-2-7b": 0.00005
513
- }
514
-
515
- total_estimated_cost = 0
516
- model_costs = []
517
-
518
- for model_name in df["model"].unique():
519
- model_tokens = df[df["model"] == model_name]["tokens_used"].sum()
520
- rate = estimated_cost_rates.get(model_name, 0.00007) # Default to average rate if unknown
521
- cost = model_tokens * rate
522
- total_estimated_cost += cost
523
- model_costs.append({"model": model_name, "tokens": model_tokens, "cost": cost})
524
-
525
  # Handling the case where there might not be enough data
526
  if not model_usage.empty:
527
  most_used_model = model_usage.iloc[model_usage["request_count"].argmax()]["model"]
528
  else:
529
  most_used_model = "N/A"
530
 
531
- # Create summary without nested f-strings to avoid the backslash issue
532
  summary = f"""
533
- ## Analytics Summary
534
-
535
- ### Overview
536
- - **Total API Requests**: {total_requests:,}
537
- - **Total Tokens Used**: {total_tokens:,}
538
- - **Estimated Cost**: ${total_estimated_cost:.2f}
539
- - **Average Response Time**: {avg_response_time:.2f} seconds
540
- - **Most Used Model**: {most_used_model}
541
- - **Date Range**: {df["timestamp"].min().date()} to {df["timestamp"].max().date()}
542
-
543
- ### Model Costs Breakdown
544
- """
545
-
546
- # Add each model cost as a separate string concatenation
547
- for cost in model_costs:
548
- summary += f"- **{cost['model']}**: {cost['tokens']:,} tokens / ${cost['cost']:.2f}\n"
549
-
550
- # Continue with the rest of the summary
551
- summary += f"""
552
- ### Usage Patterns
553
- - **Busiest Day**: {df.groupby("date")["tokens_used"].sum().idxmax()} ({df[df["date"] == df.groupby("date")["tokens_used"].sum().idxmax()]["tokens_used"].sum():,} tokens)
554
- - **Most Efficient Model**: {df.groupby("model")["response_time_sec"].mean().idxmin()} ({df.groupby("model")["response_time_sec"].mean().min():.2f}s avg response)
555
-
556
- ### Forecast
557
- - **Projected Usage (Next 7 Days)**: {prediction_data["predicted_tokens"].sum():,.0f} tokens (estimated)
558
- """
559
 
560
- return summary, model_usage_img, daily_usage_img, response_time_img, time_pattern_img, intent_analysis_img, model_comparison_img, forecast_chart, export_analytics_csv(df), df.to_dict("records")
561
 
562
  except Exception as e:
563
  error_message = f"Error generating analytics: {str(e)}"
564
- return error_message, None, None, None, None, None, None, None, None, []
565
 
566
  # Define available models
567
  models = [
@@ -575,17 +258,11 @@ models = [
575
  # Define templates
576
  templates = ["General Assistant", "Code Helper", "Creative Writer", "Technical Expert", "Data Analyst"]
577
 
578
- # Define date range options for analytics filtering
579
- date_ranges = ["all", "last_7_days", "last_30_days", "last_90_days"]
580
-
581
  # Create the Gradio interface
582
- with gr.Blocks(title="Enhanced Groq AI Chat Playground") as app:
583
- # Store session ID (hidden from UI)
584
- session_id = gr.State(None)
585
-
586
  gr.Markdown("# Groq AI Chat Playground")
587
 
588
- # Create tabs for Chat, Analytics and Settings
589
  with gr.Tabs():
590
  with gr.Tab("Chat"):
591
  # New model information accordion
@@ -670,7 +347,7 @@ with gr.Blocks(title="Enhanced Groq AI Chat Playground") as app:
670
  label="Top P (nucleus sampling probability threshold)"
671
  )
672
 
673
- chatbot = gr.Chatbot(label="Conversation", height=500, type="messages")
674
 
675
  with gr.Row():
676
  message_input = gr.Textbox(
@@ -683,138 +360,82 @@ with gr.Blocks(title="Enhanced Groq AI Chat Playground") as app:
683
  submit_button = gr.Button("Send", variant="primary")
684
  clear_button = gr.Button("Clear Conversation")
685
 
686
- # Enhanced Analytics Dashboard Tab
687
  with gr.Tab("Analytics Dashboard"):
688
  with gr.Column():
689
- gr.Markdown("# Enhanced Usage Analytics Dashboard")
 
 
 
690
 
691
  with gr.Row():
692
- refresh_analytics_button = gr.Button("Refresh Analytics", variant="primary")
693
- date_filter = gr.Dropdown(
694
- choices=date_ranges,
695
- value="all",
696
- label="Date Range Filter",
697
- info="Filter analytics by time period"
698
- )
699
- export_button = gr.Button("Export Data to CSV")
700
 
701
- analytics_summary = gr.Markdown()
702
 
703
- with gr.Tabs():
704
- with gr.Tab("Overview"):
705
- with gr.Row():
706
- with gr.Column():
707
- model_usage_chart = gr.HTML(label="Token Usage by Model")
708
- with gr.Column():
709
- daily_usage_chart = gr.HTML(label="Daily Token Usage")
710
-
711
- response_time_chart = gr.HTML(label="Response Time by Model")
712
-
713
- with gr.Tab("Usage Patterns"):
714
- time_pattern_chart = gr.HTML(label="Usage by Time and Day")
715
- intent_analysis_chart = gr.HTML(label="Message Intent Analysis")
716
-
717
- with gr.Tab("Model Comparison"):
718
- model_comparison_chart = gr.HTML(label="Model Performance Comparison")
719
-
720
- with gr.Tab("Forecast"):
721
- forecast_chart = gr.HTML(label="Token Usage Forecast")
722
- gr.Markdown("""This forecast uses linear regression on your historical data to predict token usage for the next 7 days.
723
- Note that predictions become more accurate with more usage data.""")
724
-
725
- with gr.Tab("Raw Data"):
726
- raw_data_table = gr.DataFrame(label="Raw Analytics Data")
727
- export_status = gr.Textbox(label="Export Status")
728
-
729
- # Define functions for button callbacks
730
- def test_api_connection_btn(api_key):
731
- """Callback for testing API connection"""
732
- is_valid, validation_message = validate_api_key(api_key)
733
- if not is_valid:
734
- return validation_message
735
 
736
- connection_valid, connection_message = test_api_connection(api_key)
737
- return connection_message
738
-
739
- def refresh_analytics_callback(date_range):
740
- """Callback for refreshing analytics dashboard"""
741
- return generate_enhanced_analytics(date_range)
742
-
743
- def export_data_callback(df_records):
744
- """Callback for exporting data to CSV"""
745
- try:
746
- df = pd.DataFrame(df_records)
747
- return export_analytics_csv(df)
748
- except Exception as e:
749
- return f"Error exporting data: {str(e)}"
750
-
751
- # Set up event handlers
752
- test_button.click(
753
- test_api_connection_btn,
754
- inputs=[api_key_input],
755
- outputs=[api_status]
756
- )
757
-
758
- submit_button.click(
759
- enhanced_chat_with_groq,
760
- inputs=[
761
- api_key_input,
762
- model_dropdown,
763
- message_input,
764
- temperature_slider,
765
- max_tokens_slider,
766
- top_p_slider,
767
- chatbot,
768
- template_dropdown,
769
- session_id
770
- ],
771
- outputs=[chatbot, session_id]
772
- )
773
-
774
- message_input.submit(
775
- enhanced_chat_with_groq,
776
- inputs=[
777
- api_key_input,
778
- model_dropdown,
779
- message_input,
780
- temperature_slider,
781
- max_tokens_slider,
782
- top_p_slider,
783
- chatbot,
784
- template_dropdown,
785
- session_id
786
- ],
787
- outputs=[chatbot, session_id]
788
- )
789
-
790
- clear_button.click(
791
- clear_conversation,
792
- outputs=[chatbot, session_id]
793
- )
794
-
795
- refresh_analytics_button.click(
796
- refresh_analytics_callback,
797
- inputs=[date_filter],
798
- outputs=[
799
- analytics_summary,
800
- model_usage_chart,
801
- daily_usage_chart,
802
- response_time_chart,
803
- time_pattern_chart,
804
- intent_analysis_chart,
805
- model_comparison_chart,
806
- forecast_chart,
807
- export_status,
808
- raw_data_table
809
- ]
810
- )
811
-
812
- export_button.click(
813
- export_data_callback,
814
- inputs=[raw_data_table],
815
- outputs=[export_status]
816
- )
817
 
818
- # Launch the application
819
  if __name__ == "__main__":
820
- app.launch(share=False) # Set share=True for public URL
 
4
  from groq import Groq
5
  import pandas as pd
6
  import matplotlib.pyplot as plt
 
7
  import io
8
  import base64
9
  from datetime import datetime, timedelta
10
  import json
 
 
 
 
 
 
 
 
 
11
 
12
  def validate_api_key(api_key):
13
  """Validate if the API key has the correct format."""
 
41
  # Ensure analytics directory exists
42
  os.makedirs("analytics", exist_ok=True)
43
 
44
+ def log_chat_interaction(model, tokens_used, response_time, user_message_length):
45
+ """Log chat interactions for analytics"""
46
  timestamp = datetime.now().isoformat()
47
 
 
 
 
 
48
  log_file = "analytics/chat_log.json"
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  log_entry = {
51
  "timestamp": timestamp,
52
  "model": model,
53
  "tokens_used": tokens_used,
54
  "response_time_sec": response_time,
55
+ "user_message_length": user_message_length
 
 
 
 
 
56
  }
57
 
58
  # Append to existing log or create new file
 
69
 
70
  with open(log_file, "w") as f:
71
  json.dump(logs, f, indent=2)
 
 
72
 
73
  def get_template_prompt(template_name):
74
  """Get system prompt for a given template name"""
 
82
 
83
  return templates.get(template_name, "")
84
 
85
+ def enhanced_chat_with_groq(api_key, model, user_message, temperature, max_tokens, top_p, chat_history, template_name=""):
86
  """Enhanced chat function with analytics logging"""
87
  start_time = datetime.now()
88
 
 
92
  # Validate and process as before
93
  is_valid, message = validate_api_key(api_key)
94
  if not is_valid:
95
+ return chat_history + [[user_message, f"Error: {message}"]]
96
 
97
  connection_valid, connection_message = test_api_connection(api_key)
98
  if not connection_valid:
99
+ return chat_history + [[user_message, f"Error: {connection_message}"]]
100
 
101
  try:
102
  # Format history
 
126
  response_time = (end_time - start_time).total_seconds()
127
  tokens_used = response.usage.total_tokens
128
 
 
 
 
129
  # Log the interaction
130
+ log_chat_interaction(
131
  model=model,
132
  tokens_used=tokens_used,
133
  response_time=response_time,
134
+ user_message_length=len(user_message)
 
 
135
  )
136
 
137
  # Extract response
138
  assistant_response = response.choices[0].message.content
139
 
140
+ return chat_history + [[user_message, assistant_response]]
141
 
142
  except Exception as e:
143
  error_message = f"Error: {str(e)}"
144
+ return chat_history + [[user_message, error_message]]
145
 
146
  def clear_conversation():
147
  """Clear the conversation history."""
148
+ return []
149
 
150
  def plt_to_html(fig):
151
  """Convert matplotlib figure to HTML img tag"""
152
  buf = io.BytesIO()
153
+ fig.savefig(buf, format="png", bbox_inches="tight")
154
  buf.seek(0)
155
  img_str = base64.b64encode(buf.read()).decode("utf-8")
156
  plt.close(fig)
157
  return f'<img src="data:image/png;base64,{img_str}" alt="Chart">'
158
 
159
+ def generate_analytics():
160
+ """Generate analytics from the chat log"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  log_file = "analytics/chat_log.json"
162
 
163
  if not os.path.exists(log_file):
164
+ return "No analytics data available yet.", None, None, None, []
165
 
166
  try:
167
  with open(log_file, "r") as f:
168
  logs = json.load(f)
169
 
170
  if not logs:
171
+ return "No analytics data available yet.", None, None, None, []
172
 
173
  # Convert to DataFrame
174
  df = pd.DataFrame(logs)
175
  df["timestamp"] = pd.to_datetime(df["timestamp"])
176
 
177
+ # Generate usage by model chart
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  model_usage = df.groupby("model").agg({
179
  "tokens_used": "sum",
180
  "timestamp": "count"
 
182
  model_usage.columns = ["model", "total_tokens", "request_count"]
183
 
184
  fig1 = plt.figure(figsize=(10, 6))
185
+ plt.bar(model_usage["model"], model_usage["total_tokens"])
186
+ plt.title("Token Usage by Model")
187
+ plt.xlabel("Model")
188
+ plt.ylabel("Total Tokens Used")
189
  plt.xticks(rotation=45)
 
 
 
 
 
190
  plt.tight_layout()
191
  model_usage_img = plt_to_html(fig1)
192
 
193
+ # Generate usage over time chart
194
  df["date"] = df["timestamp"].dt.date
195
  daily_usage = df.groupby("date").agg({
196
  "tokens_used": "sum"
197
  }).reset_index()
198
 
199
  fig2 = plt.figure(figsize=(10, 6))
200
+ plt.plot(daily_usage["date"], daily_usage["tokens_used"], marker="o")
201
+ plt.title("Daily Token Usage")
202
+ plt.xlabel("Date")
203
+ plt.ylabel("Tokens Used")
204
+ plt.grid(True)
 
 
 
 
 
 
205
  plt.tight_layout()
206
  daily_usage_img = plt_to_html(fig2)
207
 
208
+ # Generate response time chart
209
  model_response_time = df.groupby("model").agg({
210
+ "response_time_sec": "mean"
211
  }).reset_index()
 
212
 
213
  fig3 = plt.figure(figsize=(10, 6))
214
+ plt.bar(model_response_time["model"], model_response_time["response_time_sec"])
215
+ plt.title("Average Response Time by Model")
216
+ plt.xlabel("Model")
217
+ plt.ylabel("Response Time (seconds)")
 
 
 
 
 
 
 
218
  plt.xticks(rotation=45)
 
 
 
 
 
219
  plt.tight_layout()
220
  response_time_img = plt_to_html(fig3)
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  # Summary statistics
223
  total_tokens = df["tokens_used"].sum()
224
  total_requests = len(df)
225
  avg_response_time = df["response_time_sec"].mean()
226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  # Handling the case where there might not be enough data
228
  if not model_usage.empty:
229
  most_used_model = model_usage.iloc[model_usage["request_count"].argmax()]["model"]
230
  else:
231
  most_used_model = "N/A"
232
 
 
233
  summary = f"""
234
+ ## Analytics Summary
235
+
236
+ - **Total API Requests**: {total_requests}
237
+ - **Total Tokens Used**: {total_tokens:,}
238
+ - **Average Response Time**: {avg_response_time:.2f} seconds
239
+ - **Most Used Model**: {most_used_model}
240
+ - **Date Range**: {df["timestamp"].min().date()} to {df["timestamp"].max().date()}
241
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
+ return summary, model_usage_img, daily_usage_img, response_time_img, df.to_dict("records")
244
 
245
  except Exception as e:
246
  error_message = f"Error generating analytics: {str(e)}"
247
+ return error_message, None, None, None, []
248
 
249
  # Define available models
250
  models = [
 
258
  # Define templates
259
  templates = ["General Assistant", "Code Helper", "Creative Writer", "Technical Expert", "Data Analyst"]
260
 
 
 
 
261
  # Create the Gradio interface
262
+ with gr.Blocks(title="Groq AI Chat Playground") as app:
 
 
 
263
  gr.Markdown("# Groq AI Chat Playground")
264
 
265
+ # Create tabs for Chat and Analytics
266
  with gr.Tabs():
267
  with gr.Tab("Chat"):
268
  # New model information accordion
 
347
  label="Top P (nucleus sampling probability threshold)"
348
  )
349
 
350
+ chatbot = gr.Chatbot(label="Conversation", height=500)
351
 
352
  with gr.Row():
353
  message_input = gr.Textbox(
 
360
  submit_button = gr.Button("Send", variant="primary")
361
  clear_button = gr.Button("Clear Conversation")
362
 
363
+ # Analytics Dashboard Tab
364
  with gr.Tab("Analytics Dashboard"):
365
  with gr.Column():
366
+ gr.Markdown("# Usage Analytics Dashboard")
367
+ refresh_analytics_button = gr.Button("Refresh Analytics")
368
+
369
+ analytics_summary = gr.Markdown()
370
 
371
  with gr.Row():
372
+ with gr.Column():
373
+ model_usage_chart = gr.HTML(label="Token Usage by Model")
374
+ with gr.Column():
375
+ daily_usage_chart = gr.HTML(label="Daily Token Usage")
 
 
 
 
376
 
377
+ response_time_chart = gr.HTML(label="Response Time by Model")
378
 
379
+ with gr.Accordion("Raw Data", open=False):
380
+ analytics_table = gr.DataFrame(label="Raw Analytics Data")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
 
382
+ # Connect components with functions
383
+ submit_button.click(
384
+ fn=enhanced_chat_with_groq,
385
+ inputs=[
386
+ api_key_input,
387
+ model_dropdown,
388
+ message_input,
389
+ temperature_slider,
390
+ max_tokens_slider,
391
+ top_p_slider,
392
+ chatbot,
393
+ template_dropdown
394
+ ],
395
+ outputs=chatbot
396
+ ).then(
397
+ fn=lambda: "",
398
+ inputs=None,
399
+ outputs=message_input
400
+ )
401
+
402
+ message_input.submit(
403
+ fn=enhanced_chat_with_groq,
404
+ inputs=[
405
+ api_key_input,
406
+ model_dropdown,
407
+ message_input,
408
+ temperature_slider,
409
+ max_tokens_slider,
410
+ top_p_slider,
411
+ chatbot,
412
+ template_dropdown
413
+ ],
414
+ outputs=chatbot
415
+ ).then(
416
+ fn=lambda: "",
417
+ inputs=None,
418
+ outputs=message_input
419
+ )
420
+
421
+ clear_button.click(
422
+ fn=clear_conversation,
423
+ inputs=None,
424
+ outputs=chatbot
425
+ )
426
+
427
+ test_button.click(
428
+ fn=test_api_connection,
429
+ inputs=[api_key_input],
430
+ outputs=[api_status]
431
+ )
432
+
433
+ refresh_analytics_button.click(
434
+ fn=generate_analytics,
435
+ inputs=[],
436
+ outputs=[analytics_summary, model_usage_chart, daily_usage_chart, response_time_chart, analytics_table]
437
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
 
439
+ # Launch the app
440
  if __name__ == "__main__":
441
+ app.launch(share=False)