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

@@ -398,6 +398,56 @@ class TestWorkflowOutcomeLLM:
)
assert "10 dossiers" in rapport
def test_refine_modele_via_vlm_config(self):
"""Le payload _llm_refine_summary utilise le modèle résolu par vlm_config."""
ctx = get_domain_context("tim_codage")
captured = {}
def fake_post(url, json=None, **kwargs):
captured["url"] = url
captured["model"] = (json or {}).get("model")
resp = MagicMock()
resp.ok = True
resp.json.return_value = {"message": {"content": "ok"}}
return resp
fake_requests = MagicMock()
fake_requests.post.side_effect = fake_post
with patch.dict("sys.modules", {"requests": fake_requests}), patch(
"agent_v0.server_v1.domain_context.vlm_config.get_vlm_model",
return_value="modele-resolu:test",
):
ctx._llm_refine_summary(
template="ok", subs={"workflow_name": "x"}, success=True
)
assert captured["model"] == "modele-resolu:test"
def test_refine_endpoint_par_defaut_11434(self, monkeypatch):
"""Sans GEMMA4_PORT, _llm_refine_summary vise 11434, pas le port mort 11435."""
monkeypatch.delenv("GEMMA4_PORT", raising=False)
ctx = get_domain_context("tim_codage")
captured = {}
def fake_post(url, json=None, **kwargs):
captured["url"] = url
resp = MagicMock()
resp.ok = True
resp.json.return_value = {"message": {"content": "ok"}}
return resp
fake_requests = MagicMock()
fake_requests.post.side_effect = fake_post
with patch.dict("sys.modules", {"requests": fake_requests}):
ctx._llm_refine_summary(
template="ok", subs={"workflow_name": "x"}, success=True
)
assert ":11434" in captured["url"]
assert ":11435" not in captured["url"]
def test_llm_refine_network_error_safe(self):
"""_llm_refine_summary ne doit jamais lever, même si requests échoue."""
ctx = get_domain_context("tim_codage")