Files
BSN-Chatsystem/docs/alicia-aufgaben-chat-agent.md
T
Hermes Agent 2fd3b7b887
Quality Gate / 🛡️ Lint + Type Check + Tests (push) Failing after 12m34s
docs: Alicia-Aufgaben für Chat-Agent (Guard + RAG für WhatsApp/Telegram)
2026-06-25 10:33:04 +02:00

185 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 40224310) 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 52935317)
Alternativ: `webhook_queue.py``telegram_intake()` (Zeilen 172215).
**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).