martinbrahm commited on
Commit
3d18df1
·
verified ·
1 Parent(s): 0459685

Upload main.py

Browse files
Files changed (1) hide show
  1. main.py +49 -46
main.py CHANGED
@@ -7,10 +7,9 @@ from datetime import datetime
7
 
8
  app = FastAPI()
9
 
10
- # --- KONFIGURATION ---
11
  COLLECTION_KNOWLEDGE = "knowledge_base"
12
  COLLECTION_RULES = "availability_rules"
13
- COLLECTION_INBOX = "inbox"
14
  KNOWLEDGE_CACHE = []
15
 
16
  # --- FIREBASE VERBINDUNG ---
@@ -31,50 +30,31 @@ except Exception as e:
31
  # --- CACHE LADEN ---
32
  def reload_knowledge():
33
  global KNOWLEDGE_CACHE
34
- if not db: return 0
35
  try:
36
  docs = db.collection(COLLECTION_KNOWLEDGE).stream()
37
  KNOWLEDGE_CACHE = [d.to_dict() for d in docs]
38
  print(f"📚 {len(KNOWLEDGE_CACHE)} Einträge geladen.")
39
- return len(KNOWLEDGE_CACHE)
40
  except Exception as e:
41
  print(f"❌ Cache Fehler: {e}")
42
- return 0
43
 
44
  @app.on_event("startup")
45
  async def startup():
46
  reload_knowledge()
47
 
48
  def get_stem(word):
 
49
  w = word.lower().strip()
50
  for end in ["ern", "en", "er", "es", "st", "te", "e", "s", "t"]:
51
  if w.endswith(end) and len(w) > len(end)+2: return w[:-len(end)]
52
  return w
53
 
54
  # ==========================================
55
- # 1. HAUPTSEITE & MONITORING (Repariert!)
56
- # ==========================================
57
- @app.get("/")
58
- def home():
59
- # Hier ist die Info zurück!
60
- return {
61
- "status": "Online",
62
- "docs_loaded": len(KNOWLEDGE_CACHE),
63
- "endpoints": ["/check_availability", "/search", "/refresh_knowledge"]
64
- }
65
-
66
- @app.get("/refresh_knowledge")
67
- def refresh():
68
- count = reload_knowledge()
69
- return {"status": "Cache aktualisiert", "docs_loaded": count}
70
-
71
- # ==========================================
72
- # 2. TOOL: VERFÜGBARKEIT PRÜFEN
73
  # ==========================================
74
  @app.post("/check_availability")
75
  async def check_availability(request: Request):
76
  print("🚦 TOOL CALL: checkAvailability")
77
-
78
  today = datetime.now().strftime("%Y-%m-%d")
79
  status = "available"
80
  message = "Normaler Betrieb."
@@ -85,16 +65,13 @@ async def check_availability(request: Request):
85
  for r in rules:
86
  rd = r.to_dict()
87
  if rd.get('start_date') <= today <= rd.get('end_date'):
88
- print(f"🛑 REGEL GEFUNDEN: {rd.get('name')}")
89
  status = "unavailable"
90
  message = rd.get('instruction_text')
91
  break
92
  except Exception as e:
93
  print(f"❌ ERROR CHECK: {e}")
94
- return {"result": json.dumps({"status": "available", "instruction": "Fehler ignoriert, normal arbeiten."})}
95
 
96
- print(f"👉 RESULTAT: {status} | {message}")
97
-
98
  return {
99
  "result": json.dumps({
100
  "status": status,
@@ -103,7 +80,7 @@ async def check_availability(request: Request):
103
  }
104
 
105
  # ==========================================
106
- # 3. TOOL: WISSENSSUCHE
107
  # ==========================================
108
  @app.post("/search")
109
  async def search(request: Request):
@@ -111,6 +88,7 @@ async def search(request: Request):
111
  data = await request.json()
112
  query = ""
113
 
 
114
  if "search_query" in data: query = data["search_query"]
115
  elif "message" in data and "toolCalls" in data["message"]:
116
  args = data["message"]["toolCalls"][0]["function"]["arguments"]
@@ -120,44 +98,69 @@ async def search(request: Request):
120
  print(f"🔎 FRAGE: '{query}'")
121
  if not query: return {"result": "Akustik-Fehler."}
122
 
123
- STOP_WORDS = ["capaneo", "udo", "schober", "firma", "gmbh", "hallo", "demo"]
 
 
 
 
124
  q_words = [get_stem(w) for w in query.lower().split() if len(w)>2]
125
  relevant_words = [w for w in q_words if w not in STOP_WORDS]
126
-
127
- if not relevant_words:
128
- return {"result": "Dazu habe ich keine Informationen."}
129
 
 
 
 
130
  best_doc = None
131
  best_score = 0
132
 
133
  for doc in KNOWLEDGE_CACHE:
134
  score = 0
135
- txt = (doc.get("question", "") + " " + doc.get("answer", "")).lower()
136
- kws = [k.lower() for k in doc.get("keywords", [])]
 
 
137
 
138
- for k in kws:
139
- k_stem = get_stem(k)
140
- if k_stem in relevant_words: score += 30
141
- for w in relevant_words:
142
- if w in txt: score += 5
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
  if score > best_score:
145
  best_score = score
146
  best_doc = doc
147
 
148
- if best_doc and best_score >= 15:
149
- print(f"🏆 TREFFER ({best_score}): {best_doc.get('question')}")
 
150
  return {"result": best_doc.get("answer")}
151
  else:
152
- return {"result": "Dazu habe ich keine Informationen."}
 
153
 
154
  except Exception as e:
155
  print(f"❌ SEARCH ERROR: {e}")
156
- return {"result": "Systemfehler."}
157
 
158
  # ==========================================
159
- # 4. MÜLLSCHLUCKER (Gegen 404 Fehler)
160
  # ==========================================
161
  @app.post("/vapi-incoming")
162
  async def dummy_incoming(request: Request):
163
- return {"status": "ok"}
 
 
 
 
 
7
 
8
  app = FastAPI()
9
 
10
+ # --- SETUP ---
11
  COLLECTION_KNOWLEDGE = "knowledge_base"
12
  COLLECTION_RULES = "availability_rules"
 
13
  KNOWLEDGE_CACHE = []
14
 
15
  # --- FIREBASE VERBINDUNG ---
 
30
  # --- CACHE LADEN ---
31
  def reload_knowledge():
32
  global KNOWLEDGE_CACHE
33
+ if not db: return
34
  try:
35
  docs = db.collection(COLLECTION_KNOWLEDGE).stream()
36
  KNOWLEDGE_CACHE = [d.to_dict() for d in docs]
37
  print(f"📚 {len(KNOWLEDGE_CACHE)} Einträge geladen.")
 
38
  except Exception as e:
39
  print(f"❌ Cache Fehler: {e}")
 
40
 
41
  @app.on_event("startup")
42
  async def startup():
43
  reload_knowledge()
44
 
45
  def get_stem(word):
46
+ # Einfaches Stemming für bessere Treffer
47
  w = word.lower().strip()
48
  for end in ["ern", "en", "er", "es", "st", "te", "e", "s", "t"]:
49
  if w.endswith(end) and len(w) > len(end)+2: return w[:-len(end)]
50
  return w
51
 
52
  # ==========================================
53
+ # TOOL 1: VERFÜGBARKEIT (Bleibt wie es ist)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  # ==========================================
55
  @app.post("/check_availability")
56
  async def check_availability(request: Request):
57
  print("🚦 TOOL CALL: checkAvailability")
 
58
  today = datetime.now().strftime("%Y-%m-%d")
59
  status = "available"
60
  message = "Normaler Betrieb."
 
65
  for r in rules:
66
  rd = r.to_dict()
67
  if rd.get('start_date') <= today <= rd.get('end_date'):
68
+ print(f"🛑 REGEL AKTIV: {rd.get('name')}")
69
  status = "unavailable"
70
  message = rd.get('instruction_text')
71
  break
72
  except Exception as e:
73
  print(f"❌ ERROR CHECK: {e}")
 
74
 
 
 
75
  return {
76
  "result": json.dumps({
77
  "status": status,
 
80
  }
81
 
82
  # ==========================================
83
+ # TOOL 2: SUCHE (Jetzt mit Udo & Capaneo Priorität)
84
  # ==========================================
85
  @app.post("/search")
86
  async def search(request: Request):
 
88
  data = await request.json()
89
  query = ""
90
 
91
+ # Parsing
92
  if "search_query" in data: query = data["search_query"]
93
  elif "message" in data and "toolCalls" in data["message"]:
94
  args = data["message"]["toolCalls"][0]["function"]["arguments"]
 
98
  print(f"🔎 FRAGE: '{query}'")
99
  if not query: return {"result": "Akustik-Fehler."}
100
 
101
+ # --- UPDATE: STOP WÖRTER BEREINIGT ---
102
+ # Wir entfernen "capaneo" und "udo" hier! Sie sind wichtig!
103
+ # Nur Füllwörter bleiben gesperrt.
104
+ STOP_WORDS = ["hallo", "guten", "tag", "moin", "bitte", "danke", "frage", "kannst", "sagen"]
105
+
106
  q_words = [get_stem(w) for w in query.lower().split() if len(w)>2]
107
  relevant_words = [w for w in q_words if w not in STOP_WORDS]
 
 
 
108
 
109
+ if not relevant_words:
110
+ return {"result": "Dazu habe ich keine Informationen."}
111
+
112
  best_doc = None
113
  best_score = 0
114
 
115
  for doc in KNOWLEDGE_CACHE:
116
  score = 0
117
+ # Wir holen Titel (Frage) und Inhalt (Antwort)
118
+ title = doc.get("question", "").lower()
119
+ content = doc.get("answer", "").lower()
120
+ keywords = [k.lower() for k in doc.get("keywords", [])]
121
 
122
+ for word in relevant_words:
123
+ word_stem = get_stem(word)
124
+
125
+ # 1. TITEL TREFFER (Das Wichtigste!)
126
+ # Wenn der Kunde "Capaneo" sagt und im Titel steht "Wer ist Capaneo" -> BINGO!
127
+ if word in title:
128
+ score += 50
129
+
130
+ # 2. KEYWORD TREFFER
131
+ # Keywords sind auch stark
132
+ for k in keywords:
133
+ if get_stem(k) == word_stem:
134
+ score += 30
135
+
136
+ # 3. TEXT TREFFER (Nur Beiwerk)
137
+ # Verhindert, dass jedes Dokument mit "Capaneo" im Footer gewinnt
138
+ if word in content:
139
+ score += 5
140
 
141
  if score > best_score:
142
  best_score = score
143
  best_doc = doc
144
 
145
+ # Score Schwelle auf 20 (damit "Hallo" keine Treffer bringt, aber "Udo" schon)
146
+ if best_doc and best_score >= 20:
147
+ print(f"🏆 TREFFER ({best_score} Pkt): {best_doc.get('question')}")
148
  return {"result": best_doc.get("answer")}
149
  else:
150
+ print(f"⚠️ Zu wenig Relevanz (Max Score: {best_score})")
151
+ return {"result": "Dazu habe ich leider keine spezifischen Informationen in meiner Datenbank."}
152
 
153
  except Exception as e:
154
  print(f"❌ SEARCH ERROR: {e}")
155
+ return {"result": "Fehler."}
156
 
157
  # ==========================================
158
+ # 3. MÜLLSCHLUCKER
159
  # ==========================================
160
  @app.post("/vapi-incoming")
161
  async def dummy_incoming(request: Request):
162
+ return {"status": "ok"}
163
+
164
+ @app.get("/")
165
+ def home():
166
+ return {"status": "Online", "docs_loaded": len(KNOWLEDGE_CACHE)}