feat(perception): autonomous FSD ad marker learning with zero-latency structural persistence
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user