import os import gradio as gr from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import FAISS from googleapiclient.discovery import build from google.oauth2.service_account import Credentials import pickle import time # Initialize embeddings model embeddings = HuggingFaceEmbeddings( model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2" ) def load_or_create_vector_store(): """Load existing vector store or create new one""" if os.path.exists("vector_store.pkl"): with open("vector_store.pkl", "rb") as f: return pickle.load(f) # Google Sheets setup SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"] SPREADSHEET_ID = "13mB_WfOQtOxE1bYO1o-f8aYfh-ooRV1fhOASk9M2DwI" # Load credentials from environment gcp_credentials = os.getenv("GCP_CREDENTIALS") if not gcp_credentials: return None with open("gcp_credentials.json", "w") as f: f.write(gcp_credentials) creds = Credentials.from_service_account_file( "gcp_credentials.json", scopes=SCOPES ) service = build("sheets", "v4", credentials=creds) # Load all sheets sheets = [ "geburtstagsinfos", "oeffnungszeiten", "hallenregeln", "hinweise", "kontakt", "attraktionen" ] # Prepare documents for embeddings documents = [] for sheet_name in sheets: try: result = service.spreadsheets().values().get( spreadsheetId=SPREADSHEET_ID, range=sheet_name ).execute() rows = result.get('values', [])[1:] # Skip header for row in rows: if len(row) >= 2: doc_text = f"Category: {sheet_name}\nQuestion: {row[0]}\nAnswer: {row[1]}" documents.append(doc_text) except Exception as e: print(f"Error loading {sheet_name}: {e}") # Create vector store vector_store = FAISS.from_texts(documents, embeddings) # Save for future use with open("vector_store.pkl", "wb") as f: pickle.dump(vector_store, f) return vector_store # Load or create the vector store vector_store = load_or_create_vector_store() def format_response(results): """Format search results into a nice response""" if not results: return """Ups! 😅 Dazu habe ich leider keine passende Information gefunden. Aber ich kenne mich super aus mit: - Unseren Öffnungszeiten ⏰ - Den Hallenregeln 📋 - Geburtstagsfeiern 🎂 - Unseren tollen Attraktionen 🎯 - Anfahrt & Kontakt 📍 Frag mich einfach danach!""" # Kategorien prüfen query_text = results[0].page_content.lower() # Adress-/Kontaktanfragen if 'kontakt' in query_text or 'wo finde' in query_text or 'adresse' in query_text: for result in results: if 'contact' in result.metadata.get('source', ''): return f"Cool, dass Du zu uns kommen möchtest! Hier findest Du uns:\n\n{result.page_content}\n\nBis bald! 🚀" # Geburtstagsfragen if 'geburtstag' in query_text or 'feiern' in query_text: birthday_info = [] for result in results: if 'geburtstagsinfos' in result.metadata.get('source', '').lower(): birthday_info.append(result.page_content) if birthday_info: return "Hier sind alle wichtigen Infos zu Kindergeburtstagen:\n\n• " + "\n\n• ".join(birthday_info) # Standardantwort mit dem besten Match return results[0].page_content def chat(message, history): """Main chat function""" try: if not message.strip(): return "", history if not vector_store: return "Entschuldigung, der Service ist gerade nicht verfügbar. Bitte versuche es später noch einmal.", history # Search for similar content results = vector_store.similarity_search(message, k=1) response = format_response(results) history.append({"role": "user", "content": message}) history.append({"role": "assistant", "content": response}) return "", history except Exception as e: print(f"Error in chat: {e}") return "Entschuldigung, es ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.", history # Gradio Interface with gr.Blocks(css=""" .gradio-container {max-width: 800px !important} .message-wrap {max-width: 800px !important} .message {padding: 15px !important; border-radius: 12px !important; margin: 8px !important} .user-message {background-color: #ff6b00 !important; color: white !important; margin-left: 15% !important} .bot-message {background-color: #f5f5f5 !important; margin-right: 15% !important} .input-row {margin-top: 20px !important} footer {display: none !important} """) as demo: chatbot = gr.Chatbot( value=[], elem_id="chatbot", height=500, avatar_images=("🧑", "🤖"), type="messages" ) msg = gr.Textbox( label="Deine Nachricht", placeholder="Was möchtest Du wissen?", lines=2 ) submit = gr.Button("Senden", variant="primary") msg.submit(chat, [msg, chatbot], [msg, chatbot]) submit.click(chat, [msg, chatbot], [msg, chatbot]) # Example questions gr.Examples( examples=[ "Was sind die Öffnungszeiten?", "Wie kann ich einen Kindergeburtstag feiern?", "Welche Regeln gibt es?", "Was kostet ein Kindergeburtstag?", "Wo finde ich euch?" ], inputs=msg ) demo.launch()