feat: adaptiver Modell-Router (Circuit-Breaker) + parallele KI-Analyse

Der reale Erst-Scan dauerte ~10 min, weil pro Kandidat sequenziell erst die
rate-limited Free-Modelle (429) probiert wurden. Zwei Hebel beheben das:

1. ModelRouter: programmatische Telemetrie statt LLM-Orchestrator. Pro Modell
   Erfolg/Latenz; ausgefallene/rate-limited Modelle bekommen per Circuit-Breaker
   einen Cooldown und werden übersprungen, das schnellste gesunde Modell zuerst.
   Failsafe-Pruning toter Slugs über OpenRouter /models (24h-Cache). State
   persistent in data/ai_router_state.json.

2. Parallelisierung: ThreadPoolExecutor mit konfigurierbarer max_concurrency
   (Default 8, I/O-gebunden → an API-Rate-Limits gebunden, nicht an CPU-Kerne).
   Klassifikationen laufen nebenläufig, Merge im Hauptthread (keine Locks),
   findings deterministisch sortiert. Fingerprint-Gruppierung: identischer
   Inhalt wird nur einmal klassifiziert, Funde aber für alle URLs emittiert.

Realtest bredelar.info: Frisch-Scan von ~10 min auf 1:01 min; Breaker öffnete
14× (Free-Modelle übersprungen), alle Verdikte von gemini-2.5-flash-lite.

Config: max_concurrency, breaker_failure_threshold, breaker_cooldown_seconds,
refresh_models. Tests: 251 grün (+12: Router-Reihung/Breaker/Pruning-failsafe,
parallel==sequenziell, Dedup, deterministische Reihenfolge).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-13 02:51:30 +02:00
commit 125d80e7f9
7 changed files with 415 additions and 65 deletions

View file

@ -274,6 +274,13 @@ kostenlose Modelle, Stufe 3 ein günstiges Bezahlmodell. Schlägt ein Modell feh
es langsamer als `attempt_timeout`, wird automatisch zur nächsten Stufe eskaliert. Im Report
und Ledger wird festgehalten, welche Stufe das Verdikt geliefert hat.
Ein **adaptiver Router** lernt während des Laufs, welche Modelle funktionieren: rate-limited oder
ausgefallene Modelle werden per Circuit-Breaker (`breaker_*`) für eine Cooldown-Zeit übersprungen,
das schnellste gesunde Modell zuerst probiert, und tote Slugs über OpenRouter `/models`
(`refresh_models`) failsafe aussortiert. Mehrere Inhalte werden **parallel** geprüft
(`max_concurrency`, Default 8) — die Stellgröße ist an die API-Rate-Limits gebunden, nicht an
CPU-Kerne. Das beschleunigt vor allem den Erst-Scan einer Site erheblich.
`site_context` ist entscheidend: Die KI bewertet die **thematische Passung** zur
deklarierten Beschreibung, nicht einzelne Schlüsselwörter — eingestreute Heimat-Begriffe
machen Spam so nicht unauffällig.