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

6.4 KiB
Raw Blame History

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


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

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:

# 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

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.pytelegram_intake() (Zeilen 172215).

Wo einbauen: Nachdem die Nachricht aus dem Telegram-Update extrahiert wurde.

Logik: Gleiche wie WhatsApp:

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

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:

# 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

# 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).