feat(perception): autonomous FSD ad marker learning with zero-latency structural persistence

This commit is contained in:
2026-04-29 21:25:03 +02:00
parent a560225dc9
commit ca91ae4b33
2 changed files with 63 additions and 0 deletions

View File

@@ -68,6 +68,10 @@ class ResonanceEvaluatorPlugin(BehaviorPlugin):
else:
if vibe.get("is_ad"):
logger.info("🛡️ [Resonance Oracle] Visually identified post as an Ad! Skipping...")
marker = vibe.get("ad_marker_text")
if marker and marker.strip():
from GramAddict.core.utils import learn_ad_marker
learn_ad_marker(marker, ctx.context_xml)
from GramAddict.core.utils import humanized_scroll
humanized_scroll(ctx.device)
return BehaviorResult(executed=True, should_skip=True)

View File

@@ -1,4 +1,6 @@
import logging
import json
import os
import random
from time import sleep
@@ -95,6 +97,62 @@ def get_value(count, name, default=0):
return default
_LEARNED_AD_MARKERS_FILE = os.path.join(os.getcwd(), "learned_ad_markers.json")
_LEARNED_AD_MARKERS_CACHE = None
def get_learned_ad_markers() -> set:
global _LEARNED_AD_MARKERS_CACHE
if _LEARNED_AD_MARKERS_CACHE is not None:
return _LEARNED_AD_MARKERS_CACHE
if os.path.exists(_LEARNED_AD_MARKERS_FILE):
try:
with open(_LEARNED_AD_MARKERS_FILE, "r") as f:
_LEARNED_AD_MARKERS_CACHE = set(json.load(f))
except Exception as e:
logger.error(f"Failed to load learned ad markers: {e}")
_LEARNED_AD_MARKERS_CACHE = set()
else:
_LEARNED_AD_MARKERS_CACHE = set()
return _LEARNED_AD_MARKERS_CACHE
def learn_ad_marker(marker: str, xml_hierarchy: str):
global _LEARNED_AD_MARKERS_CACHE
if not marker or len(marker) > 30:
return
marker = marker.strip().lower()
# Structural verification: the VLM-suggested marker MUST exist as an exact node text/desc in the current UI!
import xml.etree.ElementTree as ET
try:
root = ET.fromstring(xml_hierarchy)
found_in_ui = False
for node in root.iter("node"):
text = node.attrib.get("text", "").strip().lower()
desc = node.attrib.get("content-desc", "").strip().lower()
if text == marker or desc == marker:
found_in_ui = True
break
if not found_in_ui:
logger.debug(f"🧠 [Autonomous FSD] Rejected hallucinated Ad marker '{marker}' (not found as exact node match in UI).")
return
except Exception:
return
markers = get_learned_ad_markers()
if marker not in markers and marker not in {"ad", "sponsored", "advertisement", "gesponsert", "anzeige", "werbung"}:
markers.add(marker)
logger.info(f"🧠 [Autonomous FSD] Verified and Learned new Ad marker: '{marker}'. Persisting for zero-latency detection.", extra={"color": f"{Style.BRIGHT}{Fore.GREEN}"})
try:
with open(_LEARNED_AD_MARKERS_FILE, "w") as f:
json.dump(list(markers), f)
except Exception as e:
logger.error(f"Failed to save learned ad markers: {e}")
def is_ad(xml_hierarchy: str, cognitive_stack: dict = None) -> bool:
"""
Checks if the current view contains an advertisement using autonomous learning.
@@ -125,6 +183,7 @@ def is_ad(xml_hierarchy: str, cognitive_stack: dict = None) -> bool:
# Standalone label patterns: match only when the text/desc IS the ad marker,
# not when "ad" appears inside longer phrases like "Create messaging ad"
AD_EXACT_LABELS = {"ad", "sponsored", "advertisement", "gesponsert", "anzeige", "werbung"}
AD_EXACT_LABELS.update(get_learned_ad_markers())
try:
root = ET.fromstring(xml_hierarchy)