feat(agent): add learn action flow and grounding guards
This commit is contained in:
121
tests/unit/test_autonomous_planner_owl_flag.py
Normal file
121
tests/unit/test_autonomous_planner_owl_flag.py
Normal file
@@ -0,0 +1,121 @@
|
||||
"""Tests pour le feature flag AGENT_CHAT_ENABLE_OWL (C1b).
|
||||
|
||||
Contexte : depuis 2026-05-25, OWL-v2 ne se charge plus au boot du service
|
||||
rpa-agent-chat par défaut (économie ~600 MiB VRAM constatée par Codex après
|
||||
restart C1). Activation via AGENT_CHAT_ENABLE_OWL=1.
|
||||
|
||||
Référence : inbox_claude/2026-05-25_1327_codex-to-claude_C1-post-restart-ok-c1b-vram.md
|
||||
Fix : agent_chat/autonomous_planner.py _init_visual_detection() l. 139-...
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(ROOT))
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_owl_skipped_by_default(monkeypatch):
|
||||
"""Sans AGENT_CHAT_ENABLE_OWL, OWL ne doit PAS se charger au boot."""
|
||||
monkeypatch.delenv("AGENT_CHAT_ENABLE_OWL", raising=False)
|
||||
from agent_chat.autonomous_planner import AutonomousPlanner
|
||||
|
||||
planner = AutonomousPlanner(llm_model="qwen2.5:7b")
|
||||
assert planner._owl_detector is None, (
|
||||
f"OWL chargé alors que flag OFF (économie VRAM perdue) : "
|
||||
f"{planner._owl_detector}"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_owl_skipped_when_flag_zero(monkeypatch):
|
||||
"""AGENT_CHAT_ENABLE_OWL=0 → OWL skip."""
|
||||
monkeypatch.setenv("AGENT_CHAT_ENABLE_OWL", "0")
|
||||
from agent_chat.autonomous_planner import AutonomousPlanner
|
||||
|
||||
planner = AutonomousPlanner(llm_model="qwen2.5:7b")
|
||||
assert planner._owl_detector is None
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_owl_skipped_when_flag_false(monkeypatch):
|
||||
"""AGENT_CHAT_ENABLE_OWL=false → OWL skip (alias accepté)."""
|
||||
monkeypatch.setenv("AGENT_CHAT_ENABLE_OWL", "false")
|
||||
from agent_chat.autonomous_planner import AutonomousPlanner
|
||||
|
||||
planner = AutonomousPlanner(llm_model="qwen2.5:7b")
|
||||
assert planner._owl_detector is None
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_owl_init_attempted_when_flag_one(monkeypatch):
|
||||
"""AGENT_CHAT_ENABLE_OWL=1 → tentative d'init (succès ou échec rattrapé).
|
||||
|
||||
Le test ne valide PAS que OWL charge effectivement (dépend GPU + modèle
|
||||
HF disponible), juste que le code passe la garde du flag et tente l'init.
|
||||
On mocke OwlDetector pour vérifier qu'il est instancié.
|
||||
"""
|
||||
monkeypatch.setenv("AGENT_CHAT_ENABLE_OWL", "1")
|
||||
from agent_chat import autonomous_planner as ap_module
|
||||
|
||||
calls = []
|
||||
|
||||
class FakeOwl:
|
||||
def __init__(self, **kwargs):
|
||||
calls.append(kwargs)
|
||||
|
||||
monkeypatch.setattr(ap_module, "OwlDetector", FakeOwl)
|
||||
monkeypatch.setattr(ap_module, "VISUAL_DETECTION_AVAILABLE", True)
|
||||
|
||||
planner = ap_module.AutonomousPlanner(llm_model="qwen2.5:7b")
|
||||
assert planner._owl_detector is not None, (
|
||||
"OWL doit être instancié quand AGENT_CHAT_ENABLE_OWL=1"
|
||||
)
|
||||
assert len(calls) == 1
|
||||
assert calls[0].get("confidence_threshold") == 0.1
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_owl_device_override(monkeypatch):
|
||||
"""AGENT_CHAT_OWL_DEVICE=cpu force le device CPU même si CUDA dispo."""
|
||||
monkeypatch.setenv("AGENT_CHAT_ENABLE_OWL", "1")
|
||||
monkeypatch.setenv("AGENT_CHAT_OWL_DEVICE", "cpu")
|
||||
from agent_chat import autonomous_planner as ap_module
|
||||
|
||||
calls = []
|
||||
|
||||
class FakeOwl:
|
||||
def __init__(self, **kwargs):
|
||||
calls.append(kwargs)
|
||||
|
||||
monkeypatch.setattr(ap_module, "OwlDetector", FakeOwl)
|
||||
monkeypatch.setattr(ap_module, "VISUAL_DETECTION_AVAILABLE", True)
|
||||
|
||||
ap_module.AutonomousPlanner(llm_model="qwen2.5:7b")
|
||||
assert calls[0].get("device") == "cpu"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_owl_init_exception_caught(monkeypatch):
|
||||
"""Si OWL crash à l'init (OOM CUDA, modèle absent, etc.), AutonomousPlanner
|
||||
doit continuer à booter avec _owl_detector=None."""
|
||||
monkeypatch.setenv("AGENT_CHAT_ENABLE_OWL", "1")
|
||||
from agent_chat import autonomous_planner as ap_module
|
||||
|
||||
class CrashOwl:
|
||||
def __init__(self, **kwargs):
|
||||
raise RuntimeError("CUDA out of memory (simulation)")
|
||||
|
||||
monkeypatch.setattr(ap_module, "OwlDetector", CrashOwl)
|
||||
monkeypatch.setattr(ap_module, "VISUAL_DETECTION_AVAILABLE", True)
|
||||
|
||||
planner = ap_module.AutonomousPlanner(llm_model="qwen2.5:7b")
|
||||
assert planner._owl_detector is None, (
|
||||
"L'exception doit être catchée — AutonomousPlanner ne doit pas crash"
|
||||
)
|
||||
Reference in New Issue
Block a user