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

@@ -16,13 +16,13 @@ from typing import Any, Dict, List, Optional
import requests
from core.detection import vlm_config
from .schema import ExtractionField, ExtractionSchema
logger = logging.getLogger(__name__)
# Configuration Ollama (coherente avec le reste du projet)
OLLAMA_DEFAULT_URL = os.environ.get("OLLAMA_URL", "http://localhost:11434")
OLLAMA_DEFAULT_MODEL = os.environ.get("RPA_VLM_MODEL", os.environ.get("VLM_MODEL", "gemma4:e4b"))
class FieldExtractor:
@@ -38,19 +38,34 @@ class FieldExtractor:
def __init__(
self,
ollama_url: str = OLLAMA_DEFAULT_URL,
ollama_model: str = OLLAMA_DEFAULT_MODEL,
ollama_model: Optional[str] = None,
timeout: int = 60,
):
"""
Args:
ollama_url: URL du serveur Ollama
ollama_model: Modele VLM a utiliser
ollama_model: Modele VLM a utiliser (None = resolution lazy via vlm_config)
timeout: Timeout en secondes pour les appels VLM
"""
self.ollama_url = ollama_url.rstrip("/")
self.ollama_model = ollama_model
self._ollama_model = ollama_model # None → resolu paresseusement
self.timeout = timeout
@property
def ollama_model(self) -> str:
"""Modele VLM, resolu paresseusement via vlm_config si non fourni.
Resolution differee au premier acces (pas a l'import ni a la
construction) : evite tout hardcode gemma4 et tout appel reseau a froid.
"""
if not self._ollama_model:
self._ollama_model = vlm_config.get_vlm_model(self.ollama_url)
return self._ollama_model
@ollama_model.setter
def ollama_model(self, value: Optional[str]) -> None:
self._ollama_model = value
# ------------------------------------------------------------------
# API publique
# ------------------------------------------------------------------