import os import json import time import requests from anthropic import Anthropic from openai import OpenAI import gradio as gr import pandas as pd from huggingface_hub import CommitScheduler from datetime import datetime, timedelta import uuid from user_agents import parse as parse_ua import schedule import threading # --- Konfiguration --- CHARGENODE_URL = "https://www.chargenode.eu" # Kontrollera om vi kör i Hugging Face-miljön IS_HUGGINGFACE = os.environ.get("SPACE_ID") is not None # OpenAI-klient behålls för bakåtkompatibilitet OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") if not OPENAI_API_KEY: raise ValueError("OPENAI_API_KEY saknas") client = OpenAI(api_key=OPENAI_API_KEY) # Lägg till Anthropic API-nyckel och klient ANTHROPIC_API_KEY = os.environ.get("ANTHROPIC_API_KEY") if not ANTHROPIC_API_KEY: raise ValueError("ANTHROPIC_API_KEY saknas") anthropic_client = Anthropic(api_key=ANTHROPIC_API_KEY) log_folder = "logs" os.makedirs(log_folder, exist_ok=True) log_file_path = os.path.join(log_folder, "conversation_log_v2.txt") # Skapa en tom loggfil om den inte finns if not os.path.exists(log_file_path): with open(log_file_path, "w", encoding="utf-8") as f: f.write("") # Skapa en tom fil print(f"Skapade tom loggfil: {log_file_path}") hf_token = os.environ.get("HF_TOKEN") if not hf_token: raise ValueError("HF_TOKEN saknas") # Minsta möjliga konfiguration som bör fungera scheduler = CommitScheduler( repo_id="ChargeNodeEurope/logfiles", repo_type="dataset", folder_path=log_folder, path_in_repo="logs_v2", every=300, # Vänta 5 minuter token=hf_token ) # --- Globala variabler --- last_log = None # Sparar loggdata från senaste svar för feedback full_context = None # Används för att spara hela kontexten # --- Förbättrad loggfunktion --- def safe_append_to_log(log_entry): """Säker metod för att lägga till loggdata utan att förlora historisk information.""" try: # Öppna filen i append-läge with open(log_file_path, "a", encoding="utf-8") as log_file: log_json = json.dumps(log_entry) log_file.write(log_json + "\n") log_file.flush() # Säkerställ att data skrivs till disk omedelbart print(f"Loggpost tillagd: {log_entry.get('timestamp', 'okänd tid')}") return True except Exception as e: print(f"Fel vid loggning: {e}") # Försök skapa mappen om den inte finns try: os.makedirs(os.path.dirname(log_file_path), exist_ok=True) # Försök igen with open(log_file_path, "a", encoding="utf-8") as log_file: log_json = json.dumps(log_entry) log_file.write(log_json + "\n") print("Loggpost tillagd efter återhämtning") return True except Exception as retry_error: print(f"Kritiskt fel vid loggning: {retry_error}") return False # --- Laddar textkällor --- def load_local_files(): """Laddar alla lokala filer och returnerar som en sammanhängande text.""" uploaded_text = "" allowed = [".txt", ".docx", ".pdf", ".csv", ".xls", ".xlsx"] excluded = ["requirements.txt", "app.py", "conversation_log.txt", "conversation_log_v2.txt", "secrets", "prompt.txt"] for file in os.listdir("."): if file.lower().endswith(tuple(allowed)) and file not in excluded: try: if file.endswith(".txt"): with open(file, "r", encoding="utf-8") as f: content = f.read() elif file.endswith(".docx"): from docx import Document # Import sker vid behov content = "\n".join([p.text for p in Document(file).paragraphs]) elif file.endswith(".pdf"): import PyPDF2 # Import sker vid behov with open(file, "rb") as f: reader = PyPDF2.PdfReader(f) content = "\n".join([p.extract_text() or "" for p in reader.pages]) elif file.endswith(".csv"): content = pd.read_csv(file).to_string() elif file.endswith((".xls", ".xlsx")): if file == "FAQ stadat.xlsx": df = pd.read_excel(file) rows = [] for index, row in df.iterrows(): rows.append(f"Fråga: {row['Fråga']}\nSvar: {row['Svar']}") content = "\n\n".join(rows) else: content = pd.read_excel(file).to_string() uploaded_text += f"\n\nFIL: {file}\n{content}" except Exception as e: print(f"Fel vid läsning av {file}: {str(e)}") return uploaded_text.strip() def load_prompt(): """Läser in system-prompts från prompt.txt med bättre felhantering.""" try: with open("prompt.txt", "r", encoding="utf-8") as f: prompt_content = f.read().strip() if not prompt_content: print("Varning: prompt.txt är tom, använder standardprompt") return "Du är ChargeNode's AI-assistent. Svara på frågor om ChargeNode's produkter och tjänster baserat på den tillhandahållna informationen." return prompt_content except FileNotFoundError: print("Varning: prompt.txt hittades inte, använder standardprompt") return "Du är ChargeNode's AI-assistent. Svara på frågor om ChargeNode's produkter och tjänster baserat på den tillhandahållna informationen." except Exception as e: print(f"Fel vid inläsning av prompt.txt: {e}, använder standardprompt") return "Du är ChargeNode's AI-assistent. Svara på frågor om ChargeNode's produkter och tjänster baserat på den tillhandahållna informationen." def load_full_context(): """Laddar hela kontexten en gång och cachar resultatet.""" global full_context if full_context is None: print("Laddar alla textfiler till fullständig kontext...") full_context = load_local_files() print(f"Laddade {len(full_context)} tecken till kontext") return full_context # Ladda prompt template prompt_template = load_prompt() def generate_answer(query): """Genererar svar baserat på fråga med hela kontexten.""" # Hämta hela kontexten context = load_full_context() if not context.strip(): return "Jag hittar ingen relevant information i mina källor.\n\nDetta är ett AI genererat svar." # System-prompts och användarfråga system_prompt = prompt_template # Skapa ett renare användarmeddelande user_message = f"""Jag har en fråga om ChargeNode. Hela dataunderlaget du kan använda för att svara: {context} Min fråga är: {query}""" try: # Använd Claude Haiku med hela kontexten response = anthropic_client.messages.create( model="claude-3-haiku-20240307", max_tokens=500, temperature=0.2, system=system_prompt, messages=[ {"role": "user", "content": user_message} ] ) answer = response.content[0].text return answer + "\n\nAI-genererat. Otillräcklig hjälp? Kontakta support@chargenode.eu eller 010-2051055" except Exception as e: return f"Tekniskt fel: {str(e)}\n\nAI-genererat. Kontakta support@chargenode.eu eller 010-2051055" # --- Slack Integration --- def send_to_slack(subject, content, color="#2a9d8f"): """Basfunktion för att skicka meddelanden till Slack.""" webhook_url = os.environ.get("SLACK_WEBHOOK_URL") if not webhook_url: print("Slack webhook URL saknas") return False try: # Formatera meddelandet för Slack payload = { "blocks": [ { "type": "header", "text": { "type": "plain_text", "text": subject } }, { "type": "section", "text": { "type": "mrkdwn", "text": content } } ] } response = requests.post( webhook_url, json=payload, headers={"Content-Type": "application/json"} ) if response.status_code == 200: print(f"Slack-meddelande skickat: {subject}") return True else: print(f"Slack-anrop misslyckades: {response.status_code}, {response.text}") return False except Exception as e: print(f"Fel vid sändning till Slack: {type(e).__name__}: {e}") return False # --- Feedback & Like-funktion --- def vote(data: gr.LikeData): """ Hanterar feedback från Gradio's inbyggda like-funktion. data.liked är True om uppvote, annars False. data.value innehåller information om meddelandet. """ feedback_type = "up" if data.liked else "down" global last_log log_entry = { "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "feedback": feedback_type, "bot_reply": data.value if not isinstance(data.value, dict) else data.value.get("value") } # Om global logdata finns, lägg till ytterligare metadata. if last_log: log_entry.update({ "session_id": last_log.get("session_id"), "user_message": last_log.get("user_message"), }) # Använd den förbättrade loggfunktionen safe_append_to_log(log_entry) # Skicka feedback till Slack try: if feedback_type == "down": # Skicka bara negativ feedback feedback_message = f""" *⚠️ Negativ feedback registrerad* *Fråga:* {last_log.get('user_message', 'Okänd fråga')} *Svar:* {log_entry.get('bot_reply', 'Okänt svar')[:300]}{'...' if len(log_entry.get('bot_reply', '')) > 300 else ''} """ # Skicka asynkront threading.Thread( target=lambda: send_to_slack("Negativ feedback", feedback_message, "#ff0000"), daemon=True ).start() except Exception as e: print(f"Kunde inte skicka feedback till Slack: {e}") return # --- Rapportering --- def read_logs(): """Läs alla loggposter från loggfilen.""" logs = [] try: if os.path.exists(log_file_path): with open(log_file_path, "r", encoding="utf-8") as file: line_count = 0 for line in file: line_count += 1 try: log_entry = json.loads(line.strip()) logs.append(log_entry) except json.JSONDecodeError as e: print(f"Varning: Kunde inte tolka rad {line_count}: {e}") continue print(f"Läste {len(logs)} av {line_count} loggposter") else: print(f"Loggfil saknas: {log_file_path}") except Exception as e: print(f"Fel vid läsning av loggfil: {e}") return logs def get_latest_conversations(logs, limit=50): """Hämta de senaste frågorna och svaren.""" conversations = [] for log in reversed(logs): if 'user_message' in log and 'bot_reply' in log: conversations.append({ 'user_message': log['user_message'], 'bot_reply': log['bot_reply'], 'timestamp': log.get('timestamp', '') }) if len(conversations) >= limit: break return conversations def get_feedback_stats(logs): """Sammanfatta feedback (tumme upp/ned).""" feedback_count = {"up": 0, "down": 0} negative_feedback_examples = [] for log in logs: if 'feedback' in log: feedback = log.get('feedback') if feedback in feedback_count: feedback_count[feedback] += 1 # Samla exempel på negativ feedback if feedback == "down" and 'user_message' in log and len(negative_feedback_examples) < 10: negative_feedback_examples.append({ 'user_message': log.get('user_message', 'Okänd fråga'), 'bot_reply': log.get('bot_reply', 'Okänt svar') }) return feedback_count, negative_feedback_examples def generate_monthly_stats(days=30): """Genererar omfattande statistik över botanvändning för den senaste månaden.""" print(f"Genererar statistik för de senaste {days} dagarna...") # Hämta loggar logs = read_logs() if not logs: return {"error": "Inga loggar hittades för den angivna perioden"} # Filtrera på datumintervall now = datetime.now() cutoff_date = now - timedelta(days=days) filtered_logs = [] for log in logs: if 'timestamp' in log: try: log_date = datetime.strptime(log['timestamp'], "%Y-%m-%d %H:%M:%S") if log_date >= cutoff_date: filtered_logs.append(log) except: pass # Hoppa över poster med ogiltigt datum logs = filtered_logs # Basstatistik total_conversations = sum(1 for log in logs if 'user_message' in log) unique_sessions = len(set(log.get('session_id', 'unknown') for log in logs if 'session_id' in log)) unique_users = len(set(log.get('user_id', 'unknown') for log in logs if 'user_id' in log)) # Feedback-statistik feedback_logs = [log for log in logs if 'feedback' in log] positive_feedback = sum(1 for log in feedback_logs if log.get('feedback') == 'up') negative_feedback = sum(1 for log in feedback_logs if log.get('feedback') == 'down') feedback_ratio = (positive_feedback / len(feedback_logs) * 100) if feedback_logs else 0 # Svarstidsstatistik response_times = [log.get('response_time', 0) for log in logs if 'response_time' in log] avg_response_time = sum(response_times) / len(response_times) if response_times else 0 # Plattformsstatistik platforms = {} browsers = {} operating_systems = {} for log in logs: if 'platform' in log: platforms[log['platform']] = platforms.get(log['platform'], 0) + 1 if 'browser' in log: browsers[log['browser']] = browsers.get(log['browser'], 0) + 1 if 'os' in log: operating_systems[log['os']] = operating_systems.get(log['os'], 0) + 1 # Skapa rapport report = { "period": f"Senaste {days} dagarna", "generated_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "basic_stats": { "total_conversations": total_conversations, "unique_sessions": unique_sessions, "unique_users": unique_users, "messages_per_user": round(total_conversations / unique_users, 2) if unique_users else 0 }, "feedback": { "positive": positive_feedback, "negative": negative_feedback, "ratio_percent": round(feedback_ratio, 1) }, "performance": { "avg_response_time": round(avg_response_time, 2) }, "platform_distribution": platforms, "browser_distribution": browsers, "os_distribution": operating_systems } return report def simple_status_report(): """Skickar en förenklad statusrapport till Slack.""" print("Genererar statusrapport för Slack...") try: # Generera statistik stats = generate_monthly_stats(days=7) # Senaste veckan # Skapa innehåll för Slack now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") subject = f"ChargeNode AI Bot - Status {now}" if 'error' in stats: content = f"*Fel vid generering av statistik:* {stats['error']}" return send_to_slack(subject, content, "#ff0000") # Formatera statistik basic = stats["basic_stats"] feedback = stats["feedback"] perf = stats["performance"] content = f""" *ChargeNode AI Bot - Statusrapport {now}* *Basstatistik* (senaste 7 dagarna) - Totalt antal konversationer: {basic['total_conversations']} - Unika sessioner: {basic['unique_sessions']} - Unika användare: {basic['unique_users']} - Genomsnittlig svarstid: {perf['avg_response_time']} sekunder *Feedback* - 👍 Tumme upp: {feedback['positive']} - 👎 Tumme ned: {feedback['negative']} - Nöjdhet: {feedback['ratio_percent']}% """ # Lägg till de senaste konversationerna logs = read_logs() conversations = get_latest_conversations(logs, 3) if conversations: content += "\n*Senaste konversationer*\n" for conv in conversations: content += f""" > *Tid:* {conv['timestamp']} > *Fråga:* {conv['user_message'][:100]}{'...' if len(conv['user_message']) > 100 else ''} > *Svar:* {conv['bot_reply'][:100]}{'...' if len(conv['bot_reply']) > 100 else ''} """ # Skicka till Slack return send_to_slack(subject, content, "#2a9d8f") except Exception as e: print(f"Fel vid generering av statusrapport: {e}") # Skicka felmeddelande till Slack error_subject = f"ChargeNode AI Bot - Fel vid statusrapport" error_content = f"*Fel vid generering av statusrapport:* {str(e)}" return send_to_slack(error_subject, error_content, "#ff0000") def send_support_to_slack(områdeskod, uttagsnummer, email, chat_history): """Skickar en supportförfrågan till Slack.""" try: # Formatera chat-historiken chat_content = "" for msg in chat_history: if msg['role'] == 'user': chat_content += f">*Användare:* {msg['content']}\n\n" elif msg['role'] == 'assistant': chat_content += f">*Bot:* {msg['content'][:300]}{'...' if len(msg['content']) > 300 else ''}\n\n" # Skapa innehåll subject = f"Support förfrågan - {datetime.now().strftime('%Y-%m-%d %H:%M')}" content = f""" *Användarinformation* - *Områdeskod:* {områdeskod or 'Ej angiven'} - *Uttagsnummer:* {uttagsnummer or 'Ej angiven'} - *Email:* {email} - *Tidpunkt:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} *Chatthistorik:* {chat_content} """ # Skicka till Slack return send_to_slack(subject, content, "#e76f51") except Exception as e: print(f"Fel vid sändning av support till Slack: {type(e).__name__}: {e}") return False # --- Schemaläggning av rapporter --- def run_scheduler(): """Kör schemaläggaren i en separat tråd med förenklad statusrapportering.""" # Använd den förenklade funktionen för rapportering schedule.every().day.at("08:00").do(simple_status_report) schedule.every().day.at("12:00").do(simple_status_report) schedule.every().day.at("17:00").do(simple_status_report) # Veckorapport på måndagar schedule.every().monday.at("09:00").do(lambda: send_to_slack( "Veckostatistik", f"*ChargeNode AI Bot - Veckostatistik*\n\n{json.dumps(generate_monthly_stats(7), indent=2)}", "#3498db" )) while True: schedule.run_pending() time.sleep(60) # Kontrollera varje minut # Starta schemaläggaren i en separat tråd scheduler_thread = threading.Thread(target=run_scheduler, daemon=True) scheduler_thread.start() # Kör en statusrapport vid uppstart för att verifiera att allt fungerar try: print("Skickar en inledande statusrapport för att verifiera Slack-integrationen...") # Anropa inte direkt här - sker i schemaläggaren except Exception as e: print(f"Information: Statusrapport kommer att skickas enligt schema: {e}") # --- Gradio UI --- initial_chat = [{"role": "assistant", "content": "Detta är ChargeNode's AI bot. Hur kan jag hjälpa dig idag?"}] custom_css = """ body {background-color: #f7f7f7; font-family: Arial, sans-serif; margin: 0; padding: 0;} h1 {font-family: Helvetica, sans-serif; color: #2a9d8f; text-align: center; margin-bottom: 0.5em;} .gradio-container {max-width: 400px; margin: 0; padding: 10px; position: fixed; bottom: 20px; right: 20px; box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1); border-radius: 10px; background-color: #fff;} #chatbot_conversation { max-height: 300px; overflow-y: auto; } .gr-button {background-color: #2a9d8f; color: #fff; border: none; border-radius: 4px; padding: 8px 16px; margin: 5px;} .gr-button:hover {background-color: #264653;} .support-btn {background-color: #000000; color: #ffffff; margin-top: 5px; margin-bottom: 10px;} .support-btn:hover {background-color: #333333;} .flex-row {display: flex; flex-direction: row; gap: 5px;} .gr-form {padding: 10px; border: 1px solid #eee; border-radius: 4px; margin-bottom: 10px;} .chat-preview {max-height: 150px; overflow-y: auto; border: 1px solid #eee; padding: 8px; margin-top: 10px; font-size: 12px; background-color: #f9f9f9;} .success-message {font-size: 16px; font-weight: normal; margin-bottom: 15px;} /* Dölj Gradio-footer */ footer {display: none !important;} .footer {display: none !important;} .gr-footer {display: none !important;} .gradio-footer {display: none !important;} .gradio-container .footer {display: none !important;} .gradio-container .gr-footer {display: none !important;} """ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app: gr.Markdown("Ställ din fråga om ChargeNodes produkter och tjänster nedan. Om du inte gillar botten, så ring oss gärna på 010 – 205 10 55") # Chat interface with gr.Group(visible=True) as chat_interface: chatbot = gr.Chatbot(value=initial_chat, type="messages", elem_id="chatbot_conversation") chatbot.like(vote, None, None) with gr.Row(): msg = gr.Textbox(label="Meddelande", placeholder="Ange din fråga...") with gr.Row(): with gr.Column(scale=1): clear = gr.Button("Rensa") with gr.Column(scale=1): support_btn = gr.Button("Behöver du mer hjälp?", elem_classes="support-btn") # Support form interface (initially hidden) with gr.Group(visible=False) as support_interface: gr.Markdown("### Vänligen fyll i din områdeskod, uttagsnummer och din email adress") with gr.Group(elem_classes="gr-form"): områdeskod = gr.Textbox(label="Områdeskod", placeholder="Områdeskod (valfritt)", info="Numeriskt värde") uttagsnummer = gr.Textbox(label="Uttagsnummer", placeholder="Uttagsnummer (valfritt)", info="Numeriskt värde") email = gr.Textbox(label="Din email adress", placeholder="din@email.se", info="Email adress krävs") gr.Markdown("### Chat som skickas till support:") chat_preview = gr.Markdown(elem_classes="chat-preview") with gr.Row(): back_btn = gr.Button("Tillbaka") send_support_btn = gr.Button("Skicka") # Success message (initially hidden) with gr.Group(visible=False) as success_interface: gr.Markdown("Tack för att du kontaktar support@chargenode.eu. Vi återkommer inom kort", elem_classes="success-message") back_to_chat_btn = gr.Button("Tillbaka till chatten") def respond(message, chat_history, request: gr.Request): global last_log start = time.time() response = generate_answer(message) elapsed = round(time.time() - start, 2) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") session_id = str(uuid.uuid4()) # Använd session_id från tidigare logg om det finns if last_log and 'session_id' in last_log: session_id = last_log.get('session_id') user_id = request.client.host if request else "okänd" ua_str = request.headers.get("user-agent", "") ref = request.headers.get("referer", "") ip = request.headers.get("x-forwarded-for", user_id).split(",")[0] ua = parse_ua(ua_str) browser = f"{ua.browser.family} {ua.browser.version_string}" osys = f"{ua.os.family} {ua.os.version_string}" platform = "webb" if "chargenode.eu" in ref: platform = "chargenode.eu" elif "localhost" in ref: platform = "test" elif "app" in ref: platform = "app" log_data = { "timestamp": timestamp, "user_id": user_id, "session_id": session_id, "user_message": message, "bot_reply": response, "response_time": elapsed, "ip": ip, "browser": browser, "os": osys, "platform": platform } # Använd den förbättrade loggfunktionen safe_append_to_log(log_data) last_log = log_data # Skicka varje konversation direkt till Slack try: # Konversationsinnehåll conversation_content = f""" *Ny konversation {timestamp}* *Användare:* {message} *Bot:* {response[:300]}{'...' if len(response) > 300 else ''} *Sessionsinfo:* {session_id[:8]}... | {browser} | {platform} """ # Skicka asynkront för att inte blockera svarstiden threading.Thread( target=lambda: send_to_slack(f"Ny konversation", conversation_content), daemon=True ).start() except Exception as e: print(f"Kunde inte skicka konversation till Slack: {e}") chat_history.append({"role": "user", "content": message}) chat_history.append({"role": "assistant", "content": response}) return "", chat_history def format_chat_preview(chat_history): if not chat_history: return "Ingen chatthistorik att visa." preview = "" for msg in chat_history: sender = "Användare" if msg["role"] == "user" else "Bot" content = msg["content"] if len(content) > 100: # Truncate long messages content = content[:100] + "..." preview += f"**{sender}:** {content}\n\n" return preview def show_support_form(chat_history): preview = format_chat_preview(chat_history) return { chat_interface: gr.Group(visible=False), support_interface: gr.Group(visible=True), success_interface: gr.Group(visible=False), chat_preview: preview } def back_to_chat(): return { chat_interface: gr.Group(visible=True), support_interface: gr.Group(visible=False), success_interface: gr.Group(visible=False) } def submit_support_form(områdeskod, uttagsnummer, email, chat_history): """Hanterar formulärinskickningen med bättre felhantering.""" print(f"Support-förfrågan: områdeskod={områdeskod}, uttagsnummer={uttagsnummer}, email={email}") # Validera input med tydligare loggning validation_errors = [] if områdeskod and not områdeskod.isdigit(): print(f"Validerar områdeskod: '{områdeskod}' (felaktig)") validation_errors.append("Områdeskod måste vara numerisk.") else: print(f"Validerar områdeskod: '{områdeskod}' (ok)") if uttagsnummer and not uttagsnummer.isdigit(): print(f"Validerar uttagsnummer: '{uttagsnummer}' (felaktig)") validation_errors.append("Uttagsnummer måste vara numerisk.") else: print(f"Validerar uttagsnummer: '{uttagsnummer}' (ok)") if not email: print("Validerar email: (saknas)") validation_errors.append("En giltig e-postadress krävs.") elif '@' not in email or '.' not in email.split('@')[1]: print(f"Validerar email: '{email}' (felaktigt format)") validation_errors.append("En giltig e-postadress krävs.") else: print(f"Validerar email: '{email}' (ok)") # Om det finns valideringsfel if validation_errors: print(f"Valideringsfel: {validation_errors}") return { chat_interface: gr.Group(visible=False), support_interface: gr.Group(visible=True), success_interface: gr.Group(visible=False), chat_preview: "\n".join(["**Fel:**"] + validation_errors) } # Om formuläret klarade valideringen, försök skicka till Slack try: print("Försöker skicka supportförfrågan till Slack...") # Skapa en förenklad chathistorik för loggning chat_summary = [] for msg in chat_history: if 'role' in msg and 'content' in msg: chat_summary.append(f"{msg['role']}: {msg['content'][:30]}...") print(f"Chatthistorik att skicka: {chat_summary}") # Skicka till Slack success = send_support_to_slack(områdeskod, uttagsnummer, email, chat_history) if success: print("Support-förfrågan skickad till Slack framgångsrikt") return { chat_interface: gr.Group(visible=False), support_interface: gr.Group(visible=False), success_interface: gr.Group(visible=True) } else: print("Support-förfrågan till Slack misslyckades") return { chat_interface: gr.Group(visible=False), support_interface: gr.Group(visible=True), success_interface: gr.Group(visible=False), chat_preview: "**Ett fel uppstod när meddelandet skulle skickas. Vänligen försök igen senare.**" } except Exception as e: print(f"Oväntat fel vid hantering av support-formulär: {e}") return { chat_interface: gr.Group(visible=False), support_interface: gr.Group(visible=True), success_interface: gr.Group(visible=False), chat_preview: f"**Ett fel uppstod: {str(e)}**" } msg.submit(respond, [msg, chatbot], [msg, chatbot]) clear.click(lambda: None, None, chatbot, queue=False) support_btn.click(show_support_form, chatbot, [chat_interface, support_interface, success_interface, chat_preview]) back_btn.click(back_to_chat, None, [chat_interface, support_interface, success_interface]) back_to_chat_btn.click(back_to_chat, None, [chat_interface, support_interface, success_interface]) send_support_btn.click( submit_support_form, [områdeskod, uttagsnummer, email, chatbot], [chat_interface, support_interface, success_interface, chat_preview] ) # Ladda kontexten direkt vid uppstart print("Förbereder hela kontexten vid uppstart...") load_full_context() print("Kontext laddad och redo!") if __name__ == "__main__": app.launch(share=True)