""" Tests pour le gestionnaire d'embeddings. """ import pytest import numpy as np import tempfile import shutil from pathlib import Path from geniusia2.core.embeddings_manager import EmbeddingsManager @pytest.fixture def temp_index_dir(): """Crée un répertoire temporaire pour les tests.""" temp_dir = tempfile.mkdtemp() yield temp_dir shutil.rmtree(temp_dir) @pytest.fixture def embeddings_manager(temp_index_dir): """Crée une instance du gestionnaire d'embeddings pour les tests.""" return EmbeddingsManager( model_name="ViT-B-32", pretrained="openai", index_path=temp_index_dir, device="cpu" ) def test_initialization(embeddings_manager): """Test l'initialisation du gestionnaire.""" assert embeddings_manager.clip_model is not None assert embeddings_manager.faiss_index is not None assert embeddings_manager.embedding_dim > 0 def test_encode_image(embeddings_manager): """Test l'encodage d'une image.""" # Créer une image de test test_image = np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8) # Encoder l'image embedding = embeddings_manager.encode_image(test_image) # Vérifier la forme et le type assert isinstance(embedding, np.ndarray) assert embedding.shape == (embeddings_manager.embedding_dim,) assert embedding.dtype == np.float32 or embedding.dtype == np.float64 def test_add_to_index(embeddings_manager): """Test l'ajout d'embeddings à l'index.""" # Créer un embedding de test embedding = np.random.randn(embeddings_manager.embedding_dim).astype(np.float32) metadata = {"task_id": "test_task", "label": "button"} # Ajouter à l'index idx = embeddings_manager.add_to_index(embedding, metadata) # Vérifier assert idx == 0 assert embeddings_manager.faiss_index.ntotal == 1 assert idx in embeddings_manager.metadata_store def test_search_similar(embeddings_manager): """Test la recherche de similarité.""" # Ajouter plusieurs embeddings embeddings = [] for i in range(5): emb = np.random.randn(embeddings_manager.embedding_dim).astype(np.float32) embeddings.append(emb) embeddings_manager.add_to_index(emb, {"id": i}) # Rechercher des embeddings similaires query = embeddings[0] results = embeddings_manager.search_similar(query, k=3) # Vérifier assert len(results) == 3 assert results[0]["id"] == 0 # Le plus similaire devrait être lui-même assert "distance" in results[0] assert "similarity" in results[0] assert "metadata" in results[0] def test_embedding_similarity(embeddings_manager): """Test le calcul de similarité cosinus.""" # Créer deux embeddings identiques emb1 = np.random.randn(embeddings_manager.embedding_dim).astype(np.float32) emb2 = emb1.copy() # Calculer la similarité similarity = embeddings_manager.get_embedding_similarity(emb1, emb2) # Devrait être proche de 1.0 assert 0.99 <= similarity <= 1.0 # Créer deux embeddings orthogonaux emb3 = np.zeros(embeddings_manager.embedding_dim, dtype=np.float32) emb3[0] = 1.0 emb4 = np.zeros(embeddings_manager.embedding_dim, dtype=np.float32) emb4[1] = 1.0 similarity_ortho = embeddings_manager.get_embedding_similarity(emb3, emb4) # Devrait être proche de 0.5 (orthogonal) assert 0.4 <= similarity_ortho <= 0.6 def test_save_and_load_index(temp_index_dir): """Test la sauvegarde et le chargement de l'index.""" # Créer un gestionnaire et ajouter des données manager1 = EmbeddingsManager( model_name="ViT-B-32", index_path=temp_index_dir, device="cpu" ) embedding = np.random.randn(manager1.embedding_dim).astype(np.float32) metadata = {"test": "data"} manager1.add_to_index(embedding, metadata) manager1.save_index() # Créer un nouveau gestionnaire qui charge l'index manager2 = EmbeddingsManager( model_name="ViT-B-32", index_path=temp_index_dir, device="cpu" ) # Vérifier que les données sont chargées assert manager2.faiss_index.ntotal == 1 assert 0 in manager2.metadata_store assert manager2.metadata_store[0]["test"] == "data" def test_rebuild_index(embeddings_manager): """Test la reconstruction de l'index.""" # Ajouter des embeddings for i in range(3): emb = np.random.randn(embeddings_manager.embedding_dim).astype(np.float32) embeddings_manager.add_to_index(emb, {"id": i}) initial_count = embeddings_manager.faiss_index.ntotal # Reconstruire l'index embeddings_manager.rebuild_index() # Vérifier que le nombre d'embeddings est préservé assert embeddings_manager.faiss_index.ntotal == initial_count def test_get_stats(embeddings_manager): """Test l'obtention des statistiques.""" stats = embeddings_manager.get_stats() assert "num_embeddings" in stats assert "embedding_dim" in stats assert "model_name" in stats assert "device" in stats assert stats["model_name"] == "ViT-B-32" def test_clear_index(embeddings_manager): """Test l'effacement de l'index.""" # Ajouter des embeddings for i in range(3): emb = np.random.randn(embeddings_manager.embedding_dim).astype(np.float32) embeddings_manager.add_to_index(emb, {"id": i}) assert embeddings_manager.faiss_index.ntotal == 3 # Effacer l'index embeddings_manager.clear_index() # Vérifier assert embeddings_manager.faiss_index.ntotal == 0 assert len(embeddings_manager.metadata_store) == 0 def test_empty_search(embeddings_manager): """Test la recherche sur un index vide.""" query = np.random.randn(embeddings_manager.embedding_dim).astype(np.float32) results = embeddings_manager.search_similar(query, k=5) assert results == [] if __name__ == "__main__": pytest.main([__file__, "-v"])