feat: KI-gestützte Inhaltsanalyse via OpenRouter (hash-gegated)
Optionale semantische Prüfung von Text und Bildern (inkl. OCR) auf problematische Inhalte ohne Link-Signal: Pornografie, Propaganda, diffamierende/strafbare Texte, versteckter Spam, themenfremde Werbung, widersprüchliche Aussagen. Bewertet die thematische Passung zum deklarierten site_context — eingestreute Heimat-Begriffe täuschen die Erkennung nicht. Kern: - scanner/ai_analyzer.py: run_ai_analysis + score_ai_findings. Hash-Gate über data/ai_ledger.json → unveränderte Inhalte = Cache- Treffer = kein API-Call. Nur neue/geänderte Inhalte kosten etwas. - Modell-Kette mit zweifacher Eskalation (Stufe 1+2 free, Stufe 3 günstig bezahlt); eskaliert bei Fehler ODER Timeout (attempt_timeout). Erfolgreiches Modell wird im Ledger vermerkt. - KI-Funde sind auf GELB gedeckelt — ROT bleibt harten Integritäts- Signalen vorbehalten. Graceful degradation: ohne Key/bei Fehler wird übersprungen, Scan läuft unverändert weiter. Integration: - baseline.py: load/save_ai_ledger, dismiss_ai_entries. - config.py: ai_analysis-Block + ai_* Scoring-Schlüssel. - __main__.py: Einhängung in cmd_scan/cmd_check, ai-dismiss-Subcommand, approve quittiert zugehörige Funde, status-Anzeige, diff-only + report. - alerter.py + __main__.py: beanstandete Dateien erscheinen mit URL, Begründung und Quittier-Fingerprint in E-Mail UND Markdown-Report. - plain.py: laienverständliche KI-Sätze. API-Key nur aus Umgebungsvariable (OPENROUTER_API_KEY). Audio/Video als abschaltbare Hooks vorbereitet (default aus). Modelle live gegen OpenRouter verifiziert; Demo auf bredelar.info zeigte korrekte Erkennung (echter Inhalt clean, eingeschleuster Casino-Spam mit Heimat-Begriffen als hidden_spam erkannt). Tests: 227 grün (+26 für ai_analyzer, +1 für E-Mail-KI-Abschnitt). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
0aaf53135a
commit
cae3dbb985
11 changed files with 1301 additions and 7 deletions
79
README.md
79
README.md
|
|
@ -59,6 +59,7 @@ dafür **nichts** extra einzurichten — ein täglicher Aufruf genügt für alle
|
|||
| `report --diff-only` | Nur Textdiffs geänderter Seiten (farbig, kompakt) |
|
||||
| `status` | Baseline-Datum, letzter Scan, Risiko-Level |
|
||||
| `test-alert` | Test-E-Mail senden, ohne echten Scan (SMTP-Check) |
|
||||
| `ai-dismiss --all` | KI-Funde als geprüft/akzeptiert quittieren (Fehlalarm) |
|
||||
|
||||
Alle Befehle akzeptieren `--config path/to/config.yaml` und `--verbose`.
|
||||
|
||||
|
|
@ -219,6 +220,84 @@ Nach dem ersten `init` alle legitimen externen Domains in
|
|||
|
||||
---
|
||||
|
||||
## KI-Inhaltsanalyse (optional)
|
||||
|
||||
Der Integritäts-Kern erkennt strukturelle Manipulationen (fremde Links, Hidden Content,
|
||||
Webshells). Die optionale KI-Analyse ergänzt ihn um **semantische** Prüfung von Text und
|
||||
Bildern: Pornografie, Propaganda, diffamierende/strafbare Inhalte, versteckter Spam,
|
||||
thematisch unpassende Werbung, widersprüchliche Aussagen — auch ohne Link-Signal und
|
||||
inklusive Text in Bildern (OCR).
|
||||
|
||||
**Kostengate:** Jeder Inhalt bekommt einen Hash. Unveränderte Inhalte liegen mit ihrem
|
||||
Verdikt im Cache (`data/ai_ledger.json`) → **kein API-Call**. Nur neue oder geänderte
|
||||
Inhalte lösen eine (günstige) OpenRouter-Abfrage aus. Dadurch läuft die Analyse bei jedem
|
||||
Scan mit und kostet an den meisten Tagen 0 €.
|
||||
|
||||
KI-Funde sind **auf Gelb gedeckelt** — sie lösen nie allein ROT aus (das bleibt harten
|
||||
Integritäts-Signalen vorbehalten). Fehlt der API-Key oder schlägt eine Abfrage fehl, wird
|
||||
die Analyse übersprungen und der Scan läuft unverändert weiter.
|
||||
|
||||
### Aktivieren
|
||||
|
||||
In `config.yaml`:
|
||||
```yaml
|
||||
ai_analysis:
|
||||
enabled: true
|
||||
api_key_env: "OPENROUTER_API_KEY"
|
||||
site_context: "Heimat- und Vereinswebsite über die Bergbaugeschichte in Bredelar."
|
||||
ai_confidence_min: 0.7
|
||||
attempt_timeout: 30 # Zeitlimit je Modell-Versuch → eskaliert bei Langsamkeit
|
||||
text:
|
||||
enabled: true
|
||||
models: # Kette: Stufe 1+2 free, Stufe 3 günstig bezahlt
|
||||
- "qwen/qwen3-next-80b-a3b-instruct:free"
|
||||
- "meta-llama/llama-3.3-70b-instruct:free"
|
||||
- "google/gemini-2.5-flash-lite"
|
||||
image:
|
||||
enabled: true
|
||||
models: # multimodal: Inhalt + OCR
|
||||
- "google/gemma-4-31b-it:free"
|
||||
- "nvidia/nemotron-nano-12b-v2-vl:free"
|
||||
- "google/gemini-2.5-flash-lite"
|
||||
```
|
||||
|
||||
Die Modelle werden als **Kette mit zweifacher Eskalation** abgearbeitet: Stufe 1 und 2 sind
|
||||
kostenlose Modelle, Stufe 3 ein günstiges Bezahlmodell. Schlägt ein Modell fehl oder antwortet
|
||||
es langsamer als `attempt_timeout`, wird automatisch zur nächsten Stufe eskaliert. Im Report
|
||||
und Ledger wird festgehalten, welche Stufe das Verdikt geliefert hat.
|
||||
|
||||
`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.
|
||||
|
||||
API-Key als Umgebungsvariable setzen (nie in config.yaml):
|
||||
```bash
|
||||
export OPENROUTER_API_KEY="sk-or-..."
|
||||
```
|
||||
|
||||
### Fehlalarm quittieren
|
||||
|
||||
Stuft die KI legitimen Inhalt fälschlich als auffällig ein:
|
||||
```bash
|
||||
python -m scanner https://ihre-website.de ai-dismiss --all # alle offenen Funde
|
||||
python -m scanner https://ihre-website.de ai-dismiss --hash <fingerprint>
|
||||
```
|
||||
Ein `approve --all` / `--url` quittiert die zugehörigen KI-Funde automatisch mit.
|
||||
|
||||
### Modelle (OpenRouter)
|
||||
|
||||
Pro Modalität eine Kette mit zweifacher Eskalation (Stufe 1+2 free, Stufe 3 bezahlt):
|
||||
|
||||
| Zweck | Stufe 1 (free) | Stufe 2 (free) | Stufe 3 (bezahlt) |
|
||||
|---|---|---|---|
|
||||
| Text/Semantik | `qwen3-next-80b-a3b-instruct:free` | `llama-3.3-70b-instruct:free` | `gemini-2.5-flash-lite` |
|
||||
| Bild + OCR | `gemma-4-31b-it:free` | `nemotron-nano-12b-v2-vl:free` | `gemini-2.5-flash-lite` |
|
||||
|
||||
Audio/Video sind als abschaltbare Hooks vorbereitet (`ai_analysis.audio/video`,
|
||||
default aus).
|
||||
|
||||
---
|
||||
|
||||
## Verzeichnisstruktur
|
||||
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue