Spaces:
Build error
Build error
| # slack_reporter/app.py – nyckeltal från nystartad JSONL-logg | |
| import os | |
| import time | |
| import schedule | |
| import pandas as pd | |
| import requests | |
| import logging | |
| import re | |
| from datetime import datetime, timedelta | |
| from huggingface_hub import hf_hub_download | |
| import gradio as gr | |
| # --- Loggning --- | |
| logging.basicConfig( | |
| filename="slack_reporter.log", | |
| level=logging.INFO, | |
| format="%(asctime)s %(levelname)s %(message)s" | |
| ) | |
| # --- Konfiguration --- | |
| REPO_ID = "ChargeNodeEurope/logfiles" | |
| LOG_FILENAME = "logs_v2/conversation_log_v2.txt" | |
| WEBHOOK_URL = os.environ.get("SLACK_WEBHOOK_URL") | |
| HF_TOKEN = os.environ.get("HF_TOKEN") | |
| # --- Funktion: Skicka Slack-meddelande med nyckeltal --- | |
| def send_summary_to_slack(summary_text): | |
| payload = {"text": f"📊 Daglig sammanställning:\n{summary_text}"} | |
| try: | |
| response = requests.post(WEBHOOK_URL, json=payload) | |
| logging.info(f"Slack response status: {response.status_code}") | |
| logging.info(f"Slack response text: {response.text}") | |
| response.raise_for_status() | |
| logging.info("Slack-meddelande postat.") | |
| except Exception as e: | |
| logging.error(f"Fel vid Slack-post: {e}", exc_info=True) | |
| raise | |
| # --- Funktion: Bygg nyckeltalstext --- | |
| def generate_summary(df): | |
| now = datetime.now() | |
| yesterday = now - timedelta(days=1) | |
| last_14 = now - timedelta(days=14) | |
| # Konvertera timestamp till datetime | |
| df["timestamp"] = pd.to_datetime(df["timestamp"], errors="coerce") | |
| # Filtrera loggar för senaste 24h och 14 dagar | |
| df_day = df[df["timestamp"] >= yesterday.replace(hour=0, minute=0, second=0)] | |
| df_14 = df[df["timestamp"] >= last_14] | |
| summary = [] | |
| summary.append(f"📅 Datum: {now.strftime('%Y-%m-%d')}") | |
| summary.append(f"🗨️ Antal meddelanden senaste 24h: {len(df_day)}") | |
| summary.append(f"👥 Unika sessioner senaste 24h: {df_day['session_id'].nunique()}") | |
| # Beräkna snitt antal meddelanden per session (om minst en session finns) | |
| unique_sessions = df_day['session_id'].nunique() | |
| avg_messages_per_session = round(len(df_day) / unique_sessions, 2) if unique_sessions > 0 else 0 | |
| summary.append(f"📊 Meddelanden per session (snitt): {avg_messages_per_session}") | |
| # Snittsvarstid (om kolumnen finns och har giltiga värden) | |
| if "response_time" in df_day.columns and not df_day["response_time"].empty: | |
| avg_response_time = round(df_day["response_time"].mean(), 2) | |
| summary.append(f"🕒 Snittsvarstid senaste 24h: {avg_response_time} sekunder") | |
| else: | |
| summary.append("🕒 Snittsvarstid senaste 24h: N/A") | |
| summary.append(f"📊 Antal meddelanden (14 dagar): {len(df_14)}") | |
| summary.append(f"📈 Unika användare (14 dagar): {df_14['user_id'].nunique()}") | |
| # Likes och dislikes under senaste 24h | |
| if "feedback" in df_day.columns: | |
| df_day_feedback = df_day.dropna(subset=["feedback"]) | |
| likes = df_day_feedback[df_day_feedback["feedback"] == "up"].shape[0] | |
| dislikes = df_day_feedback[df_day_feedback["feedback"] == "down"].shape[0] | |
| else: | |
| likes, dislikes = 0, 0 | |
| summary.append(f"👍 Likes senaste 24h: {likes}") | |
| summary.append(f"👎 Dislikes senaste 24h: {dislikes}") | |
| # Nyckeltal kring webbläsare: visa de tre mest använda | |
| if "browser" in df_day.columns: | |
| browser_counts = df_day["browser"].value_counts() | |
| top_browsers = browser_counts.head(3) | |
| browser_summary = "🌐 Browser-fördelning senaste 24h: " + ", ".join([f"{browser}: {count}" for browser, count in top_browsers.items()]) | |
| else: | |
| browser_summary = "🌐 Browser-fördelning senaste 24h: Ingen data" | |
| summary.append(browser_summary) | |
| # Tre exempel på frågor och svar med tumme ner | |
| if "feedback" in df_day.columns: | |
| df_down = df_day[df_day["feedback"] == "down"].dropna(subset=["user_message", "bot_reply"]) | |
| else: | |
| df_down = pd.DataFrame() | |
| if not df_down.empty: | |
| examples = df_down.head(3) | |
| examples_text = "❌ Exempel på frågor och svar med tumme ner:\n" | |
| for idx, row in examples.iterrows(): | |
| examples_text += f"• Fråga: {row['user_message']}\n Svar: {row['bot_reply']}\n" | |
| else: | |
| examples_text = "❌ Inga exempel med tumme ner hittades senaste 24h." | |
| summary.append(examples_text) | |
| return "\n".join(summary) | |
| # --- Huvudfunktion --- | |
| def run_report(): | |
| try: | |
| logging.info("Startar rapportgenerering...") | |
| log_path = hf_hub_download( | |
| repo_id=REPO_ID, | |
| filename=LOG_FILENAME, | |
| repo_type="dataset", | |
| token=HF_TOKEN | |
| ) | |
| try: | |
| df = pd.read_json(log_path, lines=True) | |
| logging.info("Loggfil läst som JSONL.") | |
| except Exception as e: | |
| logging.error(f"Kunde inte läsa logg som JSONL: {e}", exc_info=True) | |
| return "❌ Loggfilen kunde inte läsas som JSONL." | |
| if df.empty: | |
| logging.warning("Inga loggrader hittades – avbryter.") | |
| return "⚠️ Inga loggar att rapportera." | |
| summary = generate_summary(df) | |
| send_summary_to_slack(summary) | |
| return "✅ Slack-meddelande skickat." | |
| except Exception as e: | |
| logging.error(f"Fel vid körning: {e}", exc_info=True) | |
| return f"❌ Fel vid körning: {e}" | |
| # --- Schemaläggning --- | |
| schedule.every().day.at("08:20").do(run_report) | |
| def run_schedule(): | |
| while True: | |
| schedule.run_pending() | |
| time.sleep(60) | |
| import threading | |
| threading.Thread(target=run_schedule, daemon=True).start() | |
| # --- Gradio-knapp --- | |
| with gr.Blocks() as app: | |
| gr.Markdown("# Slack Reporter – Nyckeltal") | |
| btn = gr.Button("Skicka rapport nu") | |
| output = gr.Textbox() | |
| btn.click(fn=run_report, outputs=output) | |
| if __name__ == "__main__": | |
| app.launch() | |