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
|
|
@ -103,6 +103,23 @@ class TestFormatBody:
|
|||
body = _format_body(_report("yellow"))
|
||||
assert "python -m scanner" in body
|
||||
|
||||
def test_ai_finding_includes_url_and_reason(self):
|
||||
"""Beanstandete Dateien müssen mit URL und Begründung im Body stehen."""
|
||||
rep = _report("yellow")
|
||||
rep["ai_result"] = {
|
||||
"checked": 1, "cache_hits": 0, "api_calls": 1, "skipped": None,
|
||||
"findings": [{
|
||||
"kind": "image", "url": "https://x.de/galerie",
|
||||
"asset_url": "https://x.de/img/bad.jpg", "fingerprint": "a1b2c3d4",
|
||||
"category": "pornography", "severity": "high", "confidence": 0.95,
|
||||
"explanation": "Explizite Darstellung, passt nicht zum Thema.",
|
||||
}],
|
||||
}
|
||||
body = _format_body(rep)
|
||||
assert "https://x.de/img/bad.jpg" in body # URL der Datei
|
||||
assert "Explizite Darstellung" in body # Begründung
|
||||
assert "ai-dismiss --hash a1b2c3d4" in body # Quittier-Hinweis
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# send_alert — level filtering
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue