k96beni commited on
Commit
aef1ab8
·
verified ·
1 Parent(s): 25ea55d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +266 -315
app.py CHANGED
@@ -9,7 +9,7 @@ import numpy as np
9
  import faiss
10
  import pandas as pd
11
  from huggingface_hub import CommitScheduler
12
- from datetime import datetime
13
  import uuid
14
  from user_agents import parse as parse_ua
15
  import schedule
@@ -46,54 +46,6 @@ scheduler = CommitScheduler(
46
 
47
  # --- Globala variabler ---
48
  last_log = None # Sparar loggdata från senaste svar för feedback
49
- # Lägg till i början av skriptet med andra globala variabler
50
- active_sessions = {} # Dictionary för att spåra aktiva sessioner: {session_id: (senaste_tid, meddelanden)}
51
- # --- Slack Webhook funktionalitet ---
52
- def send_report_to_slack(subject, content):
53
- """Skickar rapport till Slack via webhook."""
54
- webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
55
- if not webhook_url:
56
- print("Slack webhook URL saknas i miljövariabler")
57
- return False
58
-
59
- try:
60
- print(f"Skickar rapport till Slack: {subject}")
61
-
62
- # Formatera meddelandet för Slack
63
- message = {
64
- "blocks": [
65
- {
66
- "type": "header",
67
- "text": {
68
- "type": "plain_text",
69
- "text": subject
70
- }
71
- },
72
- {
73
- "type": "section",
74
- "text": {
75
- "type": "mrkdwn",
76
- "text": content
77
- }
78
- }
79
- ]
80
- }
81
-
82
- response = requests.post(
83
- webhook_url,
84
- json=message,
85
- headers={"Content-Type": "application/json"}
86
- )
87
-
88
- if response.status_code == 200:
89
- print(f"Slack-rapport skickad framgångsrikt")
90
- return True
91
- else:
92
- print(f"Slack-anrop misslyckades: {response.status_code}, {response.text}")
93
- return False
94
- except Exception as e:
95
- print(f"Fel vid sändning till Slack: {type(e).__name__}: {e}")
96
- return False
97
 
98
  # --- Laddar textkällor ---
99
  def load_local_files():
@@ -234,7 +186,44 @@ def vote(data: gr.LikeData):
234
  with scheduler.lock:
235
  with open(log_file_path, "a", encoding="utf-8") as log_file:
236
  log_file.write(json.dumps(log_entry) + "\n")
237
- # Inget utdata krävs här, Gradio hanterar färgändringarna.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  return
239
 
240
  # --- Rapportering ---
@@ -287,260 +276,132 @@ def get_feedback_stats(logs):
287
 
288
  return feedback_count, negative_feedback_examples
289
 
290
- # Skicka statusrapport till Slack
291
- def send_status_slack():
292
- """Skickar ett statusmeddelande till Slack med utökad statistik."""
293
- print("Försöker skicka status-rapport till Slack...")
294
 
295
  try:
296
- # Samla in statistik
297
- logs = read_logs()
298
-
299
- # Beräkna tid för 24 timmar sedan och 14 dagar sedan
300
- now = datetime.now()
301
- yesterday = now - timedelta(days=1)
302
- two_weeks_ago = now - timedelta(days=14)
303
-
304
- # Konvertera timestamps till datetime
305
- for log in logs:
306
- if 'timestamp' in log:
307
- try:
308
- log['datetime'] = datetime.strptime(log['timestamp'], "%Y-%m-%d %H:%M:%S")
309
- except:
310
- log['datetime'] = now # Default om formatering misslyckas
311
-
312
- # Filtrera loggar för senaste 24h och 14 dagar
313
- logs_24h = [log for log in logs if 'datetime' in log and log['datetime'] >= yesterday]
314
- logs_14d = [log for log in logs if 'datetime' in log and log['datetime'] >= two_weeks_ago]
315
-
316
- # 1. Samla statistik
317
- conversations = get_latest_conversations(logs)
318
- feedback_stats, negative_examples = get_feedback_stats(logs)
319
-
320
- # Basinformation
321
- total_sessions = len(set(log.get('session_id', 'unknown') for log in logs if 'session_id' in log))
322
- total_questions = sum(1 for log in logs if 'user_message' in log)
323
-
324
- # 24h statistik
325
- sessions_24h = len(set(log.get('session_id', 'unknown') for log in logs_24h if 'session_id' in log))
326
- messages_24h = sum(1 for log in logs_24h if 'user_message' in log)
327
-
328
- # Beräkna snitt antal meddelanden per session (om minst en session finns)
329
- avg_messages_per_session = round(messages_24h / sessions_24h, 2) if sessions_24h > 0 else 0
330
-
331
- # Snittsvarstid
332
- response_times_24h = [log.get('response_time', 0) for log in logs_24h if 'response_time' in log]
333
- avg_response_time = round(sum(response_times_24h) / len(response_times_24h), 2) if response_times_24h else 0
334
-
335
- # 14 dagars statistik
336
- messages_14d = sum(1 for log in logs_14d if 'user_message' in log)
337
- unique_users_14d = len(set(log.get('user_id', 'unknown') for log in logs_14d if 'user_id' in log))
338
-
339
- # Likes och dislikes
340
- likes_24h = sum(1 for log in logs_24h if log.get('feedback') == 'up')
341
- dislikes_24h = sum(1 for log in logs_24h if log.get('feedback') == 'down')
342
-
343
- # Browser-fördelning
344
- browser_counts = {}
345
- for log in logs_24h:
346
- if 'browser' in log:
347
- browser = log['browser']
348
- browser_counts[browser] = browser_counts.get(browser, 0) + 1
349
 
350
- # Sortera browsers efter antal
351
- top_browsers = sorted(browser_counts.items(), key=lambda x: x[1], reverse=True)[:3]
352
- browser_text = ", ".join([f"{browser}: {count}" for browser, count in top_browsers]) if top_browsers else "Ingen data"
353
-
354
- # 2. Formatera för Slack (Markdown)
355
- slack_date = now.strftime("%Y-%m-%d")
356
- subject = f"ChargeNode AI Bot - Daglig rapport {slack_date}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
 
358
  content = f"""
359
- *ChargeNode AI Bot - Statusrapport {now.strftime('%Y-%m-%d %H:%M:%S')}*
360
-
361
- *Sammanfattning*
362
- - Datum: {slack_date}
363
- - Antal meddelanden senaste 24h: {messages_24h}
364
- - Unika sessioner senaste 24h: {sessions_24h}
365
- - Meddelanden per session (snitt): {avg_messages_per_session}
366
- - Snittsvarstid senaste 24h: {avg_response_time} sekunder
367
- - Antal meddelanden (14 dagar): {messages_14d}
368
- - Unika användare (14 dagar): {unique_users_14d}
369
- - Tumme upp senaste 24h: {likes_24h}
370
- - Tumme ned senaste 24h: {dislikes_24h}
371
- - Browser-fördelning senaste 24h: {browser_text}
372
-
373
- *Trender*
374
- - Totalt antal sessioner: {total_sessions}
375
- - Totalt antal frågor: {total_questions}
376
-
377
- *De 5 senaste frågorna*
378
- """
379
-
380
- # Lägg till de senaste frågorna (begränsa till 5 för Slack)
381
- for i, conv in enumerate(conversations[:5]):
382
- content += f"""
383
- > *Tid:* {conv['timestamp']}
384
- > *Fråga:* {conv['user_message']}
385
- > *Svar:* {conv['bot_reply'][:150]}...
386
  """
387
 
388
- # Lägg till negativ feedback
389
- content += "\n*Exempel negativ feedback*\n"
390
-
391
- if negative_examples:
392
- for example in negative_examples[:3]: # Begränsa till 3 för Slack
 
 
 
393
  content += f"""
394
- > *Fråga:* {example['user_message']}
395
- > *Svar:* {example['bot_reply'][:150]}...
 
396
  """
397
  else:
398
- content += "_Inga exempel på negativ feedback hittades._"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
 
400
- # 3. Skicka till Slack
401
- success = send_report_to_slack(subject, content)
402
 
403
- if success:
404
- print(f"Status-rapport skickad till Slack: {now}")
405
  return True
406
  else:
407
- print("Status-rapport till Slack misslyckades.")
408
  return False
 
409
  except Exception as e:
410
- print(f"Fel vid sändning av status-rapport till Slack: {e}")
411
- return False
412
-
413
- # Funktion för att skicka en avslutad session till Slack
414
- def send_session_to_slack(session_id, messages):
415
- """Skickar en avslutad chatsession till Slack."""
416
- if not messages:
417
- return False
418
-
419
- try:
420
- user_messages = [msg for msg in messages if msg.get('role') == 'user']
421
- bot_messages = [msg for msg in messages if msg.get('role') == 'assistant']
422
-
423
- if not user_messages:
424
- return False # Ingen användarsession att rapportera
425
-
426
- # Räkna feedback
427
- likes = sum(1 for msg in messages if msg.get('feedback') == 'up')
428
- dislikes = sum(1 for msg in messages if msg.get('feedback') == 'down')
429
-
430
- # Hämta information om sessionen
431
- first_msg_time = messages[0].get('timestamp', 'okänd tid')
432
- last_msg_time = messages[-1].get('timestamp', 'okänd tid')
433
-
434
- # Formatera sessionen för Slack
435
- subject = f"Avslutad chatsession {session_id[:8]} - {first_msg_time}"
436
 
437
- content = f"""
438
- *Chatsession avslutad*
439
- - *Session ID:* {session_id[:8]}...
440
- - *Starttid:* {first_msg_time}
441
- - *Sluttid:* {last_msg_time}
442
- - *Antal frågor:* {len(user_messages)}
443
- - *Antal svar:* {len(bot_messages)}
444
- - *Tumme upp:* {likes}
445
- - *Tumme ned:* {dislikes}
446
-
447
- *Konversation:*
448
- """
449
-
450
- # Lägg till konversationen
451
- for i, msg in enumerate(messages):
452
- if msg.get('role') == 'user':
453
- content += f"> *Användare:* {msg.get('content', '')}\n\n"
454
- elif msg.get('role') == 'assistant':
455
- content += f"> *Bot:* {msg.get('content', '')[:150]}...\n\n"
456
-
457
- # Skicka till Slack
458
- success = send_report_to_slack(subject, content)
459
- return success
460
- except Exception as e:
461
- print(f"Fel vid sändning av sessionrapport till Slack: {e}")
462
  return False
463
 
464
- # Modifiera respond-funktionen för att spåra sessioner
465
- def respond(message, chat_history, request: gr.Request):
466
- global last_log, active_sessions
467
- start = time.time()
468
- response = generate_answer(message)
469
- elapsed = round(time.time() - start, 2)
470
-
471
- timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
472
- session_id = str(uuid.uuid4())
473
- user_id = request.client.host if request else "okänd"
474
-
475
- # Resten av din befintliga kod här...
476
-
477
- # Spara sessionsdata för chattrapporter
478
- if last_log and 'session_id' in last_log:
479
- # Använd session_id från tidigare logg om det finns
480
- session_id = last_log.get('session_id')
481
-
482
- # Uppdatera aktiva sessioner
483
- if session_id not in active_sessions:
484
- active_sessions[session_id] = {
485
- 'last_activity': datetime.now(),
486
- 'messages': []
487
- }
488
-
489
- # Lägg till användarfråga
490
- active_sessions[session_id]['messages'].append({
491
- 'role': 'user',
492
- 'content': message,
493
- 'timestamp': timestamp
494
- })
495
-
496
- # Lägg till bot-svar
497
- active_sessions[session_id]['messages'].append({
498
- 'role': 'assistant',
499
- 'content': response,
500
- 'timestamp': timestamp
501
- })
502
-
503
- # Uppdatera senaste aktivitet
504
- active_sessions[session_id]['last_activity'] = datetime.now()
505
-
506
- # Fortsätt med din befintliga kod...
507
- chat_history.append({"role": "user", "content": message})
508
- chat_history.append({"role": "assistant", "content": response})
509
- return "", chat_history
510
-
511
- # Periodisk kontroll av inaktiva sessioner
512
- def check_inactive_sessions():
513
- """Kontrollerar efter inaktiva sessioner och skickar dem till Slack."""
514
- now = datetime.now()
515
- sessions_to_remove = []
516
-
517
- for session_id, session_data in active_sessions.items():
518
- last_activity = session_data['last_activity']
519
- inactive_time = (now - last_activity).total_seconds() / 60 # i minuter
520
-
521
- if inactive_time >= 2: # Inaktiv i minst 2 minuter
522
- # Skicka sessionen till Slack
523
- send_session_to_slack(session_id, session_data['messages'])
524
- sessions_to_remove.append(session_id)
525
-
526
- # Ta bort skickade sessioner
527
- for session_id in sessions_to_remove:
528
- del active_sessions[session_id]
529
-
530
- # Uppdatera schemaläggningsfunktionen för att kontrollera inaktiva sessioner
531
- def run_scheduler():
532
- """Kör schemaläggaren i en separat tråd."""
533
- # Schemalägga rapporter till Slack
534
- schedule.every().day.at("09:32").do(send_status_slack)
535
- schedule.every().day.at("15:00").do(send_status_slack)
536
- schedule.every().day.at("08:00").do(send_status_slack)
537
-
538
- # Kontrollera inaktiva sessioner var 30:e sekund
539
- schedule.every(30).seconds.do(check_inactive_sessions)
540
-
541
- while True:
542
- schedule.run_pending()
543
- time.sleep(10) # Kontrollera var 10:e sekund
544
  def send_support_to_slack(områdeskod, uttagsnummer, email, chat_history):
545
  """Skickar en supportförfrågan till Slack."""
546
  try:
@@ -550,52 +411,89 @@ def send_support_to_slack(områdeskod, uttagsnummer, email, chat_history):
550
  if msg['role'] == 'user':
551
  chat_content += f">*Användare:* {msg['content']}\n\n"
552
  elif msg['role'] == 'assistant':
553
- chat_content += f">*Bot:* {msg['content']}\n\n"
554
 
555
  # Skapa rubrik och innehåll
556
- subject = f"Support förfrågan från ChargeNode AI Bot - {datetime.now().strftime('%Y-%m-%d %H:%M')}"
557
-
558
- content = f"""
559
- *Användarinformation*
560
- - *Områdeskod:* {områdeskod or 'Ej angiven'}
561
- - *Uttagsnummer:* {uttagsnummer or 'Ej angiven'}
562
- - *Email:* {email}
563
- - *Tidpunkt:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
564
-
565
- *Chatthistorik*
566
- {chat_content}
567
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
 
569
- # Skicka till Slack
570
- success = send_report_to_slack(subject, content)
571
- return success
 
 
 
 
572
  except Exception as e:
573
  print(f"Fel vid sändning av support till Slack: {type(e).__name__}: {e}")
574
  return False
575
 
576
  # --- Schemaläggning av rapporter ---
577
  def run_scheduler():
578
- """Kör schemaläggaren i en separat tråd."""
579
- # Schemalägga rapporter till Slack
580
- schedule.every().day.at("09:32").do(send_status_slack)
581
- schedule.every().day.at("15:00").do(send_status_slack)
582
- schedule.every().day.at("08:00").do(send_status_slack)
583
 
584
  while True:
585
  schedule.run_pending()
586
  time.sleep(60) # Kontrollera varje minut
587
 
588
- # Starta schemaläggaren i en separat tråd
589
  scheduler_thread = threading.Thread(target=run_scheduler, daemon=True)
590
  scheduler_thread.start()
591
 
592
- # Skicka status-rapport till Slack vid uppstart
593
  try:
594
- send_status_slack()
 
595
  except Exception as e:
596
- print(f"Kunde inte skicka status-rapport till Slack vid uppstart: {e}")
597
 
598
- # --- Gradio with Chatbot and support functionality ---
599
  initial_chat = [{"role": "assistant", "content": "Detta är ChargeNode's AI bot. Hur kan jag hjälpa dig idag?"}]
600
 
601
  custom_css = """
@@ -605,13 +503,12 @@ h1 {font-family: Helvetica, sans-serif; color: #2a9d8f; text-align: center; marg
605
  #chatbot_conversation { max-height: 300px; overflow-y: auto; }
606
  .gr-button {background-color: #2a9d8f; color: #fff; border: none; border-radius: 4px; padding: 8px 16px; margin: 5px;}
607
  .gr-button:hover {background-color: #264653;}
608
- .support-btn {background-color: #e76f51; margin-top: 5px; margin-bottom: 10px;}
609
- .support-btn:hover {background-color: #e85d04;}
610
  .flex-row {display: flex; flex-direction: row; gap: 5px;}
611
  .gr-form {padding: 10px; border: 1px solid #eee; border-radius: 4px; margin-bottom: 10px;}
612
  .chat-preview {max-height: 150px; overflow-y: auto; border: 1px solid #eee; padding: 8px; margin-top: 10px; font-size: 12px; background-color: #f9f9f9;}
613
  .success-message {font-size: 16px; font-weight: normal; margin-bottom: 15px;}
614
-
615
  /* Dölj Gradio-footer */
616
  footer {display: none !important;}
617
  .footer {display: none !important;}
@@ -656,7 +553,7 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
656
 
657
  # Success message (initially hidden)
658
  with gr.Group(visible=False) as success_interface:
659
- gr.Markdown("Tack för att du kontaktar använt vår chat. All information är skickad till vår kundtjänst. Vi återkommer inom kort", elem_classes="success-message")
660
  back_to_chat_btn = gr.Button("Tillbaka till chatten")
661
 
662
  def respond(message, chat_history, request: gr.Request):
@@ -667,6 +564,11 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
667
 
668
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
669
  session_id = str(uuid.uuid4())
 
 
 
 
 
670
  user_id = request.client.host if request else "okänd"
671
 
672
  ua_str = request.headers.get("user-agent", "")
@@ -702,6 +604,55 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
702
  log_file.write(json.dumps(log_data) + "\n")
703
  last_log = log_data
704
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
705
  chat_history.append({"role": "user", "content": message})
706
  chat_history.append({"role": "assistant", "content": response})
707
  return "", chat_history
 
9
  import faiss
10
  import pandas as pd
11
  from huggingface_hub import CommitScheduler
12
+ from datetime import datetime, timedelta
13
  import uuid
14
  from user_agents import parse as parse_ua
15
  import schedule
 
46
 
47
  # --- Globala variabler ---
48
  last_log = None # Sparar loggdata från senaste svar för feedback
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  # --- Laddar textkällor ---
51
  def load_local_files():
 
186
  with scheduler.lock:
187
  with open(log_file_path, "a", encoding="utf-8") as log_file:
188
  log_file.write(json.dumps(log_entry) + "\n")
189
+
190
+ # Skicka feedback till Slack
191
+ try:
192
+ webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
193
+ if webhook_url and feedback_type == "down": # Skicka bara negativ feedback
194
+ feedback_message = {
195
+ "blocks": [
196
+ {
197
+ "type": "header",
198
+ "text": {
199
+ "type": "plain_text",
200
+ "text": "⚠️ Negativ feedback registrerad"
201
+ }
202
+ },
203
+ {
204
+ "type": "section",
205
+ "text": {
206
+ "type": "mrkdwn",
207
+ "text": f"*Fråga:* {last_log.get('user_message', 'Okänd fråga')}"
208
+ }
209
+ },
210
+ {
211
+ "type": "section",
212
+ "text": {
213
+ "type": "mrkdwn",
214
+ "text": f"*Svar:* {log_entry.get('bot_reply', 'Okänt svar')[:300]}{'...' if len(log_entry.get('bot_reply', '')) > 300 else ''}"
215
+ }
216
+ }
217
+ ]
218
+ }
219
+ # Skicka asynkront
220
+ threading.Thread(
221
+ target=lambda: requests.post(webhook_url, json=feedback_message),
222
+ daemon=True
223
+ ).start()
224
+ except Exception as e:
225
+ print(f"Kunde inte skicka feedback till Slack: {e}")
226
+
227
  return
228
 
229
  # --- Rapportering ---
 
276
 
277
  return feedback_count, negative_feedback_examples
278
 
279
+ # --- Slack-integration ---
280
+ def simple_status_report():
281
+ """Förenklad statusrapport som garanterar att data skickas."""
282
+ print("Skickar förenklad statusrapport till Slack...")
283
 
284
  try:
285
+ # Läs loggfilen rad för rad för att undvika JSON-parsningsproblem
286
+ messages = []
287
+ sessions = set()
288
+ users = set()
289
+ feedback_up = 0
290
+ feedback_down = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
 
292
+ try:
293
+ with open(log_file_path, "r", encoding="utf-8") as f:
294
+ for line in f:
295
+ try:
296
+ # Försök tolka JSON-data
297
+ data = json.loads(line.strip())
298
+
299
+ # Samla grundläggande statistik direkt från rå data
300
+ if 'user_message' in data:
301
+ messages.append(data)
302
+ if 'session_id' in data:
303
+ sessions.add(data['session_id'])
304
+ if 'user_id' in data:
305
+ users.add(data['user_id'])
306
+ if 'feedback' in data:
307
+ if data['feedback'] == 'up':
308
+ feedback_up += 1
309
+ elif data['feedback'] == 'down':
310
+ feedback_down += 1
311
+ except json.JSONDecodeError:
312
+ continue # Hoppa över ogiltiga rader
313
+ except Exception as e:
314
+ # Om filläsning misslyckas helt, rapportera detta
315
+ webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
316
+ error_payload = {
317
+ "text": f"⚠️ *Fel vid läsning av loggfil:* {str(e)}"
318
+ }
319
+ requests.post(webhook_url, json=error_payload)
320
+ return False
321
+
322
+ # Skapa enkel statistik som garanterat fungerar
323
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
324
+ subject = f"ChargeNode AI Bot - Status {now}"
325
 
326
  content = f"""
327
+ *ChargeNode AI Bot - Statusrapport*
328
+
329
+ *Basstatistik* (direkt från loggfiler)
330
+ - Tidpunkt: {now}
331
+ - Totalt antal meddelanden: {len(messages)}
332
+ - Unika sessioner: {len(sessions)}
333
+ - Unika användare: {len(users)}
334
+ - Tumme upp: {feedback_up}
335
+ - Tumme ned: {feedback_down}
336
+
337
+ *Senaste aktivitet*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  """
339
 
340
+ # Lägg till de 3 senaste meddelandena (om det finns några)
341
+ recent_messages = sorted(messages, key=lambda x: x.get('timestamp', ''), reverse=True)[:3]
342
+ if recent_messages:
343
+ for msg in recent_messages:
344
+ user_message = msg.get('user_message', 'Okänd fråga')
345
+ bot_reply = msg.get('bot_reply', 'Okänt svar')
346
+ timestamp = msg.get('timestamp', 'Okänd tid')
347
+
348
  content += f"""
349
+ > *Tid:* {timestamp}
350
+ > *Fråga:* {user_message[:100]}{"..." if len(user_message) > 100 else ""}
351
+ > *Svar:* {bot_reply[:100]}{"..." if len(bot_reply) > 100 else ""}
352
  """
353
  else:
354
+ content += "_Inga meddelanden hittades_"
355
+
356
+ # Skicka till Slack med enkel webhook
357
+ webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
358
+ if not webhook_url:
359
+ print("Slack webhook URL saknas")
360
+ return False
361
+
362
+ payload = {
363
+ "blocks": [
364
+ {
365
+ "type": "header",
366
+ "text": {
367
+ "type": "plain_text",
368
+ "text": subject
369
+ }
370
+ },
371
+ {
372
+ "type": "section",
373
+ "text": {
374
+ "type": "mrkdwn",
375
+ "text": content
376
+ }
377
+ }
378
+ ]
379
+ }
380
 
381
+ response = requests.post(webhook_url, json=payload)
 
382
 
383
+ if response.status_code == 200:
384
+ print(f"Förenklad statusrapport skickad till Slack: {now}")
385
  return True
386
  else:
387
+ print(f"Slack-anrop misslyckades: {response.status_code}, {response.text}")
388
  return False
389
+
390
  except Exception as e:
391
+ print(f"Fel vid sändning av förenklad statusrapport: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
 
393
+ # Skicka felmeddelande till Slack som sista utväg
394
+ try:
395
+ webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
396
+ error_payload = {
397
+ "text": f"⚠️ *Fel vid generering av statusrapport:* {str(e)}"
398
+ }
399
+ requests.post(webhook_url, json=error_payload)
400
+ except:
401
+ pass
402
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  return False
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
  def send_support_to_slack(områdeskod, uttagsnummer, email, chat_history):
406
  """Skickar en supportförfrågan till Slack."""
407
  try:
 
411
  if msg['role'] == 'user':
412
  chat_content += f">*Användare:* {msg['content']}\n\n"
413
  elif msg['role'] == 'assistant':
414
+ chat_content += f">*Bot:* {msg['content'][:300]}{'...' if len(msg['content']) > 300 else ''}\n\n"
415
 
416
  # Skapa rubrik och innehåll
417
+ webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
418
+ if not webhook_url:
419
+ print("Slack webhook URL saknas")
420
+ return False
421
+
422
+ payload = {
423
+ "blocks": [
424
+ {
425
+ "type": "header",
426
+ "text": {
427
+ "type": "plain_text",
428
+ "text": f"Support förfrågan - {datetime.now().strftime('%Y-%m-%d %H:%M')}"
429
+ }
430
+ },
431
+ {
432
+ "type": "section",
433
+ "fields": [
434
+ {
435
+ "type": "mrkdwn",
436
+ "text": f"*Områdeskod:* {områdeskod or 'Ej angiven'}"
437
+ },
438
+ {
439
+ "type": "mrkdwn",
440
+ "text": f"*Uttagsnummer:* {uttagsnummer or 'Ej angiven'}"
441
+ },
442
+ {
443
+ "type": "mrkdwn",
444
+ "text": f"*Email:* {email}"
445
+ },
446
+ {
447
+ "type": "mrkdwn",
448
+ "text": f"*Tidpunkt:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
449
+ }
450
+ ]
451
+ },
452
+ {
453
+ "type": "section",
454
+ "text": {
455
+ "type": "mrkdwn",
456
+ "text": "*Chatthistorik:*\n" + chat_content
457
+ }
458
+ }
459
+ ]
460
+ }
461
 
462
+ response = requests.post(webhook_url, json=payload)
463
+ if response.status_code == 200:
464
+ print("Support-förfrågan skickad till Slack")
465
+ return True
466
+ else:
467
+ print(f"Slack-anrop för support misslyckades: {response.status_code}, {response.text}")
468
+ return False
469
  except Exception as e:
470
  print(f"Fel vid sändning av support till Slack: {type(e).__name__}: {e}")
471
  return False
472
 
473
  # --- Schemaläggning av rapporter ---
474
  def run_scheduler():
475
+ """Kör schemaläggaren i en separat tråd med förenklad statusrapportering."""
476
+ # Använd den förenklade funktionen för rapportering
477
+ schedule.every().day.at("08:00").do(simple_status_report)
478
+ schedule.every().day.at("12:00").do(simple_status_report)
479
+ schedule.every().day.at("17:00").do(simple_status_report)
480
 
481
  while True:
482
  schedule.run_pending()
483
  time.sleep(60) # Kontrollera varje minut
484
 
485
+ # Starta schemaläggaren i en separat tråd
486
  scheduler_thread = threading.Thread(target=run_scheduler, daemon=True)
487
  scheduler_thread.start()
488
 
489
+ # Kör en statusrapport direkt vid uppstart för att verifiera att allt fungerar
490
  try:
491
+ print("Försöker skicka startrapport till Slack...")
492
+ simple_status_report()
493
  except Exception as e:
494
+ print(f"Kunde inte skicka startrapport: {e}")
495
 
496
+ # --- Gradio UI ---
497
  initial_chat = [{"role": "assistant", "content": "Detta är ChargeNode's AI bot. Hur kan jag hjälpa dig idag?"}]
498
 
499
  custom_css = """
 
503
  #chatbot_conversation { max-height: 300px; overflow-y: auto; }
504
  .gr-button {background-color: #2a9d8f; color: #fff; border: none; border-radius: 4px; padding: 8px 16px; margin: 5px;}
505
  .gr-button:hover {background-color: #264653;}
506
+ .support-btn {background-color: #000000; color: #ffffff; margin-top: 5px; margin-bottom: 10px;}
507
+ .support-btn:hover {background-color: #333333;}
508
  .flex-row {display: flex; flex-direction: row; gap: 5px;}
509
  .gr-form {padding: 10px; border: 1px solid #eee; border-radius: 4px; margin-bottom: 10px;}
510
  .chat-preview {max-height: 150px; overflow-y: auto; border: 1px solid #eee; padding: 8px; margin-top: 10px; font-size: 12px; background-color: #f9f9f9;}
511
  .success-message {font-size: 16px; font-weight: normal; margin-bottom: 15px;}
 
512
  /* Dölj Gradio-footer */
513
  footer {display: none !important;}
514
  .footer {display: none !important;}
 
553
 
554
  # Success message (initially hidden)
555
  with gr.Group(visible=False) as success_interface:
556
+ gr.Markdown("Tack för att du kontaktar support@chargenode.eu. Vi återkommer inom kort", elem_classes="success-message")
557
  back_to_chat_btn = gr.Button("Tillbaka till chatten")
558
 
559
  def respond(message, chat_history, request: gr.Request):
 
564
 
565
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
566
  session_id = str(uuid.uuid4())
567
+
568
+ # Använd session_id från tidigare logg om det finns
569
+ if last_log and 'session_id' in last_log:
570
+ session_id = last_log.get('session_id')
571
+
572
  user_id = request.client.host if request else "okänd"
573
 
574
  ua_str = request.headers.get("user-agent", "")
 
604
  log_file.write(json.dumps(log_data) + "\n")
605
  last_log = log_data
606
 
607
+ # Skicka varje konversation direkt till Slack
608
+ try:
609
+ webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
610
+ if webhook_url:
611
+ # Förenkla innehållet för att säkerställa att det fungerar
612
+ slack_message = {
613
+ "blocks": [
614
+ {
615
+ "type": "header",
616
+ "text": {
617
+ "type": "plain_text",
618
+ "text": f"Ny konversation {timestamp}"
619
+ }
620
+ },
621
+ {
622
+ "type": "section",
623
+ "text": {
624
+ "type": "mrkdwn",
625
+ "text": f"*Användare:* {message}"
626
+ }
627
+ },
628
+ {
629
+ "type": "section",
630
+ "text": {
631
+ "type": "mrkdwn",
632
+ "text": f"*Bot:* {response[:300]}{'...' if len(response) > 300 else ''}"
633
+ }
634
+ },
635
+ {
636
+ "type": "context",
637
+ "elements": [
638
+ {
639
+ "type": "mrkdwn",
640
+ "text": f"Session: {session_id[:8]}... | Browser: {browser} | Platform: {platform}"
641
+ }
642
+ ]
643
+ }
644
+ ]
645
+ }
646
+
647
+ # Använd asynkront anrop för att inte blockera svarstiden
648
+ # Detta kräver att requests körs i en separat tråd
649
+ threading.Thread(
650
+ target=lambda: requests.post(webhook_url, json=slack_message),
651
+ daemon=True
652
+ ).start()
653
+ except Exception as e:
654
+ print(f"Kunde inte skicka konversation till Slack: {e}")
655
+
656
  chat_history.append({"role": "user", "content": message})
657
  chat_history.append({"role": "assistant", "content": response})
658
  return "", chat_history