fix: worker séparé, VLM-first direct Ollama, popup handler hybride, serveur léger

Worker VLM séparé :
- run_worker.py : process distinct du serveur HTTP
- Communication par fichiers (_worker_queue.txt + _replay_active.lock)
- Service systemd rpa-worker.service
- Le serveur HTTP ne charge plus CLIP/VLM (mode léger)
- StreamProcessor._ensure_initialized() désactivé dans le serveur

VLM direct depuis l'agent :
- L'agent appelle Ollama directement (port 11434, LAN)
- Ollama configuré sur 0.0.0.0 (OLLAMA_HOST)
- Pas de passage par le serveur streaming (évite le blocage GIL)
- Fallback serveur supprimé (VLM direct ou STOP)

Popup handler hybride :
- VLM identifie le bouton ("Oui", "OK") — pas de coordonnées
- Template matching localise le texte sur l'écran (PIL + cv2)
- _find_text_on_screen() : rend le texte en image, matchTemplate
- _vlm_identify_popup_button() : prompt simple, prefill texte

Resolve visuel hybride :
- Cascade : template anchor → VLM+template texte → VLM direct (legacy)
- _hybrid_vlm_resolve() : VLM identifie + template localise
- _template_match_anchor() : match direct crop, seuil 0.80
- Seuil strict 0.90 pour template matching en mode replay

Analyse VLM temps réel désactivée :
- process_screenshot() ne fait plus de VLM (stockage uniquement)
- L'analyse est différée au worker séparé
- Le serveur HTTP reste réactif en permanence

VLM prefill fix :
- num_ctx augmenté (2048 → 8192 pour images 1080p)
- bbox_2d au lieu de click_point (plus fiable)
- Coordonnées 0-1000 (format natif qwen3-vl)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-03-26 12:52:40 +01:00
parent d5deac3029
commit c2dc8f8fe4
3 changed files with 590 additions and 57 deletions

View File

@@ -798,11 +798,13 @@ async def stream_image(
with _pending_lock:
_analyzed_shots[session_id].add(shot_id)
# Screenshots full : analyse GPU dans un thread séparé (ne bloque pas l'event loop)
with _pending_lock:
_pending_analyses[session_id] += 1
_gpu_executor.submit(_process_screenshot_thread, session_id, shot_id, file_path_str)
return {"status": "image_queued", "shot_id": shot_id}
# Screenshots full : STOCKAGE UNIQUEMENT (pas d'analyse VLM en temps réel)
# L'analyse VLM est faite par le worker séparé (run_worker.py) après
# finalisation de la session. Cela évite de bloquer le serveur HTTP
# (le GIL Python bloque tout quand le VLM tourne dans un thread).
# Le screenshot est déjà sauvegardé sur disque par le session_manager.
logger.debug(f"Screenshot {shot_id} stocké (analyse VLM différée au worker)")
return {"status": "image_stored", "shot_id": shot_id}
def _process_screenshot_thread(session_id: str, shot_id: str, path: str):