feat(p1x): de-hardcode VLM models/endpoints to vlm_config (DGX-ready)

Migre les call-sites VLM serveur vers la configuration centrale pour
fonctionner sur DGX (tunnel Ollama 11434), où gemma4:* est absent et le
port Docker 11435 est mort.

- task_planner, replay_verifier, domain_context, ir_builder, resolve_engine
  (popup): modele -> vlm_config.get_vlm_model(), defaut 11435 -> 11434
  (override GEMMA4_PORT legacy conserve)
- resolve_engine (grounding bbox x2): nouvel helper
  vlm_config.get_bbox_grounding_model() (var dediee RPA_BBOX_GROUNDING_MODEL,
  fallback RPA_GROUNDING_MODEL puis qwen2.5vl:7b-rpa) -> desambiguise le
  conflit D5-v3b, bbox_2d + num_ctx 4096 preserves
- safety_checks_provider: defaut -> get_vlm_model(), override
  RPA_SAFETY_CHECKS_LLM_MODEL preserve
- ui_detector: default_factory + resolution lazy (corrige aussi un gel a
  l'import), pas d'appel reseau a l'import
- field_extractor: property lazy via vlm_config

TDD strict (RED->GREEN), 305 tests verts, tests mockes HTTP (zero dependance
DGX reel), aucun alias Ollama.

Hors perimetre (arbitrage Dom): client Lea agent_v1/executor.py (gele),
chemin V4 observe_reason_act (RPA_REASONING_MODEL), core/config.py defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-06-03 14:06:03 +02:00
parent 4e7c2a7628
commit 4dc7d840d6
21 changed files with 739 additions and 37 deletions

View File

@@ -27,6 +27,7 @@ from typing import Any, Dict, List, Optional
from pydantic import BaseModel
from core.grounding.bbox_parser import parse_bbox_to_norm, parse_bbox_to_norm_validated
from core.detection import vlm_config
logger = logging.getLogger("api_stream")
@@ -878,8 +879,8 @@ def _resolve_by_grounding(
) -> Optional[Dict[str, Any]]:
"""Résoudre une cible via grounding VLM direct.
Le modèle VLM (gemma4:e4b par défaut, configurable via RPA_VLM_MODEL)
reçoit le screenshot + une description textuelle et retourne
Le modèle de grounding bbox (résolu via vlm_config.get_bbox_grounding_model,
défaut qwen2.5vl:7b-rpa) reçoit le screenshot + une description et retourne
directement les coordonnées de l'élément. Pas de SomEngine,
pas de numérotation — le VLM fait du grounding UI natif.
@@ -944,7 +945,9 @@ def _resolve_by_grounding(
# Le grounding nécessite un modèle entraîné pour les coordonnées (bbox_2d).
# Qwen2.5-VL est le seul qui retourne des positions précises.
# gemma4 comprend les images mais ne sait pas localiser en coordonnées.
_grounding_model = os.environ.get("RPA_GROUNDING_MODEL", "qwen2.5vl:7b")
# D5-v3b : résolution via helper dédié (var RPA_BBOX_GROUNDING_MODEL,
# défaut qwen2.5vl:7b-rpa présent sur DGX) — désambiguïse RPA_GROUNDING_MODEL.
_grounding_model = vlm_config.get_bbox_grounding_model()
# Appel VLM — vLLM (GPU, rapide) en priorité, Ollama en fallback
import requests as _requests
@@ -2909,7 +2912,7 @@ def _pre_analyze_screen_sync(
) -> Dict[str, Any]:
"""Pré-analyse synchrone de l'écran via VLM.
Utilise gemma4 (Docker port 11435) pour détecter :
Utilise le VLM (résolu via vlm_config, endpoint Ollama) pour détecter :
1. Popups/dialogues modaux (avec coordonnées du bouton à cliquer)
2. États incohérents avec l'attendu
@@ -2917,7 +2920,10 @@ def _pre_analyze_screen_sync(
"""
import requests as _requests
gemma4_port = os.environ.get("GEMMA4_PORT", "11435")
# Endpoint VLM : piloté par config (Ollama local ou tunnel DGX = 11434).
# GEMMA4_PORT conservé comme override legacy (ancien conteneur Docker 11435).
_default_port = vlm_config.DEFAULT_OLLAMA_ENDPOINT.rsplit(":", 1)[-1]
gemma4_port = os.environ.get("GEMMA4_PORT", _default_port)
gemma4_url = f"http://localhost:{gemma4_port}/api/chat"
# Charger le contexte métier pour l'Observer
@@ -2945,7 +2951,7 @@ def _pre_analyze_screen_sync(
resp = _requests.post(
gemma4_url,
json={
"model": "gemma4:e4b",
"model": vlm_config.get_vlm_model(),
"messages": messages,
"stream": False,
"think": True,
@@ -3030,7 +3036,7 @@ def _locate_popup_button(
resp = _requests.post(
ollama_url,
json={
"model": "qwen2.5vl:7b",
"model": vlm_config.get_bbox_grounding_model(),
"messages": [{"role": "user", "content": prompt, "images": [screenshot_b64]}],
"stream": False,
# D5-v3a (2026-05-25) num_ctx=4096 explicite : éviter fuite 8192