Phase 3 - State Transformation: - transform_state() function with alpha/beta parameters - compute_adaptive_params() for dynamic transformation - StateTransformer class for state management Phase 4 - Occasion Logger: - OccasionLog dataclass for structured logging - OccasionLogger for JSON file storage - Profile evolution tracking and statistics Phase 5 - Occasion Manager: - Full cycle: Prehension → Concrescence → Satisfaction - Search integration (thoughts, library) - State creation and logging orchestration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
216 lines
7.1 KiB
Python
216 lines
7.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Tests pour Phase 4 - Logging des occasions."""
|
|
|
|
import tempfile
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from ..occasion_logger import OccasionLogger, OccasionLog
|
|
|
|
|
|
class TestOccasionLog:
|
|
"""Tests de la structure OccasionLog."""
|
|
|
|
def test_create_occasion_log(self):
|
|
"""Créer un OccasionLog basique."""
|
|
log = OccasionLog(
|
|
occasion_id=1,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user",
|
|
trigger_content="Test",
|
|
previous_state_id=0,
|
|
prehended_thoughts_count=5,
|
|
prehended_docs_count=2,
|
|
response_summary="Response",
|
|
new_state_id=1,
|
|
alpha_used=0.85,
|
|
beta_used=0.15,
|
|
processing_time_ms=1000
|
|
)
|
|
|
|
assert log.occasion_id == 1
|
|
assert log.trigger_type == "user"
|
|
assert log.alpha_used == 0.85
|
|
|
|
def test_default_lists(self):
|
|
"""Les listes par défaut sont vides."""
|
|
log = OccasionLog(
|
|
occasion_id=1,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user",
|
|
trigger_content="Test",
|
|
previous_state_id=0,
|
|
prehended_thoughts_count=0,
|
|
prehended_docs_count=0,
|
|
response_summary="Response",
|
|
new_state_id=1,
|
|
alpha_used=0.85,
|
|
beta_used=0.15
|
|
)
|
|
|
|
assert log.new_thoughts == []
|
|
assert log.tools_used == []
|
|
assert log.prehended_thoughts == []
|
|
|
|
|
|
class TestOccasionLogger:
|
|
"""Tests du logger d'occasions."""
|
|
|
|
@pytest.fixture
|
|
def temp_logger(self):
|
|
"""Créer un logger avec répertoire temporaire."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
yield OccasionLogger(tmpdir)
|
|
|
|
def test_log_and_retrieve(self, temp_logger):
|
|
"""Logger et relire une occasion."""
|
|
occasion = OccasionLog(
|
|
occasion_id=42,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user",
|
|
trigger_content="Question test",
|
|
previous_state_id=5,
|
|
prehended_thoughts_count=3,
|
|
prehended_docs_count=1,
|
|
response_summary="Réponse test",
|
|
new_thoughts=["Nouvelle pensée"],
|
|
tools_used=["search_thoughts"],
|
|
new_state_id=6,
|
|
alpha_used=0.82,
|
|
beta_used=0.18,
|
|
processing_time_ms=2500
|
|
)
|
|
|
|
# Logger
|
|
filepath = temp_logger.log(occasion)
|
|
assert filepath.exists()
|
|
|
|
# Relire
|
|
loaded = temp_logger.get_occasion(42)
|
|
assert loaded is not None
|
|
assert loaded.occasion_id == 42
|
|
assert loaded.trigger_content == "Question test"
|
|
assert loaded.new_thoughts == ["Nouvelle pensée"]
|
|
|
|
def test_get_nonexistent(self, temp_logger):
|
|
"""Récupérer une occasion inexistante retourne None."""
|
|
loaded = temp_logger.get_occasion(99999)
|
|
assert loaded is None
|
|
|
|
def test_get_recent_occasions(self, temp_logger):
|
|
"""Récupérer les occasions récentes."""
|
|
# Créer plusieurs occasions
|
|
for i in range(5):
|
|
occasion = OccasionLog(
|
|
occasion_id=i,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user",
|
|
trigger_content=f"Question {i}",
|
|
previous_state_id=max(0, i - 1),
|
|
prehended_thoughts_count=i,
|
|
prehended_docs_count=1,
|
|
response_summary=f"Réponse {i}",
|
|
new_state_id=i,
|
|
alpha_used=0.85,
|
|
beta_used=0.15,
|
|
processing_time_ms=1000 + i * 100
|
|
)
|
|
temp_logger.log(occasion)
|
|
|
|
# Récupérer les 3 dernières
|
|
recent = temp_logger.get_recent_occasions(3)
|
|
assert len(recent) == 3
|
|
|
|
# Vérifier l'ordre (plus récent d'abord)
|
|
assert recent[0].occasion_id == 4
|
|
assert recent[1].occasion_id == 3
|
|
assert recent[2].occasion_id == 2
|
|
|
|
def test_get_last_occasion_id(self, temp_logger):
|
|
"""Récupérer l'ID de la dernière occasion."""
|
|
# Vide
|
|
assert temp_logger.get_last_occasion_id() == -1
|
|
|
|
# Ajouter une occasion
|
|
occasion = OccasionLog(
|
|
occasion_id=10,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user",
|
|
trigger_content="Test",
|
|
previous_state_id=0,
|
|
prehended_thoughts_count=0,
|
|
prehended_docs_count=0,
|
|
response_summary="Response",
|
|
new_state_id=1,
|
|
alpha_used=0.85,
|
|
beta_used=0.15
|
|
)
|
|
temp_logger.log(occasion)
|
|
|
|
assert temp_logger.get_last_occasion_id() == 10
|
|
|
|
def test_profile_evolution(self, temp_logger):
|
|
"""Tracer l'évolution d'une composante."""
|
|
# Créer des occasions avec évolution de curiosité
|
|
for i in range(5):
|
|
occasion = OccasionLog(
|
|
occasion_id=i,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user",
|
|
trigger_content=f"Question {i}",
|
|
previous_state_id=max(0, i - 1),
|
|
prehended_thoughts_count=0,
|
|
prehended_docs_count=0,
|
|
response_summary=f"Réponse {i}",
|
|
new_state_id=i,
|
|
alpha_used=0.85,
|
|
beta_used=0.15,
|
|
profile_before={"epistemic": {"curiosity": 0.5 + i * 0.05}},
|
|
profile_after={"epistemic": {"curiosity": 0.5 + (i + 1) * 0.05}}
|
|
)
|
|
temp_logger.log(occasion)
|
|
|
|
evolution = temp_logger.get_profile_evolution("curiosity", last_n=5)
|
|
|
|
assert len(evolution) == 5
|
|
# Vérifier que la curiosité augmente
|
|
values = [v for _, v in evolution]
|
|
assert values[-1] > values[0]
|
|
|
|
def test_statistics(self, temp_logger):
|
|
"""Calculer des statistiques."""
|
|
# Créer quelques occasions
|
|
for i in range(3):
|
|
occasion = OccasionLog(
|
|
occasion_id=i,
|
|
timestamp=datetime.now().isoformat(),
|
|
trigger_type="user" if i % 2 == 0 else "timer",
|
|
trigger_content=f"Question {i}",
|
|
previous_state_id=max(0, i - 1),
|
|
prehended_thoughts_count=0,
|
|
prehended_docs_count=0,
|
|
response_summary=f"Réponse {i}",
|
|
new_thoughts=["t1"] if i == 0 else [],
|
|
tools_used=["tool1", "tool2"],
|
|
new_state_id=i,
|
|
alpha_used=0.85,
|
|
beta_used=0.15,
|
|
processing_time_ms=1000 + i * 500
|
|
)
|
|
temp_logger.log(occasion)
|
|
|
|
stats = temp_logger.get_statistics()
|
|
|
|
assert stats["count"] == 3
|
|
assert "processing_time" in stats
|
|
assert "thoughts_created" in stats
|
|
assert "trigger_distribution" in stats
|
|
assert stats["trigger_distribution"]["user"] == 2
|
|
assert stats["trigger_distribution"]["timer"] == 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|