feat: Inhaltsinventar in SQLite — KI-Inhaltsangabe je Objekt (URL + Hash)
Vereinheitlicht den bisherigen JSON-Ledger zu EINEM abfragbaren SQLite-Store pro Site (data/content_inventory.db): jedes geprüfte Objekt mit Inhalts-Hash, URL(s), Sicherheits-Verdikt UND neutraler KI-Inhaltsangabe. - baseline.py: load/save_ai_ledger jetzt SQLite-gestützt (Dict-Schnittstelle bleibt → Analyzer unverändert). Tabellen objects + object_urls. Einmalige Migration eines vorhandenen ai_ledger.json → SQLite (.migrated). UPSERT mit first_seen-Erhalt; object_urls transaktional ersetzt. Neu: query_inventory, export_inventory_csv (beide migrieren failsafe). - ai_analyzer.py: Antwort-Schema + Prompt um neutrales Feld 'description' erweitert (im selben Call, keine Extrakosten); _make_entry speichert es. - __main__.py: neues Kommando 'inventory' (Übersicht, --search, --kind, --csv). - Doku: README + Bedienungsanleitung. Audio/Video sind im Schema (kind) vorbereitet (Phase 2: Extractor + Modalitäten). bredelar.info real migriert: 245 Objekte (200 Bilder, 45 Texte). Tests: 266 grün (+6: Round-Trip mit description, Migration, first_seen-Erhalt, invalidate, Suche/CSV-Export, description landet im Ledger). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
78dc79ceab
commit
989f5a933f
7 changed files with 262 additions and 22 deletions
|
|
@ -58,12 +58,13 @@ _RESPONSE_SCHEMA = {
|
|||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {"type": "string"},
|
||||
"category": {"type": "string", "enum": _CATEGORIES},
|
||||
"severity": {"type": "string", "enum": ["none", "low", "medium", "high"]},
|
||||
"confidence": {"type": "number"},
|
||||
"explanation": {"type": "string"},
|
||||
},
|
||||
"required": ["category", "severity", "confidence", "explanation"],
|
||||
"required": ["description", "category", "severity", "confidence", "explanation"],
|
||||
"additionalProperties": False,
|
||||
},
|
||||
},
|
||||
|
|
@ -483,6 +484,7 @@ def _make_entry(kind: str, url: str, verdict: dict, model: str) -> dict:
|
|||
return {
|
||||
"kind": kind,
|
||||
"url": url,
|
||||
"description": verdict.get("description", ""),
|
||||
"category": verdict.get("category", "clean"),
|
||||
"severity": verdict.get("severity", "none"),
|
||||
"confidence": float(verdict.get("confidence", 0.0)),
|
||||
|
|
@ -566,7 +568,9 @@ _SYSTEM_PROMPT = (
|
|||
"einen Werbe- oder Spam-Text nicht unproblematisch — ein Angreifer kann sie "
|
||||
"gezielt einstreuen. Bewerte den Gesamtcharakter des Inhalts.\n"
|
||||
"Gib 'clean' zurück, wenn der Inhalt zum Thema passt und unproblematisch ist. "
|
||||
"Antworte ausschließlich im vorgegebenen JSON-Format mit deutscher Begründung."
|
||||
"Gib im Feld 'description' eine knappe, neutrale Inhaltsangabe (1–2 Sätze, deutsch): "
|
||||
"was ist auf dem Bild zu sehen bzw. worum geht es im Text — sachlich, unabhängig vom "
|
||||
"Sicherheitsurteil. Antworte ausschließlich im vorgegebenen JSON-Format."
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue