Files
Geniusia_v2/geniusia2/tests/test_learning_manager.py
2026-03-05 00:20:25 +01:00

406 lines
11 KiB
Python

"""
Tests pour le gestionnaire d'apprentissage.
"""
import pytest
import numpy as np
import tempfile
import shutil
from pathlib import Path
from datetime import datetime
from unittest.mock import Mock, MagicMock
from geniusia2.core.learning_manager import LearningManager
from geniusia2.core.models import Action, TaskProfile
from geniusia2.core.embeddings_manager import EmbeddingsManager
from geniusia2.core.logger import Logger
@pytest.fixture
def temp_dirs():
"""Crée des répertoires temporaires pour les tests."""
temp_dir = tempfile.mkdtemp()
profiles_dir = Path(temp_dir) / "profiles"
logs_dir = Path(temp_dir) / "logs"
index_dir = Path(temp_dir) / "index"
keys_dir = Path(temp_dir) / "keys"
profiles_dir.mkdir(parents=True, exist_ok=True)
logs_dir.mkdir(parents=True, exist_ok=True)
index_dir.mkdir(parents=True, exist_ok=True)
keys_dir.mkdir(parents=True, exist_ok=True)
yield {
"profiles": str(profiles_dir),
"logs": str(logs_dir),
"index": str(index_dir),
"keys": str(keys_dir)
}
shutil.rmtree(temp_dir)
@pytest.fixture
def mock_embeddings_manager(temp_dirs):
"""Crée un gestionnaire d'embeddings mocké."""
return EmbeddingsManager(
model_name="ViT-B-32",
index_path=temp_dirs["index"],
device="cpu"
)
@pytest.fixture
def mock_logger(temp_dirs):
"""Crée un logger mocké."""
return Logger(
log_dir=temp_dirs["logs"],
key_path=temp_dirs["keys"]
)
@pytest.fixture
def learning_manager(mock_embeddings_manager, mock_logger, temp_dirs):
"""Crée une instance du gestionnaire d'apprentissage pour les tests."""
config = {
"thresholds": {
"autopilot_observations": 20,
"autopilot_concordance": 0.95,
"confidence_min": 0.90,
"rollback_confidence": 0.85
}
}
return LearningManager(
embeddings_manager=mock_embeddings_manager,
logger=mock_logger,
config=config,
profiles_path=temp_dirs["profiles"]
)
def test_initialization(learning_manager):
"""Test l'initialisation du gestionnaire."""
assert learning_manager.mode == "shadow"
assert len(learning_manager.tasks) == 0
assert learning_manager.current_task_id is None
def test_observe_action(learning_manager):
"""Test l'enregistrement d'une observation."""
action = Action(
action_type="click",
target_element="valider_button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test Window"
)
learning_manager.observe(action)
# Vérifier qu'une tâche a été créée
assert len(learning_manager.tasks) == 1
# Vérifier les propriétés de la tâche
task_id = list(learning_manager.tasks.keys())[0]
task = learning_manager.tasks[task_id]
assert task.observation_count == 1
assert task.mode == "shadow"
assert len(task.action_sequence) == 1
assert task.window_whitelist == ["Test Window"]
def test_mode_transition_shadow_to_assist(learning_manager):
"""Test la transition de Shadow vers Assisté."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
# Observer 5 fois pour déclencher la transition
for _ in range(5):
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
task = learning_manager.tasks[task_id]
# Devrait être passé en mode Assisté
assert task.mode == "assist"
assert task.observation_count == 5
def test_calculate_confidence(learning_manager):
"""Test le calcul du score de confiance."""
# Créer une tâche de test
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
# Calculer la confiance
confidence = learning_manager.calculate_confidence(
vision_conf=0.9,
llm_score=0.8,
task_id=task_id
)
# Vérifier la formule : 0.6 * 0.9 + 0.3 * 0.8 + 0.1 * 0.0 = 0.78
assert 0.77 <= confidence <= 0.79
def test_confirm_action_accept(learning_manager):
"""Test la confirmation d'une action acceptée."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
# Accepter l'action
learning_manager.confirm_action({
"type": "accept",
"task_id": task_id
})
task = learning_manager.tasks[task_id]
assert task.concordance_rate == 1.0
def test_confirm_action_reject(learning_manager):
"""Test la confirmation d'une action rejetée."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
# Rejeter l'action
learning_manager.confirm_action({
"type": "reject",
"task_id": task_id
})
task = learning_manager.tasks[task_id]
assert task.concordance_rate == 0.0
def test_confirm_action_correct(learning_manager):
"""Test la correction d'une action."""
action = Action(
action_type="click",
target_element="wrong_button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
# Corriger l'action
corrected_action = Action(
action_type="click",
target_element="correct_button",
bbox=(200, 100, 50, 30),
confidence=0.95,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.confirm_action({
"type": "correct",
"task_id": task_id,
"corrected_action": corrected_action
})
task = learning_manager.tasks[task_id]
assert task.correction_count == 1
assert len(task.action_sequence) == 2
def test_should_transition_to_auto(learning_manager):
"""Test la vérification des critères pour passer en Autopilot."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
# Observer 20 fois
for _ in range(20):
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
task = learning_manager.tasks[task_id]
# Définir une concordance élevée
task.concordance_rate = 0.96
# Devrait être éligible pour Autopilot
assert learning_manager.should_transition_to_auto(task_id)
def test_rollback_if_low_confidence(learning_manager):
"""Test la rétrogradation en cas de confiance faible."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
task = learning_manager.tasks[task_id]
# Forcer le mode Auto avec confiance faible
task.mode = "auto"
task.confidence_score = 0.85 # En dessous du seuil de 0.90
learning_manager.rollback_if_low_confidence(task_id)
# Devrait être rétrogradé en Assisté
assert task.mode == "assist"
def test_evaluate_task(learning_manager):
"""Test l'évaluation d'une tâche."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
metrics = learning_manager.evaluate_task(task_id)
assert "task_id" in metrics
assert "task_name" in metrics
assert "mode" in metrics
assert "observation_count" in metrics
assert "concordance_rate" in metrics
assert "confidence_score" in metrics
assert "correction_count" in metrics
assert metrics["observation_count"] == 1
def test_get_all_tasks(learning_manager):
"""Test la récupération de toutes les tâches."""
# Créer plusieurs tâches
for i in range(3):
action = Action(
action_type="click",
target_element=f"button_{i}",
bbox=(100 + i*50, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title=f"Test_{i}"
)
learning_manager.observe(action)
all_tasks = learning_manager.get_all_tasks()
assert len(all_tasks) == 3
assert all(isinstance(task, dict) for task in all_tasks)
def test_get_task_stats(learning_manager):
"""Test les statistiques globales."""
# Créer des tâches dans différents modes
for i in range(3):
action = Action(
action_type="click",
target_element=f"button_{i}",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title=f"Test_{i}"
)
learning_manager.observe(action)
stats = learning_manager.get_task_stats()
assert "total_tasks" in stats
assert "shadow_tasks" in stats
assert "assist_tasks" in stats
assert "auto_tasks" in stats
assert stats["total_tasks"] == 3
def test_record_execution(learning_manager):
"""Test l'enregistrement d'une exécution."""
action = Action(
action_type="click",
target_element="button",
bbox=(100, 100, 50, 30),
confidence=0.9,
embedding=np.random.rand(512).astype(np.float32),
timestamp=datetime.now(),
window_title="Test"
)
learning_manager.observe(action)
task_id = list(learning_manager.tasks.keys())[0]
# Enregistrer une exécution
learning_manager.record_execution({
"task_id": task_id,
"confidence": 0.92
})
task = learning_manager.tasks[task_id]
assert task.confidence_score == 0.92
assert task.last_execution is not None
if __name__ == "__main__":
pytest.main([__file__, "-v"])