fix: KI-Analyse deckt standardmäßig ALLE Inhalte ab (kein Limit-Risiko)
Das per-Scan-Limit (max_pages/images_per_scan) war ein Sicherheitsrisiko: Inhalte jenseits des Fensters blieben über viele Scans ungeprüft. Eine KI-Bildanalyse ist aber nur sinnvoll, wenn ALLE Bilder geprüft werden. Neu, sauber getrennt: - Geänderte/neue/geflaggte Inhalte werden IMMER sofort geprüft (Echtzeit- Schutz), ungeachtet jeder Drossel — auch wenn das Limit klein ist. - Die Limits drosseln NUR den historischen Altbestand und sind per Default 0 = unbegrenzt → der erste Scan deckt den kompletten Bestand ab. Dank Hash-Cache eine einmalige Ausgabe; Folge-Scans prüfen nur noch Neues. - Positiver Wert bleibt als optionale Drossel nur für sehr große Sites. Tests: 257 grün (+2: geänderte Seite trotz Drossel=1 geprüft; image-Bestand backlog=0 deckt alle Bilder in einem Scan ab). Default-Werte 20/15 → 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6c7e69e635
commit
369a3b8774
5 changed files with 83 additions and 31 deletions
|
|
@ -317,7 +317,10 @@ def _analyze_text(cfg, ai_cfg, api_key, snap, diff, entries, result, router, exe
|
|||
order_fps.append(fp)
|
||||
fp_urls[fp].append(url)
|
||||
|
||||
budget = text_cfg.get("max_pages_per_scan", 20)
|
||||
# Drossel NUR für den historischen Bestand; 0 = unbegrenzt. Geänderte/neue Seiten
|
||||
# werden IMMER geprüft (Echtzeit-Schutz), ungeachtet des Limits.
|
||||
backlog_limit = text_cfg.get("max_pages_per_scan", 0)
|
||||
backlog_used = 0
|
||||
tasks, miss_fps = [], []
|
||||
for fp in order_fps:
|
||||
entry = entries.get(fp)
|
||||
|
|
@ -325,11 +328,14 @@ def _analyze_text(cfg, ai_cfg, api_key, snap, diff, entries, result, router, exe
|
|||
for url in fp_urls[fp]:
|
||||
result["cache_hits"] += 1
|
||||
_maybe_finding(result, entry, fp, url, ai_cfg)
|
||||
elif budget > 0:
|
||||
miss_fps.append(fp)
|
||||
tasks.append((fp, _text_task(fp_text[fp], site_context, models, ai_cfg, api_key, router)))
|
||||
budget -= 1
|
||||
# else: Kostendeckel erreicht — nächster Scan holt den Rest nach
|
||||
continue
|
||||
is_changed = any(u in changed for u in fp_urls[fp])
|
||||
if not is_changed and backlog_limit and backlog_used >= backlog_limit:
|
||||
continue # Bestands-Drossel erreicht — nächster Scan holt den Rest nach
|
||||
miss_fps.append(fp)
|
||||
tasks.append((fp, _text_task(fp_text[fp], site_context, models, ai_cfg, api_key, router)))
|
||||
if not is_changed:
|
||||
backlog_used += 1
|
||||
|
||||
classified = _classify_batch(tasks, executor)
|
||||
dirty = False
|
||||
|
|
@ -379,11 +385,14 @@ def _analyze_images(cfg, ai_cfg, api_key, snap, diff, entries, result, router, e
|
|||
known_img_urls = {e["url"] for e in entries.values() if e.get("kind") == "image"}
|
||||
coverage_urls = current_img_urls - known_img_urls
|
||||
|
||||
# Priorität: geänderte/geflaggte Bilder zuerst, dann mit dem Restbudget Abdeckung aufbauen.
|
||||
# Geänderte/geflaggte Bilder: IMMER prüfen (Echtzeit-Schutz, nie gedeckelt).
|
||||
# Bestands-Abdeckung: Drossel optional; 0 = unbegrenzt (volle Abdeckung im ersten Scan).
|
||||
priority = sorted((changed_img_urls | flagged_img_urls) & current_img_urls)
|
||||
coverage = sorted(coverage_urls - set(priority))
|
||||
budget = img_cfg.get("max_images_per_scan", 15)
|
||||
fetch_urls = (priority + coverage)[:budget]
|
||||
backlog_limit = img_cfg.get("max_images_per_scan", 0)
|
||||
if backlog_limit and backlog_limit > 0:
|
||||
coverage = coverage[:backlog_limit]
|
||||
fetch_urls = priority + coverage
|
||||
if not fetch_urls:
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,9 @@ DEFAULT_CONFIG: dict = {
|
|||
"google/gemini-2.5-flash-lite", # Stufe 3: günstig bezahlt, zuverlässig
|
||||
],
|
||||
"min_chars": 200, # nur Seitentexte ab dieser Größe prüfen
|
||||
"max_pages_per_scan": 20, # Kostendeckel pro Lauf
|
||||
# Drossel NUR für den historischen Bestand; 0 = unbegrenzt (volle Abdeckung im
|
||||
# ersten Scan). Geänderte/neue Seiten werden IMMER geprüft, ungeachtet dieses Werts.
|
||||
"max_pages_per_scan": 0,
|
||||
},
|
||||
"image": {
|
||||
"enabled": True,
|
||||
|
|
@ -128,7 +130,9 @@ DEFAULT_CONFIG: dict = {
|
|||
"nvidia/nemotron-nano-12b-v2-vl:free", # Stufe 2: free, Vision
|
||||
"google/gemini-2.5-flash-lite", # Stufe 3: günstig bezahlt, Vision
|
||||
],
|
||||
"max_images_per_scan": 15,
|
||||
# Drossel NUR für den Bild-Altbestand; 0 = unbegrenzt (volle Abdeckung im ersten
|
||||
# Scan). Geänderte/neue/geflaggte Bilder werden IMMER geprüft, ungeachtet des Werts.
|
||||
"max_images_per_scan": 0,
|
||||
},
|
||||
# Vorbereitet, default aus — Medien sind auf statischen Heimat-Seiten selten.
|
||||
"audio": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue