From 2fd3b7b8874bdcc11ce76022b299c0e0da527395 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Thu, 25 Jun 2026 10:33:04 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Alicia-Aufgaben=20f=C3=BCr=20Chat-Agent?= =?UTF-8?q?=20(Guard=20+=20RAG=20f=C3=BCr=20WhatsApp/Telegram)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/alicia-aufgaben-chat-agent.md | 184 +++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 docs/alicia-aufgaben-chat-agent.md diff --git a/docs/alicia-aufgaben-chat-agent.md b/docs/alicia-aufgaben-chat-agent.md new file mode 100644 index 0000000..39ebdd4 --- /dev/null +++ b/docs/alicia-aufgaben-chat-agent.md @@ -0,0 +1,184 @@ +# BSN-Chatsystem — Chat-Agent: RAG-Antworten auf WhatsApp/Telegram + +> **Für Alicia (Qwen 3.6, 256K Context)** +> **Stand:** 25.06.2026 +> **Repo:** `git@git.datenhimmel.work:danielkrause/BSN-Chatsystem.git` +> **Branch:** `main` +> **Arbeitsverzeichnis:** `/home/hermes/workspace/bsn-chatbot/` +> **Issue:** [#14](https://git.datenhimmel.work/danielkrause/BSN-Chatsystem/issues/14) + +--- + +## Ziel + +WhatsApp- und Telegram-Nutzer können natürliche Fragen an den Bot stellen und bekommen +RAG-basierte Antworten aus der Datenbank (Submissions, Aussteller, Neuheiten). + +Beispielfragen: +- „Welches Spiel ist ausverkauft?" +- „Was passiert in Halle 3?" +- „Wo finde ich eine Katze?" +- „Gibt es Neuheiten von Kosmos?" + +--- + +## Aufgabe 14a — Neues Modul: `chat_agent.py` + +### Datei: `chat_agent.py` (neue Datei im Repo-Root) + +**Funktionen:** + +1. **`is_boardgame_question(text: str) -> bool`** + - Guard-Filter: Prüft ob die Frage Brettspiel/SPIEL-bezogen ist + - Keywords: `spiel`, `brettspiel`, `halle`, `stand`, `verlag`, `aussteller`, `messe`, + `essen`, `spiel'`, `ausverkauft`, `neuheit`, `katze`, `kOSMOS`, `feuerland`, + `catan`, `pegasus`, `asmodee`, `ravensburger`, `schmidt`, `hans im glück`, + `lookout`, `zoch`, `amigo`, `queen games`, `days of wonder`, `rebel`, `portal` + - Auch erlaubt: Fragen mit `?` am Ende + deutschem Text (mind. 10 Zeichen) + - IMMER True bei offensichtlichen Brettspiel-Fragen + - IMMER False bei: Politik, Erwachseneninhalte, Beleidigungen, irrelevante Themen + +2. **`answer_question(db, message: str, sender_name: str = "", history: list | None = None) -> str`** + - Baut Kontext aus 3 Tabellen (wie `/api/chat` in `app.py`): + - `submissions` (veröffentlichte Beiträge, LIMIT 40) + - `aussteller` (Verlage/Stände, gefiltert nach Keywords) + - `neuheiten` (Spiele-Neuheiten, gefiltert nach Keywords, mit AUSVERKAUFT-Flag) + - Sendet Kontext + Frage an LLM (`deepseek-v4-flash:cloud` via `https://ui.datenhimmel.work/api/chat/completions`) + - System-Prompt: Nur antworten wenn Info im Kontext, sonst „Dazu habe ich leider keine Informationen." + - Antwort immer auf Deutsch, 2-4 Sätze, mit Markdown-Links zu `/beitrag/ID` + - API-Key aus `~/.hermes/config.yaml` lesen (wie `/api/chat`) + - Timeout: 15 Sekunden, Fallback-Text bei Fehler + +**Referenz:** Die bestehende `/api/chat`-Route in `app.py` (Zeilen 4022–4310) enthält exakt +die gleiche Logik. Extrahiere die Kernlogik in `answer_question()` und lass `/api/chat` +die neue Funktion aufrufen (Refactoring). + +### Qualität + +```bash +ruff check chat_agent.py --fix && ruff format chat_agent.py +``` + +**Commit:** `feat(chat): Chat-Agent-Modul mit Guard-Filter + RAG-Antworten` + +--- + +## Aufgabe 14b — WhatsApp-Webhook: Frage-Erkennung + Antwort + +### Datei: `app.py` — WhatsApp-Webhook (ab Zeile ~1162) + +**Einbau-Ort:** Nach dem Intake-Block (Speichern der Submission), VOR dem `db.commit()`. + +**Logik:** +```python +# Nach dem Intake (nach Thread-Erstellung/Aktualisierung): +if msg_type == "text" and not thread_found: + from chat_agent import is_boardgame_question, answer_question + if is_boardgame_question(content): + try: + reply = answer_question(db, content, sender_name) + if reply: + send_whatsapp_message(sender_id, reply) + except Exception as e: + print(f"[chat-agent error] {e}", file=sys.stderr) +``` + +**Wichtig:** +- Nur bei TEXT-Nachrichten (nicht bei Bild/Audio/Video) +- Nur bei NEUEN Threads (nicht bei Thread-Appends) +- NACH allen anderen Checks (#out, registrieren, code, „Meine Daten löschen", FAQ) +- Exception-Handling: Fehler NIE zum Webhook-500 führen → immer `return "OK", 200` +- Inline-Import (vermeidet Circular-Imports) + +### Qualität + +```bash +ruff check app.py --fix && ruff format app.py +``` + +**Commit:** `feat(whatsapp): Frage-Erkennung + Chat-Agent-Antwort im WhatsApp-Webhook` + +--- + +## Aufgabe 14c — Telegram-Webhook: Gleiche Logik + +### Datei: `app.py` — Telegram-Webhook (Zeilen 5293–5317) + +Alternativ: `webhook_queue.py` → `telegram_intake()` (Zeilen 172–215). + +**Wo einbauen:** Nachdem die Nachricht aus dem Telegram-Update extrahiert wurde. + +**Logik:** Gleiche wie WhatsApp: +```python +text = msg.get("text", "") +if text: + from chat_agent import is_boardgame_question, answer_question + if is_boardgame_question(text): + chat_id = msg.get("chat", {}).get("id") + reply = answer_question(db, text, sender_name) + # Sende Antwort via Telegram API + requests.post(f"{TELEGRAM_API}/sendMessage", json={ + "chat_id": chat_id, "text": reply, "parse_mode": "Markdown" + }) +``` + +### Qualität + +```bash +ruff check app.py --fix && ruff format app.py +``` + +**Commit:** `feat(telegram): Chat-Agent-Antwort im Telegram-Webhook` + +--- + +## Aufgabe 14d — Testfragen (manuel) + +**NICHT automatisieren.** Nachdem Alicia gebaut hat, testet Cody: + +```bash +# Test 1: Brettspiel-Frage +curl -X POST http://localhost:5002/api/chat \ + -H "Content-Type: application/json" \ + -d '{"message": "Welches Spiel ist ausverkauft?"}' + +# Test 2: Halle-Frage +curl -X POST http://localhost:5002/api/chat \ + -H "Content-Type: application/json" \ + -d '{"message": "Was passiert in Halle 3?"}' + +# Test 3: Katzen-Frage (Guard muss durchlassen!) +curl -X POST http://localhost:5002/api/chat \ + -H "Content-Type: application/json" \ + -d '{"message": "Wo finde ich eine Katze?"}' + +# Test 4: Off-Topic (Guard muss blocken) +curl -X POST http://localhost:5002/api/chat \ + -H "Content-Type: application/json" \ + -d '{"message": "Wie wird das Wetter morgen?"}' +``` + +--- + +## Qualitätsregeln + +```bash +# Vor JEDEM Commit: +ruff check . --fix && ruff format . && pytest -v +``` + +- **Commit-Messages:** `feat(chat):` / `feat(whatsapp):` / `feat(telegram):` +- **Docstrings:** Deutsch, Google-Style +- **Typ-Annotationen:** Jede Funktion (Python 3.13, PEP 604) +- **Kein `print()`** → `sys.stderr` für Debug +- **BSN-Blau `#20228a`** für Links in Antworten + +--- + +## Wichtige Hinweise + +1. **Kein Circular Import:** `chat_agent.py` importiert NICHTS aus `app.py`. Nur `sqlite3` + `requests` + `os` + `re`. +2. **Guard NICHT zu streng:** „Katze" ist ein legitimes Brettspiel-Thema (Die Crew, Katze im Sack, etc.). Der Guard soll nur WIRKLICHEN Missbrauch abwehren. +3. **Timeout:** LLM-Call max 15 Sekunden — WhatsApp erwartet schnelle Antwort (< 20s). +4. **Nie 500er:** Alle Chat-Agent-Fehler werden gefangen → immer `return "OK", 200`. +5. **`bsn-secrets` nicht nötig:** Der API-Key kommt aus `~/.hermes/config.yaml` (lokale Datei).