#!/usr/bin/env python3 """Ollama Integration für KI-gestütztes E-Mail-Parsing""" import json import requests import re from datetime import datetime OLLAMA_URL = "http://192.168.0.150:11434/api/generate" DEFAULT_MODEL = "gemma4:latest" def query_ollama(prompt, model=DEFAULT_MODEL, temperature=0.1): """Ollama API aufrufen""" try: response = requests.post( OLLAMA_URL, json={ "model": model, "prompt": prompt, "stream": False, "options": { "temperature": temperature, "num_predict": 500 } }, timeout=30 ) response.raise_for_status() return response.json() except Exception as e: return {"error": str(e)} def extract_json_from_response(text): """JSON aus Ollama-Antwort extrahieren""" # Versuche direkt als JSON zu parsen try: return json.loads(text) except: pass # Suche nach JSON-Block json_match = re.search(r'\{[\s\S]*\}', text) if json_match: try: return json.loads(json_match.group()) except: pass return {"error": "Kein gültiges JSON gefunden", "raw": text} def parse_email_with_ollama(email_subject, email_body, sender_name): """E-Mail mit Ollama parsen""" prompt = f"""Analysiere diese Restaurant-Reservierungs-E-Mail. WICHTIG: Suche nach einer Buchungsnummer im Format RES-YYYY-MM-DD-XXX. Wenn eine Buchungsnummer erwähnt wird, ist es eine Änderung oder Stornierung. Wenn keine Buchungsnummer vorhanden ist, ist es eine neue Reservierung. Absender: {sender_name} Betreff: {email_subject} E-Mail-Inhalt: --- {email_body} --- Extrahiere folgende Informationen und antworte NUR mit JSON: {{ "booking_number": "RES-2025-05-12-001" oder null, "intent": "new" | "modification" | "cancellation", "name": "Name des Gastes", "phone": "Telefonnummer", "email": "E-Mail-Adresse", "date": "YYYY-MM-DD", "time": "HH:MM", "guests": 4, "occasion": "Geburtstag/Dinner/etc. oder null", "notes": "Weitere Informationen", "confidence": 0.95, "needs_review": false, "review_reason": null }} Beispiele für Änderungen: - "Ich möchte meine Reservierung RES-2025-05-12-001 verschieben" - "Bitte stornieren Sie meinen Tisch" - "Wir sind jetzt 6 statt 4 Personen" Antworte nur mit dem JSON-Objekt, keine Erklärungen.""" result = query_ollama(prompt) if "error" in result: return { "error": result["error"], "needs_review": True, "review_reason": "Ollama-Fehler" } response_text = result.get("response", "") parsed = extract_json_from_response(response_text) # Validiere und ergänze if "confidence" not in parsed: parsed["confidence"] = 0.5 if "needs_review" not in parsed: parsed["needs_review"] = parsed.get("confidence", 0) < 0.7 return parsed def generate_confirmation_email(reservation, is_new=True): """Bestätigungsmail-Text generieren""" if is_new: template = f"""Hallo {reservation.get('name', 'Gast')}, vielen Dank für Ihre Reservierung bei uns! ━━━━━━━━━━━━━━━━━━━━━━━ 📋 BUCHUNGSNUMMER: {reservation['booking_number']} ━━━━━━━━━━━━━━━━━━━━━━━ 📅 Datum: {reservation.get('date', 'unbekannt')} ⏰ Uhrzeit: {reservation.get('time_from', 'unbekannt')} 👥 Personen: {reservation.get('guests', 'unbekannt')} 🍽️ Tisch: {reservation.get('table_name', 'wird zugewiesen')} Bei Änderungen antworten Sie einfach auf diese E-Mail und nennen Sie Ihre Buchungsnummer: {reservation['booking_number']} Wir freuen uns auf Ihren Besuch! Mit freundlichen Grüßen Ihr Restaurant-Team""" else: template = f"""Hallo {reservation.get('name', 'Gast')}, Ihre Reservierung wurde aktualisiert. ━━━━━━━━━━━━━━━━━━━━━━━ 📋 BUCHUNGSNUMMER: {reservation['booking_number']} ━━━━━━━━━━━━━━━━━━━━━━━ 📅 Neuer Termin: {reservation.get('date', 'unbekannt')} um {reservation.get('time_from', 'unbekannt')} 👥 Personen: {reservation.get('guests', 'unbekannt')} Alle anderen Details bleiben bestehen. Bei weiteren Änderungen nennen Sie bitte immer Ihre Buchungsnummer: {reservation['booking_number']} Mit freundlichen Grüßen Ihr Restaurant-Team""" return template def suggest_table_for_group(available_tables, guests, date, time, ollama_model=DEFAULT_MODEL): """Ollama schlägt optimalen Tisch vor""" tables_info = "\n".join([ f"- {t['name']}: {t['seats']} Plätze, Bereich: {t.get('area_name', 'unbekannt')}" for t in available_tables ]) prompt = f"""Schlage den besten Tisch für diese Reservierung vor: Gruppe: {guests} Personen Datum: {date} Uhrzeit: {time} Verfügbare Tische: {tables_info} Berücksichtige: - Passende Größe für {guests} Personen - Atmosphäre (Fenster bevorzugt) - Nicht zu groß oder zu klein Antworte mit JSON: {{ "suggested_table_id": 5, "reasoning": "Tisch 5 hat 6 Plätze, ist am Fenster und ideal für {guests} Personen", "alternatives": [3, 7] }}""" result = query_ollama(prompt, model=ollama_model) if "error" in result: return None return extract_json_from_response(result.get("response", ""))