Skip to content

Latest commit

 

History

History
486 lines (367 loc) · 11.7 KB

File metadata and controls

486 lines (367 loc) · 11.7 KB

Screen-Change-Gate Integration Guide

Feature: Vision Stability System v1.0 Status: ✅ Production Ready Datum: 2026-02-01


🎯 Überblick

Das Screen-Change-Gate wurde dynamisch in alle Agents integriert. Es ist:

  • Opt-In: Muss aktiviert werden (ENV Variable)
  • Nicht-invasiv: Bestehende Agents funktionieren unverändert
  • Performance: 70-95% weniger Vision-Calls
  • Immer einsatzbereit: Einmal aktivieren, überall nutzen

⚙️ Aktivierung

Schritt 1: ENV Variable setzen

In .env:

# Vision Stability System v1.0
USE_SCREEN_CHANGE_GATE=true    # Aktivieren

Optionen:

  • true = Screen-Change-Gate aktiv (empfohlen)
  • false = Deaktiviert (Standard, für Backward-Compatibility)

Schritt 2: MCP-Server neustarten

python server/mcp_server.py

Erwartete Ausgabe:

✅ Screen-Change-Detector v1.0 registriert
✅ Screen Contract Tool v1.0 registriert

Bei Agent-Start:

✅ Screen-Change-Gate AKTIV für VisualAgent
✅ Screen-Change-Gate AKTIV für ExecutorAgent

📊 Welche Agents profitieren?

Agent Profitiert? Warum?
VisualAgent ✅✅✅ Massiv! Macht bei jeder Iteration Screenshot
ExecutorAgent ✅ Ja Bei Vision-Tool-Aufrufen
CreativeAgent ⚠️ Teilweise Nur bei Bild-Analysen
DeepResearchAgent ❌ Nein Nutzt keine Vision
DeveloperAgent ❌ Nein Nutzt keine Vision
ReasoningAgent ❌ Nein Nutzt keine Vision

🔧 Wie es funktioniert

Automatische Integration in BaseAgent

Alle Agents erben von BaseAgent, welche jetzt Screen-Change-Gate Support hat:

class BaseAgent:
    def __init__(self, ...):
        # ... (bestehender Code)

        # NEU: Screen-Change-Gate Support
        self.use_screen_change_gate = os.getenv("USE_SCREEN_CHANGE_GATE", "false").lower() == "true"
        self.cached_screen_state: Optional[Dict] = None
        self.last_screen_analysis_time: float = 0

        if self.use_screen_change_gate:
            log.info(f"✅ Screen-Change-Gate AKTIV für {self.__class__.__name__}")

Neue Helper-Methoden

1. _should_analyze_screen(roi, force)

Prüft ob Screen-Analyse nötig ist.

# Beispiel: Vor Vision-Call prüfen
should_analyze = await self._should_analyze_screen()

if should_analyze:
    # Screen hat sich geändert - analysiere
    screenshot = await self._get_screenshot()
else:
    # Screen unverändert - nutze Cache (70-95% der Fälle!)
    screenshot = self.cached_screenshot

Parameter:

  • roi (Optional): Region of Interest - nur bestimmten Bereich prüfen
  • force (bool): Analyse erzwingen (Gate überspringen)

Returns:

  • True = Analyse nötig
  • False = Cache nutzen

2. _get_screen_state(screen_id, anchor_specs, element_specs, force_analysis)

Holt ScreenState mit Screen-Change-Gate Optimization.

# Beispiel: ScreenState holen (mit Cache)
state = await self._get_screen_state(
    screen_id="login_screen",
    anchor_specs=[
        {"name": "logo", "type": "text", "text": "MyApp"}
    ],
    element_specs=[
        {"name": "username", "type": "text_field", "text": "Benutzername"},
        {"name": "login_btn", "type": "button", "text": "Anmelden"}
    ]
)

if state:
    # Nutze ScreenState
    elements = state.get("elements", [])
    # ...

Parameter:

  • screen_id: Screen-Identifikator
  • anchor_specs: Anker-Spezifikationen (Liste von Dicts)
  • element_specs: Element-Spezifikationen (Liste von Dicts)
  • force_analysis: Analyse erzwingen (Cache überspringen)

Returns:

  • Dict = ScreenState
  • None = Fehler

💡 Beispiel: VisualAgent (bereits integriert!)

Vorher (ohne Screen-Change-Gate):

async def run(self, task: str) -> str:
    for _ in range(self.max_iterations):
        # IMMER Screenshot machen (teuer!)
        screenshot = await self._get_screenshot_as_base64()
        # ...

Nachher (mit Screen-Change-Gate):

async def run(self, task: str) -> str:
    for iteration in range(self.max_iterations):
        # NEU: Screen-Change-Gate
        if iteration > 0 and self.use_screen_change_gate:
            should_analyze = await self._should_analyze_screen()
            if not should_analyze:
                # Screen unverändert - überspringe Screenshot!
                continue

        # Nur bei Änderung Screenshot machen
        screenshot = await self._get_screenshot_as_base64()
        # ...

Ergebnis:

  • Ohne Gate: 20 Screenshots bei 20 Iterationen
  • Mit Gate: ~2-4 Screenshots bei 20 Iterationen
  • Ersparnis: 80-90%!

🚀 Eigene Integration (Custom Agent)

Beispiel 1: Vor Vision-Tool-Aufruf

class MyCustomAgent(BaseAgent):
    async def run(self, task: str) -> str:
        # ...

        # Vor Vision-Analyse prüfen
        if self.use_screen_change_gate:
            should_analyze = await self._should_analyze_screen()
            if not should_analyze:
                # Nutze gecachte Daten
                vision_data = self.cached_vision_data
            else:
                # Neue Analyse
                vision_data = await self._call_tool("describe_screen_with_moondream")
                self.cached_vision_data = vision_data
        else:
            # Gate deaktiviert - immer analysieren
            vision_data = await self._call_tool("describe_screen_with_moondream")

        # ...

Beispiel 2: Mit ScreenState arbeiten

class NavigationAgent(BaseAgent):
    async def navigate_to_element(self, element_name: str):
        # ScreenState holen (mit Cache!)
        state = await self._get_screen_state(
            screen_id="current_screen",
            element_specs=[
                {"name": element_name, "type": "button"}
            ]
        )

        if not state:
            return "Screen-Analyse fehlgeschlagen"

        # Element finden
        elements = state.get("elements", [])
        target = next((e for e in elements if e["name"] == element_name), None)

        if target:
            # Klicken
            await self._call_tool("click_at", {
                "x": target["x"],
                "y": target["y"]
            })

Beispiel 3: ROI für spezifischen Bereich

# Nur Formular-Bereich überwachen
roi = {"x": 100, "y": 200, "width": 600, "height": 400}

if self.use_screen_change_gate:
    should_analyze = await self._should_analyze_screen(roi=roi)
    # ...

📈 Performance-Metriken tracken

Screen-Change-Stats abrufen

# In deinem Agent
stats = await self._call_tool("get_screen_change_stats")

log.info(f"Cache-Hit-Rate: {stats['cache_hit_rate'] * 100}%")
log.info(f"Ersparnis: {stats['savings_estimate']}")
log.info(f"Avg Check-Zeit: {stats['avg_check_time_ms']}ms")

Beispiel-Output:

Cache-Hit-Rate: 90%
Ersparnis: 90% Vision-Calls gespart
Avg Check-Zeit: 23ms

Detector zurücksetzen (bei Screen-Wechsel)

# Wenn du weißt, dass sich der Screen komplett geändert hat
# (z.B. neue App geöffnet)
await self._call_tool("reset_screen_detector")

Threshold anpassen (Sensitivität)

# Sehr sensitiv (kleinste Änderungen)
await self._call_tool("set_change_threshold", {"threshold": 0.0001})

# Normal (empfohlen)
await self._call_tool("set_change_threshold", {"threshold": 0.001})

# Weniger sensitiv (nur große Änderungen)
await self._call_tool("set_change_threshold", {"threshold": 0.01})

🧪 Testing

Test 1: Ist Screen-Change-Gate aktiv?

# Test-Script
import os
from agent.timus_consolidated import ExecutorAgent

# ENV Variable setzen
os.environ["USE_SCREEN_CHANGE_GATE"] = "true"

# Agent erstellen
agent = ExecutorAgent("test tools")

# Prüfen
if agent.use_screen_change_gate:
    print("✅ Screen-Change-Gate ist AKTIV")
else:
    print("❌ Screen-Change-Gate ist INAKTIV")

Test 2: Cache-Hit-Rate messen

# Führe Navigation aus
await agent.run("Navigiere zu Element X")

# Stats abrufen
stats = await agent._call_tool("get_screen_change_stats")

print(f"Cache-Hit-Rate: {stats['cache_hit_rate'] * 100}%")
print(f"Total Checks: {stats['total_checks']}")
print(f"Changes Detected: {stats['changes_detected']}")

# Erwartung: Cache-Hit-Rate > 70%
assert stats['cache_hit_rate'] > 0.7, "Cache-Hit-Rate zu niedrig!"

⚠️ Troubleshooting

Problem: Screen-Change-Gate wird nicht aktiviert

Symptom:

# Kein Log beim Agent-Start

Lösung:

  1. Prüfe .env:

    grep USE_SCREEN_CHANGE_GATE .env
    # Sollte: USE_SCREEN_CHANGE_GATE=true
  2. MCP-Server neustarten:

    python server/mcp_server.py
  3. Agent-Logs prüfen:

    # Sollte sehen:Screen-Change-Gate AKTIV für VisualAgent

Problem: Cache-Hit-Rate zu niedrig (<50%)

Symptom:

Cache-Hit-Rate: 20%

Mögliche Ursachen:

  1. Screen ändert sich tatsächlich oft (z.B. Animationen, Live-Updates)
  2. Threshold zu niedrig (zu sensitiv)

Lösungen:

  1. ROI nutzen - Nur stabilen Bereich überwachen:

    roi = {"x": 100, "y": 200, "width": 600, "height": 400}
    should_analyze = await self._should_analyze_screen(roi=roi)
  2. Threshold erhöhen - Weniger sensitiv:

    await self._call_tool("set_change_threshold", {"threshold": 0.01})
  3. Animationen deaktivieren - Falls möglich


Problem: Tool "should_analyze_screen" nicht gefunden

Symptom:

Error: Method 'should_analyze_screen' not found

Lösung: MCP-Server hat Tools nicht geladen.

  1. Prüfe server/mcp_server.py - Tools sollten in TOOL_MODULES sein:

    TOOL_MODULES = [
        # ...
        "tools.screen_change_detector.tool",
        "tools.screen_contract_tool.tool",
    ]
  2. MCP-Server neustarten

  3. Bei Start solltest du sehen:

    ✅ Screen-Change-Detector v1.0 registriert
    ✅ Screen Contract Tool v1.0 registriert
    

📚 Weitere Ressourcen

  • Vollständige Doku: tools/VISION_SYSTEM_GUIDE.md
  • Quick-Start: VISION_STABILITY_QUICKSTART.md
  • Entwicklungs-Historie: DEVELOPMENT_HISTORY_VISION_STABILITY.md
  • Tests: test_vision_stability.py

🎯 Best Practices

DO:

  1. Screen-Change-Gate für Vision-intensive Agents aktivieren

    USE_SCREEN_CHANGE_GATE=true
  2. ROI für spezifische Bereiche nutzen

    roi = {"x": 100, "y": 200, "width": 600, "height": 400}
    await self._should_analyze_screen(roi=roi)
  3. Performance-Stats regelmäßig loggen

    stats = await self._call_tool("get_screen_change_stats")
    log.info(f"Cache-Hit-Rate: {stats['cache_hit_rate']}")
  4. Detector nach großen Screen-Änderungen zurücksetzen

    # Nach App-Wechsel, Window-Resize, etc.
    await self._call_tool("reset_screen_detector")

DON'T:

  1. Nicht mit force=True missbrauchen

    # ❌ Schlecht - Gate immer bypassen
    await self._should_analyze_screen(force=True)
  2. Nicht ohne Fehlerbehandlung

    # ❌ Schlecht - kein Error-Handling
    should_analyze = await self._should_analyze_screen()
    
    # ✅ Gut - mit Error-Handling
    try:
        should_analyze = await self._should_analyze_screen()
    except Exception as e:
        log.warning(f"Screen-Change-Gate Error: {e}")
        should_analyze = True  # Fallback
  3. Nicht für non-vision Agents aktivieren

    # ❌ Overhead ohne Nutzen
    # ReasoningAgent braucht kein Screen-Change-Gate

Version: 1.0 Datum: 2026-02-01 Status: ✅ Production Ready

Die Integration ist dynamisch und immer einsatzbereit! 🚀