KI-gestützter Münchener Rathaus-Umschau PDF-Prozessor
Automatisiere die Extraktion und Analyse der offiziellen städtischen Ankündigungen Münchens
Folge @[email protected] auf Mastodon/Fediverse um täglich um 13 Uhr das Ergebnis dieses Workflows zu sehen.
rubot
ist ein leistungsstarkes CLI-Tool, das die Rathaus-Umschau PDFs Münchens in strukturierte, KI-analysierte Daten umwandelt. Perfekt für Journalisten, Forscher und Bürger, die über städtische Entscheidungen und Veranstaltungen informiert bleiben wollen.
- 📄 Automatischer PDF-Download von der offiziellen Münchner Website
- 🔍 Fortschrittliche PDF-Verarbeitung mit Docling (Layout-Analyse, Tabellen-Erkennung)
- 🤖 KI-gestützte Analyse mit OpenRouter (GPT-4, Claude, Gemini, etc.)
- ⚡ Dual-OCR-Engine-Support (EasyOCR + Tesseract) mit Runtime-Auswahl
- 📊 Strukturierte JSON-Ausgabe mit verbesserter Datenextraktion
- 💾 Intelligentes Multi-Level-Caching (PDF + Markdown + Modelle)
- 🔄 Intelligente Wiederholungslogik mit progressiven Verzögerungen für Rate-Limits
- 🛡️ Fallback-Modell-Support für automatische Ausfallsicherheit bei Modellausfällen
- 🐳 Optimierter Docker-Support mit vorinstallierten Modellen für sofortigen Start
- 🔄 Robuste Fehlerbehandlung mit automatischen Fallback-Mechanismen
- 📝 Flexible Konfiguration für verschiedene Anwendungsfälle und Umgebungen
- 🚀 Performance-Optimiert für Produktionsumgebungen
graph LR
A[📄 PDF-Download] --> B[🔍 Docling-Analyse]
B --> C[📝 Markdown-Konvertierung]
C --> D[🤖 KI-Analyse]
D --> E[📊 JSON-Ausgabe]
- 📥 Lädt Rathaus-Umschau PDFs von der offiziellen Münchner Website herunter
- 🔍 Analysiert PDF-Layout und -Struktur mit Docling's fortschrittlicher Dokumentenverarbeitung
- 📝 Konvertiert zu strukturiertem Markdown mit OCR-Unterstützung für Bilder und Tabellen
- 🧠 Analysiert Inhalt mit Ihrer Wahl eines KI-Modells über OpenRouter
- 📤 Gibt strukturiertes JSON mit extrahierten Ankündigungen und Veranstaltungen aus
- 🐍 Python 3.13+
- 🔑 OpenRouter API-Schlüssel (Hier erhalten)
- 💾 2-4GB RAM (für die PDF-Verarbeitung mit Docling und KI-Modellen)
- 🖼️ Tesseract OCR (optional, für bessere Texterkennung in Bildern)
curl -sSL https://raw.githubusercontent.com/rmoriz/rubot/main/scripts/install.sh | bash
Klicken für manuelle Installationsschritte
# Repository klonen
git clone https://github.com/rmoriz/rubot.git
cd rubot
# Virtuelle Umgebung erstellen
python -m venv rubot-env
source rubot-env/bin/activate # Unter Windows: rubot-env\Scripts\activate
# Abhängigkeiten installieren
pip install -e .
rubot verwendet Docling für fortschrittliche PDF-Verarbeitung:
- 🏗️ Layout-Verständnis: Erkennt Abschnitte, Überschriften und Leserichtung automatisch
- 🔍 Überlegene OCR: Dual-Engine-Support (EasyOCR + Tesseract) mit Runtime-Auswahl
- 📊 Tabellen-Extraktion: Strukturierte Extraktion von Tabellendaten und -struktur
- 🖼️ Bild-Verarbeitung: OCR für eingebettete Bilder und Diagramme
- ⚡ Performance-Optimierung: Intelligente Text-Extraktion vs. OCR-Entscheidungen
- 🎯 Produktionsreif: Verwendet von IBM Research, aktiv entwickelt
# OCR Engine (easyocr, tesseract, rapidocr)
export DOCLING_OCR_ENGINE=easyocr
# OCR aktivieren/deaktivieren
export DOCLING_DO_OCR=true
# Tabellen-Strukturerkennung aktivieren (standardmäßig deaktiviert für bessere Performance)
export DOCLING_DO_TABLE_STRUCTURE=false
# Modell-Cache-Verzeichnis
export DOCLING_MODEL_CACHE_DIR=/pfad/zum/modell/cache
Das Docker-Image enthält beide OCR-Engines. Sie können zur Laufzeit zwischen ihnen wählen:
# EasyOCR (Standard) - Bessere Genauigkeit
export DOCLING_OCR_ENGINE=easyocr
docker-compose up
# Tesseract - Schneller, nutzt System-Tesseract
export DOCLING_OCR_ENGINE=tesseract
docker-compose up
OCR Engine Vergleich:
Engine | Vorteile | Nachteile | Startup-Zeit |
---|---|---|---|
EasyOCR | Höhere Genauigkeit, bessere Schrifterkennung | Größere Modelle (~100MB) | ~1.2s |
Tesseract | Schneller Start, etabliert, ressourcenschonend | Geringere Genauigkeit bei komplexen Layouts | ~0.6s |
Beide Engines sind im Docker-Image verfügbar - keine separaten Builds erforderlich!
rubot wurde von PyMuPDF auf Docling migriert für deutlich bessere Ergebnisse:
Aspekt | Vorher (PyMuPDF) | Nachher (Docling) | Verbesserung |
---|---|---|---|
Text-Extraktion | Basis-Textextraktion | Layout-bewusste Analyse | 🚀 Deutlich besser |
Tabellen | Keine Strukturerkennung | Vollständige Tabellen-Analyse | 🆕 Neu verfügbar |
OCR-Engines | Nur Tesseract | EasyOCR + Tesseract | ⚡ Dual-Engine |
Dokumentverständnis | Seitenweise Verarbeitung | Intelligente Layout-Erkennung | 🧠 Viel intelligenter |
Performance | Immer OCR auf allen Seiten | Optimierte OCR-Nutzung | 🚀 Deutlich schneller |
Produktionsreife | Basis-Funktionalität | Enterprise-ready | 🎯 Produktionsreif |
Docling kann Bilder in PDFs auf verschiedene Weise in Markdown umwandeln:
# Bild-Modus konfigurieren
export DOCLING_IMAGE_MODE=placeholder # Optionen: placeholder, embedded, referenced
# Platzhalter für Bilder anpassen
export DOCLING_IMAGE_PLACEHOLDER="<!-- image -->"
Verfügbare Bild-Modi:
placeholder
(Standard): Ersetzt Bilder durch Kommentare (<!-- image -->
)embedded
: Bettet Bilder als Base64-Data-URLs ein (
)referenced
: Erstellt Markdown-Bild-Referenzen (
)
# 🔑 API-Konfiguration (erforderlich)
OPENROUTER_API_KEY=ihr_openrouter_api_schlüssel_hier
DEFAULT_MODEL=ihr_bevorzugtes_modell_hier
# 🛡️ Fallback-Modell (optional, aber empfohlen)
FALLBACK_MODEL=deepseek-r1-0528:free
# 💬 System-Prompt (erforderlich - wählen Sie einen)
DEFAULT_SYSTEM_PROMPT="Analysieren Sie den folgenden Rathaus-Umschau-Inhalt..."
# ODER eine Prompt-Datei verwenden:
# DEFAULT_PROMPT_FILE=prompts/default.txt
Alle verfügbaren Umgebungsvariablen
# 🌐 Netzwerk-Einstellungen
REQUEST_TIMEOUT=120 # PDF-Download-Timeout in Sekunden
OPENROUTER_TIMEOUT=120 # OpenRouter API-Timeout in Sekunden
# 💾 Cache-Einstellungen
CACHE_ENABLED=true # Cache aktivieren/deaktivieren
CACHE_DIR=/tmp/rubot_cache # Benutzerdefinierter Cache-Ordner
CACHE_MAX_AGE_HOURS=24 # Cache-Alter in Stunden
# 🧹 Cache-Cleanup-Einstellungen
CACHE_CLEANUP_DAYS=14 # Cache-Dateien nach N Tagen löschen (0 = deaktivieren)
SKIP_CLEANUP=1 # Automatischen Cache-Cleanup überspringen
# 📄 Verarbeitungseinstellungen
DEFAULT_TEMPERATURE=0.8 # LLM-Temperatur (0.0-1.0)
DEFAULT_MAX_TOKENS=4000 # Maximale Tokens für LLM-Antwort
# 📊 Logging
LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR
# 🔍 Docling-Konfiguration
DOCLING_OCR_ENGINE=easyocr # OCR-Engine (easyocr, tesseract, rapidocr)
DOCLING_DO_OCR=true # OCR aktivieren/deaktivieren
DOCLING_DO_TABLE_STRUCTURE=false # Tabellen-Strukturerkennung (deaktiviert für bessere Performance)
DOCLING_MODEL_CACHE_DIR=/pfad/zum/cache # Modell-Cache-Verzeichnis
DOCLING_IMAGE_MODE=placeholder # Bild-Modus (placeholder, embedded, referenced)
DOCLING_IMAGE_PLACEHOLDER="<!-- image -->" # Platzhalter für Bilder
# 🔇 Python-Warnungen (PyTorch MPS-Warnungen auf macOS unterdrücken)
PYTHONWARNINGS=ignore::UserWarning
# 📅 Heutige Rathaus-Umschau verarbeiten
rubot
# 🗓️ Bestimmtes Datum verarbeiten
rubot --date 2025-07-17
# 💾 In Datei speichern
rubot --date 2025-07-17 --output ergebnis.json
# 🎨 Benutzerdefinierten Prompt und Modell verwenden
rubot --date 2025-07-17 --prompt benutzer_prompt.txt --model gpt-4
# 🧹 Cache-Cleanup nach 7 Tagen
rubot --date 2025-07-17 --cache-cleanup-days 7
# 🚫 Cache-Cleanup überspringen
rubot --date 2025-07-17 --skip-cleanup
Option | Beschreibung | Standard | Umgebungsvariable |
---|---|---|---|
--date |
📅 Datum im JJJJ-MM-TT-Format | heute | - |
--output |
📁 Ausgabedateipfad | stdout | - |
--prompt |
📝 Pfad zur System-Prompt-Datei | - | DEFAULT_PROMPT_FILE |
--model |
🤖 OpenRouter-Modell-ID | - | DEFAULT_MODEL |
--temperature |
🌡️ LLM-Temperatur | 0.8 | DEFAULT_TEMPERATURE |
--max-tokens |
🔢 Maximale Tokens für Antwort | 4000 | DEFAULT_MAX_TOKENS |
--config |
⚙️ Pfad zur Config-Datei | .env | - |
--no-cache |
🚫 Cache deaktivieren | false | CACHE_ENABLED=false |
--cache-dir |
📂 Benutzerdefinierter Cache-Ordner | System-Temp | CACHE_DIR |
--cache-cleanup-days |
🧹 Cache-Dateien nach N Tagen löschen | 14 | CACHE_CLEANUP_DAYS |
--skip-cleanup |
🚫 Cache-Cleanup überspringen | false | SKIP_CLEANUP=1 |
--verbose |
🔍 Debug-Ausgabe aktivieren | false | LOG_LEVEL=DEBUG |
-h/--help |
❓ Hilfemeldung anzeigen | - | - |
--version |
🔢 Versionsnummer anzeigen | - | - |
rubot validiert frühzeitig, ob Prompt-Dateien existieren, bevor der PDF-Download startet:
# ❌ Fehlschlag mit klarer Fehlermeldung (vor PDF-Download)
rubot --prompt /nonexistent/prompt.txt --date 2024-01-15
# Error: Prompt file not found: /nonexistent/prompt.txt
# ❌ Auch für DEFAULT_PROMPT_FILE aus Umgebungsvariablen
DEFAULT_PROMPT_FILE=/missing/prompt.txt rubot --date 2024-01-15
# Error: Prompt file not found: /missing/prompt.txt
# ✅ Funktioniert mit gültiger Prompt-Datei
rubot --prompt prompts/default.txt --date 2024-01-15
# ✅ Oder mit DEFAULT_SYSTEM_PROMPT (keine Datei erforderlich)
DEFAULT_SYSTEM_PROMPT="Analysiere das Dokument..." rubot --date 2024-01-15
Vorteile:
- 🚀 Schneller Fehlschlag: Keine Zeit mit PDF-Downloads verschwendet
- 🐳 Docker-freundlich: Erkennt Volume-Mount-Probleme frühzeitig
- 🔍 Klare Fehlermeldungen: Zeigt genau welche Datei fehlt
rubot implementiert eine intelligente Wiederholungsstrategie, die für OpenRouter API Rate-Limits optimiert ist:
- Sofortiger Wiederholungsversuch (0 Sekunden Verzögerung) - für vorübergehende Netzwerkfehler
- 30 Sekunden warten und wiederholen - erste Rate-Limit-Verzögerung
- 60 Sekunden warten und wiederholen - progressive Verzögerung
- 120 Sekunden warten und wiederholen - letzter Versuch mit primärem Modell
- Fallback-Modell versuchen (falls konfiguriert) - automatische Ausfallsicherheit
Gesamte Wiederholungszeit: ~3,5 Minuten vor Fallback (vs. 30+ Minuten mit festen Verzögerungen)
Konfigurieren Sie ein Backup-Modell für hohe Verfügbarkeit:
# Primäres Modell (erforderlich)
DEFAULT_MODEL=moonshotai/kimi-k2:free
# Fallback-Modell (optional, aber empfohlen)
FALLBACK_MODEL=deepseek-r1-0528:free
Vorteile:
- 🛡️ Ausfallsicherheit: Automatische Ausfallsicherheit bei Ausfall oder Rate-Limiting des primären Modells
- 💰 Kostenoptimierung: Teures primäres Modell, günstiges Fallback verwenden
- 🌐 Anbietervielfalt: Reduzierung der Abhängigkeit von einem einzigen Anbieter
- ⚡ Null Ausfallzeit: Nahtloser Wechsel ohne Benutzereingriff
11:08:00 - Primäres Modell fehlgeschlagen: Rate-Limit überschritten
11:08:00 - Sofortiger Wiederholungsversuch #1 (keine Verzögerung)
11:08:00 - Wiederholung #1 fehlgeschlagen: Rate-Limit überschritten
11:08:00 - Warte 30 Sekunden vor Wiederholung #2...
11:08:30 - Wiederholung #2 fehlgeschlagen: Rate-Limit überschritten
11:08:30 - Warte 60 Sekunden vor Wiederholung #3...
11:09:30 - Wiederholung #3 fehlgeschlagen: Rate-Limit überschritten
11:09:30 - Warte 120 Sekunden vor Wiederholung #4...
11:11:30 - Alle Versuche mit primärem Modell fehlgeschlagen
11:11:30 - Versuche Fallback auf Modell: deepseek-r1-0528:free
11:11:32 - ERFOLG mit Fallback-Modell!
Wichtig für VM-Nutzer: Vermeiden Sie die qemu64
CPU-Architektur in virtuellen Maschinen, da diese PyTorch zum Absturz bringen kann. Weitere Details finden Sie in der Virtualisierungs-Dokumentation.
# Mit Tesseract OCR (schneller Start)
docker run --rm \
-e OPENROUTER_API_KEY=ihr_schlüssel \
-e DEFAULT_MODEL=moonshotai/kimi-k2:free \
-e DOCLING_OCR_ENGINE=tesseract \
-v $(pwd)/output:/app/output \
ghcr.io/rmoriz/rubot:latest \
--date 2024-01-15 --output /app/output/ergebnis.json
# Mit EasyOCR (bessere Genauigkeit)
docker run --rm \
-e OPENROUTER_API_KEY=ihr_schlüssel \
-e DOCLING_OCR_ENGINE=easyocr \
ghcr.io/rmoriz/rubot:latest
✨ Beide OCR-Engines sind im Image verfügbar - wählen Sie zur Laufzeit!
Klicken für docker-compose.yml
version: "3.8"
services:
rubot:
image: ghcr.io/rmoriz/rubot:latest
environment:
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
- DEFAULT_MODEL=${DEFAULT_MODEL:-moonshotai/kimi-k2:free}
- DOCLING_OCR_ENGINE=${DOCLING_OCR_ENGINE:-tesseract}
- CACHE_ENABLED=true
- CACHE_MAX_AGE_HOURS=24
- CACHE_CLEANUP_DAYS=14
volumes:
- ./cache:/app/cache
- ./output:/app/output
- ./models:/app/models # Persistente Modell-Cache
- ./prompts:/app/prompts # Prompt-Dateien mounten
command:
[
"--date",
"2024-01-15",
"--output",
"/app/output/ergebnis.json",
"--prompt",
"/app/prompts/default.txt",
]
rubot funktioniert mit jedem OpenRouter-kompatiblen Modell. Wählen Sie basierend auf Ihren Bedürfnissen:
Modell | Anbieter | Beste für | Kosten |
---|---|---|---|
moonshotai/kimi-k2:free |
Moonshot AI | 📝 Textanalyse, Nachdenken | Kostenlos |
deepseek-r1-0528:free |
DeepSeek | 🎯 Schnell, zuverlässig | Kostenlos |
💡 Tipp: Starten Sie mit dem kostenlosen
moonshotai/kimi-k2:free
für Textanalyse.
📋 Sehen Sie die vollständige Liste unter OpenRouter Models
Das Tool gibt strukturiertes JSON mit extrahierter Information aus:
📋 Beispielausgabe
{
"issue": "134",
"year": "2025",
"id": "2025-07-17",
"summary": "Rathaus-Umschau 134/2025: Sanierung Markt Wiener Platz, Neubau Thomas-Wimmer-Haus in Laim...",
"social_media_post": "# KI-Kommentar zur Rathaus-Umschau 134 vom 17.07.2025...",
"announcements": [
{
"title": "Markt am Wiener Platz wird saniert",
"description": "Großreparatur statt Neubau: 3 Mio € Eigenfinanzierung...",
"category": "construction",
"date": "Ende 2027",
"location": "Wiener Platz, Haidhausen"
}
],
"events": [
{
"title": "Eröffnung naturnaher Pausenhof Guardinistraße 60",
"date": "18. Juli 2025",
"time": "14:00",
"location": "Grund- und Mittelschule Guardinistraße 60",
"description": "Erster naturnaher Pausenhof Münchens mit Bürgermeisterin Dietl"
}
],
"important_dates": [
{
"description": "Akkreditierung für OEZ-Gedenkveranstaltung",
"date": "19. Juli 2025",
"details": "für Medienvertreter*innen"
}
]
}
- 📝 Zusammenfassung: KI-generierter Überblick über das Dokument
- 📢 Ankündigungen: Städtische Entscheidungen, Politikänderungen, öffentliche Bekanntmachungen
- 🎉 Veranstaltungen: Bevorstehende Veranstaltungen, Treffen, öffentliche Versammlungen
- 📊 Metadaten: Verarbeitungsinformationen und Quelldetails
# Alle Tests ausführen
pytest
# Mit Abdeckung ausführen
pytest --cov=rubot --cov-report=html
# Spezifische Testdatei ausführen
pytest tests/test_simple.py -v
# 🧹 Linting
flake8 rubot/
# 🔍 Typ-Überprüfung
mypy rubot/
# ✨ Formatierung
black rubot/
rubot/
├── 🤖 rubot/
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli.py # 🖥️ CLI-Schnittstelle
│ ├── config.py # ⚙️ Konfigurationsverwaltung
│ ├── downloader.py # 📥 PDF-Download
│ ├── llm.py # 🧠 OpenRouter API-Integration
│ ├── cache.py # 💾 Cache-Funktionalität
│ ├── retry.py # 🔄 Wiederholungsmechanismen
│ ├── models.py # 📊 Datenmodelle
│ ├── logger.py # 📝 Logging-Konfiguration
│ └── utils.py # 🛠️ Hilfsfunktionen
├── 🧪 tests/ # Test-Suite
├── 💬 prompts/ # System-Prompt-Vorlagen
└── 📖 docs/ # Dokumentation
Wir heißen Beiträge willkommen! So können Sie loslegen:
- 🍴 Forken Sie das Repository
- 🌿 Erstellen Sie einen Feature-Branch (
git checkout -b feature/amazing-feature
) - ✨ Machen Sie Ihre Änderungen
- 🧪 Hinzufügen Sie Tests für neue Funktionalitäten
- ✅ Stellen Sie sicher, dass alle Tests bestehen
- 📝 Committen Sie Ihre Änderungen (
git commit -m 'Add amazing feature'
) - 🚀 Pushen Sie zum Branch (
git push origin feature/amazing-feature
) - 🎯 Reichen Sie einen Pull-Request ein
- 🌍 Internationalisierung: Unterstützung für andere Sprachen
- 📊 Exportformate: CSV, Excel, XML Ausgabeoptionen
- 🔌 Integrationen: Slack, Discord, E-Mail-Benachrichtigungen
- 🎨 UI: Web-Schnittstelle oder Desktop-App
- 📈 Analytics: Trendanalyse und Berichterstattung
Dieses Projekt ist unter der GNU Affero General Public License v3.0 lizenziert - siehe die LICENSE-Datei für Details.
Dieses Projekt verwendet Docling für die PDF-zu-Markdown-Konvertierung. Docling ist unter der MIT-Lizenz verfügbar.
Docling Modell-Daten: Die in Docker-Images enthaltenen vortrainierten Modelle und Trainingsdaten von Docling sind unter der CDLA-Permissive-2.0 Lizenz lizenziert. Diese Lizenz erlaubt die kommerzielle Nutzung und Weiterverteilung der Modell-Daten.
Gemacht mit ❤️ für die Münchner Community
Wenn Sie rubot nützlich finden, erwägen Sie bitte, ihm einen ⭐ auf GitHub zu geben!