Initial commit
This commit is contained in:
405
geniusia2/tests/test_learning_manager.py
Normal file
405
geniusia2/tests/test_learning_manager.py
Normal file
@@ -0,0 +1,405 @@
|
||||
"""
|
||||
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"])
|
||||
Reference in New Issue
Block a user